[llvm] r353131 - [WebAssembly] Make disassembler always emit most canonical name.

Wouter van Oortmerssen via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 4 17:19:45 PST 2019


Author: aardappel
Date: Mon Feb  4 17:19:45 2019
New Revision: 353131

URL: http://llvm.org/viewvc/llvm-project?rev=353131&view=rev
Log:
[WebAssembly] Make disassembler always emit most canonical name.

Summary:
There are a few instructions that all map to the same opcode, so
when disassembling, we have to pick one. That was just the first one
before (the except_ref variant in the case of "call"), now it is the
one marked as IsCanonical in tablegen, or failing that, the shortest
name (which is typically the "canonical" one).

Also introduced a canonical "end" instruction for this purpose.

Reviewers: dschuff, tlively

Subscribers: sbc100, jgravelle-google, aheejin, llvm-commits, sunfish

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D57713

Modified:
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrCall.td
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrControl.td
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrFormats.td
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
    llvm/trunk/test/MC/Disassembler/WebAssembly/wasm.txt
    llvm/trunk/test/MC/WebAssembly/objdump.s
    llvm/trunk/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrCall.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrCall.td?rev=353131&r1=353130&r2=353131&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrCall.td (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrCall.td Mon Feb  4 17:19:45 2019
@@ -93,17 +93,18 @@ let Uses = [SP32, SP64], isCall = 1 in {
   defm "" : SIMD_CALL<v4f32, "v128.">;
   defm "" : SIMD_CALL<v2f64, "v128.">;
 
+  let IsCanonical = 1 in {
   defm CALL_VOID : I<(outs), (ins function32_op:$callee, variable_ops),
-                     (outs), (ins function32_op:$callee),
-                     [(WebAssemblycall0 (i32 imm:$callee))],
-                     "call    \t$callee", "call\t$callee", 0x10>;
+                    (outs), (ins function32_op:$callee),
+                    [(WebAssemblycall0 (i32 imm:$callee))],
+                    "call    \t$callee", "call\t$callee", 0x10>;
 
   let isCodeGenOnly = 1 in {
     defm PCALL_INDIRECT_VOID : I<(outs), (ins I32:$callee, variable_ops),
-                                 (outs), (ins I32:$callee),
-                                 [(WebAssemblycall0 I32:$callee)],
-                                 "PSEUDO CALL INDIRECT\t$callee",
-                                 "PSEUDO CALL INDIRECT\t$callee">;
+                                (outs), (ins I32:$callee),
+                                [(WebAssemblycall0 I32:$callee)],
+                                "PSEUDO CALL INDIRECT\t$callee",
+                                "PSEUDO CALL INDIRECT\t$callee">;
   } // isCodeGenOnly = 1
 
   defm CALL_INDIRECT_VOID : I<(outs),
@@ -113,6 +114,7 @@ let Uses = [SP32, SP64], isCall = 1 in {
                               [],
                               "call_indirect\t", "call_indirect\t$type",
                               0x11>;
+  }
 } // Uses = [SP32,SP64], isCall = 1
 
 // Patterns for matching a direct call to a global address.

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrControl.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrControl.td?rev=353131&r1=353130&r2=353131&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrControl.td (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrControl.td Mon Feb  4 17:19:45 2019
@@ -81,6 +81,10 @@ defm ELSE : NRI<(outs), (ins), [], "else
 defm END_BLOCK : NRI<(outs), (ins), [], "end_block", 0x0b>;
 defm END_LOOP  : NRI<(outs), (ins), [], "end_loop", 0x0b>;
 defm END_IF    : NRI<(outs), (ins), [], "end_if", 0x0b>;
+// Generic instruction, for disassembler.
+let IsCanonical = 1 in {
+defm END       : NRI<(outs), (ins), [], "end", 0x0b>;
+}
 let isTerminator = 1, isBarrier = 1 in
 defm END_FUNCTION : NRI<(outs), (ins), [], "end_function", 0x0b>;
 } // Uses = [VALUE_STACK], Defs = [VALUE_STACK]

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrFormats.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrFormats.td?rev=353131&r1=353130&r2=353131&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrFormats.td (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrFormats.td Mon Feb  4 17:19:45 2019
@@ -22,6 +22,9 @@ class WebAssemblyInst<bits<32> inst, str
   let Namespace   = "WebAssembly";
   let Pattern     = [];
   let AsmString   = asmstr;
+  // When there are multiple instructions that map to the same encoding (in
+  // e.g. the disassembler use case) prefer the one where IsCanonical == 1.
+  bit IsCanonical = 0;
 }
 
 // Normal instructions. Default instantiation of a WebAssemblyInst.

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td?rev=353131&r1=353130&r2=353131&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td Mon Feb  4 17:19:45 2019
@@ -125,12 +125,14 @@ defm "" : ConstVec<v8i16,
                      ImmI16:$i0, ImmI16:$i1, ImmI16:$i2, ImmI16:$i3,
                      ImmI16:$i4, ImmI16:$i5, ImmI16:$i6, ImmI16:$i7),
                    "$i0, $i1, $i2, $i3, $i4, $i5, $i6, $i7">;
+let IsCanonical = 1 in {
 defm "" : ConstVec<v4i32,
-                   (ins vec_i32imm_op:$i0, vec_i32imm_op:$i1,
+                  (ins vec_i32imm_op:$i0, vec_i32imm_op:$i1,
                         vec_i32imm_op:$i2, vec_i32imm_op:$i3),
-                   (build_vector (i32 imm:$i0), (i32 imm:$i1),
-                                 (i32 imm:$i2), (i32 imm:$i3)),
-                   "$i0, $i1, $i2, $i3">;
+                  (build_vector (i32 imm:$i0), (i32 imm:$i1),
+                                (i32 imm:$i2), (i32 imm:$i3)),
+                  "$i0, $i1, $i2, $i3">;
+}
 defm "" : ConstVec<v2i64,
                    (ins vec_i64imm_op:$i0, vec_i64imm_op:$i1),
                    (build_vector (i64 imm:$i0), (i64 imm:$i1)),

Modified: llvm/trunk/test/MC/Disassembler/WebAssembly/wasm.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/WebAssembly/wasm.txt?rev=353131&r1=353130&r2=353131&view=diff
==============================================================================
--- llvm/trunk/test/MC/Disassembler/WebAssembly/wasm.txt (original)
+++ llvm/trunk/test/MC/Disassembler/WebAssembly/wasm.txt Mon Feb  4 17:19:45 2019
@@ -22,6 +22,10 @@
 # FIXME: WebAssemblyInstPrinter does not print immediates.
 0x11 0x80 0x01 0x00
 
+# CHECK: call 0
+# CHECK-NOT: except_ref.call 0
+0x10 0x00
+
 # CHECK: local.get 128
 0x20 0x80 0x01
 
@@ -29,8 +33,7 @@
 # CHECK: i64.trunc_sat_f64_u
 0xFC 0x07
 
-# v128.const is arbitrarily disassembled as v16i8
-# CHECK: v128.const 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+# CHECK: v128.const 50462976, 117835012, 185207048, 252579084
 0xFD 0x02 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F
 
 # CHECK: v8x16.shuffle 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
@@ -48,3 +51,7 @@
 # Check br_table, which has its own operand type.
 # CHECK: br_table {0, 1, 2}
 0x0E 0x02 0x00 0x01 0x02
+
+# This can mean end_block/end_loop/end_if/end_function/end_try..
+# CHECK: end
+0x0B

Modified: llvm/trunk/test/MC/WebAssembly/objdump.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/WebAssembly/objdump.s?rev=353131&r1=353130&r2=353131&view=diff
==============================================================================
--- llvm/trunk/test/MC/WebAssembly/objdump.s (original)
+++ llvm/trunk/test/MC/WebAssembly/objdump.s Mon Feb  4 17:19:45 2019
@@ -19,8 +19,8 @@ test1:
 # CHECK-LABEL: test0:
 # CHECK-NEXT:        .local  f32, f64, v128, v128
 # CHECK-NEXT:       9:       20 02  local.get	2
-# CHECK-NEXT:       b:       0b     end_block
+# CHECK-NEXT:       b:       0b     end
 # CHECK-LABEL: test1:
 # CHECK-NEXT:        .local  i32, i64, except_ref
 # CHECK-NEXT:      14:       20 03  local.get	3
-# CHECK-NEXT:      16:       0b     end_block
+# CHECK-NEXT:      16:       0b     end

Modified: llvm/trunk/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp?rev=353131&r1=353130&r2=353131&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp Mon Feb  4 17:19:45 2019
@@ -50,12 +50,33 @@ void emitWebAssemblyDisassemblerTables(
     auto IsStackBased =
         StackString &&
         reinterpret_cast<const StringInit *>(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
-      // disassembly purposes.
-      CGIP = std::make_pair(I, &CGI);
+    if (!IsStackBased)
+      continue;
+    if (CGIP.second) {
+      // We already have an instruction for this slot, so decide which one
+      // should be the canonical one. This determines which variant gets
+      // printed in a disassembly. We want e.g. "call" not "i32.call", and
+      // "end" when we don't know if its "end_loop" or "end_block" etc.
+      auto IsCanonicalExisting = CGIP.second->TheDef->getValue("IsCanonical")
+                                     ->getValue()
+                                     ->getAsString() == "1";
+      // We already have one marked explicitly as canonical, so keep it.
+      if (IsCanonicalExisting)
+        continue;
+      auto IsCanonicalNew =
+          Def.getValue("IsCanonical")->getValue()->getAsString() == "1";
+      // If the new one is explicitly marked as canonical, take it.
+      if (!IsCanonicalNew) {
+        // Neither the existing or new instruction is canonical.
+        // Pick the one with with the shortest name as heuristic.
+        // Though ideally IsCanonical is always defined for at least one
+        // variant so this never has to apply.
+        if (CGIP.second->AsmString.size() <= CGI.AsmString.size())
+          continue;
+      }
     }
+    // Set this instruction as the one to use.
+    CGIP = std::make_pair(I, &CGI);
   }
   OS << "#include \"MCTargetDesc/WebAssemblyMCTargetDesc.h\"\n";
   OS << "\n";




More information about the llvm-commits mailing list