diff options
| -rw-r--r-- | llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td | 16 | ||||
| -rw-r--r-- | llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td | 4 | ||||
| -rw-r--r-- | llvm/lib/Target/WebAssembly/WebAssemblyInstrFormats.td | 3 | ||||
| -rw-r--r-- | llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td | 10 | ||||
| -rw-r--r-- | llvm/test/MC/Disassembler/WebAssembly/wasm.txt | 11 | ||||
| -rw-r--r-- | llvm/test/MC/WebAssembly/objdump.s | 4 | ||||
| -rw-r--r-- | llvm/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp | 31 |
7 files changed, 59 insertions, 20 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td index a4efa85aadf..6b7c9b24ddc 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td @@ -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. diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td index 8160cab7520..59faeb88c5e 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td @@ -81,6 +81,10 @@ defm ELSE : NRI<(outs), (ins), [], "else", 0x05>; 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] diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrFormats.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrFormats.td index 2a2c79c56d6..aff4d20d8d8 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrFormats.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrFormats.td @@ -22,6 +22,9 @@ class WebAssemblyInst<bits<32> inst, string asmstr, string stack> : StackRel, 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. diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td index ab0f48c9a1e..71c469d755b 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td @@ -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)), diff --git a/llvm/test/MC/Disassembler/WebAssembly/wasm.txt b/llvm/test/MC/Disassembler/WebAssembly/wasm.txt index 2632f231cec..8a119fb6b0f 100644 --- a/llvm/test/MC/Disassembler/WebAssembly/wasm.txt +++ b/llvm/test/MC/Disassembler/WebAssembly/wasm.txt @@ -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 diff --git a/llvm/test/MC/WebAssembly/objdump.s b/llvm/test/MC/WebAssembly/objdump.s index d156ec60eef..f1cedc7db86 100644 --- a/llvm/test/MC/WebAssembly/objdump.s +++ b/llvm/test/MC/WebAssembly/objdump.s @@ -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 diff --git a/llvm/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp b/llvm/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp index 249be3b1b95..9f5ae70f836 100644 --- a/llvm/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp +++ b/llvm/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp @@ -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"; |

