1 //==- X86MnemonicTables.cpp - Generate mnemonic extraction tables. -*- C++ -*-// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This tablegen backend is responsible for emitting tables that group 10 // instructions by their mnemonic name wrt AsmWriter Variant (e.g. isADD, etc). 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "CodeGenInstruction.h" 15 #include "CodeGenTarget.h" 16 #include "X86DisassemblerTables.h" 17 #include "X86RecognizableInstr.h" 18 #include "llvm/TableGen/Error.h" 19 #include "llvm/TableGen/TableGenBackend.h" 20 21 using namespace llvm; 22 23 namespace { 24 25 class X86MnemonicTablesEmitter { 26 CodeGenTarget Target; 27 28 public: 29 X86MnemonicTablesEmitter(RecordKeeper &R) : Target(R) {} 30 31 // Output X86 mnemonic tables. 32 void run(raw_ostream &OS); 33 }; 34 35 void X86MnemonicTablesEmitter::run(raw_ostream &OS) { 36 emitSourceFileHeader("X86 Mnemonic tables", OS); 37 OS << "namespace llvm {\nnamespace X86 {\n\n"; 38 Record *AsmWriter = Target.getAsmWriter(); 39 unsigned Variant = AsmWriter->getValueAsInt("Variant"); 40 41 // Hold all instructions grouped by mnemonic 42 StringMap<SmallVector<const CodeGenInstruction *, 0>> MnemonicToCGInstrMap; 43 44 // Unused 45 X86Disassembler::DisassemblerTables Tables; 46 ArrayRef<const CodeGenInstruction *> NumberedInstructions = 47 Target.getInstructionsByEnumValue(); 48 for (unsigned II = 0, IE = NumberedInstructions.size(); II != IE; ++II) { 49 const CodeGenInstruction *I = NumberedInstructions[II]; 50 X86Disassembler::RecognizableInstr RI(Tables, *I, II); 51 Record *Def = I->TheDef; 52 if ( // Filter non-X86 instructions 53 !Def->isSubClassOf("X86Inst") || 54 // Skip pseudo instructions as they may contain non-alnum characters in 55 // mnemonic 56 (RI.IsCodeGenOnly && !RI.ForceDisassemble) || 57 // Non-parsable instruction defs contain prefix as part of AsmString 58 Def->getValueAsString("AsmVariantName") == "NonParsable" || 59 // Skip CodeGenInstructions that are not real standalone instructions 60 RI.Form == X86Local::PrefixByte || RI.Form == X86Local::Pseudo) 61 continue; 62 // Flatten an instruction assembly string. 63 std::string AsmString = I->FlattenAsmStringVariants(I->AsmString, Variant); 64 StringRef Mnemonic(AsmString); 65 // Extract a mnemonic assuming it's separated by \t 66 Mnemonic = Mnemonic.take_until([](char C) { return C == '\t'; }); 67 68 // Special case: CMOVCC, JCC, SETCC have "${cond}" in mnemonic. 69 // Replace it with "CC" in-place. 70 size_t CondPos = Mnemonic.find("${cond}"); 71 if (CondPos != StringRef::npos) 72 Mnemonic = AsmString.replace(CondPos, StringRef::npos, "CC"); 73 74 // It's intentional that we put a std::string to the map (StringRef::upper 75 // returns a string) as AsmString is deallocated at the end of the iteration 76 MnemonicToCGInstrMap[Mnemonic.upper()].push_back(I); 77 } 78 79 OS << "#ifdef GET_X86_MNEMONIC_TABLES_H\n"; 80 OS << "#undef GET_X86_MNEMONIC_TABLES_H\n\n"; 81 for (StringRef Mnemonic : MnemonicToCGInstrMap.keys()) 82 OS << "bool is" << Mnemonic << "(unsigned Opcode);\n"; 83 OS << "#endif // GET_X86_MNEMONIC_TABLES_H\n\n"; 84 85 OS << "#ifdef GET_X86_MNEMONIC_TABLES_CPP\n"; 86 OS << "#undef GET_X86_MNEMONIC_TABLES_CPP\n\n"; 87 for (StringRef Mnemonic : MnemonicToCGInstrMap.keys()) { 88 OS << "bool is" << Mnemonic << "(unsigned Opcode) {\n"; 89 auto Mnemonics = MnemonicToCGInstrMap[Mnemonic]; 90 if (Mnemonics.size() == 1) { 91 const CodeGenInstruction *CGI = *Mnemonics.begin(); 92 OS << "\treturn Opcode == " << CGI->TheDef->getName() << ";\n}\n\n"; 93 } else { 94 OS << "\tswitch (Opcode) {\n"; 95 for (const CodeGenInstruction *CGI : Mnemonics) { 96 OS << "\tcase " << CGI->TheDef->getName() << ":\n"; 97 } 98 OS << "\t\treturn true;\n\t}\n\treturn false;\n}\n\n"; 99 } 100 } 101 OS << "#endif // GET_X86_MNEMONIC_TABLES_CPP\n\n"; 102 OS << "} // end namespace X86\n} // end namespace llvm"; 103 } 104 105 } // namespace 106 107 namespace llvm { 108 void EmitX86MnemonicTables(RecordKeeper &RK, raw_ostream &OS) { 109 X86MnemonicTablesEmitter(RK).run(OS); 110 } 111 } // namespace llvm 112