xref: /freebsd-src/contrib/llvm-project/llvm/utils/TableGen/VTEmitter.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
106c3fb27SDimitry Andric //===- VTEmitter.cpp - Generate properties from ValueTypes.td -------------===//
206c3fb27SDimitry Andric //
306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606c3fb27SDimitry Andric //
706c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
806c3fb27SDimitry Andric 
906c3fb27SDimitry Andric #include "llvm/ADT/StringRef.h"
1006c3fb27SDimitry Andric #include "llvm/Support/raw_ostream.h"
1106c3fb27SDimitry Andric #include "llvm/TableGen/Record.h"
1206c3fb27SDimitry Andric #include "llvm/TableGen/TableGenBackend.h"
1306c3fb27SDimitry Andric #include <array>
1406c3fb27SDimitry Andric #include <cassert>
1506c3fb27SDimitry Andric #include <map>
1606c3fb27SDimitry Andric using namespace llvm;
1706c3fb27SDimitry Andric 
1806c3fb27SDimitry Andric namespace {
1906c3fb27SDimitry Andric 
2006c3fb27SDimitry Andric class VTEmitter {
2106c3fb27SDimitry Andric private:
2206c3fb27SDimitry Andric   RecordKeeper &Records;
2306c3fb27SDimitry Andric 
2406c3fb27SDimitry Andric public:
2506c3fb27SDimitry Andric   VTEmitter(RecordKeeper &R) : Records(R) {}
2606c3fb27SDimitry Andric 
2706c3fb27SDimitry Andric   void run(raw_ostream &OS);
2806c3fb27SDimitry Andric };
2906c3fb27SDimitry Andric 
3006c3fb27SDimitry Andric } // End anonymous namespace.
3106c3fb27SDimitry Andric 
32*0fca6ea1SDimitry Andric static void VTtoGetLLVMTyString(raw_ostream &OS, const Record *VT) {
33*0fca6ea1SDimitry Andric   bool IsVector = VT->getValueAsBit("isVector");
34*0fca6ea1SDimitry Andric   if (IsVector)
35*0fca6ea1SDimitry Andric     OS << (VT->getValueAsBit("isScalable") ? "Scalable" : "Fixed")
36*0fca6ea1SDimitry Andric        << "VectorType::get(";
37*0fca6ea1SDimitry Andric 
38*0fca6ea1SDimitry Andric   auto OutputVT = IsVector ? VT->getValueAsDef("ElementType") : VT;
39*0fca6ea1SDimitry Andric   int64_t OutputVTSize = OutputVT->getValueAsInt("Size");
40*0fca6ea1SDimitry Andric 
41*0fca6ea1SDimitry Andric   if (OutputVT->getValueAsBit("isFP")) {
42*0fca6ea1SDimitry Andric     StringRef FloatTy;
43*0fca6ea1SDimitry Andric     auto OutputVTName = OutputVT->getValueAsString("LLVMName");
44*0fca6ea1SDimitry Andric     switch (OutputVTSize) {
45*0fca6ea1SDimitry Andric     default:
46*0fca6ea1SDimitry Andric       llvm_unreachable("Unhandled case");
47*0fca6ea1SDimitry Andric     case 16:
48*0fca6ea1SDimitry Andric       FloatTy = (OutputVTName == "bf16") ? "BFloatTy" : "HalfTy";
49*0fca6ea1SDimitry Andric       break;
50*0fca6ea1SDimitry Andric     case 32:
51*0fca6ea1SDimitry Andric       FloatTy = "FloatTy";
52*0fca6ea1SDimitry Andric       break;
53*0fca6ea1SDimitry Andric     case 64:
54*0fca6ea1SDimitry Andric       FloatTy = "DoubleTy";
55*0fca6ea1SDimitry Andric       break;
56*0fca6ea1SDimitry Andric     case 80:
57*0fca6ea1SDimitry Andric       FloatTy = "X86_FP80Ty";
58*0fca6ea1SDimitry Andric       break;
59*0fca6ea1SDimitry Andric     case 128:
60*0fca6ea1SDimitry Andric       FloatTy = (OutputVTName == "ppcf128") ? "PPC_FP128Ty" : "FP128Ty";
61*0fca6ea1SDimitry Andric       break;
62*0fca6ea1SDimitry Andric     }
63*0fca6ea1SDimitry Andric     OS << "Type::get" << FloatTy << "(Context)";
64*0fca6ea1SDimitry Andric   } else if (OutputVT->getValueAsBit("isInteger")) {
65*0fca6ea1SDimitry Andric     // We only have Type::getInt1Ty, Int8, Int16, Int32, Int64, and Int128
66*0fca6ea1SDimitry Andric     if ((isPowerOf2_64(OutputVTSize) && OutputVTSize >= 8 &&
67*0fca6ea1SDimitry Andric          OutputVTSize <= 128) ||
68*0fca6ea1SDimitry Andric         OutputVTSize == 1)
69*0fca6ea1SDimitry Andric       OS << "Type::getInt" << OutputVTSize << "Ty(Context)";
70*0fca6ea1SDimitry Andric     else
71*0fca6ea1SDimitry Andric       OS << "Type::getIntNTy(Context, " << OutputVTSize << ")";
72*0fca6ea1SDimitry Andric   } else
73*0fca6ea1SDimitry Andric     llvm_unreachable("Unhandled case");
74*0fca6ea1SDimitry Andric 
75*0fca6ea1SDimitry Andric   if (IsVector)
76*0fca6ea1SDimitry Andric     OS << ", " << VT->getValueAsInt("nElem") << ")";
77*0fca6ea1SDimitry Andric }
78*0fca6ea1SDimitry Andric 
7906c3fb27SDimitry Andric void VTEmitter::run(raw_ostream &OS) {
805f757f3fSDimitry Andric   emitSourceFileHeader("ValueTypes Source Fragment", OS, Records);
8106c3fb27SDimitry Andric 
8206c3fb27SDimitry Andric   std::array<const Record *, 256> VTsByNumber = {};
8306c3fb27SDimitry Andric   auto ValueTypes = Records.getAllDerivedDefinitions("ValueType");
8406c3fb27SDimitry Andric   for (auto *VT : ValueTypes) {
8506c3fb27SDimitry Andric     auto Number = VT->getValueAsInt("Value");
8606c3fb27SDimitry Andric     assert(0 <= Number && Number < (int)VTsByNumber.size() &&
8706c3fb27SDimitry Andric            "ValueType should be uint8_t");
8806c3fb27SDimitry Andric     assert(!VTsByNumber[Number] && "Duplicate ValueType");
8906c3fb27SDimitry Andric     VTsByNumber[Number] = VT;
9006c3fb27SDimitry Andric   }
9106c3fb27SDimitry Andric 
9206c3fb27SDimitry Andric   struct VTRange {
9306c3fb27SDimitry Andric     StringRef First;
9406c3fb27SDimitry Andric     StringRef Last;
9506c3fb27SDimitry Andric     bool Closed;
9606c3fb27SDimitry Andric   };
9706c3fb27SDimitry Andric 
9806c3fb27SDimitry Andric   std::map<StringRef, VTRange> VTRanges;
9906c3fb27SDimitry Andric 
10006c3fb27SDimitry Andric   auto UpdateVTRange = [&VTRanges](const char *Key, StringRef Name,
10106c3fb27SDimitry Andric                                    bool Valid) {
10206c3fb27SDimitry Andric     if (Valid) {
10306c3fb27SDimitry Andric       if (!VTRanges.count(Key))
10406c3fb27SDimitry Andric         VTRanges[Key].First = Name;
10506c3fb27SDimitry Andric       assert(!VTRanges[Key].Closed && "Gap detected!");
10606c3fb27SDimitry Andric       VTRanges[Key].Last = Name;
10706c3fb27SDimitry Andric     } else if (VTRanges.count(Key)) {
10806c3fb27SDimitry Andric       VTRanges[Key].Closed = true;
10906c3fb27SDimitry Andric     }
11006c3fb27SDimitry Andric   };
11106c3fb27SDimitry Andric 
11206c3fb27SDimitry Andric   OS << "#ifdef GET_VT_ATTR // (Ty, n, sz, Any, Int, FP, Vec, Sc)\n";
11306c3fb27SDimitry Andric   for (const auto *VT : VTsByNumber) {
11406c3fb27SDimitry Andric     if (!VT)
11506c3fb27SDimitry Andric       continue;
11606c3fb27SDimitry Andric     auto Name = VT->getValueAsString("LLVMName");
11706c3fb27SDimitry Andric     auto Value = VT->getValueAsInt("Value");
118*0fca6ea1SDimitry Andric     bool IsInteger = VT->getValueAsBit("isInteger");
119*0fca6ea1SDimitry Andric     bool IsFP = VT->getValueAsBit("isFP");
120*0fca6ea1SDimitry Andric     bool IsVector = VT->getValueAsBit("isVector");
121*0fca6ea1SDimitry Andric     bool IsScalable = VT->getValueAsBit("isScalable");
122*0fca6ea1SDimitry Andric     bool IsNormalValueType =  VT->getValueAsBit("isNormalValueType");
123*0fca6ea1SDimitry Andric     int64_t NElem = IsVector ? VT->getValueAsInt("nElem") : 0;
124*0fca6ea1SDimitry Andric     StringRef EltName = IsVector ? VT->getValueAsDef("ElementType")->getName()
125*0fca6ea1SDimitry Andric                                  : "INVALID_SIMPLE_VALUE_TYPE";
12606c3fb27SDimitry Andric 
12706c3fb27SDimitry Andric     UpdateVTRange("INTEGER_FIXEDLEN_VECTOR_VALUETYPE", Name,
12806c3fb27SDimitry Andric                   IsInteger && IsVector && !IsScalable);
12906c3fb27SDimitry Andric     UpdateVTRange("INTEGER_SCALABLE_VECTOR_VALUETYPE", Name,
13006c3fb27SDimitry Andric                   IsInteger && IsScalable);
13106c3fb27SDimitry Andric     UpdateVTRange("FP_FIXEDLEN_VECTOR_VALUETYPE", Name,
13206c3fb27SDimitry Andric                   IsFP && IsVector && !IsScalable);
13306c3fb27SDimitry Andric     UpdateVTRange("FP_SCALABLE_VECTOR_VALUETYPE", Name, IsFP && IsScalable);
13406c3fb27SDimitry Andric     UpdateVTRange("FIXEDLEN_VECTOR_VALUETYPE", Name, IsVector && !IsScalable);
13506c3fb27SDimitry Andric     UpdateVTRange("SCALABLE_VECTOR_VALUETYPE", Name, IsScalable);
13606c3fb27SDimitry Andric     UpdateVTRange("VECTOR_VALUETYPE", Name, IsVector);
13706c3fb27SDimitry Andric     UpdateVTRange("INTEGER_VALUETYPE", Name, IsInteger && !IsVector);
13806c3fb27SDimitry Andric     UpdateVTRange("FP_VALUETYPE", Name, IsFP && !IsVector);
139*0fca6ea1SDimitry Andric     UpdateVTRange("VALUETYPE", Name, IsNormalValueType);
14006c3fb27SDimitry Andric 
14106c3fb27SDimitry Andric     // clang-format off
14206c3fb27SDimitry Andric     OS << "  GET_VT_ATTR("
14306c3fb27SDimitry Andric        << Name << ", "
14406c3fb27SDimitry Andric        << Value << ", "
14506c3fb27SDimitry Andric        << VT->getValueAsInt("Size") << ", "
146*0fca6ea1SDimitry Andric        << VT->getValueAsBit("isOverloaded") << ", "
14706c3fb27SDimitry Andric        << (IsInteger ? Name[0] == 'i' ? 3 : 1 : 0) << ", "
14806c3fb27SDimitry Andric        << (IsFP ? Name[0] == 'f' ? 3 : 1 : 0) << ", "
14906c3fb27SDimitry Andric        << IsVector << ", "
150*0fca6ea1SDimitry Andric        << IsScalable << ", "
151*0fca6ea1SDimitry Andric        << NElem << ", "
152*0fca6ea1SDimitry Andric        << EltName << ")\n";
15306c3fb27SDimitry Andric     // clang-format on
15406c3fb27SDimitry Andric   }
15506c3fb27SDimitry Andric   OS << "#endif\n\n";
15606c3fb27SDimitry Andric 
15706c3fb27SDimitry Andric   OS << "#ifdef GET_VT_RANGES\n";
15806c3fb27SDimitry Andric   for (const auto &KV : VTRanges) {
15906c3fb27SDimitry Andric     assert(KV.second.Closed);
16006c3fb27SDimitry Andric     OS << "  FIRST_" << KV.first << " = " << KV.second.First << ",\n"
16106c3fb27SDimitry Andric        << "  LAST_" << KV.first << " = " << KV.second.Last << ",\n";
16206c3fb27SDimitry Andric   }
16306c3fb27SDimitry Andric   OS << "#endif\n\n";
16406c3fb27SDimitry Andric 
165*0fca6ea1SDimitry Andric   OS << "#ifdef GET_VT_VECATTR // (Ty, Sc, nElem, ElTy)\n";
16606c3fb27SDimitry Andric   for (const auto *VT : VTsByNumber) {
167*0fca6ea1SDimitry Andric     if (!VT || !VT->getValueAsBit("isVector"))
16806c3fb27SDimitry Andric       continue;
16906c3fb27SDimitry Andric     const auto *ElTy = VT->getValueAsDef("ElementType");
17006c3fb27SDimitry Andric     assert(ElTy);
17106c3fb27SDimitry Andric     // clang-format off
17206c3fb27SDimitry Andric     OS << "  GET_VT_VECATTR("
17306c3fb27SDimitry Andric        << VT->getValueAsString("LLVMName") << ", "
174*0fca6ea1SDimitry Andric        << VT->getValueAsBit("isScalable") << ", "
17506c3fb27SDimitry Andric        << VT->getValueAsInt("nElem") << ", "
176*0fca6ea1SDimitry Andric        << ElTy->getName() << ")\n";
17706c3fb27SDimitry Andric     // clang-format on
17806c3fb27SDimitry Andric   }
17906c3fb27SDimitry Andric   OS << "#endif\n\n";
180*0fca6ea1SDimitry Andric 
181*0fca6ea1SDimitry Andric   OS << "#ifdef GET_VT_EVT\n";
182*0fca6ea1SDimitry Andric   for (const auto *VT : VTsByNumber) {
183*0fca6ea1SDimitry Andric     if (!VT)
184*0fca6ea1SDimitry Andric       continue;
185*0fca6ea1SDimitry Andric     bool IsInteger = VT->getValueAsBit("isInteger");
186*0fca6ea1SDimitry Andric     bool IsVector = VT->getValueAsBit("isVector");
187*0fca6ea1SDimitry Andric     bool IsFP = VT->getValueAsBit("isFP");
188*0fca6ea1SDimitry Andric 
189*0fca6ea1SDimitry Andric     if (!IsInteger && !IsVector && !IsFP)
190*0fca6ea1SDimitry Andric       continue;
191*0fca6ea1SDimitry Andric 
192*0fca6ea1SDimitry Andric     OS << "  GET_VT_EVT(" << VT->getValueAsString("LLVMName") << ", ";
193*0fca6ea1SDimitry Andric     VTtoGetLLVMTyString(OS, VT);
194*0fca6ea1SDimitry Andric     OS << ")\n";
195*0fca6ea1SDimitry Andric   }
196*0fca6ea1SDimitry Andric   OS << "#endif\n\n";
19706c3fb27SDimitry Andric }
19806c3fb27SDimitry Andric 
19906c3fb27SDimitry Andric static TableGen::Emitter::OptClass<VTEmitter> X("gen-vt", "Generate ValueType");
200