llvm-project/llvm/utils/TableGen/Basic/TargetFeaturesEmitter.cpp

175 lines
5.2 KiB
C++

//===- TargetFeaturesEmitter.cpp - Generate CPU Target feature ----===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This tablegen backend exports cpu target features
// and cpu sub-type.
//
//===----------------------------------------------------------------------===//
#include "TargetFeaturesEmitter.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/TableGenBackend.h"
#include "llvm/TargetParser/SubtargetFeature.h"
using namespace llvm;
using FeatureMapTy = DenseMap<const Record *, unsigned>;
using ConstRecVec = std::vector<const Record *>;
TargetFeaturesEmitter::TargetFeaturesEmitter(const RecordKeeper &R)
: Records(R) {
ArrayRef<const Record *> Targets = Records.getAllDerivedDefinitions("Target");
if (Targets.size() == 0)
PrintFatalError("No 'Target' subclasses defined!");
if (Targets.size() != 1)
PrintFatalError("Multiple subclasses of Target defined!");
Target = Targets[0]->getName();
}
FeatureMapTy TargetFeaturesEmitter::enumeration(raw_ostream &OS) {
ArrayRef<const Record *> DefList =
Records.getAllDerivedDefinitions("SubtargetFeature");
unsigned N = DefList.size();
if (N == 0)
return FeatureMapTy();
if (N + 1 > MAX_SUBTARGET_FEATURES)
PrintFatalError(
"Too many subtarget features! Bump MAX_SUBTARGET_FEATURES.");
OS << "namespace " << Target << " {\n";
OS << "enum {\n";
FeatureMapTy FeatureMap;
for (unsigned I = 0; I < N; ++I) {
const Record *Def = DefList[I];
// Print the Feature Name.
OS << " " << Def->getName() << " = " << I << ",\n";
FeatureMap[Def] = I;
}
OS << " " << "NumSubtargetFeatures = " << N << "\n";
// Close enumeration and namespace
OS << "};\n";
OS << "} // end namespace " << Target << "\n";
return FeatureMap;
}
void TargetFeaturesEmitter::printFeatureMask(
raw_ostream &OS, ArrayRef<const Record *> FeatureList,
const FeatureMapTy &FeatureMap) {
std::array<uint64_t, MAX_SUBTARGET_WORDS> Mask = {};
for (const Record *Feature : FeatureList) {
unsigned Bit = FeatureMap.lookup(Feature);
Mask[Bit / 64] |= 1ULL << (Bit % 64);
}
OS << "{ { { ";
for (unsigned I = 0; I != Mask.size(); ++I) {
OS << "0x";
OS.write_hex(Mask[I]);
OS << "ULL, ";
}
OS << "} } }";
}
void TargetFeaturesEmitter::printFeatureKeyValues(
raw_ostream &OS, const FeatureMapTy &FeatureMap) {
std::vector<const Record *> FeatureList =
Records.getAllDerivedDefinitions("SubtargetFeature");
// Remove features with empty name.
llvm::erase_if(FeatureList, [](const Record *Rec) {
return Rec->getValueAsString("Name").empty();
});
if (FeatureList.empty())
return;
llvm::sort(FeatureList, LessRecordFieldName());
// Begin feature table.
OS << "// Sorted (by key) array of values for CPU features.\n"
<< "extern const llvm::BasicSubtargetFeatureKV " << "Basic" << Target
<< "FeatureKV[] = {\n";
for (const Record *Feature : FeatureList) {
StringRef Name = Feature->getName();
StringRef ValueName = Feature->getValueAsString("Name");
OS << " { " << "\"" << ValueName << "\", " << Target << "::" << Name
<< ", ";
ConstRecVec ImpliesList = Feature->getValueAsListOfDefs("Implies");
printFeatureMask(OS, ImpliesList, FeatureMap);
OS << " },\n";
}
// End feature table.
OS << "};\n";
}
void TargetFeaturesEmitter::printCPUKeyValues(raw_ostream &OS,
const FeatureMapTy &FeatureMap) {
// Gather and sort processor information
std::vector<const Record *> ProcessorList =
Records.getAllDerivedDefinitions("Processor");
llvm::sort(ProcessorList, LessRecordFieldName());
// Begin processor table.
OS << "// Sorted (by key) array of values for CPU subtype.\n"
<< "extern const llvm::BasicSubtargetSubTypeKV " << "Basic" << Target
<< "SubTypeKV[] = {\n";
for (const Record *Processor : ProcessorList) {
StringRef Name = Processor->getValueAsString("Name");
ConstRecVec FeatureList = Processor->getValueAsListOfDefs("Features");
OS << " { " << "\"" << Name << "\", ";
printFeatureMask(OS, FeatureList, FeatureMap);
OS << " },\n";
}
// End processor table.
OS << "};\n";
}
void TargetFeaturesEmitter::run(raw_ostream &OS) {
OS << "// Autogenerated by TargetFeatureEmitter.cpp\n\n";
OS << "\n#ifdef GET_SUBTARGETFEATURES_ENUM\n";
OS << "#undef GET_SUBTARGETFEATURES_ENUM\n\n";
OS << "namespace llvm {\n";
auto FeatureMap = enumeration(OS);
OS << "} // end namespace llvm\n\n";
OS << "#endif // GET_SUBTARGETFEATURES_ENUM\n\n";
OS << "\n#ifdef GET_SUBTARGETFEATURES_KV\n";
OS << "#undef GET_SUBTARGETFEATURES_KV\n\n";
OS << "namespace llvm {\n";
printFeatureKeyValues(OS, FeatureMap);
OS << "\n";
printCPUKeyValues(OS, FeatureMap);
OS << "\n";
OS << "} // end namespace llvm\n\n";
OS << "#endif // GET_SUBTARGETFEATURES_KV\n\n";
}
static TableGen::Emitter::OptClass<TargetFeaturesEmitter>
X("gen-target-features", "Generate subtarget enumerations");