175 lines
5.2 KiB
C++
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");
|