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