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 86 if (IsVector) 87 OS << ", " << VT->getValueAsInt("nElem") << ")"; 88 } 89 90 void VTEmitter::run(raw_ostream &OS) { 91 emitSourceFileHeader("ValueTypes Source Fragment", OS, Records); 92 93 std::vector<const Record *> VTsByNumber{512}; 94 for (auto *VT : Records.getAllDerivedDefinitions("ValueType")) { 95 auto Number = VT->getValueAsInt("Value"); 96 assert(0 <= Number && Number < (int)VTsByNumber.size() && 97 "ValueType should be uint16_t"); 98 assert(!VTsByNumber[Number] && "Duplicate ValueType"); 99 VTsByNumber[Number] = VT; 100 } 101 102 struct VTRange { 103 StringRef First; 104 StringRef Last; 105 bool Closed; 106 }; 107 108 std::map<StringRef, VTRange> VTRanges; 109 110 auto UpdateVTRange = [&VTRanges](const char *Key, StringRef Name, 111 bool Valid) { 112 if (Valid) { 113 auto [It, Inserted] = VTRanges.try_emplace(Key); 114 if (Inserted) 115 It->second.First = Name; 116 assert(!It->second.Closed && "Gap detected!"); 117 It->second.Last = Name; 118 } else if (auto It = VTRanges.find(Key); It != VTRanges.end()) { 119 It->second.Closed = true; 120 } 121 }; 122 123 OS << "#ifdef GET_VT_ATTR // (Ty, n, sz, Any, Int, FP, Vec, Sc, Tup, NF, " 124 "NElem, EltTy)\n"; 125 for (const auto *VT : VTsByNumber) { 126 if (!VT) 127 continue; 128 auto Name = VT->getValueAsString("LLVMName"); 129 auto Value = VT->getValueAsInt("Value"); 130 bool IsInteger = VT->getValueAsBit("isInteger"); 131 bool IsFP = VT->getValueAsBit("isFP"); 132 bool IsVector = VT->getValueAsBit("isVector"); 133 bool IsScalable = VT->getValueAsBit("isScalable"); 134 bool IsRISCVVecTuple = VT->getValueAsBit("isRISCVVecTuple"); 135 int64_t NF = VT->getValueAsInt("NF"); 136 bool IsNormalValueType = VT->getValueAsBit("isNormalValueType"); 137 int64_t NElem = IsVector ? VT->getValueAsInt("nElem") : 0; 138 StringRef EltName = IsVector ? VT->getValueAsDef("ElementType")->getName() 139 : "INVALID_SIMPLE_VALUE_TYPE"; 140 141 UpdateVTRange("INTEGER_FIXEDLEN_VECTOR_VALUETYPE", Name, 142 IsInteger && IsVector && !IsScalable); 143 UpdateVTRange("INTEGER_SCALABLE_VECTOR_VALUETYPE", Name, 144 IsInteger && IsScalable); 145 UpdateVTRange("FP_FIXEDLEN_VECTOR_VALUETYPE", Name, 146 IsFP && IsVector && !IsScalable); 147 UpdateVTRange("FP_SCALABLE_VECTOR_VALUETYPE", Name, IsFP && IsScalable); 148 UpdateVTRange("FIXEDLEN_VECTOR_VALUETYPE", Name, IsVector && !IsScalable); 149 UpdateVTRange("SCALABLE_VECTOR_VALUETYPE", Name, IsScalable); 150 UpdateVTRange("RISCV_VECTOR_TUPLE_VALUETYPE", Name, IsRISCVVecTuple); 151 UpdateVTRange("VECTOR_VALUETYPE", Name, IsVector); 152 UpdateVTRange("INTEGER_VALUETYPE", Name, IsInteger && !IsVector); 153 UpdateVTRange("FP_VALUETYPE", Name, IsFP && !IsVector); 154 UpdateVTRange("VALUETYPE", Name, IsNormalValueType); 155 156 // clang-format off 157 OS << " GET_VT_ATTR(" 158 << Name << ", " 159 << Value << ", " 160 << VT->getValueAsInt("Size") << ", " 161 << VT->getValueAsBit("isOverloaded") << ", " 162 << (IsInteger ? Name[0] == 'i' ? 3 : 1 : 0) << ", " 163 << (IsFP ? Name[0] == 'f' ? 3 : 1 : 0) << ", " 164 << IsVector << ", " 165 << IsScalable << ", " 166 << IsRISCVVecTuple << ", " 167 << NF << ", " 168 << NElem << ", " 169 << EltName << ")\n"; 170 // clang-format on 171 } 172 OS << "#endif\n\n"; 173 174 OS << "#ifdef GET_VT_RANGES\n"; 175 for (const auto &KV : VTRanges) { 176 assert(KV.second.Closed); 177 OS << " FIRST_" << KV.first << " = " << KV.second.First << ",\n" 178 << " LAST_" << KV.first << " = " << KV.second.Last << ",\n"; 179 } 180 OS << "#endif\n\n"; 181 182 OS << "#ifdef GET_VT_VECATTR // (Ty, Sc, Tup, nElem, ElTy)\n"; 183 for (const auto *VT : VTsByNumber) { 184 if (!VT || !VT->getValueAsBit("isVector")) 185 continue; 186 const auto *ElTy = VT->getValueAsDef("ElementType"); 187 assert(ElTy); 188 // clang-format off 189 OS << " GET_VT_VECATTR(" 190 << VT->getValueAsString("LLVMName") << ", " 191 << VT->getValueAsBit("isScalable") << ", " 192 << VT->getValueAsBit("isRISCVVecTuple") << ", " 193 << VT->getValueAsInt("nElem") << ", " 194 << ElTy->getName() << ")\n"; 195 // clang-format on 196 } 197 OS << "#endif\n\n"; 198 199 OS << "#ifdef GET_VT_EVT\n"; 200 for (const auto *VT : VTsByNumber) { 201 if (!VT) 202 continue; 203 bool IsInteger = VT->getValueAsBit("isInteger"); 204 bool IsVector = VT->getValueAsBit("isVector"); 205 bool IsFP = VT->getValueAsBit("isFP"); 206 bool IsRISCVVecTuple = VT->getValueAsBit("isRISCVVecTuple"); 207 208 if (!IsInteger && !IsVector && !IsFP && !IsRISCVVecTuple) 209 continue; 210 211 OS << " GET_VT_EVT(" << VT->getValueAsString("LLVMName") << ", "; 212 vTtoGetLlvmTyString(OS, VT); 213 OS << ")\n"; 214 } 215 OS << "#endif\n\n"; 216 } 217 218 static TableGen::Emitter::OptClass<VTEmitter> X("gen-vt", "Generate ValueType"); 219