summaryrefslogtreecommitdiffstats
path: root/llvm/utils/TableGen
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/utils/TableGen')
-rw-r--r--llvm/utils/TableGen/AsmMatcherEmitter.cpp33
-rw-r--r--llvm/utils/TableGen/CodeEmitterGen.cpp60
-rw-r--r--llvm/utils/TableGen/SubtargetFeatureInfo.cpp34
-rw-r--r--llvm/utils/TableGen/SubtargetFeatureInfo.h15
-rw-r--r--llvm/utils/TableGen/Types.cpp7
-rw-r--r--llvm/utils/TableGen/Types.h3
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
OpenPOWER on IntegriCloud