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