summaryrefslogtreecommitdiff
path: root/llvm/utils/TableGen/CodeEmitterGen.cpp
diff options
context:
space:
mode:
authorDavid Green <david.green@arm.com>2022-07-13 12:53:32 +0100
committerDavid Green <david.green@arm.com>2022-07-13 12:53:32 +0100
commite2fb8c0f4b940e0285ee36c112469fa75d4b60ff (patch)
tree9ddad5979a2ef957f57ef996caa3a953089305fd /llvm/utils/TableGen/CodeEmitterGen.cpp
parent35efe1d806358df6e45dde8218a143138dd8f0a8 (diff)
Move instruction predicate verification to emitInstruction
D25618 added a method to verify the instruction predicates for an emitted instruction, through verifyInstructionPredicates added into <Target>MCCodeEmitter::encodeInstruction. This is a very useful idea, but the implementation inside MCCodeEmitter made it only fire for object files, not assembly which most of the llvm test suite uses. This patch moves the code into the <Target>_MC::verifyInstructionPredicates method, inside the InstrInfo. The allows it to be called from other places, such as in this patch where it is called from the <Target>AsmPrinter::emitInstruction methods which should trigger for both assembly and object files. It can also be called from other places such as verifyInstruction, but that is not done here (it tends to catch errors earlier, but in reality just shows all the mir tests that have incorrect feature predicates). The interface was also simplified slightly, moving computeAvailableFeatures into the function so that it does not need to be called externally. The ARM, AMDGPU (but not R600), AVR, Mips and X86 backends all currently show errors in the test-suite, so have been disabled with FIXME comments. Differential Revision: https://reviews.llvm.org/D129506
Diffstat (limited to 'llvm/utils/TableGen/CodeEmitterGen.cpp')
-rw-r--r--llvm/utils/TableGen/CodeEmitterGen.cpp133
1 files changed, 0 insertions, 133 deletions
diff --git a/llvm/utils/TableGen/CodeEmitterGen.cpp b/llvm/utils/TableGen/CodeEmitterGen.cpp
index 2b9931b23c11..1d00c3cfd069 100644
--- a/llvm/utils/TableGen/CodeEmitterGen.cpp
+++ b/llvm/utils/TableGen/CodeEmitterGen.cpp
@@ -332,14 +332,6 @@ std::string CodeEmitterGen::getInstructionCaseForEncoding(Record *R, Record *Enc
return Case;
}
-static std::string
-getNameForFeatureBitset(const std::vector<Record *> &FeatureBitset) {
- std::string Name = "CEFBS";
- for (const auto &Feature : FeatureBitset)
- Name += ("_" + Feature->getName()).str();
- return Name;
-}
-
static void emitInstBits(raw_ostream &OS, const APInt &Bits) {
for (unsigned I = 0; I < Bits.getNumWords(); ++I)
OS << ((I > 0) ? ", " : "") << "UINT64_C(" << utostr(Bits.getRawData()[I])
@@ -530,131 +522,6 @@ void CodeEmitterGen::run(raw_ostream &o) {
o << " return Value;\n";
o << "}\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::emitSubtargetFeatureBitEnumeration(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::emitComputeAssemblerAvailableFeatures(
- Target.getName(), "MCCodeEmitter", "computeAvailableFeatures",
- SubtargetFeatures, o);
-
- std::vector<std::vector<Record *>> FeatureBitsets;
- for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
- FeatureBitsets.emplace_back();
- for (Record *Predicate : Inst->TheDef->getValueAsListOfDefs("Predicates")) {
- const auto &I = SubtargetFeatures.find(Predicate);
- if (I != SubtargetFeatures.end())
- FeatureBitsets.back().push_back(I->second.TheDef);
- }
- }
-
- llvm::sort(FeatureBitsets, [&](const std::vector<Record *> &A,
- const std::vector<Record *> &B) {
- if (A.size() < B.size())
- return true;
- if (A.size() > B.size())
- return false;
- for (auto Pair : zip(A, B)) {
- if (std::get<0>(Pair)->getName() < std::get<1>(Pair)->getName())
- return true;
- if (std::get<0>(Pair)->getName() > std::get<1>(Pair)->getName())
- return false;
- }
- return false;
- });
- FeatureBitsets.erase(
- std::unique(FeatureBitsets.begin(), FeatureBitsets.end()),
- FeatureBitsets.end());
- o << "#ifndef NDEBUG\n"
- << "// Feature bitsets.\n"
- << "enum : " << getMinimalTypeForRange(FeatureBitsets.size()) << " {\n"
- << " CEFBS_None,\n";
- for (const auto &FeatureBitset : FeatureBitsets) {
- if (FeatureBitset.empty())
- continue;
- o << " " << getNameForFeatureBitset(FeatureBitset) << ",\n";
- }
- o << "};\n\n"
- << "static constexpr FeatureBitset FeatureBitsets[] = {\n"
- << " {}, // CEFBS_None\n";
- for (const auto &FeatureBitset : FeatureBitsets) {
- if (FeatureBitset.empty())
- continue;
- o << " {";
- for (const auto &Feature : FeatureBitset) {
- const auto &I = SubtargetFeatures.find(Feature);
- assert(I != SubtargetFeatures.end() && "Didn't import predicate?");
- o << I->second.getEnumBitName() << ", ";
- }
- o << "},\n";
- }
- o << "};\n"
- << "#endif // NDEBUG\n\n";
-
-
- // Emit the predicate verifier.
- o << "void " << Target.getName()
- << "MCCodeEmitter::verifyInstructionPredicates(\n"
- << " const MCInst &Inst, const FeatureBitset &AvailableFeatures) const {\n"
- << "#ifndef NDEBUG\n"
- << " static " << getMinimalTypeForRange(FeatureBitsets.size())
- << " RequiredFeaturesRefs[] = {\n";
- unsigned InstIdx = 0;
- for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
- o << " CEFBS";
- unsigned NumPredicates = 0;
- for (Record *Predicate : Inst->TheDef->getValueAsListOfDefs("Predicates")) {
- const auto &I = SubtargetFeatures.find(Predicate);
- if (I != SubtargetFeatures.end()) {
- o << '_' << I->second.TheDef->getName();
- NumPredicates++;
- }
- }
- if (!NumPredicates)
- o << "_None";
- o << ", // " << Inst->TheDef->getName() << " = " << InstIdx << "\n";
- InstIdx++;
- }
- o << " };\n\n";
- o << " assert(Inst.getOpcode() < " << InstIdx << ");\n";
- o << " const FeatureBitset &RequiredFeatures = "
- "FeatureBitsets[RequiredFeaturesRefs[Inst.getOpcode()]];\n";
- o << " FeatureBitset MissingFeatures =\n"
- << " (AvailableFeatures & RequiredFeatures) ^\n"
- << " RequiredFeatures;\n"
- << " if (MissingFeatures.any()) {\n"
- << " std::ostringstream Msg;\n"
- << " Msg << \"Attempting to emit \" << "
- "MCII.getName(Inst.getOpcode()).str()\n"
- << " << \" instruction but the \";\n"
- << " for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i)\n"
- << " if (MissingFeatures.test(i))\n"
- << " Msg << SubtargetFeatureNames[i] << \" \";\n"
- << " Msg << \"predicate(s) are not met\";\n"
- << " report_fatal_error(Msg.str().c_str());\n"
- << " }\n"
- << "#else\n"
- << " // Silence unused variable warning on targets that don't use MCII for "
- "other purposes (e.g. BPF).\n"
- << " (void)MCII;\n"
- << "#endif // NDEBUG\n";
- o << "}\n";
- o << "#endif\n";
}
} // end anonymous namespace