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 <cassert> |
14 | #include <map> |
15 | using namespace llvm; |
16 | |
17 | namespace { |
18 | |
19 | class VTEmitter { |
20 | private: |
21 | const RecordKeeper &Records; |
22 | |
23 | public: |
24 | VTEmitter(const RecordKeeper &R) : Records(R) {} |
25 | |
26 | void run(raw_ostream &OS); |
27 | }; |
28 | |
29 | } // End anonymous namespace. |
30 | |
31 | static void vTtoGetLlvmTyString(raw_ostream &OS, const Record *VT) { |
32 | bool IsVector = VT->getValueAsBit(FieldName: "isVector" ); |
33 | bool IsRISCVVecTuple = VT->getValueAsBit(FieldName: "isRISCVVecTuple" ); |
34 | |
35 | if (IsRISCVVecTuple) { |
36 | unsigned NElem = VT->getValueAsInt(FieldName: "nElem" ); |
37 | unsigned Sz = VT->getValueAsInt(FieldName: "Size" ); |
38 | OS << "TargetExtType::get(Context, \"riscv.vector.tuple\", " |
39 | "ScalableVectorType::get(Type::getInt8Ty(Context), " |
40 | << (Sz / (NElem * 8)) << "), " << NElem << ")" ; |
41 | return; |
42 | } |
43 | |
44 | if (IsVector) |
45 | OS << (VT->getValueAsBit(FieldName: "isScalable" ) ? "Scalable" : "Fixed" ) |
46 | << "VectorType::get(" ; |
47 | |
48 | auto OutputVT = IsVector ? VT->getValueAsDef(FieldName: "ElementType" ) : VT; |
49 | int64_t OutputVTSize = OutputVT->getValueAsInt(FieldName: "Size" ); |
50 | |
51 | if (OutputVT->getValueAsBit(FieldName: "isFP" )) { |
52 | StringRef FloatTy; |
53 | auto OutputVTName = OutputVT->getValueAsString(FieldName: "LLVMName" ); |
54 | switch (OutputVTSize) { |
55 | default: |
56 | llvm_unreachable("Unhandled case" ); |
57 | case 16: |
58 | FloatTy = (OutputVTName == "bf16" ) ? "BFloatTy" : "HalfTy" ; |
59 | break; |
60 | case 32: |
61 | FloatTy = "FloatTy" ; |
62 | break; |
63 | case 64: |
64 | FloatTy = "DoubleTy" ; |
65 | break; |
66 | case 80: |
67 | FloatTy = "X86_FP80Ty" ; |
68 | break; |
69 | case 128: |
70 | FloatTy = (OutputVTName == "ppcf128" ) ? "PPC_FP128Ty" : "FP128Ty" ; |
71 | break; |
72 | } |
73 | OS << "Type::get" << FloatTy << "(Context)" ; |
74 | } else if (OutputVT->getValueAsBit(FieldName: "isInteger" )) { |
75 | // We only have Type::getInt1Ty, Int8, Int16, Int32, Int64, and Int128 |
76 | if ((isPowerOf2_64(Value: OutputVTSize) && OutputVTSize >= 8 && |
77 | OutputVTSize <= 128) || |
78 | OutputVTSize == 1) |
79 | OS << "Type::getInt" << OutputVTSize << "Ty(Context)" ; |
80 | else |
81 | OS << "Type::getIntNTy(Context, " << OutputVTSize << ")" ; |
82 | } else { |
83 | llvm_unreachable("Unhandled case" ); |
84 | } |
85 | |
86 | if (IsVector) |
87 | OS << ", " << VT->getValueAsInt(FieldName: "nElem" ) << ")" ; |
88 | } |
89 | |
90 | void VTEmitter::run(raw_ostream &OS) { |
91 | emitSourceFileHeader(Desc: "ValueTypes Source Fragment" , OS, Record: Records); |
92 | |
93 | std::vector<const Record *> VTsByNumber{512}; |
94 | for (auto *VT : Records.getAllDerivedDefinitions(ClassName: "ValueType" )) { |
95 | auto Number = VT->getValueAsInt(FieldName: "Value" ); |
96 | assert(0 <= Number && Number < (int)VTsByNumber.size() && |
97 | "ValueType should be uint16_t" ); |
98 | assert(!VTsByNumber[Number] && "Duplicate ValueType" ); |
99 | VTsByNumber[Number] = VT; |
100 | } |
101 | |
102 | struct VTRange { |
103 | StringRef First; |
104 | StringRef Last; |
105 | bool Closed; |
106 | }; |
107 | |
108 | std::map<StringRef, VTRange> VTRanges; |
109 | |
110 | auto UpdateVTRange = [&VTRanges](const char *Key, StringRef Name, |
111 | bool Valid) { |
112 | if (Valid) { |
113 | auto [It, Inserted] = VTRanges.try_emplace(k: Key); |
114 | if (Inserted) |
115 | It->second.First = Name; |
116 | assert(!It->second.Closed && "Gap detected!" ); |
117 | It->second.Last = Name; |
118 | } else if (auto It = VTRanges.find(x: Key); It != VTRanges.end()) { |
119 | It->second.Closed = true; |
120 | } |
121 | }; |
122 | |
123 | OS << "#ifdef GET_VT_ATTR // (Ty, n, sz, Any, Int, FP, Vec, Sc, Tup, NF, " |
124 | "NElem, EltTy)\n" ; |
125 | for (const auto *VT : VTsByNumber) { |
126 | if (!VT) |
127 | continue; |
128 | auto Name = VT->getValueAsString(FieldName: "LLVMName" ); |
129 | auto Value = VT->getValueAsInt(FieldName: "Value" ); |
130 | bool IsInteger = VT->getValueAsBit(FieldName: "isInteger" ); |
131 | bool IsFP = VT->getValueAsBit(FieldName: "isFP" ); |
132 | bool IsVector = VT->getValueAsBit(FieldName: "isVector" ); |
133 | bool IsScalable = VT->getValueAsBit(FieldName: "isScalable" ); |
134 | bool IsRISCVVecTuple = VT->getValueAsBit(FieldName: "isRISCVVecTuple" ); |
135 | int64_t NF = VT->getValueAsInt(FieldName: "NF" ); |
136 | bool IsNormalValueType = VT->getValueAsBit(FieldName: "isNormalValueType" ); |
137 | int64_t NElem = IsVector ? VT->getValueAsInt(FieldName: "nElem" ) : 0; |
138 | StringRef EltName = IsVector ? VT->getValueAsDef(FieldName: "ElementType" )->getName() |
139 | : "INVALID_SIMPLE_VALUE_TYPE" ; |
140 | |
141 | UpdateVTRange("INTEGER_FIXEDLEN_VECTOR_VALUETYPE" , Name, |
142 | IsInteger && IsVector && !IsScalable); |
143 | UpdateVTRange("INTEGER_SCALABLE_VECTOR_VALUETYPE" , Name, |
144 | IsInteger && IsScalable); |
145 | UpdateVTRange("FP_FIXEDLEN_VECTOR_VALUETYPE" , Name, |
146 | IsFP && IsVector && !IsScalable); |
147 | UpdateVTRange("FP_SCALABLE_VECTOR_VALUETYPE" , Name, IsFP && IsScalable); |
148 | UpdateVTRange("FIXEDLEN_VECTOR_VALUETYPE" , Name, IsVector && !IsScalable); |
149 | UpdateVTRange("SCALABLE_VECTOR_VALUETYPE" , Name, IsScalable); |
150 | UpdateVTRange("RISCV_VECTOR_TUPLE_VALUETYPE" , Name, IsRISCVVecTuple); |
151 | UpdateVTRange("VECTOR_VALUETYPE" , Name, IsVector); |
152 | UpdateVTRange("INTEGER_VALUETYPE" , Name, IsInteger && !IsVector); |
153 | UpdateVTRange("FP_VALUETYPE" , Name, IsFP && !IsVector); |
154 | UpdateVTRange("VALUETYPE" , Name, IsNormalValueType); |
155 | |
156 | // clang-format off |
157 | OS << " GET_VT_ATTR(" |
158 | << Name << ", " |
159 | << Value << ", " |
160 | << VT->getValueAsInt(FieldName: "Size" ) << ", " |
161 | << VT->getValueAsBit(FieldName: "isOverloaded" ) << ", " |
162 | << (IsInteger ? Name[0] == 'i' ? 3 : 1 : 0) << ", " |
163 | << (IsFP ? Name[0] == 'f' ? 3 : 1 : 0) << ", " |
164 | << IsVector << ", " |
165 | << IsScalable << ", " |
166 | << IsRISCVVecTuple << ", " |
167 | << NF << ", " |
168 | << NElem << ", " |
169 | << EltName << ")\n" ; |
170 | // clang-format on |
171 | } |
172 | OS << "#endif\n\n" ; |
173 | |
174 | OS << "#ifdef GET_VT_RANGES\n" ; |
175 | for (const auto &KV : VTRanges) { |
176 | assert(KV.second.Closed); |
177 | OS << " FIRST_" << KV.first << " = " << KV.second.First << ",\n" |
178 | << " LAST_" << KV.first << " = " << KV.second.Last << ",\n" ; |
179 | } |
180 | OS << "#endif\n\n" ; |
181 | |
182 | OS << "#ifdef GET_VT_VECATTR // (Ty, Sc, Tup, nElem, ElTy)\n" ; |
183 | for (const auto *VT : VTsByNumber) { |
184 | if (!VT || !VT->getValueAsBit(FieldName: "isVector" )) |
185 | continue; |
186 | const auto *ElTy = VT->getValueAsDef(FieldName: "ElementType" ); |
187 | assert(ElTy); |
188 | // clang-format off |
189 | OS << " GET_VT_VECATTR(" |
190 | << VT->getValueAsString(FieldName: "LLVMName" ) << ", " |
191 | << VT->getValueAsBit(FieldName: "isScalable" ) << ", " |
192 | << VT->getValueAsBit(FieldName: "isRISCVVecTuple" ) << ", " |
193 | << VT->getValueAsInt(FieldName: "nElem" ) << ", " |
194 | << ElTy->getName() << ")\n" ; |
195 | // clang-format on |
196 | } |
197 | OS << "#endif\n\n" ; |
198 | |
199 | OS << "#ifdef GET_VT_EVT\n" ; |
200 | for (const auto *VT : VTsByNumber) { |
201 | if (!VT) |
202 | continue; |
203 | bool IsInteger = VT->getValueAsBit(FieldName: "isInteger" ); |
204 | bool IsVector = VT->getValueAsBit(FieldName: "isVector" ); |
205 | bool IsFP = VT->getValueAsBit(FieldName: "isFP" ); |
206 | bool IsRISCVVecTuple = VT->getValueAsBit(FieldName: "isRISCVVecTuple" ); |
207 | |
208 | if (!IsInteger && !IsVector && !IsFP && !IsRISCVVecTuple) |
209 | continue; |
210 | |
211 | OS << " GET_VT_EVT(" << VT->getValueAsString(FieldName: "LLVMName" ) << ", " ; |
212 | vTtoGetLlvmTyString(OS, VT); |
213 | OS << ")\n" ; |
214 | } |
215 | OS << "#endif\n\n" ; |
216 | } |
217 | |
218 | static TableGen::Emitter::OptClass<VTEmitter> X("gen-vt" , "Generate ValueType" ); |
219 | |