[TableGen] Added a function for identification of unsupported opcodes.

This change implements generation of a function which may be used by a backend to check if a given instruction is supported for a specific subtarget.

Reviewers: sdesmalen

Differential Revision: https://reviews.llvm.org/D88214
This commit is contained in:
Dmitry Preobrazhensky 2020-10-05 14:23:41 +03:00
parent 96c8a17c80
commit e70e7d1019
1 changed files with 69 additions and 0 deletions

View File

@ -3094,6 +3094,67 @@ static void emitMnemonicSpellChecker(raw_ostream &OS, CodeGenTarget &Target,
OS << "\n"; OS << "\n";
} }
static void emitMnemonicChecker(raw_ostream &OS,
CodeGenTarget &Target,
unsigned VariantCount,
bool HasMnemonicFirst,
bool HasMnemonicAliases) {
OS << "static bool " << Target.getName()
<< "CheckMnemonic(StringRef Mnemonic,\n";
OS << " "
<< "const FeatureBitset &AvailableFeatures,\n";
OS << " "
<< "unsigned VariantID) {\n";
if (!VariantCount) {
OS << " return false;\n";
} else {
if (HasMnemonicAliases) {
OS << " // Process all MnemonicAliases to remap the mnemonic.\n";
OS << " applyMnemonicAliases(Mnemonic, AvailableFeatures, VariantID);";
OS << "\n\n";
}
OS << " // Find the appropriate table for this asm variant.\n";
OS << " const MatchEntry *Start, *End;\n";
OS << " switch (VariantID) {\n";
OS << " default: llvm_unreachable(\"invalid variant!\");\n";
for (unsigned VC = 0; VC != VariantCount; ++VC) {
Record *AsmVariant = Target.getAsmParserVariant(VC);
int AsmVariantNo = AsmVariant->getValueAsInt("Variant");
OS << " case " << AsmVariantNo << ": Start = std::begin(MatchTable" << VC
<< "); End = std::end(MatchTable" << VC << "); break;\n";
}
OS << " }\n\n";
OS << " // Search the table.\n";
if (HasMnemonicFirst) {
OS << " auto MnemonicRange = "
"std::equal_range(Start, End, Mnemonic, LessOpcode());\n\n";
} else {
OS << " auto MnemonicRange = std::make_pair(Start, End);\n";
OS << " unsigned SIndex = Mnemonic.empty() ? 0 : 1;\n";
OS << " if (!Mnemonic.empty())\n";
OS << " MnemonicRange = "
<< "std::equal_range(Start, End, Mnemonic.lower(), LessOpcode());\n\n";
}
OS << " if (MnemonicRange.first == MnemonicRange.second)\n";
OS << " return false;\n\n";
OS << " for (const MatchEntry *it = MnemonicRange.first, "
<< "*ie = MnemonicRange.second;\n";
OS << " it != ie; ++it) {\n";
OS << " const FeatureBitset &RequiredFeatures =\n";
OS << " FeatureBitsets[it->RequiredFeaturesIdx];\n";
OS << " if ((AvailableFeatures & RequiredFeatures) == ";
OS << "RequiredFeatures)\n";
OS << " return true;\n";
OS << " }\n";
OS << " return false;\n";
}
OS << "}\n";
OS << "\n";
}
// Emit a function mapping match classes to strings, for debugging. // Emit a function mapping match classes to strings, for debugging.
static void emitMatchClassKindNames(std::forward_list<ClassInfo> &Infos, static void emitMatchClassKindNames(std::forward_list<ClassInfo> &Infos,
@ -3909,6 +3970,14 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
emitMnemonicSpellChecker(OS, Target, VariantCount); emitMnemonicSpellChecker(OS, Target, VariantCount);
OS << "#endif // GET_MNEMONIC_SPELL_CHECKER\n\n"; OS << "#endif // GET_MNEMONIC_SPELL_CHECKER\n\n";
OS << "\n#ifdef GET_MNEMONIC_CHECKER\n";
OS << "#undef GET_MNEMONIC_CHECKER\n\n";
emitMnemonicChecker(OS, Target, VariantCount,
HasMnemonicFirst, HasMnemonicAliases);
OS << "#endif // GET_MNEMONIC_CHECKER\n\n";
} }
namespace llvm { namespace llvm {