summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/utils/TableGen/CodeEmitterGen.cpp')
-rw-r--r--contrib/llvm/utils/TableGen/CodeEmitterGen.cpp87
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
OpenPOWER on IntegriCloud