diff options
Diffstat (limited to 'contrib/llvm/utils/TableGen/CodeEmitterGen.cpp')
-rw-r--r-- | contrib/llvm/utils/TableGen/CodeEmitterGen.cpp | 87 |
1 files changed, 80 insertions, 7 deletions
diff --git a/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp index 400913e..f34c0de 100644 --- a/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp +++ b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp @@ -13,24 +13,35 @@ // //===----------------------------------------------------------------------===// +#include "CodeGenInstruction.h" #include "CodeGenTarget.h" +#include "SubtargetFeatureInfo.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/Support/Debug.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" +#include <cassert> +#include <cstdint> #include <map> +#include <set> #include <string> +#include <utility> #include <vector> + using namespace llvm; namespace { class CodeEmitterGen { RecordKeeper &Records; + public: CodeEmitterGen(RecordKeeper &R) : Records(R) {} void run(raw_ostream &o); + private: int getVariableBit(const std::string &VarName, BitsInit *BI, int bit); std::string getInstructionCase(Record *R, CodeGenTarget &Target); @@ -173,7 +184,6 @@ AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName, } } - std::string CodeEmitterGen::getInstructionCase(Record *R, CodeGenTarget &Target) { std::string Case; @@ -259,7 +269,7 @@ void CodeEmitterGen::run(raw_ostream &o) { o << " UINT64_C(0)\n };\n"; // Map to accumulate all the cases. - std::map<std::string, std::vector<std::string> > CaseMap; + std::map<std::string, std::vector<std::string>> CaseMap; // Construct all cases statement for each opcode for (std::vector<Record*>::iterator IC = Insts.begin(), EC = Insts.end(); @@ -269,7 +279,7 @@ void CodeEmitterGen::run(raw_ostream &o) { R->getValueAsBit("isPseudo")) continue; const std::string &InstName = R->getValueAsString("Namespace") + "::" - + R->getName(); + + R->getName().str(); std::string Case = getInstructionCase(R, Target); CaseMap[Case].push_back(InstName); @@ -283,7 +293,7 @@ void CodeEmitterGen::run(raw_ostream &o) { << " switch (opcode) {\n"; // Emit each case statement - std::map<std::string, std::vector<std::string> >::iterator IE, EE; + std::map<std::string, std::vector<std::string>>::iterator IE, EE; for (IE = CaseMap.begin(), EE = CaseMap.end(); IE != EE; ++IE) { const std::string &Case = IE->first; std::vector<std::string> &InstList = IE->second; @@ -307,9 +317,72 @@ 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" + << "#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 +} // end anonymous namespace namespace llvm { @@ -318,4 +391,4 @@ void EmitCodeEmitter(RecordKeeper &RK, raw_ostream &OS) { CodeEmitterGen(RK).run(OS); } -} // End llvm namespace +} // end namespace llvm |