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 <array> 14 #include <cassert> 15 #include <map> 16 using namespace llvm; 17 18 namespace { 19 20 class VTEmitter { 21 private: 22 RecordKeeper &Records; 23 24 public: 25 VTEmitter(RecordKeeper &R) : Records(R) {} 26 27 void run(raw_ostream &OS); 28 }; 29 30 } // End anonymous namespace. 31 32 void VTEmitter::run(raw_ostream &OS) { 33 emitSourceFileHeader("ValueTypes Source Fragment", OS); 34 35 std::array<const Record *, 256> VTsByNumber = {}; 36 auto ValueTypes = Records.getAllDerivedDefinitions("ValueType"); 37 for (auto *VT : ValueTypes) { 38 auto Number = VT->getValueAsInt("Value"); 39 assert(0 <= Number && Number < (int)VTsByNumber.size() && 40 "ValueType should be uint8_t"); 41 assert(!VTsByNumber[Number] && "Duplicate ValueType"); 42 VTsByNumber[Number] = VT; 43 } 44 45 struct VTRange { 46 StringRef First; 47 StringRef Last; 48 bool Closed; 49 }; 50 51 std::map<StringRef, VTRange> VTRanges; 52 53 auto UpdateVTRange = [&VTRanges](const char *Key, StringRef Name, 54 bool Valid) { 55 if (Valid) { 56 if (!VTRanges.count(Key)) 57 VTRanges[Key].First = Name; 58 assert(!VTRanges[Key].Closed && "Gap detected!"); 59 VTRanges[Key].Last = Name; 60 } else if (VTRanges.count(Key)) { 61 VTRanges[Key].Closed = true; 62 } 63 }; 64 65 OS << "#ifdef GET_VT_ATTR // (Ty, n, sz, Any, Int, FP, Vec, Sc)\n"; 66 for (const auto *VT : VTsByNumber) { 67 if (!VT) 68 continue; 69 auto Name = VT->getValueAsString("LLVMName"); 70 auto Value = VT->getValueAsInt("Value"); 71 bool IsInteger = VT->getValueAsInt("isInteger"); 72 bool IsFP = VT->getValueAsInt("isFP"); 73 bool IsVector = VT->getValueAsInt("isVector"); 74 bool IsScalable = VT->getValueAsInt("isScalable"); 75 76 UpdateVTRange("INTEGER_FIXEDLEN_VECTOR_VALUETYPE", Name, 77 IsInteger && IsVector && !IsScalable); 78 UpdateVTRange("INTEGER_SCALABLE_VECTOR_VALUETYPE", Name, 79 IsInteger && IsScalable); 80 UpdateVTRange("FP_FIXEDLEN_VECTOR_VALUETYPE", Name, 81 IsFP && IsVector && !IsScalable); 82 UpdateVTRange("FP_SCALABLE_VECTOR_VALUETYPE", Name, IsFP && IsScalable); 83 UpdateVTRange("FIXEDLEN_VECTOR_VALUETYPE", Name, IsVector && !IsScalable); 84 UpdateVTRange("SCALABLE_VECTOR_VALUETYPE", Name, IsScalable); 85 UpdateVTRange("VECTOR_VALUETYPE", Name, IsVector); 86 UpdateVTRange("INTEGER_VALUETYPE", Name, IsInteger && !IsVector); 87 UpdateVTRange("FP_VALUETYPE", Name, IsFP && !IsVector); 88 UpdateVTRange("VALUETYPE", Name, Value < 224); 89 90 // clang-format off 91 OS << " GET_VT_ATTR(" 92 << Name << ", " 93 << Value << ", " 94 << VT->getValueAsInt("Size") << ", " 95 << VT->getValueAsInt("isOverloaded") << ", " 96 << (IsInteger ? Name[0] == 'i' ? 3 : 1 : 0) << ", " 97 << (IsFP ? Name[0] == 'f' ? 3 : 1 : 0) << ", " 98 << IsVector << ", " 99 << IsScalable << ")\n"; 100 // clang-format on 101 } 102 OS << "#endif\n\n"; 103 104 OS << "#ifdef GET_VT_RANGES\n"; 105 for (const auto &KV : VTRanges) { 106 assert(KV.second.Closed); 107 OS << " FIRST_" << KV.first << " = " << KV.second.First << ",\n" 108 << " LAST_" << KV.first << " = " << KV.second.Last << ",\n"; 109 } 110 OS << "#endif\n\n"; 111 112 OS << "#ifdef GET_VT_VECATTR // (Ty, Sc, nElem, ElTy, ElSz)\n"; 113 for (const auto *VT : VTsByNumber) { 114 if (!VT || !VT->getValueAsInt("isVector")) 115 continue; 116 const auto *ElTy = VT->getValueAsDef("ElementType"); 117 assert(ElTy); 118 // clang-format off 119 OS << " GET_VT_VECATTR(" 120 << VT->getValueAsString("LLVMName") << ", " 121 << VT->getValueAsInt("isScalable") << ", " 122 << VT->getValueAsInt("nElem") << ", " 123 << ElTy->getName() << ", " 124 << ElTy->getValueAsInt("Size") << ")\n"; 125 // clang-format on 126 } 127 OS << "#endif\n\n"; 128 } 129 130 static TableGen::Emitter::OptClass<VTEmitter> X("gen-vt", "Generate ValueType"); 131