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 NF = VT->getValueAsInt(FieldName: "NF");
37 unsigned Sz = VT->getValueAsInt(FieldName: "Size");
38 OS << "TargetExtType::get(Context, \"riscv.vector.tuple\", "
39 "ScalableVectorType::get(Type::getInt8Ty(Context), "
40 << (Sz / (NF * 8)) << "), " << NF << ")";
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 unsigned Number = 0;
95 std::vector<const Record *> Defs(
96 Records.getAllDerivedDefinitions(ClassName: "ValueType"));
97 // Emit VTs in the order they were declared so that VTRanges stay contiguous.
98 llvm::sort(C&: Defs, Comp: LessRecordByID());
99 for (auto *VT : Defs) {
100 ++Number;
101 assert(Number < VTsByNumber.size() && "ValueType should be uint16_t");
102 VTsByNumber[Number] = VT;
103 }
104
105 struct VTRange {
106 StringRef First;
107 StringRef Last;
108 bool Closed;
109 };
110
111 std::map<StringRef, VTRange> VTRanges;
112
113 auto UpdateVTRange = [&VTRanges](const char *Key, StringRef Name,
114 bool Valid) {
115 if (Valid) {
116 auto [It, Inserted] = VTRanges.try_emplace(k: Key);
117 if (Inserted)
118 It->second.First = Name;
119 assert(!It->second.Closed && "Gap detected!");
120 It->second.Last = Name;
121 } else if (auto It = VTRanges.find(x: Key); It != VTRanges.end()) {
122 It->second.Closed = true;
123 }
124 };
125
126 OS << "#ifdef GET_VT_ATTR // (Ty, sz, Any, Int, FP, Vec, Sc, Tup, NF, "
127 "NElem, EltTy)\n";
128 for (const auto *VT : VTsByNumber) {
129 if (!VT)
130 continue;
131 auto Name = VT->getValueAsString(FieldName: "LLVMName");
132 bool IsInteger = VT->getValueAsBit(FieldName: "isInteger");
133 bool IsFP = VT->getValueAsBit(FieldName: "isFP");
134 bool IsVector = VT->getValueAsBit(FieldName: "isVector");
135 bool IsScalable = VT->getValueAsBit(FieldName: "isScalable");
136 bool IsRISCVVecTuple = VT->getValueAsBit(FieldName: "isRISCVVecTuple");
137 bool IsCheriCapability = VT->getValueAsBit(FieldName: "isCheriCapability");
138 int64_t NF = VT->getValueAsInt(FieldName: "NF");
139 bool IsNormalValueType = VT->getValueAsBit(FieldName: "isNormalValueType");
140 int64_t NElem = IsVector ? VT->getValueAsInt(FieldName: "nElem") : 0;
141 StringRef EltName = IsVector ? VT->getValueAsDef(FieldName: "ElementType")->getName()
142 : "INVALID_SIMPLE_VALUE_TYPE";
143
144 UpdateVTRange("INTEGER_FIXEDLEN_VECTOR_VALUETYPE", Name,
145 IsInteger && IsVector && !IsScalable);
146 UpdateVTRange("INTEGER_SCALABLE_VECTOR_VALUETYPE", Name,
147 IsInteger && IsScalable);
148 UpdateVTRange("FP_FIXEDLEN_VECTOR_VALUETYPE", Name,
149 IsFP && IsVector && !IsScalable);
150 UpdateVTRange("FP_SCALABLE_VECTOR_VALUETYPE", Name, IsFP && IsScalable);
151 UpdateVTRange("FIXEDLEN_VECTOR_VALUETYPE", Name, IsVector && !IsScalable);
152 UpdateVTRange("SCALABLE_VECTOR_VALUETYPE", Name, IsScalable);
153 UpdateVTRange("RISCV_VECTOR_TUPLE_VALUETYPE", Name, IsRISCVVecTuple);
154 UpdateVTRange("VECTOR_VALUETYPE", Name, IsVector);
155 UpdateVTRange("INTEGER_VALUETYPE", Name, IsInteger && !IsVector);
156 UpdateVTRange("FP_VALUETYPE", Name, IsFP && !IsVector);
157 UpdateVTRange("VALUETYPE", Name, IsNormalValueType);
158 UpdateVTRange("CHERI_CAPABILITY_VALUETYPE", Name, IsCheriCapability);
159
160 // clang-format off
161 OS << " GET_VT_ATTR("
162 << Name << ", "
163 << VT->getValueAsInt(FieldName: "Size") << ", "
164 << VT->getValueAsBit(FieldName: "isOverloaded") << ", "
165 << (IsInteger ? Name[0] == 'i' ? 3 : 1 : 0) << ", "
166 << (IsFP ? Name[0] == 'f' ? 3 : 1 : 0) << ", "
167 << IsVector << ", "
168 << IsScalable << ", "
169 << IsRISCVVecTuple << ", "
170 << NF << ", "
171 << NElem << ", "
172 << EltName << ")\n";
173 // clang-format on
174 }
175 OS << "#endif\n\n";
176
177 OS << "#ifdef GET_VT_RANGES\n";
178 for (const auto &KV : VTRanges) {
179 assert(KV.second.Closed);
180 OS << " FIRST_" << KV.first << " = " << KV.second.First << ",\n"
181 << " LAST_" << KV.first << " = " << KV.second.Last << ",\n";
182 }
183 OS << "#endif\n\n";
184
185 OS << "#ifdef GET_VT_VECATTR // (Ty, Sc, Tup, nElem, ElTy)\n";
186 for (const auto *VT : VTsByNumber) {
187 if (!VT || !VT->getValueAsBit(FieldName: "isVector"))
188 continue;
189 const auto *ElTy = VT->getValueAsDef(FieldName: "ElementType");
190 assert(ElTy);
191 // clang-format off
192 OS << " GET_VT_VECATTR("
193 << VT->getValueAsString(FieldName: "LLVMName") << ", "
194 << VT->getValueAsBit(FieldName: "isScalable") << ", "
195 << VT->getValueAsBit(FieldName: "isRISCVVecTuple") << ", "
196 << VT->getValueAsInt(FieldName: "nElem") << ", "
197 << ElTy->getName() << ")\n";
198 // clang-format on
199 }
200 OS << "#endif\n\n";
201
202 OS << "#ifdef GET_VT_EVT\n";
203 for (const auto *VT : VTsByNumber) {
204 if (!VT)
205 continue;
206 bool IsInteger = VT->getValueAsBit(FieldName: "isInteger");
207 bool IsVector = VT->getValueAsBit(FieldName: "isVector");
208 bool IsFP = VT->getValueAsBit(FieldName: "isFP");
209 bool IsRISCVVecTuple = VT->getValueAsBit(FieldName: "isRISCVVecTuple");
210
211 if (!IsInteger && !IsVector && !IsFP && !IsRISCVVecTuple)
212 continue;
213
214 OS << " GET_VT_EVT(" << VT->getValueAsString(FieldName: "LLVMName") << ", ";
215 vTtoGetLlvmTyString(OS, VT);
216 OS << ")\n";
217 }
218 OS << "#endif\n\n";
219}
220
221static TableGen::Emitter::OptClass<VTEmitter> X("gen-vt", "Generate ValueType");
222