From e70e7d1019ca8562b614a67c26995da42c0336ad Mon Sep 17 00:00:00 2001 From: Dmitry Preobrazhensky Date: Mon, 5 Oct 2020 14:23:41 +0300 Subject: [PATCH] [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 --- llvm/utils/TableGen/AsmMatcherEmitter.cpp | 69 +++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/llvm/utils/TableGen/AsmMatcherEmitter.cpp index 5b722b20e048..3f05ab5b9955 100644 --- a/llvm/utils/TableGen/AsmMatcherEmitter.cpp +++ b/llvm/utils/TableGen/AsmMatcherEmitter.cpp @@ -3094,6 +3094,67 @@ static void emitMnemonicSpellChecker(raw_ostream &OS, CodeGenTarget &Target, 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. static void emitMatchClassKindNames(std::forward_list &Infos, @@ -3909,6 +3970,14 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { emitMnemonicSpellChecker(OS, Target, VariantCount); 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 {