1 | //===- VTEmitter.cpp - Generate properties from ValueTypes.td -------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "llvm/ADT/StringRef.h" |
10 | #include "llvm/Support/raw_ostream.h" |
11 | #include "llvm/TableGen/Record.h" |
12 | #include "llvm/TableGen/TableGenBackend.h" |
13 | #include <array> |
14 | #include <cassert> |
15 | #include <map> |
16 | using namespace llvm; |
17 | |
18 | namespace { |
19 | |
20 | class VTEmitter { |
21 | private: |
22 | RecordKeeper &Records; |
23 | |
24 | public: |
25 | VTEmitter(RecordKeeper &R) : Records(R) {} |
26 | |
27 | void run(raw_ostream &OS); |
28 | }; |
29 | |
30 | } // End anonymous namespace. |
31 | |
32 | void VTEmitter::run(raw_ostream &OS) { |
33 | emitSourceFileHeader(Desc: "ValueTypes Source Fragment" , OS, Record: Records); |
34 | |
35 | std::array<const Record *, 256> VTsByNumber = {}; |
36 | auto ValueTypes = Records.getAllDerivedDefinitions(ClassName: "ValueType" ); |
37 | for (auto *VT : ValueTypes) { |
38 | auto Number = VT->getValueAsInt(FieldName: "Value" ); |
39 | assert(0 <= Number && Number < (int)VTsByNumber.size() && |
40 | "ValueType should be uint8_t" ); |
41 | assert(!VTsByNumber[Number] && "Duplicate ValueType" ); |
42 | VTsByNumber[Number] = VT; |
43 | } |
44 | |
45 | struct VTRange { |
46 | StringRef First; |
47 | StringRef Last; |
48 | bool Closed; |
49 | }; |
50 | |
51 | std::map<StringRef, VTRange> VTRanges; |
52 | |
53 | auto UpdateVTRange = [&VTRanges](const char *Key, StringRef Name, |
54 | bool Valid) { |
55 | if (Valid) { |
56 | if (!VTRanges.count(x: Key)) |
57 | VTRanges[Key].First = Name; |
58 | assert(!VTRanges[Key].Closed && "Gap detected!" ); |
59 | VTRanges[Key].Last = Name; |
60 | } else if (VTRanges.count(x: Key)) { |
61 | VTRanges[Key].Closed = true; |
62 | } |
63 | }; |
64 | |
65 | OS << "#ifdef GET_VT_ATTR // (Ty, n, sz, Any, Int, FP, Vec, Sc)\n" ; |
66 | for (const auto *VT : VTsByNumber) { |
67 | if (!VT) |
68 | continue; |
69 | auto Name = VT->getValueAsString(FieldName: "LLVMName" ); |
70 | auto Value = VT->getValueAsInt(FieldName: "Value" ); |
71 | bool IsInteger = VT->getValueAsInt(FieldName: "isInteger" ); |
72 | bool IsFP = VT->getValueAsInt(FieldName: "isFP" ); |
73 | bool IsVector = VT->getValueAsInt(FieldName: "isVector" ); |
74 | bool IsScalable = VT->getValueAsInt(FieldName: "isScalable" ); |
75 | |
76 | UpdateVTRange("INTEGER_FIXEDLEN_VECTOR_VALUETYPE" , Name, |
77 | IsInteger && IsVector && !IsScalable); |
78 | UpdateVTRange("INTEGER_SCALABLE_VECTOR_VALUETYPE" , Name, |
79 | IsInteger && IsScalable); |
80 | UpdateVTRange("FP_FIXEDLEN_VECTOR_VALUETYPE" , Name, |
81 | IsFP && IsVector && !IsScalable); |
82 | UpdateVTRange("FP_SCALABLE_VECTOR_VALUETYPE" , Name, IsFP && IsScalable); |
83 | UpdateVTRange("FIXEDLEN_VECTOR_VALUETYPE" , Name, IsVector && !IsScalable); |
84 | UpdateVTRange("SCALABLE_VECTOR_VALUETYPE" , Name, IsScalable); |
85 | UpdateVTRange("VECTOR_VALUETYPE" , Name, IsVector); |
86 | UpdateVTRange("INTEGER_VALUETYPE" , Name, IsInteger && !IsVector); |
87 | UpdateVTRange("FP_VALUETYPE" , Name, IsFP && !IsVector); |
88 | UpdateVTRange("VALUETYPE" , Name, Value < 224); |
89 | |
90 | // clang-format off |
91 | OS << " GET_VT_ATTR(" |
92 | << Name << ", " |
93 | << Value << ", " |
94 | << VT->getValueAsInt(FieldName: "Size" ) << ", " |
95 | << VT->getValueAsInt(FieldName: "isOverloaded" ) << ", " |
96 | << (IsInteger ? Name[0] == 'i' ? 3 : 1 : 0) << ", " |
97 | << (IsFP ? Name[0] == 'f' ? 3 : 1 : 0) << ", " |
98 | << IsVector << ", " |
99 | << IsScalable << ")\n" ; |
100 | // clang-format on |
101 | } |
102 | OS << "#endif\n\n" ; |
103 | |
104 | OS << "#ifdef GET_VT_RANGES\n" ; |
105 | for (const auto &KV : VTRanges) { |
106 | assert(KV.second.Closed); |
107 | OS << " FIRST_" << KV.first << " = " << KV.second.First << ",\n" |
108 | << " LAST_" << KV.first << " = " << KV.second.Last << ",\n" ; |
109 | } |
110 | OS << "#endif\n\n" ; |
111 | |
112 | OS << "#ifdef GET_VT_VECATTR // (Ty, Sc, nElem, ElTy, ElSz)\n" ; |
113 | for (const auto *VT : VTsByNumber) { |
114 | if (!VT || !VT->getValueAsInt(FieldName: "isVector" )) |
115 | continue; |
116 | const auto *ElTy = VT->getValueAsDef(FieldName: "ElementType" ); |
117 | assert(ElTy); |
118 | // clang-format off |
119 | OS << " GET_VT_VECATTR(" |
120 | << VT->getValueAsString(FieldName: "LLVMName" ) << ", " |
121 | << VT->getValueAsInt(FieldName: "isScalable" ) << ", " |
122 | << VT->getValueAsInt(FieldName: "nElem" ) << ", " |
123 | << ElTy->getName() << ", " |
124 | << ElTy->getValueAsInt(FieldName: "Size" ) << ")\n" ; |
125 | // clang-format on |
126 | } |
127 | OS << "#endif\n\n" ; |
128 | } |
129 | |
130 | static TableGen::Emitter::OptClass<VTEmitter> X("gen-vt" , "Generate ValueType" ); |
131 | |