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:
VTEmitter(const RecordKeeper & R)24 VTEmitter(const RecordKeeper &R) : Records(R) {}
25
26 void run(raw_ostream &OS);
27 };
28
29 } // End anonymous namespace.
30
vTtoGetLlvmTyString(raw_ostream & OS,const Record * VT)31 static void vTtoGetLlvmTyString(raw_ostream &OS, const Record *VT) {
32 bool IsVector = VT->getValueAsBit("isVector");
33 bool IsRISCVVecTuple = VT->getValueAsBit("isRISCVVecTuple");
34
35 if (IsRISCVVecTuple) {
36 unsigned NElem = VT->getValueAsInt("nElem");
37 unsigned Sz = VT->getValueAsInt("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("isScalable") ? "Scalable" : "Fixed")
46 << "VectorType::get(";
47
48 auto OutputVT = IsVector ? VT->getValueAsDef("ElementType") : VT;
49 int64_t OutputVTSize = OutputVT->getValueAsInt("Size");
50
51 if (OutputVT->getValueAsBit("isFP")) {
52 StringRef FloatTy;
53 auto OutputVTName = OutputVT->getValueAsString("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("isInteger")) {
75 // We only have Type::getInt1Ty, Int8, Int16, Int32, Int64, and Int128
76 if ((isPowerOf2_64(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("nElem") << ")";
88 }
89
run(raw_ostream & OS)90 void VTEmitter::run(raw_ostream &OS) {
91 emitSourceFileHeader("ValueTypes Source Fragment", OS, Records);
92
93 std::vector<const Record *> VTsByNumber{512};
94 for (auto *VT : Records.getAllDerivedDefinitions("ValueType")) {
95 auto Number = VT->getValueAsInt("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(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(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("LLVMName");
129 auto Value = VT->getValueAsInt("Value");
130 bool IsInteger = VT->getValueAsBit("isInteger");
131 bool IsFP = VT->getValueAsBit("isFP");
132 bool IsVector = VT->getValueAsBit("isVector");
133 bool IsScalable = VT->getValueAsBit("isScalable");
134 bool IsRISCVVecTuple = VT->getValueAsBit("isRISCVVecTuple");
135 int64_t NF = VT->getValueAsInt("NF");
136 bool IsNormalValueType = VT->getValueAsBit("isNormalValueType");
137 int64_t NElem = IsVector ? VT->getValueAsInt("nElem") : 0;
138 StringRef EltName = IsVector ? VT->getValueAsDef("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("Size") << ", "
161 << VT->getValueAsBit("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("isVector"))
185 continue;
186 const auto *ElTy = VT->getValueAsDef("ElementType");
187 assert(ElTy);
188 // clang-format off
189 OS << " GET_VT_VECATTR("
190 << VT->getValueAsString("LLVMName") << ", "
191 << VT->getValueAsBit("isScalable") << ", "
192 << VT->getValueAsBit("isRISCVVecTuple") << ", "
193 << VT->getValueAsInt("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("isInteger");
204 bool IsVector = VT->getValueAsBit("isVector");
205 bool IsFP = VT->getValueAsBit("isFP");
206 bool IsRISCVVecTuple = VT->getValueAsBit("isRISCVVecTuple");
207
208 if (!IsInteger && !IsVector && !IsFP && !IsRISCVVecTuple)
209 continue;
210
211 OS << " GET_VT_EVT(" << VT->getValueAsString("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