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 bool IsCodeGenOnly = RI.IsCodeGenOnly; 53 bool ForceDisassemble = RI.ForceDisassemble; 54 uint8_t Form = RI.Form; 55 if ( // Filter non-X86 instructions 56 !Def->isSubClassOf("X86Inst") || 57 // Skip pseudo instructions as they may contain non-alnum characters in 58 // mnemonic 59 (IsCodeGenOnly && !ForceDisassemble) || 60 // Non-parsable instruction defs contain prefix as part of AsmString 61 Def->getValueAsString("AsmVariantName") == "NonParsable" || 62 // Skip CodeGenInstructions that are not real standalone instructions 63 Form == X86Local::PrefixByte || Form == X86Local::Pseudo) 64 continue; 65 // Flatten an instruction assembly string. 66 std::string AsmString = I->FlattenAsmStringVariants(I->AsmString, Variant); 67 StringRef Mnemonic(AsmString); 68 // Extract a mnemonic assuming it's separated by \t 69 Mnemonic = Mnemonic.take_until([](char C) { return C == '\t'; }); 70 71 // Special case: CMOVCC, JCC, SETCC have "${cond}" in mnemonic. 72 // Replace it with "CC" in-place. 73 size_t CondPos = Mnemonic.find("${cond}"); 74 if (CondPos != StringRef::npos) 75 Mnemonic = AsmString.replace(CondPos, StringRef::npos, "CC"); 76 77 // It's intentional that we put a std::string to the map (StringRef::upper 78 // returns a string) as AsmString is deallocated at the end of the iteration 79 MnemonicToCGInstrMap[Mnemonic.upper()].push_back(I); 80 } 81 82 OS << "#ifdef GET_X86_MNEMONIC_TABLES_H\n"; 83 OS << "#undef GET_X86_MNEMONIC_TABLES_H\n\n"; 84 for (StringRef Mnemonic : MnemonicToCGInstrMap.keys()) 85 OS << "bool is" << Mnemonic << "(unsigned Opcode);\n"; 86 OS << "#endif // GET_X86_MNEMONIC_TABLES_H\n\n"; 87 88 OS << "#ifdef GET_X86_MNEMONIC_TABLES_CPP\n"; 89 OS << "#undef GET_X86_MNEMONIC_TABLES_CPP\n\n"; 90 for (StringRef Mnemonic : MnemonicToCGInstrMap.keys()) { 91 OS << "bool is" << Mnemonic << "(unsigned Opcode) {\n"; 92 auto Mnemonics = MnemonicToCGInstrMap[Mnemonic]; 93 if (Mnemonics.size() == 1) { 94 const CodeGenInstruction *CGI = *Mnemonics.begin(); 95 OS << "\treturn Opcode == " << CGI->TheDef->getName() << ";\n}\n\n"; 96 } else { 97 OS << "\tswitch (Opcode) {\n"; 98 for (const CodeGenInstruction *CGI : Mnemonics) { 99 OS << "\tcase " << CGI->TheDef->getName() << ":\n"; 100 } 101 OS << "\t\treturn true;\n\t}\n\treturn false;\n}\n\n"; 102 } 103 } 104 OS << "#endif // GET_X86_MNEMONIC_TABLES_CPP\n\n"; 105 OS << "} // end namespace X86\n} // end namespace llvm"; 106 } 107 108 } // namespace 109 110 namespace llvm { 111 void EmitX86MnemonicTables(RecordKeeper &RK, raw_ostream &OS) { 112 X86MnemonicTablesEmitter(RK).run(OS); 113 } 114 } // namespace llvm 115