xref: /freebsd-src/contrib/llvm-project/llvm/utils/TableGen/VTEmitter.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1*06c3fb27SDimitry Andric //===- VTEmitter.cpp - Generate properties from ValueTypes.td -------------===//
2*06c3fb27SDimitry Andric //
3*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*06c3fb27SDimitry Andric //
7*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
8*06c3fb27SDimitry Andric 
9*06c3fb27SDimitry Andric #include "llvm/ADT/StringRef.h"
10*06c3fb27SDimitry Andric #include "llvm/Support/raw_ostream.h"
11*06c3fb27SDimitry Andric #include "llvm/TableGen/Record.h"
12*06c3fb27SDimitry Andric #include "llvm/TableGen/TableGenBackend.h"
13*06c3fb27SDimitry Andric #include <array>
14*06c3fb27SDimitry Andric #include <cassert>
15*06c3fb27SDimitry Andric #include <map>
16*06c3fb27SDimitry Andric using namespace llvm;
17*06c3fb27SDimitry Andric 
18*06c3fb27SDimitry Andric namespace {
19*06c3fb27SDimitry Andric 
20*06c3fb27SDimitry Andric class VTEmitter {
21*06c3fb27SDimitry Andric private:
22*06c3fb27SDimitry Andric   RecordKeeper &Records;
23*06c3fb27SDimitry Andric 
24*06c3fb27SDimitry Andric public:
25*06c3fb27SDimitry Andric   VTEmitter(RecordKeeper &R) : Records(R) {}
26*06c3fb27SDimitry Andric 
27*06c3fb27SDimitry Andric   void run(raw_ostream &OS);
28*06c3fb27SDimitry Andric };
29*06c3fb27SDimitry Andric 
30*06c3fb27SDimitry Andric } // End anonymous namespace.
31*06c3fb27SDimitry Andric 
32*06c3fb27SDimitry Andric void VTEmitter::run(raw_ostream &OS) {
33*06c3fb27SDimitry Andric   emitSourceFileHeader("ValueTypes Source Fragment", OS);
34*06c3fb27SDimitry Andric 
35*06c3fb27SDimitry Andric   std::array<const Record *, 256> VTsByNumber = {};
36*06c3fb27SDimitry Andric   auto ValueTypes = Records.getAllDerivedDefinitions("ValueType");
37*06c3fb27SDimitry Andric   for (auto *VT : ValueTypes) {
38*06c3fb27SDimitry Andric     auto Number = VT->getValueAsInt("Value");
39*06c3fb27SDimitry Andric     assert(0 <= Number && Number < (int)VTsByNumber.size() &&
40*06c3fb27SDimitry Andric            "ValueType should be uint8_t");
41*06c3fb27SDimitry Andric     assert(!VTsByNumber[Number] && "Duplicate ValueType");
42*06c3fb27SDimitry Andric     VTsByNumber[Number] = VT;
43*06c3fb27SDimitry Andric   }
44*06c3fb27SDimitry Andric 
45*06c3fb27SDimitry Andric   struct VTRange {
46*06c3fb27SDimitry Andric     StringRef First;
47*06c3fb27SDimitry Andric     StringRef Last;
48*06c3fb27SDimitry Andric     bool Closed;
49*06c3fb27SDimitry Andric   };
50*06c3fb27SDimitry Andric 
51*06c3fb27SDimitry Andric   std::map<StringRef, VTRange> VTRanges;
52*06c3fb27SDimitry Andric 
53*06c3fb27SDimitry Andric   auto UpdateVTRange = [&VTRanges](const char *Key, StringRef Name,
54*06c3fb27SDimitry Andric                                    bool Valid) {
55*06c3fb27SDimitry Andric     if (Valid) {
56*06c3fb27SDimitry Andric       if (!VTRanges.count(Key))
57*06c3fb27SDimitry Andric         VTRanges[Key].First = Name;
58*06c3fb27SDimitry Andric       assert(!VTRanges[Key].Closed && "Gap detected!");
59*06c3fb27SDimitry Andric       VTRanges[Key].Last = Name;
60*06c3fb27SDimitry Andric     } else if (VTRanges.count(Key)) {
61*06c3fb27SDimitry Andric       VTRanges[Key].Closed = true;
62*06c3fb27SDimitry Andric     }
63*06c3fb27SDimitry Andric   };
64*06c3fb27SDimitry Andric 
65*06c3fb27SDimitry Andric   OS << "#ifdef GET_VT_ATTR // (Ty, n, sz, Any, Int, FP, Vec, Sc)\n";
66*06c3fb27SDimitry Andric   for (const auto *VT : VTsByNumber) {
67*06c3fb27SDimitry Andric     if (!VT)
68*06c3fb27SDimitry Andric       continue;
69*06c3fb27SDimitry Andric     auto Name = VT->getValueAsString("LLVMName");
70*06c3fb27SDimitry Andric     auto Value = VT->getValueAsInt("Value");
71*06c3fb27SDimitry Andric     bool IsInteger = VT->getValueAsInt("isInteger");
72*06c3fb27SDimitry Andric     bool IsFP = VT->getValueAsInt("isFP");
73*06c3fb27SDimitry Andric     bool IsVector = VT->getValueAsInt("isVector");
74*06c3fb27SDimitry Andric     bool IsScalable = VT->getValueAsInt("isScalable");
75*06c3fb27SDimitry Andric 
76*06c3fb27SDimitry Andric     UpdateVTRange("INTEGER_FIXEDLEN_VECTOR_VALUETYPE", Name,
77*06c3fb27SDimitry Andric                   IsInteger && IsVector && !IsScalable);
78*06c3fb27SDimitry Andric     UpdateVTRange("INTEGER_SCALABLE_VECTOR_VALUETYPE", Name,
79*06c3fb27SDimitry Andric                   IsInteger && IsScalable);
80*06c3fb27SDimitry Andric     UpdateVTRange("FP_FIXEDLEN_VECTOR_VALUETYPE", Name,
81*06c3fb27SDimitry Andric                   IsFP && IsVector && !IsScalable);
82*06c3fb27SDimitry Andric     UpdateVTRange("FP_SCALABLE_VECTOR_VALUETYPE", Name, IsFP && IsScalable);
83*06c3fb27SDimitry Andric     UpdateVTRange("FIXEDLEN_VECTOR_VALUETYPE", Name, IsVector && !IsScalable);
84*06c3fb27SDimitry Andric     UpdateVTRange("SCALABLE_VECTOR_VALUETYPE", Name, IsScalable);
85*06c3fb27SDimitry Andric     UpdateVTRange("VECTOR_VALUETYPE", Name, IsVector);
86*06c3fb27SDimitry Andric     UpdateVTRange("INTEGER_VALUETYPE", Name, IsInteger && !IsVector);
87*06c3fb27SDimitry Andric     UpdateVTRange("FP_VALUETYPE", Name, IsFP && !IsVector);
88*06c3fb27SDimitry Andric     UpdateVTRange("VALUETYPE", Name, Value < 224);
89*06c3fb27SDimitry Andric 
90*06c3fb27SDimitry Andric     // clang-format off
91*06c3fb27SDimitry Andric     OS << "  GET_VT_ATTR("
92*06c3fb27SDimitry Andric        << Name << ", "
93*06c3fb27SDimitry Andric        << Value << ", "
94*06c3fb27SDimitry Andric        << VT->getValueAsInt("Size") << ", "
95*06c3fb27SDimitry Andric        << VT->getValueAsInt("isOverloaded") << ", "
96*06c3fb27SDimitry Andric        << (IsInteger ? Name[0] == 'i' ? 3 : 1 : 0) << ", "
97*06c3fb27SDimitry Andric        << (IsFP ? Name[0] == 'f' ? 3 : 1 : 0) << ", "
98*06c3fb27SDimitry Andric        << IsVector << ", "
99*06c3fb27SDimitry Andric        << IsScalable << ")\n";
100*06c3fb27SDimitry Andric     // clang-format on
101*06c3fb27SDimitry Andric   }
102*06c3fb27SDimitry Andric   OS << "#endif\n\n";
103*06c3fb27SDimitry Andric 
104*06c3fb27SDimitry Andric   OS << "#ifdef GET_VT_RANGES\n";
105*06c3fb27SDimitry Andric   for (const auto &KV : VTRanges) {
106*06c3fb27SDimitry Andric     assert(KV.second.Closed);
107*06c3fb27SDimitry Andric     OS << "  FIRST_" << KV.first << " = " << KV.second.First << ",\n"
108*06c3fb27SDimitry Andric        << "  LAST_" << KV.first << " = " << KV.second.Last << ",\n";
109*06c3fb27SDimitry Andric   }
110*06c3fb27SDimitry Andric   OS << "#endif\n\n";
111*06c3fb27SDimitry Andric 
112*06c3fb27SDimitry Andric   OS << "#ifdef GET_VT_VECATTR // (Ty, Sc, nElem, ElTy, ElSz)\n";
113*06c3fb27SDimitry Andric   for (const auto *VT : VTsByNumber) {
114*06c3fb27SDimitry Andric     if (!VT || !VT->getValueAsInt("isVector"))
115*06c3fb27SDimitry Andric       continue;
116*06c3fb27SDimitry Andric     const auto *ElTy = VT->getValueAsDef("ElementType");
117*06c3fb27SDimitry Andric     assert(ElTy);
118*06c3fb27SDimitry Andric     // clang-format off
119*06c3fb27SDimitry Andric     OS << "  GET_VT_VECATTR("
120*06c3fb27SDimitry Andric        << VT->getValueAsString("LLVMName") << ", "
121*06c3fb27SDimitry Andric        << VT->getValueAsInt("isScalable") << ", "
122*06c3fb27SDimitry Andric        << VT->getValueAsInt("nElem") << ", "
123*06c3fb27SDimitry Andric        << ElTy->getName() << ", "
124*06c3fb27SDimitry Andric        << ElTy->getValueAsInt("Size") << ")\n";
125*06c3fb27SDimitry Andric     // clang-format on
126*06c3fb27SDimitry Andric   }
127*06c3fb27SDimitry Andric   OS << "#endif\n\n";
128*06c3fb27SDimitry Andric }
129*06c3fb27SDimitry Andric 
130*06c3fb27SDimitry Andric static TableGen::Emitter::OptClass<VTEmitter> X("gen-vt", "Generate ValueType");
131