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:
25   VTEmitter(RecordKeeper &R) : Records(R) {}
26 
27   void run(raw_ostream &OS);
28 };
29 
30 } // End anonymous namespace.
31 
32 void VTEmitter::run(raw_ostream &OS) {
33   emitSourceFileHeader("ValueTypes Source Fragment", OS);
34 
35   std::array<const Record *, 256> VTsByNumber = {};
36   auto ValueTypes = Records.getAllDerivedDefinitions("ValueType");
37   for (auto *VT : ValueTypes) {
38     auto Number = VT->getValueAsInt("Value");
39     assert(0 <= Number && Number < (int)VTsByNumber.size() &&
40            "ValueType should be uint8_t");
41     assert(!VTsByNumber[Number] && "Duplicate ValueType");
42     VTsByNumber[Number] = VT;
43   }
44 
45   struct VTRange {
46     StringRef First;
47     StringRef Last;
48     bool Closed;
49   };
50 
51   std::map<StringRef, VTRange> VTRanges;
52 
53   auto UpdateVTRange = [&VTRanges](const char *Key, StringRef Name,
54                                    bool Valid) {
55     if (Valid) {
56       if (!VTRanges.count(Key))
57         VTRanges[Key].First = Name;
58       assert(!VTRanges[Key].Closed && "Gap detected!");
59       VTRanges[Key].Last = Name;
60     } else if (VTRanges.count(Key)) {
61       VTRanges[Key].Closed = true;
62     }
63   };
64 
65   OS << "#ifdef GET_VT_ATTR // (Ty, n, sz, Any, Int, FP, Vec, Sc)\n";
66   for (const auto *VT : VTsByNumber) {
67     if (!VT)
68       continue;
69     auto Name = VT->getValueAsString("LLVMName");
70     auto Value = VT->getValueAsInt("Value");
71     bool IsInteger = VT->getValueAsInt("isInteger");
72     bool IsFP = VT->getValueAsInt("isFP");
73     bool IsVector = VT->getValueAsInt("isVector");
74     bool IsScalable = VT->getValueAsInt("isScalable");
75 
76     UpdateVTRange("INTEGER_FIXEDLEN_VECTOR_VALUETYPE", Name,
77                   IsInteger && IsVector && !IsScalable);
78     UpdateVTRange("INTEGER_SCALABLE_VECTOR_VALUETYPE", Name,
79                   IsInteger && IsScalable);
80     UpdateVTRange("FP_FIXEDLEN_VECTOR_VALUETYPE", Name,
81                   IsFP && IsVector && !IsScalable);
82     UpdateVTRange("FP_SCALABLE_VECTOR_VALUETYPE", Name, IsFP && IsScalable);
83     UpdateVTRange("FIXEDLEN_VECTOR_VALUETYPE", Name, IsVector && !IsScalable);
84     UpdateVTRange("SCALABLE_VECTOR_VALUETYPE", Name, IsScalable);
85     UpdateVTRange("VECTOR_VALUETYPE", Name, IsVector);
86     UpdateVTRange("INTEGER_VALUETYPE", Name, IsInteger && !IsVector);
87     UpdateVTRange("FP_VALUETYPE", Name, IsFP && !IsVector);
88     UpdateVTRange("VALUETYPE", Name, Value < 224);
89 
90     // clang-format off
91     OS << "  GET_VT_ATTR("
92        << Name << ", "
93        << Value << ", "
94        << VT->getValueAsInt("Size") << ", "
95        << VT->getValueAsInt("isOverloaded") << ", "
96        << (IsInteger ? Name[0] == 'i' ? 3 : 1 : 0) << ", "
97        << (IsFP ? Name[0] == 'f' ? 3 : 1 : 0) << ", "
98        << IsVector << ", "
99        << IsScalable << ")\n";
100     // clang-format on
101   }
102   OS << "#endif\n\n";
103 
104   OS << "#ifdef GET_VT_RANGES\n";
105   for (const auto &KV : VTRanges) {
106     assert(KV.second.Closed);
107     OS << "  FIRST_" << KV.first << " = " << KV.second.First << ",\n"
108        << "  LAST_" << KV.first << " = " << KV.second.Last << ",\n";
109   }
110   OS << "#endif\n\n";
111 
112   OS << "#ifdef GET_VT_VECATTR // (Ty, Sc, nElem, ElTy, ElSz)\n";
113   for (const auto *VT : VTsByNumber) {
114     if (!VT || !VT->getValueAsInt("isVector"))
115       continue;
116     const auto *ElTy = VT->getValueAsDef("ElementType");
117     assert(ElTy);
118     // clang-format off
119     OS << "  GET_VT_VECATTR("
120        << VT->getValueAsString("LLVMName") << ", "
121        << VT->getValueAsInt("isScalable") << ", "
122        << VT->getValueAsInt("nElem") << ", "
123        << ElTy->getName() << ", "
124        << ElTy->getValueAsInt("Size") << ")\n";
125     // clang-format on
126   }
127   OS << "#endif\n\n";
128 }
129 
130 static TableGen::Emitter::OptClass<VTEmitter> X("gen-vt", "Generate ValueType");
131