[WebAssembly] Use TSFlags instead of keeping a list of special-case opcodes.
authorDan Gohman <dan433584@gmail.com>
Tue, 12 Jan 2016 01:45:12 +0000 (01:45 +0000)
committerDan Gohman <dan433584@gmail.com>
Tue, 12 Jan 2016 01:45:12 +0000 (01:45 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@257433 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp
lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
lib/Target/WebAssembly/WebAssemblyInstrControl.td
lib/Target/WebAssembly/WebAssemblyInstrInfo.td

index 7ce3a00ae360efb6e3d7007901685f25524f8f6a..f92a9d0c6615f2e99bfec7f408ebde2a8463d556 100644 (file)
@@ -82,6 +82,9 @@ void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
                                           raw_ostream &O) {
   const MCOperand &Op = MI->getOperand(OpNo);
   if (Op.isReg()) {
                                           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);
     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()) {
     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()));
       O << WebAssembly::TypeToString(MVT::SimpleValueType(Op.getImm()));
-      break;
-    default:
+    else
       O << Op.getImm();
       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()));
     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);
   }
     assert(Op.isExpr() && "unknown operand kind in printOperand");
     Op.getExpr()->print(O, &MAI);
   }
index 1d3a7078a45737ee3c016393e6356274d21eeb7c..06f3ea7bf86eb66ecfe271f59bb9417760f7ef9a 100644 (file)
@@ -56,4 +56,15 @@ MCObjectWriter *createWebAssemblyELFObjectWriter(raw_pwrite_stream &OS,
 #define GET_SUBTARGETINFO_ENUM
 #include "WebAssemblyGenSubtargetInfo.inc"
 
 #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
 #endif
index 05efe8903413e552a954636c49beff30ed13ff67..1c06b08597a014adea9f531dffa7dd1deb66acf5 100644 (file)
@@ -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.
 // 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)],
 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)],
 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
 } // isTerminator = 1, hasCtrlDep = 1, isBarrier = 1
 
 // Placemarkers to indicate the start of a block or loop scope. These
index 061a253816e4a07ec129f8f90d558396f96f5d90..dfa66cd2dc1d15b0724a4cac05e64f6baed41578 100644 (file)
@@ -138,9 +138,20 @@ def : Pat<(i32 (WebAssemblywrapper texternalsym:$addr)),
 let Defs = [ARGUMENTS] in {
 
 // Function signature and local variable declaration "instructions".
 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]
 
 
 } // Defs = [ARGUMENTS]