xref: /freebsd/contrib/llvm-project/llvm/utils/TableGen/VTEmitter.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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:
VTEmitter(RecordKeeper & R)25   VTEmitter(RecordKeeper &R) : Records(R) {}
26 
27   void run(raw_ostream &OS);
28 };
29 
30 } // End anonymous namespace.
31 
VTtoGetLLVMTyString(raw_ostream & OS,const Record * VT)32 static void VTtoGetLLVMTyString(raw_ostream &OS, const Record *VT) {
33   bool IsVector = VT->getValueAsBit("isVector");
34   if (IsVector)
35     OS << (VT->getValueAsBit("isScalable") ? "Scalable" : "Fixed")
36        << "VectorType::get(";
37 
38   auto OutputVT = IsVector ? VT->getValueAsDef("ElementType") : VT;
39   int64_t OutputVTSize = OutputVT->getValueAsInt("Size");
40 
41   if (OutputVT->getValueAsBit("isFP")) {
42     StringRef FloatTy;
43     auto OutputVTName = OutputVT->getValueAsString("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("isInteger")) {
65     // We only have Type::getInt1Ty, Int8, Int16, Int32, Int64, and Int128
66     if ((isPowerOf2_64(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("nElem") << ")";
77 }
78 
run(raw_ostream & OS)79 void VTEmitter::run(raw_ostream &OS) {
80   emitSourceFileHeader("ValueTypes Source Fragment", OS, Records);
81 
82   std::array<const Record *, 256> VTsByNumber = {};
83   auto ValueTypes = Records.getAllDerivedDefinitions("ValueType");
84   for (auto *VT : ValueTypes) {
85     auto Number = VT->getValueAsInt("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(Key))
104         VTRanges[Key].First = Name;
105       assert(!VTRanges[Key].Closed && "Gap detected!");
106       VTRanges[Key].Last = Name;
107     } else if (VTRanges.count(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("LLVMName");
117     auto Value = VT->getValueAsInt("Value");
118     bool IsInteger = VT->getValueAsBit("isInteger");
119     bool IsFP = VT->getValueAsBit("isFP");
120     bool IsVector = VT->getValueAsBit("isVector");
121     bool IsScalable = VT->getValueAsBit("isScalable");
122     bool IsNormalValueType =  VT->getValueAsBit("isNormalValueType");
123     int64_t NElem = IsVector ? VT->getValueAsInt("nElem") : 0;
124     StringRef EltName = IsVector ? VT->getValueAsDef("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("Size") << ", "
146        << VT->getValueAsBit("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("isVector"))
168       continue;
169     const auto *ElTy = VT->getValueAsDef("ElementType");
170     assert(ElTy);
171     // clang-format off
172     OS << "  GET_VT_VECATTR("
173        << VT->getValueAsString("LLVMName") << ", "
174        << VT->getValueAsBit("isScalable") << ", "
175        << VT->getValueAsInt("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("isInteger");
186     bool IsVector = VT->getValueAsBit("isVector");
187     bool IsFP = VT->getValueAsBit("isFP");
188 
189     if (!IsInteger && !IsVector && !IsFP)
190       continue;
191 
192     OS << "  GET_VT_EVT(" << VT->getValueAsString("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