1 //===- TargetFeaturesEmitter.cpp - Generate CPU Target feature ----===// 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 // This tablegen backend exports cpu target features 10 // and cpu sub-type. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "TargetFeaturesEmitter.h" 15 #include "llvm/TableGen/Error.h" 16 #include "llvm/TableGen/TableGenBackend.h" 17 #include "llvm/TargetParser/SubtargetFeature.h" 18 19 using namespace llvm; 20 21 using FeatureMapTy = DenseMap<const Record *, unsigned>; 22 using ConstRecVec = std::vector<const Record *>; 23 24 TargetFeaturesEmitter::TargetFeaturesEmitter(const RecordKeeper &R) 25 : Records(R) { 26 ArrayRef<const Record *> Targets = Records.getAllDerivedDefinitions("Target"); 27 if (Targets.size() == 0) 28 PrintFatalError("No 'Target' subclasses defined!"); 29 if (Targets.size() != 1) 30 PrintFatalError("Multiple subclasses of Target defined!"); 31 Target = Targets[0]->getName(); 32 } 33 34 FeatureMapTy TargetFeaturesEmitter::enumeration(raw_ostream &OS) { 35 ArrayRef<const Record *> DefList = 36 Records.getAllDerivedDefinitions("SubtargetFeature"); 37 38 unsigned N = DefList.size(); 39 if (N == 0) 40 return FeatureMapTy(); 41 42 if (N + 1 > MAX_SUBTARGET_FEATURES) 43 PrintFatalError( 44 "Too many subtarget features! Bump MAX_SUBTARGET_FEATURES."); 45 46 OS << "namespace " << Target << " {\n"; 47 48 OS << "enum {\n"; 49 50 FeatureMapTy FeatureMap; 51 for (unsigned I = 0; I < N; ++I) { 52 const Record *Def = DefList[I]; 53 // Print the Feature Name. 54 OS << " " << Def->getName() << " = " << I << ",\n"; 55 56 FeatureMap[Def] = I; 57 } 58 59 OS << " " << "NumSubtargetFeatures = " << N << "\n"; 60 61 // Close enumeration and namespace 62 OS << "};\n"; 63 OS << "} // end namespace " << Target << "\n"; 64 return FeatureMap; 65 } 66 67 void TargetFeaturesEmitter::printFeatureMask( 68 raw_ostream &OS, ArrayRef<const Record *> FeatureList, 69 const FeatureMapTy &FeatureMap) { 70 std::array<uint64_t, MAX_SUBTARGET_WORDS> Mask = {}; 71 for (const Record *Feature : FeatureList) { 72 unsigned Bit = FeatureMap.lookup(Feature); 73 Mask[Bit / 64] |= 1ULL << (Bit % 64); 74 } 75 76 OS << "{ { { "; 77 for (unsigned I = 0; I != Mask.size(); ++I) { 78 OS << "0x"; 79 OS.write_hex(Mask[I]); 80 OS << "ULL, "; 81 } 82 OS << "} } }"; 83 } 84 85 void TargetFeaturesEmitter::printFeatureKeyValues( 86 raw_ostream &OS, const FeatureMapTy &FeatureMap) { 87 std::vector<const Record *> FeatureList = 88 Records.getAllDerivedDefinitions("SubtargetFeature"); 89 90 // Remove features with empty name. 91 llvm::erase_if(FeatureList, [](const Record *Rec) { 92 return Rec->getValueAsString("Name").empty(); 93 }); 94 95 if (FeatureList.empty()) 96 return; 97 98 llvm::sort(FeatureList, LessRecordFieldName()); 99 100 // Begin feature table. 101 OS << "// Sorted (by key) array of values for CPU features.\n" 102 << "extern const llvm::BasicSubtargetFeatureKV " << "Basic" << Target 103 << "FeatureKV[] = {\n"; 104 105 for (const Record *Feature : FeatureList) { 106 StringRef Name = Feature->getName(); 107 StringRef ValueName = Feature->getValueAsString("Name"); 108 109 OS << " { " << "\"" << ValueName << "\", " << Target << "::" << Name 110 << ", "; 111 112 ConstRecVec ImpliesList = Feature->getValueAsListOfDefs("Implies"); 113 114 printFeatureMask(OS, ImpliesList, FeatureMap); 115 116 OS << " },\n"; 117 } 118 119 // End feature table. 120 OS << "};\n"; 121 } 122 123 void TargetFeaturesEmitter::printCPUKeyValues(raw_ostream &OS, 124 const FeatureMapTy &FeatureMap) { 125 // Gather and sort processor information 126 std::vector<const Record *> ProcessorList = 127 Records.getAllDerivedDefinitions("Processor"); 128 llvm::sort(ProcessorList, LessRecordFieldName()); 129 130 // Begin processor table. 131 OS << "// Sorted (by key) array of values for CPU subtype.\n" 132 << "extern const llvm::BasicSubtargetSubTypeKV " << "Basic" << Target 133 << "SubTypeKV[] = {\n"; 134 135 for (const Record *Processor : ProcessorList) { 136 StringRef Name = Processor->getValueAsString("Name"); 137 ConstRecVec FeatureList = Processor->getValueAsListOfDefs("Features"); 138 139 OS << " { " << "\"" << Name << "\", "; 140 141 printFeatureMask(OS, FeatureList, FeatureMap); 142 OS << " },\n"; 143 } 144 145 // End processor table. 146 OS << "};\n"; 147 } 148 149 void TargetFeaturesEmitter::run(raw_ostream &OS) { 150 OS << "// Autogenerated by TargetFeatureEmitter.cpp\n\n"; 151 152 OS << "\n#ifdef GET_SUBTARGETFEATURES_ENUM\n"; 153 OS << "#undef GET_SUBTARGETFEATURES_ENUM\n\n"; 154 155 OS << "namespace llvm {\n"; 156 auto FeatureMap = enumeration(OS); 157 OS << "} // end namespace llvm\n\n"; 158 OS << "#endif // GET_SUBTARGETFEATURES_ENUM\n\n"; 159 160 OS << "\n#ifdef GET_SUBTARGETFEATURES_KV\n"; 161 OS << "#undef GET_SUBTARGETFEATURES_KV\n\n"; 162 163 OS << "namespace llvm {\n"; 164 printFeatureKeyValues(OS, FeatureMap); 165 OS << "\n"; 166 167 printCPUKeyValues(OS, FeatureMap); 168 OS << "\n"; 169 OS << "} // end namespace llvm\n\n"; 170 OS << "#endif // GET_SUBTARGETFEATURES_KV\n\n"; 171 } 172 173 static TableGen::Emitter::OptClass<TargetFeaturesEmitter> 174 X("gen-target-features", "Generate subtarget enumerations"); 175