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