Index: lib/Target/WebAssembly/CMakeLists.txt =================================================================== --- lib/Target/WebAssembly/CMakeLists.txt +++ lib/Target/WebAssembly/CMakeLists.txt @@ -9,7 +9,6 @@ tablegen(LLVM WebAssemblyGenMCCodeEmitter.inc -gen-emitter) tablegen(LLVM WebAssemblyGenRegisterInfo.inc -gen-register-info) tablegen(LLVM WebAssemblyGenSubtargetInfo.inc -gen-subtarget) -tablegen(LLVM WebAssemblyGenStackifier.inc -gen-wasm-stackifier) add_public_tablegen_target(WebAssemblyCommonTableGen) Index: lib/Target/WebAssembly/WebAssemblyInstrControl.td =================================================================== --- lib/Target/WebAssembly/WebAssemblyInstrControl.td +++ lib/Target/WebAssembly/WebAssemblyInstrControl.td @@ -43,26 +43,28 @@ let isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 in { let isCodeGenOnly = 1 in def BR_TABLE_I32 : NI<(outs), (ins I32:$index, variable_ops), - [(WebAssemblybr_table I32:$index)], 0, + [(WebAssemblybr_table I32:$index)], "false", "br_table \t$index", 0x0e> { let TSFlags{0} = 1; let TSFlags{1} = 1; } +let BaseName = "BR_TABLE_I32" in def BR_TABLE_I32_S : NI<(outs), (ins variable_ops), - [], 1, + [], "true", "br_table", 0x0e> { let TSFlags{0} = 1; let TSFlags{1} = 1; } let isCodeGenOnly = 1 in def BR_TABLE_I64 : NI<(outs), (ins I64:$index, variable_ops), - [(WebAssemblybr_table I64:$index)], 0, + [(WebAssemblybr_table I64:$index)], "false", "br_table \t$index"> { let TSFlags{0} = 1; let TSFlags{1} = 1; } +let BaseName = "BR_TABLE_I64" in def BR_TABLE_I64_S : NI<(outs), (ins variable_ops), - [], 1, + [], "true", "br_table"> { let TSFlags{0} = 1; let TSFlags{1} = 1; Index: lib/Target/WebAssembly/WebAssemblyInstrFormats.td =================================================================== --- lib/Target/WebAssembly/WebAssemblyInstrFormats.td +++ lib/Target/WebAssembly/WebAssemblyInstrFormats.td @@ -15,17 +15,19 @@ // WebAssembly Instruction Format. // We instantiate 2 of these for every actual instruction (register based // and stack based), see below. -class WebAssemblyInst inst, string asmstr, bit stack> : Instruction { - field bits<32> Inst = inst; // Instruction encoding. - field bit StackBased = stack; +class WebAssemblyInst inst, string asmstr, string stack> : StackRel, + Instruction { + bits<32> Inst = inst; // Instruction encoding. + string StackBased = stack; + string BaseName = NAME; let Namespace = "WebAssembly"; let Pattern = []; let AsmString = asmstr; } // Normal instructions. Default instantiation of a WebAssemblyInst. -class NI pattern, bit stack, string asmstr = "", - bits<32> inst = -1> +class NI pattern, string stack, + string asmstr = "", bits<32> inst = -1> : WebAssemblyInst { dag OutOperandList = oops; dag InOperandList = iops; @@ -50,8 +52,9 @@ list pattern_r, string asmstr_r = "", string asmstr_s = "", bits<32> inst = -1> { let isCodeGenOnly = 1 in - def "" : NI; - def _S : NI; + def "" : NI; + let BaseName = NAME in + def _S : NI; } // For instructions that have no register ops, so both sets are the same. Index: lib/Target/WebAssembly/WebAssemblyInstrInfo.td =================================================================== --- lib/Target/WebAssembly/WebAssemblyInstrInfo.td +++ lib/Target/WebAssembly/WebAssemblyInstrInfo.td @@ -153,6 +153,19 @@ } // OperandNamespace = "WebAssembly" +//===----------------------------------------------------------------------===// +// WebAssembly Register to Stack instruction mapping +//===----------------------------------------------------------------------===// + +class StackRel; +def getStackOpcode : InstrMapping { + let FilterClass = "StackRel"; + let RowFields = ["BaseName"]; + let ColFields = ["StackBased"]; + let KeyCol = ["false"]; + let ValueCols = [["true"]]; +} + //===----------------------------------------------------------------------===// // WebAssembly Instruction Format Definitions. //===----------------------------------------------------------------------===// Index: lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp +++ lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp @@ -30,6 +30,11 @@ #include "llvm/Support/raw_ostream.h" using namespace llvm; +// Defines llvm::WebAssembly::getStackOpcode to convert register instructions to +// stack instructions +#define GET_INSTRMAP_INFO 1 +#include "WebAssemblyGenInstrInfo.inc" + // This disables the removal of registers when lowering into MC, as required // by some current tests. static cl::opt @@ -38,7 +43,6 @@ " instruction output for test purposes only."), cl::init(false)); -static unsigned regInstructionToStackInstruction(unsigned OpCode); static void removeRegisterOperands(const MachineInstr *MI, MCInst &OutMI); MCSymbol * @@ -254,7 +258,8 @@ // Transform to _S instruction. auto RegOpcode = OutMI.getOpcode(); - auto StackOpcode = regInstructionToStackInstruction(RegOpcode); + auto StackOpcode = WebAssembly::getStackOpcode(RegOpcode); + assert(StackOpcode != -1 && "Failed to stackify instruction"); OutMI.setOpcode(StackOpcode); // Remove register operands. @@ -265,21 +270,3 @@ } } } - -static unsigned regInstructionToStackInstruction(unsigned OpCode) { - // For most opcodes, this function could have been implemented as "return - // OpCode + 1", but since table-gen alphabetically sorts them, this cannot be - // guaranteed (see e.g. BR and BR_IF). Instead we use a giant switch statement - // generated by a custom TableGen backend (WebAssemblyStackifierEmitter.cpp) - // that emits switch cases of the form - // - // case WebAssembly::RegisterInstr: return WebAssembly::StackInstr; - // - // for every pair of equivalent register and stack instructions. - switch (OpCode) { - default: - llvm_unreachable( - "unknown WebAssembly instruction in WebAssemblyMCInstLower pass"); -#include "WebAssemblyGenStackifier.inc" - } -} Index: utils/TableGen/CMakeLists.txt =================================================================== --- utils/TableGen/CMakeLists.txt +++ utils/TableGen/CMakeLists.txt @@ -46,7 +46,6 @@ X86ModRMFilters.cpp X86RecognizableInstr.cpp WebAssemblyDisassemblerEmitter.cpp - WebAssemblyStackifierEmitter.cpp CTagsEmitter.cpp ) set_target_properties(llvm-tblgen PROPERTIES FOLDER "Tablegenning") Index: utils/TableGen/TableGen.cpp =================================================================== --- utils/TableGen/TableGen.cpp +++ utils/TableGen/TableGen.cpp @@ -53,7 +53,6 @@ GenX86EVEX2VEXTables, GenX86FoldTables, GenRegisterBank, - GenWebAssemblyStackifier, }; namespace { @@ -118,9 +117,7 @@ clEnumValN(GenX86FoldTables, "gen-x86-fold-tables", "Generate X86 fold tables"), clEnumValN(GenRegisterBank, "gen-register-bank", - "Generate registers bank descriptions"), - clEnumValN(GenWebAssemblyStackifier, "gen-wasm-stackifier", - "Generate WebAssembly stackification cases"))); + "Generate registers bank descriptions"))); cl::OptionCategory PrintEnumsCat("Options for -print-enums"); cl::opt @@ -234,9 +231,6 @@ case GenX86FoldTables: EmitX86FoldTables(Records, OS); break; - case GenWebAssemblyStackifier: - EmitWebAssemblyStackifier(Records, OS); - break; } return false; Index: utils/TableGen/TableGenBackends.h =================================================================== --- utils/TableGen/TableGenBackends.h +++ utils/TableGen/TableGenBackends.h @@ -89,7 +89,6 @@ void EmitX86EVEX2VEXTables(RecordKeeper &RK, raw_ostream &OS); void EmitX86FoldTables(RecordKeeper &RK, raw_ostream &OS); void EmitRegisterBank(RecordKeeper &RK, raw_ostream &OS); -void EmitWebAssemblyStackifier(RecordKeeper &RK, raw_ostream &OS); } // End llvm namespace Index: utils/TableGen/WebAssemblyDisassemblerEmitter.cpp =================================================================== --- utils/TableGen/WebAssemblyDisassemblerEmitter.cpp +++ utils/TableGen/WebAssemblyDisassemblerEmitter.cpp @@ -42,12 +42,13 @@ auto Prefix = Opc >> 8; Opc = Opc & 0xFF; auto &CGIP = OpcodeTable[Prefix][Opc]; - // All wasm instructions have a StackBased fieldof type bit, we only want - // the instructions for which this is 1. - auto Bit = Def.getValue("StackBased")->getValue()-> - getCastTo(BitRecTy::get()); - auto IsStackBased = Bit && reinterpret_cast(Bit) - ->getValue(); + // All wasm instructions have a StackBased field of type string, we only + // want the instructions for which this is "true". + auto StackString = + Def.getValue("StackBased")->getValue()->getCastTo(StringRecTy::get()); + auto IsStackBased = + StackString && + reinterpret_cast(StackString)->getValue() == "true"; if (IsStackBased && !CGIP.second) { // this picks the first of many typed variants, which is // currently the except_ref one, though this shouldn't matter for Index: utils/TableGen/WebAssemblyStackifierEmitter.cpp =================================================================== --- utils/TableGen/WebAssemblyStackifierEmitter.cpp +++ /dev/null @@ -1,44 +0,0 @@ -//===- WebAssemblyStackifierEmitter.cpp - Stackifier cases ------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file emits the switch statement cases to translate WebAssembly -// instructions to their stack forms. -// -//===----------------------------------------------------------------------===// - -#include "WebAssemblyDisassemblerEmitter.h" -#include "llvm/TableGen/Record.h" - -namespace llvm { - -// Find all register WebAssembly instructions and their corresponding stack -// instructions. For each pair, emit a switch case of the form -// -// case WebAssembly::RegisterInstr: return WebAssembly::StackInstr; -// -// For example, -// -// case WebAssembly::ADD_I32: return WebAssembly::ADD_I32_S; -// -// This is useful for converting instructions from their register form to their -// equivalent stack form. -void EmitWebAssemblyStackifier(RecordKeeper &RK, raw_ostream &OS) { - Record *InstrClass = RK.getClass("WebAssemblyInst"); - for (auto &RecordPair : RK.getDefs()) { - if (!RecordPair.second->isSubClassOf(InstrClass)) - continue; - bool IsStackBased = RecordPair.second->getValueAsBit("StackBased"); - if (IsStackBased) - continue; - OS << " case WebAssembly::" << RecordPair.first << ": return " - << "WebAssembly::" << RecordPair.first << "_S;\n"; - } -} - -} // namespace llvm