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 <cassert> 14 #include <map> 15 using namespace llvm; 16 17 namespace { 18 19 class VTEmitter { 20 private: 21 const RecordKeeper &Records; 22 23 public: 24 VTEmitter(const RecordKeeper &R) : Records(R) {} 25 26 void run(raw_ostream &OS); 27 }; 28 29 } // End anonymous namespace. 30 31 static void vTtoGetLlvmTyString(raw_ostream &OS, const Record *VT) { 32 bool IsVector = VT->getValueAsBit("isVector"); 33 bool IsRISCVVecTuple = VT->getValueAsBit("isRISCVVecTuple"); 34 35 if (IsRISCVVecTuple) { 36 unsigned NElem = VT->getValueAsInt("nElem"); 37 unsigned Sz = VT->getValueAsInt("Size"); 38 OS << "TargetExtType::get(Context, \"riscv.vector.tuple\", " 39 "ScalableVectorType::get(Type::getInt8Ty(Context), " 40 << (Sz / (NElem * 8)) << "), " << NElem << ")"; 41 return; 42 } 43 44 if (IsVector) 45 OS << (VT->getValueAsBit("isScalable") ? "Scalable" : "Fixed") 46 << "VectorType::get("; 47 48 auto OutputVT = IsVector ? VT->getValueAsDef("ElementType") : VT; 49 int64_t OutputVTSize = OutputVT->getValueAsInt("Size"); 50 51 if (OutputVT->getValueAsBit("isFP")) { 52 StringRef FloatTy; 53 auto OutputVTName = OutputVT->getValueAsString("LLVMName"); 54 switch (OutputVTSize) { 55 default: 56 llvm_unreachable("Unhandled case"); 57 case 16: 58 FloatTy = (OutputVTName == "bf16") ? "BFloatTy" : "HalfTy"; 59 break; 60 case 32: 61 FloatTy = "FloatTy"; 62 break; 63 case 64: 64 FloatTy = "DoubleTy"; 65 break; 66 case 80: 67 FloatTy = "X86_FP80Ty"; 68 break; 69 case 128: 70 FloatTy = (OutputVTName == "ppcf128") ? "PPC_FP128Ty" : "FP128Ty"; 71 break; 72 } 73 OS << "Type::get" << FloatTy << "(Context)"; 74 } else if (OutputVT->getValueAsBit("isInteger")) { 75 // We only have Type::getInt1Ty, Int8, Int16, Int32, Int64, and Int128 76 if ((isPowerOf2_64(OutputVTSize) && OutputVTSize >= 8 && 77 OutputVTSize <= 128) || 78 OutputVTSize == 1) 79 OS << "Type::getInt" << OutputVTSize << "Ty(Context)"; 80 else 81 OS << "Type::getIntNTy(Context, " << OutputVTSize << ")"; 82 } else 83 llvm_unreachable("Unhandled case"); 84 85 if (IsVector) 86 OS << ", " << VT->getValueAsInt("nElem") << ")"; 87 } 88 89 void VTEmitter::run(raw_ostream &OS) { 90 emitSourceFileHeader("ValueTypes Source Fragment", OS, Records); 91 92 std::vector<const Record *> VTsByNumber{512}; 93 for (auto *VT : Records.getAllDerivedDefinitions("ValueType")) { 94 auto Number = VT->getValueAsInt("Value"); 95 assert(0 <= Number && Number < (int)VTsByNumber.size() && 96 "ValueType should be uint16_t"); 97 assert(!VTsByNumber[Number] && "Duplicate ValueType"); 98 VTsByNumber[Number] = VT; 99 } 100 101 struct VTRange { 102 StringRef First; 103 StringRef Last; 104 bool Closed; 105 }; 106 107 std::map<StringRef, VTRange> VTRanges; 108 109 auto UpdateVTRange = [&VTRanges](const char *Key, StringRef Name, 110 bool Valid) { 111 if (Valid) { 112 auto [It, Inserted] = VTRanges.try_emplace(Key); 113 if (Inserted) 114 It->second.First = Name; 115 assert(!It->second.Closed && "Gap detected!"); 116 It->second.Last = Name; 117 } else if (auto It = VTRanges.find(Key); It != VTRanges.end()) { 118 It->second.Closed = true; 119 } 120 }; 121 122 OS << "#ifdef GET_VT_ATTR // (Ty, n, sz, Any, Int, FP, Vec, Sc, Tup, NF, " 123 "NElem, EltTy)\n"; 124 for (const auto *VT : VTsByNumber) { 125 if (!VT) 126 continue; 127 auto Name = VT->getValueAsString("LLVMName"); 128 auto Value = VT->getValueAsInt("Value"); 129 bool IsInteger = VT->getValueAsBit("isInteger"); 130 bool IsFP = VT->getValueAsBit("isFP"); 131 bool IsVector = VT->getValueAsBit("isVector"); 132 bool IsScalable = VT->getValueAsBit("isScalable"); 133 bool IsRISCVVecTuple = VT->getValueAsBit("isRISCVVecTuple"); 134 int64_t NF = VT->getValueAsInt("NF"); 135 bool IsNormalValueType = VT->getValueAsBit("isNormalValueType"); 136 int64_t NElem = IsVector ? VT->getValueAsInt("nElem") : 0; 137 StringRef EltName = IsVector ? VT->getValueAsDef("ElementType")->getName() 138 : "INVALID_SIMPLE_VALUE_TYPE"; 139 140 UpdateVTRange("INTEGER_FIXEDLEN_VECTOR_VALUETYPE", Name, 141 IsInteger && IsVector && !IsScalable); 142 UpdateVTRange("INTEGER_SCALABLE_VECTOR_VALUETYPE", Name, 143 IsInteger && IsScalable); 144 UpdateVTRange("FP_FIXEDLEN_VECTOR_VALUETYPE", Name, 145 IsFP && IsVector && !IsScalable); 146 UpdateVTRange("FP_SCALABLE_VECTOR_VALUETYPE", Name, IsFP && IsScalable); 147 UpdateVTRange("FIXEDLEN_VECTOR_VALUETYPE", Name, IsVector && !IsScalable); 148 UpdateVTRange("SCALABLE_VECTOR_VALUETYPE", Name, IsScalable); 149 UpdateVTRange("RISCV_VECTOR_TUPLE_VALUETYPE", Name, IsRISCVVecTuple); 150 UpdateVTRange("VECTOR_VALUETYPE", Name, IsVector); 151 UpdateVTRange("INTEGER_VALUETYPE", Name, IsInteger && !IsVector); 152 UpdateVTRange("FP_VALUETYPE", Name, IsFP && !IsVector); 153 UpdateVTRange("VALUETYPE", Name, IsNormalValueType); 154 155 // clang-format off 156 OS << " GET_VT_ATTR(" 157 << Name << ", " 158 << Value << ", " 159 << VT->getValueAsInt("Size") << ", " 160 << VT->getValueAsBit("isOverloaded") << ", " 161 << (IsInteger ? Name[0] == 'i' ? 3 : 1 : 0) << ", " 162 << (IsFP ? Name[0] == 'f' ? 3 : 1 : 0) << ", " 163 << IsVector << ", " 164 << IsScalable << ", " 165 << IsRISCVVecTuple << ", " 166 << NF << ", " 167 << NElem << ", " 168 << EltName << ")\n"; 169 // clang-format on 170 } 171 OS << "#endif\n\n"; 172 173 OS << "#ifdef GET_VT_RANGES\n"; 174 for (const auto &KV : VTRanges) { 175 assert(KV.second.Closed); 176 OS << " FIRST_" << KV.first << " = " << KV.second.First << ",\n" 177 << " LAST_" << KV.first << " = " << KV.second.Last << ",\n"; 178 } 179 OS << "#endif\n\n"; 180 181 OS << "#ifdef GET_VT_VECATTR // (Ty, Sc, Tup, nElem, ElTy)\n"; 182 for (const auto *VT : VTsByNumber) { 183 if (!VT || !VT->getValueAsBit("isVector")) 184 continue; 185 const auto *ElTy = VT->getValueAsDef("ElementType"); 186 assert(ElTy); 187 // clang-format off 188 OS << " GET_VT_VECATTR(" 189 << VT->getValueAsString("LLVMName") << ", " 190 << VT->getValueAsBit("isScalable") << ", " 191 << VT->getValueAsBit("isRISCVVecTuple") << ", " 192 << VT->getValueAsInt("nElem") << ", " 193 << ElTy->getName() << ")\n"; 194 // clang-format on 195 } 196 OS << "#endif\n\n"; 197 198 OS << "#ifdef GET_VT_EVT\n"; 199 for (const auto *VT : VTsByNumber) { 200 if (!VT) 201 continue; 202 bool IsInteger = VT->getValueAsBit("isInteger"); 203 bool IsVector = VT->getValueAsBit("isVector"); 204 bool IsFP = VT->getValueAsBit("isFP"); 205 bool IsRISCVVecTuple = VT->getValueAsBit("isRISCVVecTuple"); 206 207 if (!IsInteger && !IsVector && !IsFP && !IsRISCVVecTuple) 208 continue; 209 210 OS << " GET_VT_EVT(" << VT->getValueAsString("LLVMName") << ", "; 211 vTtoGetLlvmTyString(OS, VT); 212 OS << ")\n"; 213 } 214 OS << "#endif\n\n"; 215 } 216 217 static TableGen::Emitter::OptClass<VTEmitter> X("gen-vt", "Generate ValueType"); 218