Path: blob/main/contrib/llvm-project/llvm/utils/TableGen/Basic/TargetFeaturesEmitter.cpp
213799 views
//===- TargetFeaturesEmitter.cpp - Generate CPU Target feature ----===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This tablegen backend exports cpu target features9// and cpu sub-type.10//11//===----------------------------------------------------------------------===//1213#include "TargetFeaturesEmitter.h"14#include "llvm/TableGen/Error.h"15#include "llvm/TableGen/TableGenBackend.h"16#include "llvm/TargetParser/SubtargetFeature.h"1718using namespace llvm;1920using FeatureMapTy = DenseMap<const Record *, unsigned>;21using ConstRecVec = std::vector<const Record *>;2223TargetFeaturesEmitter::TargetFeaturesEmitter(const RecordKeeper &R)24: Records(R) {25ArrayRef<const Record *> Targets = Records.getAllDerivedDefinitions("Target");26if (Targets.size() == 0)27PrintFatalError("No 'Target' subclasses defined!");28if (Targets.size() != 1)29PrintFatalError("Multiple subclasses of Target defined!");30Target = Targets[0]->getName();31}3233FeatureMapTy TargetFeaturesEmitter::enumeration(raw_ostream &OS) {34ArrayRef<const Record *> DefList =35Records.getAllDerivedDefinitions("SubtargetFeature");3637unsigned N = DefList.size();38if (N == 0)39return FeatureMapTy();4041if (N + 1 > MAX_SUBTARGET_FEATURES)42PrintFatalError(43"Too many subtarget features! Bump MAX_SUBTARGET_FEATURES.");4445OS << "namespace " << Target << " {\n";4647OS << "enum {\n";4849FeatureMapTy FeatureMap;50for (unsigned I = 0; I < N; ++I) {51const Record *Def = DefList[I];52// Print the Feature Name.53OS << " " << Def->getName() << " = " << I << ",\n";5455FeatureMap[Def] = I;56}5758OS << " " << "NumSubtargetFeatures = " << N << "\n";5960// Close enumeration and namespace61OS << "};\n";62OS << "} // end namespace " << Target << "\n";63return FeatureMap;64}6566void TargetFeaturesEmitter::printFeatureMask(67raw_ostream &OS, ArrayRef<const Record *> FeatureList,68const FeatureMapTy &FeatureMap) {69std::array<uint64_t, MAX_SUBTARGET_WORDS> Mask = {};70for (const Record *Feature : FeatureList) {71unsigned Bit = FeatureMap.lookup(Feature);72Mask[Bit / 64] |= 1ULL << (Bit % 64);73}7475OS << "{ { { ";76for (unsigned I = 0; I != Mask.size(); ++I) {77OS << "0x";78OS.write_hex(Mask[I]);79OS << "ULL, ";80}81OS << "} } }";82}8384void TargetFeaturesEmitter::printFeatureKeyValues(85raw_ostream &OS, const FeatureMapTy &FeatureMap) {86std::vector<const Record *> FeatureList =87Records.getAllDerivedDefinitions("SubtargetFeature");8889// Remove features with empty name.90llvm::erase_if(FeatureList, [](const Record *Rec) {91return Rec->getValueAsString("Name").empty();92});9394if (FeatureList.empty())95return;9697llvm::sort(FeatureList, LessRecordFieldName());9899// Begin feature table.100OS << "// Sorted (by key) array of values for CPU features.\n"101<< "extern const llvm::BasicSubtargetFeatureKV " << "Basic" << Target102<< "FeatureKV[] = {\n";103104for (const Record *Feature : FeatureList) {105StringRef Name = Feature->getName();106StringRef ValueName = Feature->getValueAsString("Name");107108OS << " { " << "\"" << ValueName << "\", " << Target << "::" << Name109<< ", ";110111ConstRecVec ImpliesList = Feature->getValueAsListOfDefs("Implies");112113printFeatureMask(OS, ImpliesList, FeatureMap);114115OS << " },\n";116}117118// End feature table.119OS << "};\n";120}121122void TargetFeaturesEmitter::printCPUKeyValues(raw_ostream &OS,123const FeatureMapTy &FeatureMap) {124// Gather and sort processor information125std::vector<const Record *> ProcessorList =126Records.getAllDerivedDefinitions("Processor");127llvm::sort(ProcessorList, LessRecordFieldName());128129// Begin processor table.130OS << "// Sorted (by key) array of values for CPU subtype.\n"131<< "extern const llvm::BasicSubtargetSubTypeKV " << "Basic" << Target132<< "SubTypeKV[] = {\n";133134for (const Record *Processor : ProcessorList) {135StringRef Name = Processor->getValueAsString("Name");136ConstRecVec FeatureList = Processor->getValueAsListOfDefs("Features");137138OS << " { " << "\"" << Name << "\", ";139140printFeatureMask(OS, FeatureList, FeatureMap);141OS << " },\n";142}143144// End processor table.145OS << "};\n";146}147148void TargetFeaturesEmitter::run(raw_ostream &OS) {149OS << "// Autogenerated by TargetFeatureEmitter.cpp\n\n";150151OS << "\n#ifdef GET_SUBTARGETFEATURES_ENUM\n";152OS << "#undef GET_SUBTARGETFEATURES_ENUM\n\n";153154OS << "namespace llvm {\n";155auto FeatureMap = enumeration(OS);156OS << "} // end namespace llvm\n\n";157OS << "#endif // GET_SUBTARGETFEATURES_ENUM\n\n";158159OS << "\n#ifdef GET_SUBTARGETFEATURES_KV\n";160OS << "#undef GET_SUBTARGETFEATURES_KV\n\n";161162OS << "namespace llvm {\n";163printFeatureKeyValues(OS, FeatureMap);164OS << "\n";165166printCPUKeyValues(OS, FeatureMap);167OS << "\n";168OS << "} // end namespace llvm\n\n";169OS << "#endif // GET_SUBTARGETFEATURES_KV\n\n";170}171172static TableGen::Emitter::OptClass<TargetFeaturesEmitter>173X("gen-target-features", "Generate subtarget enumerations");174175176