127f30029SMichael Kruse //===- VTEmitter.cpp - Generate properties from ValueTypes.td -------------===// 227f30029SMichael Kruse // 327f30029SMichael Kruse // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 427f30029SMichael Kruse // See https://llvm.org/LICENSE.txt for license information. 527f30029SMichael Kruse // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 627f30029SMichael Kruse // 727f30029SMichael Kruse //===----------------------------------------------------------------------===// 827f30029SMichael Kruse 927f30029SMichael Kruse #include "llvm/ADT/StringRef.h" 1027f30029SMichael Kruse #include "llvm/Support/raw_ostream.h" 1127f30029SMichael Kruse #include "llvm/TableGen/Record.h" 1227f30029SMichael Kruse #include "llvm/TableGen/TableGenBackend.h" 1327f30029SMichael Kruse #include <cassert> 1427f30029SMichael Kruse #include <map> 1527f30029SMichael Kruse using namespace llvm; 1627f30029SMichael Kruse 1727f30029SMichael Kruse namespace { 1827f30029SMichael Kruse 1927f30029SMichael Kruse class VTEmitter { 2027f30029SMichael Kruse private: 2127f30029SMichael Kruse const RecordKeeper &Records; 2227f30029SMichael Kruse 2327f30029SMichael Kruse public: 2427f30029SMichael Kruse VTEmitter(const RecordKeeper &R) : Records(R) {} 2527f30029SMichael Kruse 2627f30029SMichael Kruse void run(raw_ostream &OS); 2727f30029SMichael Kruse }; 2827f30029SMichael Kruse 2927f30029SMichael Kruse } // End anonymous namespace. 3027f30029SMichael Kruse 3127f30029SMichael Kruse static void vTtoGetLlvmTyString(raw_ostream &OS, const Record *VT) { 3227f30029SMichael Kruse bool IsVector = VT->getValueAsBit("isVector"); 3327f30029SMichael Kruse bool IsRISCVVecTuple = VT->getValueAsBit("isRISCVVecTuple"); 3427f30029SMichael Kruse 3527f30029SMichael Kruse if (IsRISCVVecTuple) { 3627f30029SMichael Kruse unsigned NElem = VT->getValueAsInt("nElem"); 3727f30029SMichael Kruse unsigned Sz = VT->getValueAsInt("Size"); 3827f30029SMichael Kruse OS << "TargetExtType::get(Context, \"riscv.vector.tuple\", " 3927f30029SMichael Kruse "ScalableVectorType::get(Type::getInt8Ty(Context), " 4027f30029SMichael Kruse << (Sz / (NElem * 8)) << "), " << NElem << ")"; 4127f30029SMichael Kruse return; 4227f30029SMichael Kruse } 4327f30029SMichael Kruse 4427f30029SMichael Kruse if (IsVector) 4527f30029SMichael Kruse OS << (VT->getValueAsBit("isScalable") ? "Scalable" : "Fixed") 4627f30029SMichael Kruse << "VectorType::get("; 4727f30029SMichael Kruse 4827f30029SMichael Kruse auto OutputVT = IsVector ? VT->getValueAsDef("ElementType") : VT; 4927f30029SMichael Kruse int64_t OutputVTSize = OutputVT->getValueAsInt("Size"); 5027f30029SMichael Kruse 5127f30029SMichael Kruse if (OutputVT->getValueAsBit("isFP")) { 5227f30029SMichael Kruse StringRef FloatTy; 5327f30029SMichael Kruse auto OutputVTName = OutputVT->getValueAsString("LLVMName"); 5427f30029SMichael Kruse switch (OutputVTSize) { 5527f30029SMichael Kruse default: 5627f30029SMichael Kruse llvm_unreachable("Unhandled case"); 5727f30029SMichael Kruse case 16: 5827f30029SMichael Kruse FloatTy = (OutputVTName == "bf16") ? "BFloatTy" : "HalfTy"; 5927f30029SMichael Kruse break; 6027f30029SMichael Kruse case 32: 6127f30029SMichael Kruse FloatTy = "FloatTy"; 6227f30029SMichael Kruse break; 6327f30029SMichael Kruse case 64: 6427f30029SMichael Kruse FloatTy = "DoubleTy"; 6527f30029SMichael Kruse break; 6627f30029SMichael Kruse case 80: 6727f30029SMichael Kruse FloatTy = "X86_FP80Ty"; 6827f30029SMichael Kruse break; 6927f30029SMichael Kruse case 128: 7027f30029SMichael Kruse FloatTy = (OutputVTName == "ppcf128") ? "PPC_FP128Ty" : "FP128Ty"; 7127f30029SMichael Kruse break; 7227f30029SMichael Kruse } 7327f30029SMichael Kruse OS << "Type::get" << FloatTy << "(Context)"; 7427f30029SMichael Kruse } else if (OutputVT->getValueAsBit("isInteger")) { 7527f30029SMichael Kruse // We only have Type::getInt1Ty, Int8, Int16, Int32, Int64, and Int128 7627f30029SMichael Kruse if ((isPowerOf2_64(OutputVTSize) && OutputVTSize >= 8 && 7727f30029SMichael Kruse OutputVTSize <= 128) || 7827f30029SMichael Kruse OutputVTSize == 1) 7927f30029SMichael Kruse OS << "Type::getInt" << OutputVTSize << "Ty(Context)"; 8027f30029SMichael Kruse else 8127f30029SMichael Kruse OS << "Type::getIntNTy(Context, " << OutputVTSize << ")"; 8227f30029SMichael Kruse } else 8327f30029SMichael Kruse llvm_unreachable("Unhandled case"); 8427f30029SMichael Kruse 8527f30029SMichael Kruse if (IsVector) 8627f30029SMichael Kruse OS << ", " << VT->getValueAsInt("nElem") << ")"; 8727f30029SMichael Kruse } 8827f30029SMichael Kruse 8927f30029SMichael Kruse void VTEmitter::run(raw_ostream &OS) { 9027f30029SMichael Kruse emitSourceFileHeader("ValueTypes Source Fragment", OS, Records); 9127f30029SMichael Kruse 9227f30029SMichael Kruse std::vector<const Record *> VTsByNumber{512}; 9327f30029SMichael Kruse for (auto *VT : Records.getAllDerivedDefinitions("ValueType")) { 9427f30029SMichael Kruse auto Number = VT->getValueAsInt("Value"); 9527f30029SMichael Kruse assert(0 <= Number && Number < (int)VTsByNumber.size() && 9627f30029SMichael Kruse "ValueType should be uint16_t"); 9727f30029SMichael Kruse assert(!VTsByNumber[Number] && "Duplicate ValueType"); 9827f30029SMichael Kruse VTsByNumber[Number] = VT; 9927f30029SMichael Kruse } 10027f30029SMichael Kruse 10127f30029SMichael Kruse struct VTRange { 10227f30029SMichael Kruse StringRef First; 10327f30029SMichael Kruse StringRef Last; 10427f30029SMichael Kruse bool Closed; 10527f30029SMichael Kruse }; 10627f30029SMichael Kruse 10727f30029SMichael Kruse std::map<StringRef, VTRange> VTRanges; 10827f30029SMichael Kruse 10927f30029SMichael Kruse auto UpdateVTRange = [&VTRanges](const char *Key, StringRef Name, 11027f30029SMichael Kruse bool Valid) { 11127f30029SMichael Kruse if (Valid) { 112*1714facfSKazu Hirata auto [It, Inserted] = VTRanges.try_emplace(Key); 113*1714facfSKazu Hirata if (Inserted) 114*1714facfSKazu Hirata It->second.First = Name; 115*1714facfSKazu Hirata assert(!It->second.Closed && "Gap detected!"); 116*1714facfSKazu Hirata It->second.Last = Name; 117*1714facfSKazu Hirata } else if (auto It = VTRanges.find(Key); It != VTRanges.end()) { 118*1714facfSKazu Hirata It->second.Closed = true; 11927f30029SMichael Kruse } 12027f30029SMichael Kruse }; 12127f30029SMichael Kruse 12227f30029SMichael Kruse OS << "#ifdef GET_VT_ATTR // (Ty, n, sz, Any, Int, FP, Vec, Sc, Tup, NF, " 12327f30029SMichael Kruse "NElem, EltTy)\n"; 12427f30029SMichael Kruse for (const auto *VT : VTsByNumber) { 12527f30029SMichael Kruse if (!VT) 12627f30029SMichael Kruse continue; 12727f30029SMichael Kruse auto Name = VT->getValueAsString("LLVMName"); 12827f30029SMichael Kruse auto Value = VT->getValueAsInt("Value"); 12927f30029SMichael Kruse bool IsInteger = VT->getValueAsBit("isInteger"); 13027f30029SMichael Kruse bool IsFP = VT->getValueAsBit("isFP"); 13127f30029SMichael Kruse bool IsVector = VT->getValueAsBit("isVector"); 13227f30029SMichael Kruse bool IsScalable = VT->getValueAsBit("isScalable"); 13327f30029SMichael Kruse bool IsRISCVVecTuple = VT->getValueAsBit("isRISCVVecTuple"); 13427f30029SMichael Kruse int64_t NF = VT->getValueAsInt("NF"); 13527f30029SMichael Kruse bool IsNormalValueType = VT->getValueAsBit("isNormalValueType"); 13627f30029SMichael Kruse int64_t NElem = IsVector ? VT->getValueAsInt("nElem") : 0; 13727f30029SMichael Kruse StringRef EltName = IsVector ? VT->getValueAsDef("ElementType")->getName() 13827f30029SMichael Kruse : "INVALID_SIMPLE_VALUE_TYPE"; 13927f30029SMichael Kruse 14027f30029SMichael Kruse UpdateVTRange("INTEGER_FIXEDLEN_VECTOR_VALUETYPE", Name, 14127f30029SMichael Kruse IsInteger && IsVector && !IsScalable); 14227f30029SMichael Kruse UpdateVTRange("INTEGER_SCALABLE_VECTOR_VALUETYPE", Name, 14327f30029SMichael Kruse IsInteger && IsScalable); 14427f30029SMichael Kruse UpdateVTRange("FP_FIXEDLEN_VECTOR_VALUETYPE", Name, 14527f30029SMichael Kruse IsFP && IsVector && !IsScalable); 14627f30029SMichael Kruse UpdateVTRange("FP_SCALABLE_VECTOR_VALUETYPE", Name, IsFP && IsScalable); 14727f30029SMichael Kruse UpdateVTRange("FIXEDLEN_VECTOR_VALUETYPE", Name, IsVector && !IsScalable); 14827f30029SMichael Kruse UpdateVTRange("SCALABLE_VECTOR_VALUETYPE", Name, IsScalable); 14927f30029SMichael Kruse UpdateVTRange("RISCV_VECTOR_TUPLE_VALUETYPE", Name, IsRISCVVecTuple); 15027f30029SMichael Kruse UpdateVTRange("VECTOR_VALUETYPE", Name, IsVector); 15127f30029SMichael Kruse UpdateVTRange("INTEGER_VALUETYPE", Name, IsInteger && !IsVector); 15227f30029SMichael Kruse UpdateVTRange("FP_VALUETYPE", Name, IsFP && !IsVector); 15327f30029SMichael Kruse UpdateVTRange("VALUETYPE", Name, IsNormalValueType); 15427f30029SMichael Kruse 15527f30029SMichael Kruse // clang-format off 15627f30029SMichael Kruse OS << " GET_VT_ATTR(" 15727f30029SMichael Kruse << Name << ", " 15827f30029SMichael Kruse << Value << ", " 15927f30029SMichael Kruse << VT->getValueAsInt("Size") << ", " 16027f30029SMichael Kruse << VT->getValueAsBit("isOverloaded") << ", " 16127f30029SMichael Kruse << (IsInteger ? Name[0] == 'i' ? 3 : 1 : 0) << ", " 16227f30029SMichael Kruse << (IsFP ? Name[0] == 'f' ? 3 : 1 : 0) << ", " 16327f30029SMichael Kruse << IsVector << ", " 16427f30029SMichael Kruse << IsScalable << ", " 16527f30029SMichael Kruse << IsRISCVVecTuple << ", " 16627f30029SMichael Kruse << NF << ", " 16727f30029SMichael Kruse << NElem << ", " 16827f30029SMichael Kruse << EltName << ")\n"; 16927f30029SMichael Kruse // clang-format on 17027f30029SMichael Kruse } 17127f30029SMichael Kruse OS << "#endif\n\n"; 17227f30029SMichael Kruse 17327f30029SMichael Kruse OS << "#ifdef GET_VT_RANGES\n"; 17427f30029SMichael Kruse for (const auto &KV : VTRanges) { 17527f30029SMichael Kruse assert(KV.second.Closed); 17627f30029SMichael Kruse OS << " FIRST_" << KV.first << " = " << KV.second.First << ",\n" 17727f30029SMichael Kruse << " LAST_" << KV.first << " = " << KV.second.Last << ",\n"; 17827f30029SMichael Kruse } 17927f30029SMichael Kruse OS << "#endif\n\n"; 18027f30029SMichael Kruse 18127f30029SMichael Kruse OS << "#ifdef GET_VT_VECATTR // (Ty, Sc, Tup, nElem, ElTy)\n"; 18227f30029SMichael Kruse for (const auto *VT : VTsByNumber) { 18327f30029SMichael Kruse if (!VT || !VT->getValueAsBit("isVector")) 18427f30029SMichael Kruse continue; 18527f30029SMichael Kruse const auto *ElTy = VT->getValueAsDef("ElementType"); 18627f30029SMichael Kruse assert(ElTy); 18727f30029SMichael Kruse // clang-format off 18827f30029SMichael Kruse OS << " GET_VT_VECATTR(" 18927f30029SMichael Kruse << VT->getValueAsString("LLVMName") << ", " 19027f30029SMichael Kruse << VT->getValueAsBit("isScalable") << ", " 19127f30029SMichael Kruse << VT->getValueAsBit("isRISCVVecTuple") << ", " 19227f30029SMichael Kruse << VT->getValueAsInt("nElem") << ", " 19327f30029SMichael Kruse << ElTy->getName() << ")\n"; 19427f30029SMichael Kruse // clang-format on 19527f30029SMichael Kruse } 19627f30029SMichael Kruse OS << "#endif\n\n"; 19727f30029SMichael Kruse 19827f30029SMichael Kruse OS << "#ifdef GET_VT_EVT\n"; 19927f30029SMichael Kruse for (const auto *VT : VTsByNumber) { 20027f30029SMichael Kruse if (!VT) 20127f30029SMichael Kruse continue; 20227f30029SMichael Kruse bool IsInteger = VT->getValueAsBit("isInteger"); 20327f30029SMichael Kruse bool IsVector = VT->getValueAsBit("isVector"); 20427f30029SMichael Kruse bool IsFP = VT->getValueAsBit("isFP"); 20527f30029SMichael Kruse bool IsRISCVVecTuple = VT->getValueAsBit("isRISCVVecTuple"); 20627f30029SMichael Kruse 20727f30029SMichael Kruse if (!IsInteger && !IsVector && !IsFP && !IsRISCVVecTuple) 20827f30029SMichael Kruse continue; 20927f30029SMichael Kruse 21027f30029SMichael Kruse OS << " GET_VT_EVT(" << VT->getValueAsString("LLVMName") << ", "; 21127f30029SMichael Kruse vTtoGetLlvmTyString(OS, VT); 21227f30029SMichael Kruse OS << ")\n"; 21327f30029SMichael Kruse } 21427f30029SMichael Kruse OS << "#endif\n\n"; 21527f30029SMichael Kruse } 21627f30029SMichael Kruse 21727f30029SMichael Kruse static TableGen::Emitter::OptClass<VTEmitter> X("gen-vt", "Generate ValueType"); 218