From e410c02857a0d27c0877ee2ab36d7b9d3f7ed0e6 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 12 Jan 2016 01:45:12 +0000 Subject: [PATCH] [WebAssembly] Use TSFlags instead of keeping a list of special-case opcodes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@257433 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../InstPrinter/WebAssemblyInstPrinter.cpp | 32 +++++++++++++------ .../MCTargetDesc/WebAssemblyMCTargetDesc.h | 11 +++++++ .../WebAssembly/WebAssemblyInstrControl.td | 9 ++++-- .../WebAssembly/WebAssemblyInstrInfo.td | 17 ++++++++-- 4 files changed, 54 insertions(+), 15 deletions(-) diff --git a/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp b/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp index 7ce3a00ae36..f92a9d0c661 100644 --- a/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp +++ b/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp @@ -82,6 +82,9 @@ void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) { const MCOperand &Op = MI->getOperand(OpNo); if (Op.isReg()) { + assert((OpNo < MII.get(MI->getOpcode()).getNumOperands() || + MII.get(MI->getOpcode()).TSFlags == 0) && + "WebAssembly variable_ops register ops don't use TSFlags"); unsigned WAReg = Op.getReg(); if (int(WAReg) >= 0) printRegName(O, WAReg); @@ -95,19 +98,28 @@ void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, if (OpNo < MII.get(MI->getOpcode()).getNumDefs()) O << '='; } else if (Op.isImm()) { - switch (MI->getOpcode()) { - case WebAssembly::PARAM: - case WebAssembly::RESULT: - case WebAssembly::LOCAL: + assert((OpNo < MII.get(MI->getOpcode()).getNumOperands() || + (MII.get(MI->getOpcode()).TSFlags & + WebAssemblyII::VariableOpIsImmediate)) && + "WebAssemblyII::VariableOpIsImmediate should be set for " + "variable_ops immediate ops"); + if (MII.get(MI->getOpcode()).TSFlags & + WebAssemblyII::VariableOpImmediateIsType) + // The immediates represent types. O << WebAssembly::TypeToString(MVT::SimpleValueType(Op.getImm())); - break; - default: + else O << Op.getImm(); - break; - } - } else if (Op.isFPImm()) + } else if (Op.isFPImm()) { + assert((OpNo < MII.get(MI->getOpcode()).getNumOperands() || + MII.get(MI->getOpcode()).TSFlags == 0) && + "WebAssembly variable_ops floating point ops don't use TSFlags"); O << toString(APFloat(Op.getFPImm())); - else { + } else { + assert((OpNo < MII.get(MI->getOpcode()).getNumOperands() || + (MII.get(MI->getOpcode()).TSFlags & + WebAssemblyII::VariableOpIsImmediate)) && + "WebAssemblyII::VariableOpIsImmediate should be set for " + "variable_ops expr ops"); assert(Op.isExpr() && "unknown operand kind in printOperand"); Op.getExpr()->print(O, &MAI); } diff --git a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h index 1d3a7078a45..06f3ea7bf86 100644 --- a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h +++ b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h @@ -56,4 +56,15 @@ MCObjectWriter *createWebAssemblyELFObjectWriter(raw_pwrite_stream &OS, #define GET_SUBTARGETINFO_ENUM #include "WebAssemblyGenSubtargetInfo.inc" +namespace WebAssemblyII { +enum { + // For variadic instructions, this flag indicates whether an operand + // in the variable_ops range is an immediate value. + VariableOpIsImmediate = (1 << 0), + // For immediate values in the variable_ops range, this flag indicates + // whether the value represents a type. + VariableOpImmediateIsType = (1 << 1), +}; +} // end namespace WebAssemblyII + #endif diff --git a/lib/Target/WebAssembly/WebAssemblyInstrControl.td b/lib/Target/WebAssembly/WebAssemblyInstrControl.td index 05efe890341..1c06b08597a 100644 --- a/lib/Target/WebAssembly/WebAssemblyInstrControl.td +++ b/lib/Target/WebAssembly/WebAssemblyInstrControl.td @@ -41,13 +41,18 @@ let Defs = [ARGUMENTS] in { // TODO: SelectionDAG's lowering insists on using a pointer as the index for // jump tables, so in practice we don't ever use TABLESWITCH_I64 in wasm32 mode // currently. +// Set TSFlags{0} to 1 to indicate that the variable_ops are immediates. let isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 in { def TABLESWITCH_I32 : I<(outs), (ins I32:$index, bb_op:$default, variable_ops), [(WebAssemblytableswitch I32:$index, bb:$default)], - "tableswitch\t$index, $default">; + "tableswitch\t$index, $default"> { + let TSFlags{0} = 1; +} def TABLESWITCH_I64 : I<(outs), (ins I64:$index, bb_op:$default, variable_ops), [(WebAssemblytableswitch I64:$index, bb:$default)], - "tableswitch\t$index, $default">; + "tableswitch\t$index, $default"> { + let TSFlags{0} = 1; +} } // isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 // Placemarkers to indicate the start of a block or loop scope. These diff --git a/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/lib/Target/WebAssembly/WebAssemblyInstrInfo.td index 061a253816e..dfa66cd2dc1 100644 --- a/lib/Target/WebAssembly/WebAssemblyInstrInfo.td +++ b/lib/Target/WebAssembly/WebAssemblyInstrInfo.td @@ -138,9 +138,20 @@ def : Pat<(i32 (WebAssemblywrapper texternalsym:$addr)), let Defs = [ARGUMENTS] in { // Function signature and local variable declaration "instructions". -def PARAM : I<(outs), (ins variable_ops), [], ".param \t">; -def RESULT : I<(outs), (ins variable_ops), [], ".result \t">; -def LOCAL : I<(outs), (ins variable_ops), [], ".local \t">; +// Set TSFlags{0} to 1 to indicate that the variable_ops are immediates. +// Set TSFlags{1} to 1 to indicate that the immediates represent types. +def PARAM : I<(outs), (ins variable_ops), [], ".param \t"> { + let TSFlags{0} = 1; + let TSFlags{1} = 1; +} +def RESULT : I<(outs), (ins variable_ops), [], ".result \t"> { + let TSFlags{0} = 1; + let TSFlags{1} = 1; +} +def LOCAL : I<(outs), (ins variable_ops), [], ".local \t"> { + let TSFlags{0} = 1; + let TSFlags{1} = 1; +} } // Defs = [ARGUMENTS] -- 2.34.1