173 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This tablegen backend exports cpu target features10// and cpu sub-type.11//12//===----------------------------------------------------------------------===//13 14#include "TargetFeaturesEmitter.h"15#include "llvm/TableGen/CodeGenHelpers.h"16#include "llvm/TableGen/Error.h"17#include "llvm/TableGen/TableGenBackend.h"18#include "llvm/TargetParser/SubtargetFeature.h"19 20using namespace llvm;21 22using FeatureMapTy = DenseMap<const Record *, unsigned>;23using ConstRecVec = std::vector<const Record *>;24 25TargetFeaturesEmitter::TargetFeaturesEmitter(const RecordKeeper &R)26 : Records(R) {27 ArrayRef<const Record *> Targets = Records.getAllDerivedDefinitions("Target");28 if (Targets.size() == 0)29 PrintFatalError("No 'Target' subclasses defined!");30 if (Targets.size() != 1)31 PrintFatalError("Multiple subclasses of Target defined!");32 Target = Targets[0]->getName();33}34 35FeatureMapTy TargetFeaturesEmitter::enumeration(raw_ostream &OS) {36 ArrayRef<const Record *> DefList =37 Records.getAllDerivedDefinitions("SubtargetFeature");38 39 unsigned N = DefList.size();40 if (N == 0)41 return FeatureMapTy();42 43 if (N + 1 > MAX_SUBTARGET_FEATURES)44 PrintFatalError(45 "Too many subtarget features! Bump MAX_SUBTARGET_FEATURES.");46 47 NamespaceEmitter NS(OS, Target);48 49 OS << "enum {\n";50 51 FeatureMapTy FeatureMap;52 for (unsigned I = 0; I < N; ++I) {53 const Record *Def = DefList[I];54 // Print the Feature Name.55 OS << " " << Def->getName() << " = " << I << ",\n";56 57 FeatureMap[Def] = I;58 }59 60 OS << " " << "NumSubtargetFeatures = " << N << "\n";61 62 // Close enumeration.63 OS << "};\n";64 return FeatureMap;65}66 67void 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 85void 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" << Target103 << "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 << "::" << Name110 << ", ";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 123void TargetFeaturesEmitter::printCPUKeyValues(raw_ostream &OS,124 const FeatureMapTy &FeatureMap) {125 // Gather and sort processor information126 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" << Target133 << "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 149void TargetFeaturesEmitter::run(raw_ostream &OS) {150 OS << "// Autogenerated by TargetFeatureEmitter.cpp\n\n";151 152 FeatureMapTy FeatureMap;153 {154 IfDefEmitter IfDef(OS, "GET_SUBTARGETFEATURES_ENUM");155 NamespaceEmitter NS(OS, "llvm");156 FeatureMap = enumeration(OS);157 }158 159 {160 IfDefEmitter IfDef(OS, "GET_SUBTARGETFEATURES_KV");161 NamespaceEmitter NS(OS, "llvm");162 163 printFeatureKeyValues(OS, FeatureMap);164 OS << "\n";165 166 printCPUKeyValues(OS, FeatureMap);167 OS << "\n";168 }169}170 171static TableGen::Emitter::OptClass<TargetFeaturesEmitter>172 X("gen-target-features", "Generate subtarget enumerations");173