106c3fb27SDimitry Andric //===- VTEmitter.cpp - Generate properties from ValueTypes.td -------------===// 206c3fb27SDimitry Andric // 306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 606c3fb27SDimitry Andric // 706c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 806c3fb27SDimitry Andric 906c3fb27SDimitry Andric #include "llvm/ADT/StringRef.h" 1006c3fb27SDimitry Andric #include "llvm/Support/raw_ostream.h" 1106c3fb27SDimitry Andric #include "llvm/TableGen/Record.h" 1206c3fb27SDimitry Andric #include "llvm/TableGen/TableGenBackend.h" 1306c3fb27SDimitry Andric #include <array> 1406c3fb27SDimitry Andric #include <cassert> 1506c3fb27SDimitry Andric #include <map> 1606c3fb27SDimitry Andric using namespace llvm; 1706c3fb27SDimitry Andric 1806c3fb27SDimitry Andric namespace { 1906c3fb27SDimitry Andric 2006c3fb27SDimitry Andric class VTEmitter { 2106c3fb27SDimitry Andric private: 2206c3fb27SDimitry Andric RecordKeeper &Records; 2306c3fb27SDimitry Andric 2406c3fb27SDimitry Andric public: 2506c3fb27SDimitry Andric VTEmitter(RecordKeeper &R) : Records(R) {} 2606c3fb27SDimitry Andric 2706c3fb27SDimitry Andric void run(raw_ostream &OS); 2806c3fb27SDimitry Andric }; 2906c3fb27SDimitry Andric 3006c3fb27SDimitry Andric } // End anonymous namespace. 3106c3fb27SDimitry Andric 32*0fca6ea1SDimitry Andric static void VTtoGetLLVMTyString(raw_ostream &OS, const Record *VT) { 33*0fca6ea1SDimitry Andric bool IsVector = VT->getValueAsBit("isVector"); 34*0fca6ea1SDimitry Andric if (IsVector) 35*0fca6ea1SDimitry Andric OS << (VT->getValueAsBit("isScalable") ? "Scalable" : "Fixed") 36*0fca6ea1SDimitry Andric << "VectorType::get("; 37*0fca6ea1SDimitry Andric 38*0fca6ea1SDimitry Andric auto OutputVT = IsVector ? VT->getValueAsDef("ElementType") : VT; 39*0fca6ea1SDimitry Andric int64_t OutputVTSize = OutputVT->getValueAsInt("Size"); 40*0fca6ea1SDimitry Andric 41*0fca6ea1SDimitry Andric if (OutputVT->getValueAsBit("isFP")) { 42*0fca6ea1SDimitry Andric StringRef FloatTy; 43*0fca6ea1SDimitry Andric auto OutputVTName = OutputVT->getValueAsString("LLVMName"); 44*0fca6ea1SDimitry Andric switch (OutputVTSize) { 45*0fca6ea1SDimitry Andric default: 46*0fca6ea1SDimitry Andric llvm_unreachable("Unhandled case"); 47*0fca6ea1SDimitry Andric case 16: 48*0fca6ea1SDimitry Andric FloatTy = (OutputVTName == "bf16") ? "BFloatTy" : "HalfTy"; 49*0fca6ea1SDimitry Andric break; 50*0fca6ea1SDimitry Andric case 32: 51*0fca6ea1SDimitry Andric FloatTy = "FloatTy"; 52*0fca6ea1SDimitry Andric break; 53*0fca6ea1SDimitry Andric case 64: 54*0fca6ea1SDimitry Andric FloatTy = "DoubleTy"; 55*0fca6ea1SDimitry Andric break; 56*0fca6ea1SDimitry Andric case 80: 57*0fca6ea1SDimitry Andric FloatTy = "X86_FP80Ty"; 58*0fca6ea1SDimitry Andric break; 59*0fca6ea1SDimitry Andric case 128: 60*0fca6ea1SDimitry Andric FloatTy = (OutputVTName == "ppcf128") ? "PPC_FP128Ty" : "FP128Ty"; 61*0fca6ea1SDimitry Andric break; 62*0fca6ea1SDimitry Andric } 63*0fca6ea1SDimitry Andric OS << "Type::get" << FloatTy << "(Context)"; 64*0fca6ea1SDimitry Andric } else if (OutputVT->getValueAsBit("isInteger")) { 65*0fca6ea1SDimitry Andric // We only have Type::getInt1Ty, Int8, Int16, Int32, Int64, and Int128 66*0fca6ea1SDimitry Andric if ((isPowerOf2_64(OutputVTSize) && OutputVTSize >= 8 && 67*0fca6ea1SDimitry Andric OutputVTSize <= 128) || 68*0fca6ea1SDimitry Andric OutputVTSize == 1) 69*0fca6ea1SDimitry Andric OS << "Type::getInt" << OutputVTSize << "Ty(Context)"; 70*0fca6ea1SDimitry Andric else 71*0fca6ea1SDimitry Andric OS << "Type::getIntNTy(Context, " << OutputVTSize << ")"; 72*0fca6ea1SDimitry Andric } else 73*0fca6ea1SDimitry Andric llvm_unreachable("Unhandled case"); 74*0fca6ea1SDimitry Andric 75*0fca6ea1SDimitry Andric if (IsVector) 76*0fca6ea1SDimitry Andric OS << ", " << VT->getValueAsInt("nElem") << ")"; 77*0fca6ea1SDimitry Andric } 78*0fca6ea1SDimitry Andric 7906c3fb27SDimitry Andric void VTEmitter::run(raw_ostream &OS) { 805f757f3fSDimitry Andric emitSourceFileHeader("ValueTypes Source Fragment", OS, Records); 8106c3fb27SDimitry Andric 8206c3fb27SDimitry Andric std::array<const Record *, 256> VTsByNumber = {}; 8306c3fb27SDimitry Andric auto ValueTypes = Records.getAllDerivedDefinitions("ValueType"); 8406c3fb27SDimitry Andric for (auto *VT : ValueTypes) { 8506c3fb27SDimitry Andric auto Number = VT->getValueAsInt("Value"); 8606c3fb27SDimitry Andric assert(0 <= Number && Number < (int)VTsByNumber.size() && 8706c3fb27SDimitry Andric "ValueType should be uint8_t"); 8806c3fb27SDimitry Andric assert(!VTsByNumber[Number] && "Duplicate ValueType"); 8906c3fb27SDimitry Andric VTsByNumber[Number] = VT; 9006c3fb27SDimitry Andric } 9106c3fb27SDimitry Andric 9206c3fb27SDimitry Andric struct VTRange { 9306c3fb27SDimitry Andric StringRef First; 9406c3fb27SDimitry Andric StringRef Last; 9506c3fb27SDimitry Andric bool Closed; 9606c3fb27SDimitry Andric }; 9706c3fb27SDimitry Andric 9806c3fb27SDimitry Andric std::map<StringRef, VTRange> VTRanges; 9906c3fb27SDimitry Andric 10006c3fb27SDimitry Andric auto UpdateVTRange = [&VTRanges](const char *Key, StringRef Name, 10106c3fb27SDimitry Andric bool Valid) { 10206c3fb27SDimitry Andric if (Valid) { 10306c3fb27SDimitry Andric if (!VTRanges.count(Key)) 10406c3fb27SDimitry Andric VTRanges[Key].First = Name; 10506c3fb27SDimitry Andric assert(!VTRanges[Key].Closed && "Gap detected!"); 10606c3fb27SDimitry Andric VTRanges[Key].Last = Name; 10706c3fb27SDimitry Andric } else if (VTRanges.count(Key)) { 10806c3fb27SDimitry Andric VTRanges[Key].Closed = true; 10906c3fb27SDimitry Andric } 11006c3fb27SDimitry Andric }; 11106c3fb27SDimitry Andric 11206c3fb27SDimitry Andric OS << "#ifdef GET_VT_ATTR // (Ty, n, sz, Any, Int, FP, Vec, Sc)\n"; 11306c3fb27SDimitry Andric for (const auto *VT : VTsByNumber) { 11406c3fb27SDimitry Andric if (!VT) 11506c3fb27SDimitry Andric continue; 11606c3fb27SDimitry Andric auto Name = VT->getValueAsString("LLVMName"); 11706c3fb27SDimitry Andric auto Value = VT->getValueAsInt("Value"); 118*0fca6ea1SDimitry Andric bool IsInteger = VT->getValueAsBit("isInteger"); 119*0fca6ea1SDimitry Andric bool IsFP = VT->getValueAsBit("isFP"); 120*0fca6ea1SDimitry Andric bool IsVector = VT->getValueAsBit("isVector"); 121*0fca6ea1SDimitry Andric bool IsScalable = VT->getValueAsBit("isScalable"); 122*0fca6ea1SDimitry Andric bool IsNormalValueType = VT->getValueAsBit("isNormalValueType"); 123*0fca6ea1SDimitry Andric int64_t NElem = IsVector ? VT->getValueAsInt("nElem") : 0; 124*0fca6ea1SDimitry Andric StringRef EltName = IsVector ? VT->getValueAsDef("ElementType")->getName() 125*0fca6ea1SDimitry Andric : "INVALID_SIMPLE_VALUE_TYPE"; 12606c3fb27SDimitry Andric 12706c3fb27SDimitry Andric UpdateVTRange("INTEGER_FIXEDLEN_VECTOR_VALUETYPE", Name, 12806c3fb27SDimitry Andric IsInteger && IsVector && !IsScalable); 12906c3fb27SDimitry Andric UpdateVTRange("INTEGER_SCALABLE_VECTOR_VALUETYPE", Name, 13006c3fb27SDimitry Andric IsInteger && IsScalable); 13106c3fb27SDimitry Andric UpdateVTRange("FP_FIXEDLEN_VECTOR_VALUETYPE", Name, 13206c3fb27SDimitry Andric IsFP && IsVector && !IsScalable); 13306c3fb27SDimitry Andric UpdateVTRange("FP_SCALABLE_VECTOR_VALUETYPE", Name, IsFP && IsScalable); 13406c3fb27SDimitry Andric UpdateVTRange("FIXEDLEN_VECTOR_VALUETYPE", Name, IsVector && !IsScalable); 13506c3fb27SDimitry Andric UpdateVTRange("SCALABLE_VECTOR_VALUETYPE", Name, IsScalable); 13606c3fb27SDimitry Andric UpdateVTRange("VECTOR_VALUETYPE", Name, IsVector); 13706c3fb27SDimitry Andric UpdateVTRange("INTEGER_VALUETYPE", Name, IsInteger && !IsVector); 13806c3fb27SDimitry Andric UpdateVTRange("FP_VALUETYPE", Name, IsFP && !IsVector); 139*0fca6ea1SDimitry Andric UpdateVTRange("VALUETYPE", Name, IsNormalValueType); 14006c3fb27SDimitry Andric 14106c3fb27SDimitry Andric // clang-format off 14206c3fb27SDimitry Andric OS << " GET_VT_ATTR(" 14306c3fb27SDimitry Andric << Name << ", " 14406c3fb27SDimitry Andric << Value << ", " 14506c3fb27SDimitry Andric << VT->getValueAsInt("Size") << ", " 146*0fca6ea1SDimitry Andric << VT->getValueAsBit("isOverloaded") << ", " 14706c3fb27SDimitry Andric << (IsInteger ? Name[0] == 'i' ? 3 : 1 : 0) << ", " 14806c3fb27SDimitry Andric << (IsFP ? Name[0] == 'f' ? 3 : 1 : 0) << ", " 14906c3fb27SDimitry Andric << IsVector << ", " 150*0fca6ea1SDimitry Andric << IsScalable << ", " 151*0fca6ea1SDimitry Andric << NElem << ", " 152*0fca6ea1SDimitry Andric << EltName << ")\n"; 15306c3fb27SDimitry Andric // clang-format on 15406c3fb27SDimitry Andric } 15506c3fb27SDimitry Andric OS << "#endif\n\n"; 15606c3fb27SDimitry Andric 15706c3fb27SDimitry Andric OS << "#ifdef GET_VT_RANGES\n"; 15806c3fb27SDimitry Andric for (const auto &KV : VTRanges) { 15906c3fb27SDimitry Andric assert(KV.second.Closed); 16006c3fb27SDimitry Andric OS << " FIRST_" << KV.first << " = " << KV.second.First << ",\n" 16106c3fb27SDimitry Andric << " LAST_" << KV.first << " = " << KV.second.Last << ",\n"; 16206c3fb27SDimitry Andric } 16306c3fb27SDimitry Andric OS << "#endif\n\n"; 16406c3fb27SDimitry Andric 165*0fca6ea1SDimitry Andric OS << "#ifdef GET_VT_VECATTR // (Ty, Sc, nElem, ElTy)\n"; 16606c3fb27SDimitry Andric for (const auto *VT : VTsByNumber) { 167*0fca6ea1SDimitry Andric if (!VT || !VT->getValueAsBit("isVector")) 16806c3fb27SDimitry Andric continue; 16906c3fb27SDimitry Andric const auto *ElTy = VT->getValueAsDef("ElementType"); 17006c3fb27SDimitry Andric assert(ElTy); 17106c3fb27SDimitry Andric // clang-format off 17206c3fb27SDimitry Andric OS << " GET_VT_VECATTR(" 17306c3fb27SDimitry Andric << VT->getValueAsString("LLVMName") << ", " 174*0fca6ea1SDimitry Andric << VT->getValueAsBit("isScalable") << ", " 17506c3fb27SDimitry Andric << VT->getValueAsInt("nElem") << ", " 176*0fca6ea1SDimitry Andric << ElTy->getName() << ")\n"; 17706c3fb27SDimitry Andric // clang-format on 17806c3fb27SDimitry Andric } 17906c3fb27SDimitry Andric OS << "#endif\n\n"; 180*0fca6ea1SDimitry Andric 181*0fca6ea1SDimitry Andric OS << "#ifdef GET_VT_EVT\n"; 182*0fca6ea1SDimitry Andric for (const auto *VT : VTsByNumber) { 183*0fca6ea1SDimitry Andric if (!VT) 184*0fca6ea1SDimitry Andric continue; 185*0fca6ea1SDimitry Andric bool IsInteger = VT->getValueAsBit("isInteger"); 186*0fca6ea1SDimitry Andric bool IsVector = VT->getValueAsBit("isVector"); 187*0fca6ea1SDimitry Andric bool IsFP = VT->getValueAsBit("isFP"); 188*0fca6ea1SDimitry Andric 189*0fca6ea1SDimitry Andric if (!IsInteger && !IsVector && !IsFP) 190*0fca6ea1SDimitry Andric continue; 191*0fca6ea1SDimitry Andric 192*0fca6ea1SDimitry Andric OS << " GET_VT_EVT(" << VT->getValueAsString("LLVMName") << ", "; 193*0fca6ea1SDimitry Andric VTtoGetLLVMTyString(OS, VT); 194*0fca6ea1SDimitry Andric OS << ")\n"; 195*0fca6ea1SDimitry Andric } 196*0fca6ea1SDimitry Andric OS << "#endif\n\n"; 19706c3fb27SDimitry Andric } 19806c3fb27SDimitry Andric 19906c3fb27SDimitry Andric static TableGen::Emitter::OptClass<VTEmitter> X("gen-vt", "Generate ValueType"); 200