222 lines · cpp
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-exception6//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>15using namespace llvm;16 17namespace {18 19class VTEmitter {20private:21 const RecordKeeper &Records;22 23public:24 VTEmitter(const RecordKeeper &R) : Records(R) {}25 26 void run(raw_ostream &OS);27};28 29} // End anonymous namespace.30 31static 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 NF = VT->getValueAsInt("NF");37 unsigned Sz = VT->getValueAsInt("Size");38 OS << "TargetExtType::get(Context, \"riscv.vector.tuple\", "39 "ScalableVectorType::get(Type::getInt8Ty(Context), "40 << (Sz / (NF * 8)) << "), " << NF << ")";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 Int12876 if ((isPowerOf2_64(OutputVTSize) && OutputVTSize >= 8 &&77 OutputVTSize <= 128) ||78 OutputVTSize == 1)79 OS << "Type::getInt" << OutputVTSize << "Ty(Context)";80 else81 OS << "Type::getIntNTy(Context, " << OutputVTSize << ")";82 } else {83 llvm_unreachable("Unhandled case");84 }85 86 if (IsVector)87 OS << ", " << VT->getValueAsInt("nElem") << ")";88}89 90void VTEmitter::run(raw_ostream &OS) {91 emitSourceFileHeader("ValueTypes Source Fragment", OS, Records);92 93 std::vector<const Record *> VTsByNumber{512};94 unsigned Number = 0;95 std::vector<const Record *> Defs(96 Records.getAllDerivedDefinitions("ValueType"));97 // Emit VTs in the order they were declared so that VTRanges stay contiguous.98 llvm::sort(Defs, LessRecordByID());99 for (auto *VT : Defs) {100 ++Number;101 assert(Number < VTsByNumber.size() && "ValueType should be uint16_t");102 VTsByNumber[Number] = VT;103 }104 105 struct VTRange {106 StringRef First;107 StringRef Last;108 bool Closed;109 };110 111 std::map<StringRef, VTRange> VTRanges;112 113 auto UpdateVTRange = [&VTRanges](const char *Key, StringRef Name,114 bool Valid) {115 if (Valid) {116 auto [It, Inserted] = VTRanges.try_emplace(Key);117 if (Inserted)118 It->second.First = Name;119 assert(!It->second.Closed && "Gap detected!");120 It->second.Last = Name;121 } else if (auto It = VTRanges.find(Key); It != VTRanges.end()) {122 It->second.Closed = true;123 }124 };125 126 OS << "#ifdef GET_VT_ATTR // (Ty, sz, Any, Int, FP, Vec, Sc, Tup, NF, "127 "NElem, EltTy)\n";128 for (const auto *VT : VTsByNumber) {129 if (!VT)130 continue;131 auto Name = VT->getValueAsString("LLVMName");132 bool IsInteger = VT->getValueAsBit("isInteger");133 bool IsFP = VT->getValueAsBit("isFP");134 bool IsVector = VT->getValueAsBit("isVector");135 bool IsScalable = VT->getValueAsBit("isScalable");136 bool IsRISCVVecTuple = VT->getValueAsBit("isRISCVVecTuple");137 bool IsCheriCapability = VT->getValueAsBit("isCheriCapability");138 int64_t NF = VT->getValueAsInt("NF");139 bool IsNormalValueType = VT->getValueAsBit("isNormalValueType");140 int64_t NElem = IsVector ? VT->getValueAsInt("nElem") : 0;141 StringRef EltName = IsVector ? VT->getValueAsDef("ElementType")->getName()142 : "INVALID_SIMPLE_VALUE_TYPE";143 144 UpdateVTRange("INTEGER_FIXEDLEN_VECTOR_VALUETYPE", Name,145 IsInteger && IsVector && !IsScalable);146 UpdateVTRange("INTEGER_SCALABLE_VECTOR_VALUETYPE", Name,147 IsInteger && IsScalable);148 UpdateVTRange("FP_FIXEDLEN_VECTOR_VALUETYPE", Name,149 IsFP && IsVector && !IsScalable);150 UpdateVTRange("FP_SCALABLE_VECTOR_VALUETYPE", Name, IsFP && IsScalable);151 UpdateVTRange("FIXEDLEN_VECTOR_VALUETYPE", Name, IsVector && !IsScalable);152 UpdateVTRange("SCALABLE_VECTOR_VALUETYPE", Name, IsScalable);153 UpdateVTRange("RISCV_VECTOR_TUPLE_VALUETYPE", Name, IsRISCVVecTuple);154 UpdateVTRange("VECTOR_VALUETYPE", Name, IsVector);155 UpdateVTRange("INTEGER_VALUETYPE", Name, IsInteger && !IsVector);156 UpdateVTRange("FP_VALUETYPE", Name, IsFP && !IsVector);157 UpdateVTRange("VALUETYPE", Name, IsNormalValueType);158 UpdateVTRange("CHERI_CAPABILITY_VALUETYPE", Name, IsCheriCapability);159 160 // clang-format off161 OS << " GET_VT_ATTR("162 << Name << ", "163 << VT->getValueAsInt("Size") << ", "164 << VT->getValueAsBit("isOverloaded") << ", "165 << (IsInteger ? Name[0] == 'i' ? 3 : 1 : 0) << ", "166 << (IsFP ? Name[0] == 'f' ? 3 : 1 : 0) << ", "167 << IsVector << ", "168 << IsScalable << ", "169 << IsRISCVVecTuple << ", "170 << NF << ", "171 << NElem << ", "172 << EltName << ")\n";173 // clang-format on174 }175 OS << "#endif\n\n";176 177 OS << "#ifdef GET_VT_RANGES\n";178 for (const auto &KV : VTRanges) {179 assert(KV.second.Closed);180 OS << " FIRST_" << KV.first << " = " << KV.second.First << ",\n"181 << " LAST_" << KV.first << " = " << KV.second.Last << ",\n";182 }183 OS << "#endif\n\n";184 185 OS << "#ifdef GET_VT_VECATTR // (Ty, Sc, Tup, nElem, ElTy)\n";186 for (const auto *VT : VTsByNumber) {187 if (!VT || !VT->getValueAsBit("isVector"))188 continue;189 const auto *ElTy = VT->getValueAsDef("ElementType");190 assert(ElTy);191 // clang-format off192 OS << " GET_VT_VECATTR("193 << VT->getValueAsString("LLVMName") << ", "194 << VT->getValueAsBit("isScalable") << ", "195 << VT->getValueAsBit("isRISCVVecTuple") << ", "196 << VT->getValueAsInt("nElem") << ", "197 << ElTy->getName() << ")\n";198 // clang-format on199 }200 OS << "#endif\n\n";201 202 OS << "#ifdef GET_VT_EVT\n";203 for (const auto *VT : VTsByNumber) {204 if (!VT)205 continue;206 bool IsInteger = VT->getValueAsBit("isInteger");207 bool IsVector = VT->getValueAsBit("isVector");208 bool IsFP = VT->getValueAsBit("isFP");209 bool IsRISCVVecTuple = VT->getValueAsBit("isRISCVVecTuple");210 211 if (!IsInteger && !IsVector && !IsFP && !IsRISCVVecTuple)212 continue;213 214 OS << " GET_VT_EVT(" << VT->getValueAsString("LLVMName") << ", ";215 vTtoGetLlvmTyString(OS, VT);216 OS << ")\n";217 }218 OS << "#endif\n\n";219}220 221static TableGen::Emitter::OptClass<VTEmitter> X("gen-vt", "Generate ValueType");222