diff options
Diffstat (limited to 'llvm/utils/TableGen')
-rw-r--r-- | llvm/utils/TableGen/AsmMatcherEmitter.cpp | 33 | ||||
-rw-r--r-- | llvm/utils/TableGen/CodeEmitterGen.cpp | 60 | ||||
-rw-r--r-- | llvm/utils/TableGen/SubtargetFeatureInfo.cpp | 34 | ||||
-rw-r--r-- | llvm/utils/TableGen/SubtargetFeatureInfo.h | 15 | ||||
-rw-r--r-- | llvm/utils/TableGen/Types.cpp | 7 | ||||
-rw-r--r-- | llvm/utils/TableGen/Types.h | 3 |
6 files changed, 122 insertions, 30 deletions
diff --git a/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/llvm/utils/TableGen/AsmMatcherEmitter.cpp index 25172cac00f..f80ab8e69f3 100644 --- a/llvm/utils/TableGen/AsmMatcherEmitter.cpp +++ b/llvm/utils/TableGen/AsmMatcherEmitter.cpp @@ -2364,29 +2364,6 @@ static void emitMatchRegisterAltName(CodeGenTarget &Target, Record *AsmParser, OS << "}\n\n"; } -static const char *getMinimalRequiredFeaturesType(const AsmMatcherInfo &Info) { - uint64_t MaxIndex = Info.SubtargetFeatures.size(); - if (MaxIndex > 0) - MaxIndex--; - return getMinimalTypeForRange(1ULL << MaxIndex); -} - -/// emitSubtargetFeatureFlagEnumeration - Emit the subtarget feature flag -/// definitions. -static void emitSubtargetFeatureFlagEnumeration(AsmMatcherInfo &Info, - raw_ostream &OS) { - OS << "// Flags for subtarget features that participate in " - << "instruction matching.\n"; - OS << "enum SubtargetFeatureFlag : " << getMinimalRequiredFeaturesType(Info) - << " {\n"; - for (const auto &SF : Info.SubtargetFeatures) { - const SubtargetFeatureInfo &SFI = SF.second; - OS << " " << SFI.getEnumName() << " = (1ULL << " << SFI.Index << "),\n"; - } - OS << " Feature_None = 0\n"; - OS << "};\n\n"; -} - /// emitOperandDiagnosticTypes - Emit the operand matching diagnostic types. static void emitOperandDiagnosticTypes(AsmMatcherInfo &Info, raw_ostream &OS) { // Get the set of diagnostic types from all of the operand classes. @@ -2568,7 +2545,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, // Emit the static custom operand parsing table; OS << "namespace {\n"; OS << " struct OperandMatchEntry {\n"; - OS << " " << getMinimalRequiredFeaturesType(Info) + OS << " " << getMinimalTypeForEnumBitfield(Info.SubtargetFeatures.size()) << " RequiredFeatures;\n"; OS << " " << getMinimalTypeForRange(MaxMnemonicIndex) << " Mnemonic;\n"; @@ -2837,7 +2814,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << "#undef GET_REGISTER_MATCHER\n\n"; // Emit the subtarget feature enumeration. - emitSubtargetFeatureFlagEnumeration(Info, OS); + SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration( + Info.SubtargetFeatures, OS); // Emit the function to match a register name to number. // This should be omitted for Mips target @@ -2883,7 +2861,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { // Emit the available features compute function. SubtargetFeatureInfo::emitComputeAvailableFeatures( - Info.Target.getName(), ClassName, Info.SubtargetFeatures, OS); + Info.Target.getName(), ClassName, "ComputeAvailableFeatures", + Info.SubtargetFeatures, OS); StringToOffsetTable StringTable; @@ -2921,7 +2900,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " uint16_t Opcode;\n"; OS << " " << getMinimalTypeForRange(Info.Matchables.size()) << " ConvertFn;\n"; - OS << " " << getMinimalRequiredFeaturesType(Info) + OS << " " << getMinimalTypeForEnumBitfield(Info.SubtargetFeatures.size()) << " RequiredFeatures;\n"; OS << " " << getMinimalTypeForRange( std::distance(Info.Classes.begin(), Info.Classes.end())) diff --git a/llvm/utils/TableGen/CodeEmitterGen.cpp b/llvm/utils/TableGen/CodeEmitterGen.cpp index 400913e3274..ef44757b7d4 100644 --- a/llvm/utils/TableGen/CodeEmitterGen.cpp +++ b/llvm/utils/TableGen/CodeEmitterGen.cpp @@ -14,6 +14,8 @@ //===----------------------------------------------------------------------===// #include "CodeGenTarget.h" +#include "SubtargetFeatureInfo.h" +#include "Types.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Debug.h" #include "llvm/TableGen/Record.h" @@ -307,6 +309,64 @@ void CodeEmitterGen::run(raw_ostream &o) { << " }\n" << " return Value;\n" << "}\n\n"; + + const auto &All = SubtargetFeatureInfo::getAll(Records); + std::map<Record *, SubtargetFeatureInfo, LessRecordByID> SubtargetFeatures; + SubtargetFeatures.insert(All.begin(), All.end()); + + o << "#ifdef ENABLE_INSTR_PREDICATE_VERIFIER\n" + << "#undef ENABLE_INSTR_PREDICATE_VERIFIER\n" + << "#include <sstream>\n\n"; + + // Emit the subtarget feature enumeration. + SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration(SubtargetFeatures, + o); + + // Emit the name table for error messages. + o << "#ifndef NDEBUG\n"; + SubtargetFeatureInfo::emitNameTable(SubtargetFeatures, o); + o << "#endif // NDEBUG\n"; + + // Emit the available features compute function. + SubtargetFeatureInfo::emitComputeAvailableFeatures( + Target.getName(), "MCCodeEmitter", "computeAvailableFeatures", + SubtargetFeatures, o); + + // Emit the predicate verifier. + o << "void " << Target.getName() + << "MCCodeEmitter::verifyInstructionPredicates(\n" + << " const MCInst &Inst, uint64_t AvailableFeatures) const {\n" + << "#ifndef NDEBUG\n" + << " static uint64_t RequiredFeatures[] = {\n"; + unsigned InstIdx = 0; + for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) { + o << " "; + for (Record *Predicate : Inst->TheDef->getValueAsListOfDefs("Predicates")) { + const auto &I = SubtargetFeatures.find(Predicate); + if (I != SubtargetFeatures.end()) + o << I->second.getEnumName() << " | "; + } + o << "0, // " << Inst->TheDef->getName() << " = " << InstIdx << "\n"; + InstIdx++; + } + o << " };\n\n"; + o << " assert(Inst.getOpcode() < " << InstIdx << ");\n"; + o << " uint64_t MissingFeatures =\n" + << " (AvailableFeatures & RequiredFeatures[Inst.getOpcode()]) ^\n" + << " RequiredFeatures[Inst.getOpcode()];\n" + << " if (MissingFeatures) {\n" + << " std::ostringstream Msg;\n" + << " Msg << \"Attempting to emit \" << MCII.getName(Inst.getOpcode()).str()\n" + << " << \" instruction but the \";\n" + << " for (unsigned i = 0; i < 8 * sizeof(MissingFeatures); ++i)\n" + << " if (MissingFeatures & (1ULL << i))\n" + << " Msg << SubtargetFeatureNames[i] << \" \";\n" + << " Msg << \"predicate(s) are not met\";\n" + << " report_fatal_error(Msg.str());\n" + << " }\n" + << "#endif // NDEBUG\n"; + o << "}\n"; + o << "#endif\n"; } } // End anonymous namespace diff --git a/llvm/utils/TableGen/SubtargetFeatureInfo.cpp b/llvm/utils/TableGen/SubtargetFeatureInfo.cpp index 2f9e881ef3a..7db8813050f 100644 --- a/llvm/utils/TableGen/SubtargetFeatureInfo.cpp +++ b/llvm/utils/TableGen/SubtargetFeatureInfo.cpp @@ -9,6 +9,7 @@ #include "SubtargetFeatureInfo.h" +#include "Types.h" #include "llvm/TableGen/Record.h" #include <map> @@ -42,12 +43,41 @@ SubtargetFeatureInfo::getAll(const RecordKeeper &Records) { return SubtargetFeatures; } +void SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration( + std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures, + raw_ostream &OS) { + OS << "// Flags for subtarget features that participate in " + << "instruction matching.\n"; + OS << "enum SubtargetFeatureFlag : " + << getMinimalTypeForEnumBitfield(SubtargetFeatures.size()) << " {\n"; + for (const auto &SF : SubtargetFeatures) { + const SubtargetFeatureInfo &SFI = SF.second; + OS << " " << SFI.getEnumName() << " = (1ULL << " << SFI.Index << "),\n"; + } + OS << " Feature_None = 0\n"; + OS << "};\n\n"; +} + +void SubtargetFeatureInfo::emitNameTable( + std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures, + raw_ostream &OS) { + OS << "static const char *SubtargetFeatureNames[] = {\n"; + for (const auto &SF : SubtargetFeatures) { + const SubtargetFeatureInfo &SFI = SF.second; + OS << " \"" << SFI.getEnumName() << "\",\n"; + } + // A small number of targets have no predicates. Null terminate the array to + // avoid a zero-length array. + OS << " nullptr\n" + << "};\n\n"; +} + void SubtargetFeatureInfo::emitComputeAvailableFeatures( - StringRef TargetName, StringRef ClassName, + StringRef TargetName, StringRef ClassName, StringRef FuncName, std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures, raw_ostream &OS) { OS << "uint64_t " << TargetName << ClassName << "::\n" - << "ComputeAvailableFeatures(const FeatureBitset& FB) const {\n"; + << FuncName << "(const FeatureBitset& FB) const {\n"; OS << " uint64_t Features = 0;\n"; for (const auto &SF : SubtargetFeatures) { const SubtargetFeatureInfo &SFI = SF.second; diff --git a/llvm/utils/TableGen/SubtargetFeatureInfo.h b/llvm/utils/TableGen/SubtargetFeatureInfo.h index ddd04d5bb45..b8d9123b845 100644 --- a/llvm/utils/TableGen/SubtargetFeatureInfo.h +++ b/llvm/utils/TableGen/SubtargetFeatureInfo.h @@ -14,6 +14,8 @@ #include "llvm/TableGen/Record.h" #include <map> +#include <string> +#include <vector> namespace llvm { class Record; @@ -37,6 +39,16 @@ struct SubtargetFeatureInfo { static std::vector<std::pair<Record *, SubtargetFeatureInfo>> getAll(const RecordKeeper &Records); + /// Emit the subtarget feature flag definitions. + static void emitSubtargetFeatureFlagEnumeration( + std::map<Record *, SubtargetFeatureInfo, LessRecordByID> + &SubtargetFeatures, + raw_ostream &OS); + + static void emitNameTable(std::map<Record *, SubtargetFeatureInfo, + LessRecordByID> &SubtargetFeatures, + raw_ostream &OS); + /// Emit the function to compute the list of available features given a /// subtarget. /// @@ -44,10 +56,11 @@ struct SubtargetFeatureInfo { /// <TargetName>Subtarget) /// \param ClassName The name of the class (without the <Target> prefix) /// that will contain the generated functions. + /// \param FuncName The name of the function to emit. /// \param SubtargetFeatures A map of TableGen records to the /// SubtargetFeatureInfo equivalent. static void emitComputeAvailableFeatures( - StringRef TargetName, StringRef ClassName, + StringRef TargetName, StringRef ClassName, StringRef FuncName, std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures, raw_ostream &OS); diff --git a/llvm/utils/TableGen/Types.cpp b/llvm/utils/TableGen/Types.cpp index 66f8ee42c78..35458296f8f 100644 --- a/llvm/utils/TableGen/Types.cpp +++ b/llvm/utils/TableGen/Types.cpp @@ -35,3 +35,10 @@ const char *llvm::getMinimalTypeForRange(uint64_t Range, unsigned MaxSize LLVM_A return "uint16_t"; return "uint8_t"; } + +const char *llvm::getMinimalTypeForEnumBitfield(uint64_t Size) { + uint64_t MaxIndex = Size; + if (MaxIndex > 0) + MaxIndex--; + return getMinimalTypeForRange(1ULL << MaxIndex); +} diff --git a/llvm/utils/TableGen/Types.h b/llvm/utils/TableGen/Types.h index cb81a1d1055..d511b7eae6e 100644 --- a/llvm/utils/TableGen/Types.h +++ b/llvm/utils/TableGen/Types.h @@ -17,6 +17,9 @@ namespace llvm { /// MaxSize indicates the largest size of integer to consider (in bits) and only /// supports values of at least 32. const char *getMinimalTypeForRange(uint64_t Range, unsigned MaxSize = 64); + +/// Returns the smallest unsigned integer type that can hold the given bitfield. +const char *getMinimalTypeForEnumBitfield(uint64_t Size); } #endif |