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>
15using namespace llvm;
16
17namespace {
18
19class VTEmitter {
20private:
21 const RecordKeeper &Records;
22
23public:
24 VTEmitter(const RecordKeeper &R) : Records(R) {}
25
26 void run(raw_ostream &OS);
27};
28
29} // End anonymous namespace.
30
31static 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
90void 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
218static TableGen::Emitter::OptClass<VTEmitter> X("gen-vt", "Generate ValueType");
219