diff options
| author | Wouter van Oortmerssen <aardappel@gmail.com> | 2018-06-18 21:22:44 +0000 |
|---|---|---|
| committer | Wouter van Oortmerssen <aardappel@gmail.com> | 2018-06-18 21:22:44 +0000 |
| commit | 48dac3109e40e8870b454edf253e308d76625823 (patch) | |
| tree | 56ccbb99fd9ce98b55dc3e1880016f8cea85ff30 | |
| parent | 932ba20af8742b2cf47ee8e3fa0e05e1c3a895de (diff) | |
| download | bcm5719-llvm-48dac3109e40e8870b454edf253e308d76625823.tar.gz bcm5719-llvm-48dac3109e40e8870b454edf253e308d76625823.zip | |
[WebAssembly] Modified tablegen defs to have 2 parallel instuction sets.
Summary:
One for register based, much like the existing definitions,
and one for stack based (suffix _S).
This allows us to use registers in most of LLVM (which works better),
and stack based in MC (which results in a simpler and more readable
assembler / disassembler).
Tried to keep this change as small as possible while passing tests,
follow-up commit will:
- Add reg->stack conversion in MI.
- Fix asm/disasm in MC to be stack based.
- Fix emitter to be stack based.
tests passing:
llvm-lit -v `find test -name WebAssembly`
test/CodeGen/WebAssembly
test/MC/WebAssembly
test/MC/Disassembler/WebAssembly
test/DebugInfo/WebAssembly
test/CodeGen/MIR/WebAssembly
test/tools/llvm-objdump/WebAssembly
Reviewers: dschuff, sbc100, jgravelle-google, sunfish
Subscribers: aheejin, JDevlieghere, llvm-commits
Differential Revision: https://reviews.llvm.org/D48183
llvm-svn: 334985
12 files changed, 640 insertions, 425 deletions
diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h index 8a51221a2a0..cc22a11133a 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h @@ -109,38 +109,68 @@ namespace WebAssembly { inline unsigned GetDefaultP2Align(unsigned Opcode) { switch (Opcode) { case WebAssembly::LOAD8_S_I32: + case WebAssembly::LOAD8_S_I32_S: case WebAssembly::LOAD8_U_I32: + case WebAssembly::LOAD8_U_I32_S: case WebAssembly::LOAD8_S_I64: + case WebAssembly::LOAD8_S_I64_S: case WebAssembly::LOAD8_U_I64: + case WebAssembly::LOAD8_U_I64_S: case WebAssembly::ATOMIC_LOAD8_U_I32: + case WebAssembly::ATOMIC_LOAD8_U_I32_S: case WebAssembly::ATOMIC_LOAD8_U_I64: + case WebAssembly::ATOMIC_LOAD8_U_I64_S: case WebAssembly::STORE8_I32: + case WebAssembly::STORE8_I32_S: case WebAssembly::STORE8_I64: + case WebAssembly::STORE8_I64_S: return 0; case WebAssembly::LOAD16_S_I32: + case WebAssembly::LOAD16_S_I32_S: case WebAssembly::LOAD16_U_I32: + case WebAssembly::LOAD16_U_I32_S: case WebAssembly::LOAD16_S_I64: + case WebAssembly::LOAD16_S_I64_S: case WebAssembly::LOAD16_U_I64: + case WebAssembly::LOAD16_U_I64_S: case WebAssembly::ATOMIC_LOAD16_U_I32: + case WebAssembly::ATOMIC_LOAD16_U_I32_S: case WebAssembly::ATOMIC_LOAD16_U_I64: + case WebAssembly::ATOMIC_LOAD16_U_I64_S: case WebAssembly::STORE16_I32: + case WebAssembly::STORE16_I32_S: case WebAssembly::STORE16_I64: + case WebAssembly::STORE16_I64_S: return 1; case WebAssembly::LOAD_I32: + case WebAssembly::LOAD_I32_S: case WebAssembly::LOAD_F32: + case WebAssembly::LOAD_F32_S: case WebAssembly::STORE_I32: + case WebAssembly::STORE_I32_S: case WebAssembly::STORE_F32: + case WebAssembly::STORE_F32_S: case WebAssembly::LOAD32_S_I64: + case WebAssembly::LOAD32_S_I64_S: case WebAssembly::LOAD32_U_I64: + case WebAssembly::LOAD32_U_I64_S: case WebAssembly::STORE32_I64: + case WebAssembly::STORE32_I64_S: case WebAssembly::ATOMIC_LOAD_I32: + case WebAssembly::ATOMIC_LOAD_I32_S: case WebAssembly::ATOMIC_LOAD32_U_I64: + case WebAssembly::ATOMIC_LOAD32_U_I64_S: return 2; case WebAssembly::LOAD_I64: + case WebAssembly::LOAD_I64_S: case WebAssembly::LOAD_F64: + case WebAssembly::LOAD_F64_S: case WebAssembly::STORE_I64: + case WebAssembly::STORE_I64_S: case WebAssembly::STORE_F64: + case WebAssembly::STORE_F64_S: case WebAssembly::ATOMIC_LOAD_I64: + case WebAssembly::ATOMIC_LOAD_I64_S: return 3; default: llvm_unreachable("Only loads and stores have p2align values"); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrAtomics.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrAtomics.td index 9f6cfa37356..15e48d3b33c 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrAtomics.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrAtomics.td @@ -17,8 +17,8 @@ //===----------------------------------------------------------------------===// let Defs = [ARGUMENTS] in { -def ATOMIC_LOAD_I32 : WebAssemblyLoad<I32, "i32.atomic.load", 0xfe10>; -def ATOMIC_LOAD_I64 : WebAssemblyLoad<I64, "i64.atomic.load", 0xfe11>; +defm ATOMIC_LOAD_I32 : WebAssemblyLoad<I32, "i32.atomic.load", 0xfe10>; +defm ATOMIC_LOAD_I64 : WebAssemblyLoad<I64, "i64.atomic.load", 0xfe11>; } // Defs = [ARGUMENTS] // Select loads with no constant offset. @@ -56,11 +56,11 @@ def : LoadPatExternSymOffOnly<i64, atomic_load_64, ATOMIC_LOAD_I64>; // Extending loads. Note that there are only zero-extending atomic loads, no // sign-extending loads. let Defs = [ARGUMENTS] in { -def ATOMIC_LOAD8_U_I32 : WebAssemblyLoad<I32, "i32.atomic.load8_u", 0xfe12>; -def ATOMIC_LOAD16_U_I32 : WebAssemblyLoad<I32, "i32.atomic.load16_u", 0xfe13>; -def ATOMIC_LOAD8_U_I64 : WebAssemblyLoad<I64, "i64.atomic.load8_u", 0xfe14>; -def ATOMIC_LOAD16_U_I64 : WebAssemblyLoad<I64, "i64.atomic.load16_u", 0xfe15>; -def ATOMIC_LOAD32_U_I64 : WebAssemblyLoad<I64, "i64.atomic.load32_u", 0xfe16>; +defm ATOMIC_LOAD8_U_I32 : WebAssemblyLoad<I32, "i32.atomic.load8_u", 0xfe12>; +defm ATOMIC_LOAD16_U_I32 : WebAssemblyLoad<I32, "i32.atomic.load16_u", 0xfe13>; +defm ATOMIC_LOAD8_U_I64 : WebAssemblyLoad<I64, "i64.atomic.load8_u", 0xfe14>; +defm ATOMIC_LOAD16_U_I64 : WebAssemblyLoad<I64, "i64.atomic.load16_u", 0xfe15>; +defm ATOMIC_LOAD32_U_I64 : WebAssemblyLoad<I64, "i64.atomic.load32_u", 0xfe16>; } // Defs = [ARGUMENTS] // Fragments for exending loads. These are different from regular loads because diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td index 7c09beacbdd..34262752430 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td @@ -13,57 +13,72 @@ //===----------------------------------------------------------------------===// // TODO: addr64: These currently assume the callee address is 32-bit. +// FIXME: add $type to first call_indirect asmstr (and maybe $flags) let Defs = [ARGUMENTS] in { // Call sequence markers. These have an immediate which represents the amount of // stack space to allocate or free, which is used for varargs lowering. let Uses = [SP32, SP64], Defs = [SP32, SP64], isCodeGenOnly = 1 in { -def ADJCALLSTACKDOWN : I<(outs), (ins i32imm:$amt, i32imm:$amt2), - [(WebAssemblycallseq_start timm:$amt, timm:$amt2)]>; -def ADJCALLSTACKUP : I<(outs), (ins i32imm:$amt, i32imm:$amt2), - [(WebAssemblycallseq_end timm:$amt, timm:$amt2)]>; +defm ADJCALLSTACKDOWN : NRI<(outs), (ins i32imm:$amt, i32imm:$amt2), + [(WebAssemblycallseq_start timm:$amt, timm:$amt2)]>; +defm ADJCALLSTACKUP : NRI<(outs), (ins i32imm:$amt, i32imm:$amt2), + [(WebAssemblycallseq_end timm:$amt, timm:$amt2)]>; } // isCodeGenOnly = 1 multiclass CALL<WebAssemblyRegClass vt, string prefix> { - def CALL_#vt : I<(outs vt:$dst), (ins function32_op:$callee, variable_ops), - [(set vt:$dst, (WebAssemblycall1 (i32 imm:$callee)))], - !strconcat(prefix, "call\t$dst, $callee"), - 0x10>; + defm CALL_#vt : I<(outs vt:$dst), (ins function32_op:$callee, variable_ops), + (outs), (ins function32_op:$callee), + [(set vt:$dst, (WebAssemblycall1 (i32 imm:$callee)))], + !strconcat(prefix, "call\t$dst, $callee"), + !strconcat(prefix, "call\t$callee"), + 0x10>; let isCodeGenOnly = 1 in { - def PCALL_INDIRECT_#vt : I<(outs vt:$dst), (ins I32:$callee, variable_ops), - [(set vt:$dst, (WebAssemblycall1 I32:$callee))], - "PSEUDO CALL INDIRECT\t$callee">; + defm PCALL_INDIRECT_#vt : I<(outs vt:$dst), (ins I32:$callee, variable_ops), + (outs), (ins I32:$callee), + [(set vt:$dst, (WebAssemblycall1 I32:$callee))], + "PSEUDO CALL INDIRECT\t$callee", + "PSEUDO CALL INDIRECT\t$callee">; } // isCodeGenOnly = 1 - def CALL_INDIRECT_#vt : I<(outs vt:$dst), - (ins TypeIndex:$type, i32imm:$flags, variable_ops), - [], - !strconcat(prefix, "call_indirect\t$dst"), - 0x11>; + defm CALL_INDIRECT_#vt : I<(outs vt:$dst), + (ins TypeIndex:$type, i32imm:$flags, variable_ops), + (outs), (ins TypeIndex:$type, i32imm:$flags), + [], + !strconcat(prefix, "call_indirect\t$dst"), + !strconcat(prefix, "call_indirect\t$type"), + 0x11>; } multiclass SIMD_CALL<ValueType vt, string prefix> { - def CALL_#vt : SIMD_I<(outs V128:$dst), (ins function32_op:$callee, variable_ops), + defm CALL_#vt : SIMD_I<(outs V128:$dst), (ins function32_op:$callee, + variable_ops), + (outs), (ins function32_op:$callee), [(set (vt V128:$dst), - (WebAssemblycall1 (i32 imm:$callee)))], + (WebAssemblycall1 (i32 imm:$callee)))], !strconcat(prefix, "call\t$dst, $callee"), + !strconcat(prefix, "call\t$callee"), 0x10>; let isCodeGenOnly = 1 in { - def PCALL_INDIRECT_#vt : SIMD_I<(outs V128:$dst), - (ins I32:$callee, variable_ops), - [(set (vt V128:$dst), - (WebAssemblycall1 I32:$callee))], - "PSEUDO CALL INDIRECT\t$callee">; + defm PCALL_INDIRECT_#vt : SIMD_I<(outs V128:$dst), + (ins I32:$callee, variable_ops), + (outs), (ins I32:$callee), + [(set (vt V128:$dst), + (WebAssemblycall1 I32:$callee))], + "PSEUDO CALL INDIRECT\t$callee", + "PSEUDO CALL INDIRECT\t$callee">; } // isCodeGenOnly = 1 - def CALL_INDIRECT_#vt : SIMD_I<(outs V128:$dst), + defm CALL_INDIRECT_#vt : SIMD_I<(outs V128:$dst), (ins TypeIndex:$type, i32imm:$flags, - variable_ops), + variable_ops), + (outs), (ins TypeIndex:$type, i32imm:$flags), [], - !strconcat(prefix, "call_indirect\t$dst"), + !strconcat(prefix, + "call_indirect\t$dst"), + !strconcat(prefix, "call_indirect\t$type"), 0x11>; } @@ -78,20 +93,26 @@ let Uses = [SP32, SP64], isCall = 1 in { defm "" : SIMD_CALL<v4i32, "i32x4.">; defm "" : SIMD_CALL<v4f32, "f32x4.">; - def CALL_VOID : I<(outs), (ins function32_op:$callee, variable_ops), - [(WebAssemblycall0 (i32 imm:$callee))], - "call \t$callee", 0x10>; + 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>; let isCodeGenOnly = 1 in { - def PCALL_INDIRECT_VOID : I<(outs), (ins I32:$callee, variable_ops), - [(WebAssemblycall0 I32:$callee)], - "PSEUDO CALL INDIRECT\t$callee">; + 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">; } // isCodeGenOnly = 1 - def CALL_INDIRECT_VOID : I<(outs), - (ins TypeIndex:$type, i32imm:$flags, variable_ops), - [], - "call_indirect\t", 0x11>; + defm CALL_INDIRECT_VOID : I<(outs), + (ins TypeIndex:$type, i32imm:$flags, + variable_ops), + (outs), (ins TypeIndex:$type, i32imm:$flags), + [], + "call_indirect\t", "call_indirect\t$type", + 0x11>; } // Uses = [SP32,SP64], isCall = 1 } // Defs = [ARGUMENTS] diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td index e9824e14ca3..93cc3198eb5 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td @@ -16,15 +16,17 @@ let Defs = [ARGUMENTS] in { let isBranch = 1, isTerminator = 1, hasCtrlDep = 1 in { // The condition operand is a boolean value which WebAssembly represents as i32. -def BR_IF : I<(outs), (ins bb_op:$dst, I32:$cond), - [(brcond I32:$cond, bb:$dst)], - "br_if \t$dst, $cond", 0x0d>; +defm BR_IF : I<(outs), (ins bb_op:$dst, I32:$cond), + (outs), (ins bb_op:$dst), + [(brcond I32:$cond, bb:$dst)], + "br_if \t$dst, $cond", "br_if \t$dst", 0x0d>; let isCodeGenOnly = 1 in -def BR_UNLESS : I<(outs), (ins bb_op:$dst, I32:$cond), []>; +defm BR_UNLESS : I<(outs), (ins bb_op:$dst, I32:$cond), + (outs), (ins bb_op:$dst), []>; let isBarrier = 1 in { -def BR : I<(outs), (ins bb_op:$dst), - [(br bb:$dst)], - "br \t$dst", 0x0c>; +defm BR : NRI<(outs), (ins bb_op:$dst), + [(br bb:$dst)], + "br \t$dst", 0x0c>; } // isBarrier = 1 } // isBranch = 1, isTerminator = 1, hasCtrlDep = 1 @@ -42,16 +44,30 @@ let Defs = [ARGUMENTS] in { // currently. // Set TSFlags{0} to 1 to indicate that the variable_ops are immediates. // Set TSFlags{1} to 1 to indicate that the immediates represent labels. +// FIXME: this can't inherit from I<> since there is no way to inherit from a +// multiclass and still have the let statements. let isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 in { -def BR_TABLE_I32 : I<(outs), (ins I32:$index, variable_ops), - [(WebAssemblybr_table I32:$index)], - "br_table \t$index", 0x0e> { +def BR_TABLE_I32 : NI<(outs), (ins I32:$index, variable_ops), + [(WebAssemblybr_table I32:$index)], 0, + "br_table \t$index", 0x0e> { let TSFlags{0} = 1; let TSFlags{1} = 1; } -def BR_TABLE_I64 : I<(outs), (ins I64:$index, variable_ops), - [(WebAssemblybr_table I64:$index)], - "br_table \t$index"> { +def BR_TABLE_I32_S : NI<(outs), (ins I32:$index), + [], 1, + "br_table \t$index", 0x0e> { + let TSFlags{0} = 1; + let TSFlags{1} = 1; +} +def BR_TABLE_I64 : NI<(outs), (ins I64:$index, variable_ops), + [(WebAssemblybr_table I64:$index)], 0, + "br_table \t$index"> { + let TSFlags{0} = 1; + let TSFlags{1} = 1; +} +def BR_TABLE_I64_S : NI<(outs), (ins I64:$index), + [], 1, + "br_table \t$index"> { let TSFlags{0} = 1; let TSFlags{1} = 1; } @@ -59,40 +75,42 @@ def BR_TABLE_I64 : I<(outs), (ins I64:$index, variable_ops), // This is technically a control-flow instruction, since all it affects is the // IP. -def NOP : I<(outs), (ins), [], "nop", 0x01>; +defm NOP : NRI<(outs), (ins), [], "nop", 0x01>; // Placemarkers to indicate the start or end of a block or loop scope. // These use/clobber VALUE_STACK to prevent them from being moved into the // middle of an expression tree. let Uses = [VALUE_STACK], Defs = [VALUE_STACK] in { -def BLOCK : I<(outs), (ins Signature:$sig), [], "block \t$sig", 0x02>; -def LOOP : I<(outs), (ins Signature:$sig), [], "loop \t$sig", 0x03>; +defm BLOCK : NRI<(outs), (ins Signature:$sig), [], "block \t$sig", 0x02>; +defm LOOP : NRI<(outs), (ins Signature:$sig), [], "loop \t$sig", 0x03>; // END_BLOCK, END_LOOP, and END_FUNCTION are represented with the same opcode in // wasm. -def END_BLOCK : I<(outs), (ins), [], "end_block", 0x0b>; -def END_LOOP : I<(outs), (ins), [], "end_loop", 0x0b>; +defm END_BLOCK : NRI<(outs), (ins), [], "end_block", 0x0b>; +defm END_LOOP : NRI<(outs), (ins), [], "end_loop", 0x0b>; let isTerminator = 1, isBarrier = 1 in -def END_FUNCTION : I<(outs), (ins), [], "end_function", 0x0b>; +defm END_FUNCTION : NRI<(outs), (ins), [], "end_function", 0x0b>; } // Uses = [VALUE_STACK], Defs = [VALUE_STACK] multiclass RETURN<WebAssemblyRegClass vt> { - def RETURN_#vt : I<(outs), (ins vt:$val), [(WebAssemblyreturn vt:$val)], - "return \t$val", 0x0f>; + defm RETURN_#vt : I<(outs), (ins vt:$val), (outs), (ins), + [(WebAssemblyreturn vt:$val)], + "return \t$val", "return", 0x0f>; // Equivalent to RETURN_#vt, for use at the end of a function when wasm // semantics return by falling off the end of the block. let isCodeGenOnly = 1 in - def FALLTHROUGH_RETURN_#vt : I<(outs), (ins vt:$val), []>; + defm FALLTHROUGH_RETURN_#vt : I<(outs), (ins vt:$val), (outs), (ins), []>; } multiclass SIMD_RETURN<ValueType vt> { - def RETURN_#vt : SIMD_I<(outs), (ins V128:$val), - [(WebAssemblyreturn (vt V128:$val))], - "return \t$val", 0x0f>; + defm RETURN_#vt : SIMD_I<(outs), (ins V128:$val), (outs), (ins), + [(WebAssemblyreturn (vt V128:$val))], + "return \t$val", "return", 0x0f>; // Equivalent to RETURN_#vt, for use at the end of a function when wasm // semantics return by falling off the end of the block. let isCodeGenOnly = 1 in - def FALLTHROUGH_RETURN_#vt : SIMD_I<(outs), (ins V128:$val), []>; + defm FALLTHROUGH_RETURN_#vt : SIMD_I<(outs), (ins V128:$val), (outs), (ins), + []>; } let isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 in { @@ -108,14 +126,14 @@ let isReturn = 1 in { defm "": SIMD_RETURN<v4i32>; defm "": SIMD_RETURN<v4f32>; - def RETURN_VOID : I<(outs), (ins), [(WebAssemblyreturn)], "return", 0x0f>; + defm RETURN_VOID : NRI<(outs), (ins), [(WebAssemblyreturn)], "return", 0x0f>; // This is to RETURN_VOID what FALLTHROUGH_RETURN_#vt is to RETURN_#vt. let isCodeGenOnly = 1 in - def FALLTHROUGH_RETURN_VOID : I<(outs), (ins), []>; + defm FALLTHROUGH_RETURN_VOID : NRI<(outs), (ins), []>; } // isReturn = 1 -def UNREACHABLE : I<(outs), (ins), [(trap)], "unreachable", 0x00>; +defm UNREACHABLE : NRI<(outs), (ins), [(trap)], "unreachable", 0x00>; } // isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 //===----------------------------------------------------------------------===// @@ -124,31 +142,37 @@ def UNREACHABLE : I<(outs), (ins), [(trap)], "unreachable", 0x00>; // Throwing an exception: throw / rethrow let isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 in { -def THROW_I32 : I<(outs), (ins i32imm:$tag, I32:$val), - [(int_wasm_throw imm:$tag, I32:$val)], "throw \t$tag, $val", - 0x08>; -def THROW_I64 : I<(outs), (ins i32imm:$tag, I64:$val), - [(int_wasm_throw imm:$tag, I64:$val)], "throw \t$tag, $val", - 0x08>; -def RETHROW : I<(outs), (ins i32imm:$rel_depth), [], "rethrow \t$rel_depth", - 0x09>; +defm THROW_I32 : I<(outs), (ins i32imm:$tag, I32:$val), + (outs), (ins i32imm:$tag), + [(int_wasm_throw imm:$tag, I32:$val)], + "throw \t$tag, $val", "throw \t$tag", + 0x08>; +defm THROW_I64 : I<(outs), (ins i32imm:$tag, I64:$val), + (outs), (ins i32imm:$tag), + [(int_wasm_throw imm:$tag, I64:$val)], + "throw \t$tag, $val", "throw \t$tag", + 0x08>; +defm RETHROW : NRI<(outs), (ins i32imm:$rel_depth), [], "rethrow \t$rel_depth", + 0x09>; } // isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 // Region within which an exception is caught: try / end_try let Uses = [VALUE_STACK], Defs = [VALUE_STACK] in { -def TRY : I<(outs), (ins Signature:$sig), [], "try \t$sig", 0x06>; -def END_TRY : I<(outs), (ins), [], "end_try", 0x0b>; +defm TRY : NRI<(outs), (ins Signature:$sig), [], "try \t$sig", 0x06>; +defm END_TRY : NRI<(outs), (ins), [], "end_try", 0x0b>; } // Uses = [VALUE_STACK], Defs = [VALUE_STACK] // Catching an exception: catch / catch_all let hasCtrlDep = 1 in { -def CATCH_I32 : I<(outs I32:$dst), (ins i32imm:$tag), - [(set I32:$dst, (int_wasm_catch imm:$tag))], - "i32.catch \t$dst, $tag", 0x07>; -def CATCH_I64 : I<(outs I64:$dst), (ins i32imm:$tag), - [(set I64:$dst, (int_wasm_catch imm:$tag))], - "i64.catch \t$dst, $tag", 0x07>; -def CATCH_ALL : I<(outs), (ins), [], "catch_all", 0x05>; +defm CATCH_I32 : I<(outs I32:$dst), (ins i32imm:$tag), + (outs), (ins i32imm:$tag), + [(set I32:$dst, (int_wasm_catch imm:$tag))], + "i32.catch \t$dst, $tag", "i32.catch \t$tag", 0x07>; +defm CATCH_I64 : I<(outs I64:$dst), (ins i32imm:$tag), + (outs), (ins i32imm:$tag), + [(set I64:$dst, (int_wasm_catch imm:$tag))], + "i64.catch \t$dst, $tag", "i64.catch \t$tag", 0x07>; +defm CATCH_ALL : NRI<(outs), (ins), [], "catch_all", 0x05>; } // Pseudo instructions: cleanupret / catchret @@ -156,8 +180,8 @@ def CATCH_ALL : I<(outs), (ins), [], "catch_all", 0x05>; // in X86 is necessary for computing EH scope membership. let isTerminator = 1, hasSideEffects = 1, isBarrier = 1, hasCtrlDep = 1, isCodeGenOnly = 1, isReturn = 1 in { - def CLEANUPRET : I<(outs), (ins), [(cleanupret)], "", 0>; - def CATCHRET : I<(outs), (ins bb_op:$dst, bb_op:$from), + defm CLEANUPRET : NRI<(outs), (ins), [(cleanupret)], "", 0>; + defm CATCHRET : NRI<(outs), (ins bb_op:$dst, bb_op:$from), [(catchret bb:$dst, bb:$from)], "", 0>; } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrConv.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrConv.td index 90e278ba7a0..c89c1b54981 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrConv.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrConv.td @@ -15,33 +15,40 @@ let Defs = [ARGUMENTS] in { -def I32_WRAP_I64 : I<(outs I32:$dst), (ins I64:$src), +defm I32_WRAP_I64 : I<(outs I32:$dst), (ins I64:$src), (outs), (ins), [(set I32:$dst, (trunc I64:$src))], - "i32.wrap/i64\t$dst, $src", 0xa7>; + "i32.wrap/i64\t$dst, $src", "i32.wrap/i64", 0xa7>; -def I64_EXTEND_S_I32 : I<(outs I64:$dst), (ins I32:$src), +defm I64_EXTEND_S_I32 : I<(outs I64:$dst), (ins I32:$src), (outs), (ins), [(set I64:$dst, (sext I32:$src))], - "i64.extend_s/i32\t$dst, $src", 0xac>; -def I64_EXTEND_U_I32 : I<(outs I64:$dst), (ins I32:$src), - [(set I64:$dst, (zext I32:$src))], - "i64.extend_u/i32\t$dst, $src", 0xad>; + "i64.extend_s/i32\t$dst, $src", "i64.extend_s/i32", + 0xac>; +defm I64_EXTEND_U_I32 : I<(outs I64:$dst), (ins I32:$src), (outs), (ins), + [(set I64:$dst, (zext I32:$src))], + "i64.extend_u/i32\t$dst, $src", "i64.extend_u/i32", + 0xad>; let Predicates = [HasSignExt] in { -def I32_EXTEND8_S_I32 : I<(outs I32:$dst), (ins I32:$src), - [(set I32:$dst, (sext_inreg I32:$src, i8))], - "i32.extend8_s\t$dst, $src", 0xc0>; -def I32_EXTEND16_S_I32 : I<(outs I32:$dst), (ins I32:$src), - [(set I32:$dst, (sext_inreg I32:$src, i16))], - "i32.extend16_s\t$dst, $src", 0xc1>; -def I64_EXTEND8_S_I64 : I<(outs I64:$dst), (ins I64:$src), - [(set I64:$dst, (sext_inreg I64:$src, i8))], - "i64.extend8_s\t$dst, $src", 0xc2>; -def I64_EXTEND16_S_I64 : I<(outs I64:$dst), (ins I64:$src), - [(set I64:$dst, (sext_inreg I64:$src, i16))], - "i64.extend16_s\t$dst, $src", 0xc3>; -def I64_EXTEND32_S_I64 : I<(outs I64:$dst), (ins I64:$src), - [(set I64:$dst, (sext_inreg I64:$src, i32))], - "i64.extend32_s\t$dst, $src", 0xc4>; +defm I32_EXTEND8_S_I32 : I<(outs I32:$dst), (ins I32:$src), (outs), (ins), + [(set I32:$dst, (sext_inreg I32:$src, i8))], + "i32.extend8_s\t$dst, $src", "i32.extend8_s", + 0xc0>; +defm I32_EXTEND16_S_I32 : I<(outs I32:$dst), (ins I32:$src), (outs), (ins), + [(set I32:$dst, (sext_inreg I32:$src, i16))], + "i32.extend16_s\t$dst, $src", "i32.extend16_s", + 0xc1>; +defm I64_EXTEND8_S_I64 : I<(outs I64:$dst), (ins I64:$src), (outs), (ins), + [(set I64:$dst, (sext_inreg I64:$src, i8))], + "i64.extend8_s\t$dst, $src", "i64.extend8_s", + 0xc2>; +defm I64_EXTEND16_S_I64 : I<(outs I64:$dst), (ins I64:$src), (outs), (ins), + [(set I64:$dst, (sext_inreg I64:$src, i16))], + "i64.extend16_s\t$dst, $src", "i64.extend16_s", + 0xc3>; +defm I64_EXTEND32_S_I64 : I<(outs I64:$dst), (ins I64:$src), (outs), (ins), + [(set I64:$dst, (sext_inreg I64:$src, i32))], + "i64.extend32_s\t$dst, $src", "i64.extend32_s", + 0xc4>; } // Predicates = [HasSignExt] } // defs = [ARGUMENTS] @@ -55,131 +62,161 @@ let Defs = [ARGUMENTS] in { // Conversion from floating point to integer instructions which don't trap on // overflow or invalid. -def I32_TRUNC_S_SAT_F32 : I<(outs I32:$dst), (ins F32:$src), - [(set I32:$dst, (fp_to_sint F32:$src))], - "i32.trunc_s:sat/f32\t$dst, $src", 0xfc00>, - Requires<[HasNontrappingFPToInt]>; -def I32_TRUNC_U_SAT_F32 : I<(outs I32:$dst), (ins F32:$src), - [(set I32:$dst, (fp_to_uint F32:$src))], - "i32.trunc_u:sat/f32\t$dst, $src", 0xfc01>, - Requires<[HasNontrappingFPToInt]>; -def I64_TRUNC_S_SAT_F32 : I<(outs I64:$dst), (ins F32:$src), - [(set I64:$dst, (fp_to_sint F32:$src))], - "i64.trunc_s:sat/f32\t$dst, $src", 0xfc04>, - Requires<[HasNontrappingFPToInt]>; -def I64_TRUNC_U_SAT_F32 : I<(outs I64:$dst), (ins F32:$src), - [(set I64:$dst, (fp_to_uint F32:$src))], - "i64.trunc_u:sat/f32\t$dst, $src", 0xfc05>, - Requires<[HasNontrappingFPToInt]>; -def I32_TRUNC_S_SAT_F64 : I<(outs I32:$dst), (ins F64:$src), - [(set I32:$dst, (fp_to_sint F64:$src))], - "i32.trunc_s:sat/f64\t$dst, $src", 0xfc02>, - Requires<[HasNontrappingFPToInt]>; -def I32_TRUNC_U_SAT_F64 : I<(outs I32:$dst), (ins F64:$src), - [(set I32:$dst, (fp_to_uint F64:$src))], - "i32.trunc_u:sat/f64\t$dst, $src", 0xfc03>, - Requires<[HasNontrappingFPToInt]>; -def I64_TRUNC_S_SAT_F64 : I<(outs I64:$dst), (ins F64:$src), - [(set I64:$dst, (fp_to_sint F64:$src))], - "i64.trunc_s:sat/f64\t$dst, $src", 0xfc06>, - Requires<[HasNontrappingFPToInt]>; -def I64_TRUNC_U_SAT_F64 : I<(outs I64:$dst), (ins F64:$src), - [(set I64:$dst, (fp_to_uint F64:$src))], - "i64.trunc_u:sat/f64\t$dst, $src", 0xfc07>, - Requires<[HasNontrappingFPToInt]>; +defm I32_TRUNC_S_SAT_F32 : I<(outs I32:$dst), (ins F32:$src), (outs), (ins), + [(set I32:$dst, (fp_to_sint F32:$src))], + "i32.trunc_s:sat/f32\t$dst, $src", + "i32.trunc_s:sat/f32", 0xfc00>, + Requires<[HasNontrappingFPToInt]>; +defm I32_TRUNC_U_SAT_F32 : I<(outs I32:$dst), (ins F32:$src), (outs), (ins), + [(set I32:$dst, (fp_to_uint F32:$src))], + "i32.trunc_u:sat/f32\t$dst, $src", + "i32.trunc_u:sat/f32", 0xfc01>, + Requires<[HasNontrappingFPToInt]>; +defm I64_TRUNC_S_SAT_F32 : I<(outs I64:$dst), (ins F32:$src), (outs), (ins), + [(set I64:$dst, (fp_to_sint F32:$src))], + "i64.trunc_s:sat/f32\t$dst, $src", + "i64.trunc_s:sat/f32", 0xfc04>, + Requires<[HasNontrappingFPToInt]>; +defm I64_TRUNC_U_SAT_F32 : I<(outs I64:$dst), (ins F32:$src), (outs), (ins), + [(set I64:$dst, (fp_to_uint F32:$src))], + "i64.trunc_u:sat/f32\t$dst, $src", + "i64.trunc_u:sat/f32", 0xfc05>, + Requires<[HasNontrappingFPToInt]>; +defm I32_TRUNC_S_SAT_F64 : I<(outs I32:$dst), (ins F64:$src), (outs), (ins), + [(set I32:$dst, (fp_to_sint F64:$src))], + "i32.trunc_s:sat/f64\t$dst, $src", + "i32.trunc_s:sat/f64", 0xfc02>, + Requires<[HasNontrappingFPToInt]>; +defm I32_TRUNC_U_SAT_F64 : I<(outs I32:$dst), (ins F64:$src), (outs), (ins), + [(set I32:$dst, (fp_to_uint F64:$src))], + "i32.trunc_u:sat/f64\t$dst, $src", + "i32.trunc_u:sat/f64", 0xfc03>, + Requires<[HasNontrappingFPToInt]>; +defm I64_TRUNC_S_SAT_F64 : I<(outs I64:$dst), (ins F64:$src), (outs), (ins), + [(set I64:$dst, (fp_to_sint F64:$src))], + "i64.trunc_s:sat/f64\t$dst, $src", + "i64.trunc_s:sat/f64", 0xfc06>, + Requires<[HasNontrappingFPToInt]>; +defm I64_TRUNC_U_SAT_F64 : I<(outs I64:$dst), (ins F64:$src), (outs), (ins), + [(set I64:$dst, (fp_to_uint F64:$src))], + "i64.trunc_u:sat/f64\t$dst, $src", + "i64.trunc_u:sat/f64", 0xfc07>, + Requires<[HasNontrappingFPToInt]>; // Conversion from floating point to integer pseudo-instructions which don't // trap on overflow or invalid. let usesCustomInserter = 1, isCodeGenOnly = 1 in { -def FP_TO_SINT_I32_F32 : I<(outs I32:$dst), (ins F32:$src), - [(set I32:$dst, (fp_to_sint F32:$src))], "", 0>, - Requires<[NotHasNontrappingFPToInt]>; -def FP_TO_UINT_I32_F32 : I<(outs I32:$dst), (ins F32:$src), - [(set I32:$dst, (fp_to_uint F32:$src))], "", 0>, - Requires<[NotHasNontrappingFPToInt]>; -def FP_TO_SINT_I64_F32 : I<(outs I64:$dst), (ins F32:$src), - [(set I64:$dst, (fp_to_sint F32:$src))], "", 0>, - Requires<[NotHasNontrappingFPToInt]>; -def FP_TO_UINT_I64_F32 : I<(outs I64:$dst), (ins F32:$src), - [(set I64:$dst, (fp_to_uint F32:$src))], "", 0>, - Requires<[NotHasNontrappingFPToInt]>; -def FP_TO_SINT_I32_F64 : I<(outs I32:$dst), (ins F64:$src), - [(set I32:$dst, (fp_to_sint F64:$src))], "", 0>, - Requires<[NotHasNontrappingFPToInt]>; -def FP_TO_UINT_I32_F64 : I<(outs I32:$dst), (ins F64:$src), - [(set I32:$dst, (fp_to_uint F64:$src))], "", 0>, - Requires<[NotHasNontrappingFPToInt]>; -def FP_TO_SINT_I64_F64 : I<(outs I64:$dst), (ins F64:$src), - [(set I64:$dst, (fp_to_sint F64:$src))], "", 0>, - Requires<[NotHasNontrappingFPToInt]>; -def FP_TO_UINT_I64_F64 : I<(outs I64:$dst), (ins F64:$src), - [(set I64:$dst, (fp_to_uint F64:$src))], "", 0>, - Requires<[NotHasNontrappingFPToInt]>; +defm FP_TO_SINT_I32_F32 : I<(outs I32:$dst), (ins F32:$src), (outs), (ins), + [(set I32:$dst, (fp_to_sint F32:$src))], "", "", 0>, + Requires<[NotHasNontrappingFPToInt]>; +defm FP_TO_UINT_I32_F32 : I<(outs I32:$dst), (ins F32:$src), (outs), (ins), + [(set I32:$dst, (fp_to_uint F32:$src))], "", "", 0>, + Requires<[NotHasNontrappingFPToInt]>; +defm FP_TO_SINT_I64_F32 : I<(outs I64:$dst), (ins F32:$src), (outs), (ins), + [(set I64:$dst, (fp_to_sint F32:$src))], "", "", 0>, + Requires<[NotHasNontrappingFPToInt]>; +defm FP_TO_UINT_I64_F32 : I<(outs I64:$dst), (ins F32:$src), (outs), (ins), + [(set I64:$dst, (fp_to_uint F32:$src))], "", "", 0>, + Requires<[NotHasNontrappingFPToInt]>; +defm FP_TO_SINT_I32_F64 : I<(outs I32:$dst), (ins F64:$src), (outs), (ins), + [(set I32:$dst, (fp_to_sint F64:$src))], "", "", 0>, + Requires<[NotHasNontrappingFPToInt]>; +defm FP_TO_UINT_I32_F64 : I<(outs I32:$dst), (ins F64:$src), (outs), (ins), + [(set I32:$dst, (fp_to_uint F64:$src))], "", "", 0>, + Requires<[NotHasNontrappingFPToInt]>; +defm FP_TO_SINT_I64_F64 : I<(outs I64:$dst), (ins F64:$src), (outs), (ins), + [(set I64:$dst, (fp_to_sint F64:$src))], "", "", 0>, + Requires<[NotHasNontrappingFPToInt]>; +defm FP_TO_UINT_I64_F64 : I<(outs I64:$dst), (ins F64:$src), (outs), (ins), + [(set I64:$dst, (fp_to_uint F64:$src))], "", "", 0>, + Requires<[NotHasNontrappingFPToInt]>; } // usesCustomInserter, isCodeGenOnly = 1 // Conversion from floating point to integer traps on overflow and invalid. let hasSideEffects = 1 in { -def I32_TRUNC_S_F32 : I<(outs I32:$dst), (ins F32:$src), - [], "i32.trunc_s/f32\t$dst, $src", 0xa8>; -def I32_TRUNC_U_F32 : I<(outs I32:$dst), (ins F32:$src), - [], "i32.trunc_u/f32\t$dst, $src", 0xa9>; -def I64_TRUNC_S_F32 : I<(outs I64:$dst), (ins F32:$src), - [], "i64.trunc_s/f32\t$dst, $src", 0xae>; -def I64_TRUNC_U_F32 : I<(outs I64:$dst), (ins F32:$src), - [], "i64.trunc_u/f32\t$dst, $src", 0xaf>; -def I32_TRUNC_S_F64 : I<(outs I32:$dst), (ins F64:$src), - [], "i32.trunc_s/f64\t$dst, $src", 0xaa>; -def I32_TRUNC_U_F64 : I<(outs I32:$dst), (ins F64:$src), - [], "i32.trunc_u/f64\t$dst, $src", 0xab>; -def I64_TRUNC_S_F64 : I<(outs I64:$dst), (ins F64:$src), - [], "i64.trunc_s/f64\t$dst, $src", 0xb0>; -def I64_TRUNC_U_F64 : I<(outs I64:$dst), (ins F64:$src), - [], "i64.trunc_u/f64\t$dst, $src", 0xb1>; +defm I32_TRUNC_S_F32 : I<(outs I32:$dst), (ins F32:$src), (outs), (ins), + [], "i32.trunc_s/f32\t$dst, $src", "i32.trunc_s/f32", + 0xa8>; +defm I32_TRUNC_U_F32 : I<(outs I32:$dst), (ins F32:$src), (outs), (ins), + [], "i32.trunc_u/f32\t$dst, $src", "i32.trunc_u/f32", + 0xa9>; +defm I64_TRUNC_S_F32 : I<(outs I64:$dst), (ins F32:$src), (outs), (ins), + [], "i64.trunc_s/f32\t$dst, $src", "i64.trunc_s/f32", + 0xae>; +defm I64_TRUNC_U_F32 : I<(outs I64:$dst), (ins F32:$src), (outs), (ins), + [], "i64.trunc_u/f32\t$dst, $src", "i64.trunc_u/f32", + 0xaf>; +defm I32_TRUNC_S_F64 : I<(outs I32:$dst), (ins F64:$src), (outs), (ins), + [], "i32.trunc_s/f64\t$dst, $src", "i32.trunc_s/f64", + 0xaa>; +defm I32_TRUNC_U_F64 : I<(outs I32:$dst), (ins F64:$src), (outs), (ins), + [], "i32.trunc_u/f64\t$dst, $src", "i32.trunc_u/f64", + 0xab>; +defm I64_TRUNC_S_F64 : I<(outs I64:$dst), (ins F64:$src), (outs), (ins), + [], "i64.trunc_s/f64\t$dst, $src", "i64.trunc_s/f64", + 0xb0>; +defm I64_TRUNC_U_F64 : I<(outs I64:$dst), (ins F64:$src), (outs), (ins), + [], "i64.trunc_u/f64\t$dst, $src", "i64.trunc_u/f64", + 0xb1>; } // hasSideEffects = 1 -def F32_CONVERT_S_I32 : I<(outs F32:$dst), (ins I32:$src), - [(set F32:$dst, (sint_to_fp I32:$src))], - "f32.convert_s/i32\t$dst, $src", 0xb2>; -def F32_CONVERT_U_I32 : I<(outs F32:$dst), (ins I32:$src), - [(set F32:$dst, (uint_to_fp I32:$src))], - "f32.convert_u/i32\t$dst, $src", 0xb3>; -def F64_CONVERT_S_I32 : I<(outs F64:$dst), (ins I32:$src), - [(set F64:$dst, (sint_to_fp I32:$src))], - "f64.convert_s/i32\t$dst, $src", 0xb7>; -def F64_CONVERT_U_I32 : I<(outs F64:$dst), (ins I32:$src), - [(set F64:$dst, (uint_to_fp I32:$src))], - "f64.convert_u/i32\t$dst, $src", 0xb8>; -def F32_CONVERT_S_I64 : I<(outs F32:$dst), (ins I64:$src), - [(set F32:$dst, (sint_to_fp I64:$src))], - "f32.convert_s/i64\t$dst, $src", 0xb4>; -def F32_CONVERT_U_I64 : I<(outs F32:$dst), (ins I64:$src), - [(set F32:$dst, (uint_to_fp I64:$src))], - "f32.convert_u/i64\t$dst, $src", 0xb5>; -def F64_CONVERT_S_I64 : I<(outs F64:$dst), (ins I64:$src), - [(set F64:$dst, (sint_to_fp I64:$src))], - "f64.convert_s/i64\t$dst, $src", 0xb9>; -def F64_CONVERT_U_I64 : I<(outs F64:$dst), (ins I64:$src), - [(set F64:$dst, (uint_to_fp I64:$src))], - "f64.convert_u/i64\t$dst, $src", 0xba>; +defm F32_CONVERT_S_I32 : I<(outs F32:$dst), (ins I32:$src), (outs), (ins), + [(set F32:$dst, (sint_to_fp I32:$src))], + "f32.convert_s/i32\t$dst, $src", "f32.convert_s/i32", + 0xb2>; +defm F32_CONVERT_U_I32 : I<(outs F32:$dst), (ins I32:$src), (outs), (ins), + [(set F32:$dst, (uint_to_fp I32:$src))], + "f32.convert_u/i32\t$dst, $src", "f32.convert_u/i32", + 0xb3>; +defm F64_CONVERT_S_I32 : I<(outs F64:$dst), (ins I32:$src), (outs), (ins), + [(set F64:$dst, (sint_to_fp I32:$src))], + "f64.convert_s/i32\t$dst, $src", "f64.convert_s/i32", + 0xb7>; +defm F64_CONVERT_U_I32 : I<(outs F64:$dst), (ins I32:$src), (outs), (ins), + [(set F64:$dst, (uint_to_fp I32:$src))], + "f64.convert_u/i32\t$dst, $src", "f64.convert_u/i32", + 0xb8>; +defm F32_CONVERT_S_I64 : I<(outs F32:$dst), (ins I64:$src), (outs), (ins), + [(set F32:$dst, (sint_to_fp I64:$src))], + "f32.convert_s/i64\t$dst, $src", "f32.convert_s/i64", + 0xb4>; +defm F32_CONVERT_U_I64 : I<(outs F32:$dst), (ins I64:$src), (outs), (ins), + [(set F32:$dst, (uint_to_fp I64:$src))], + "f32.convert_u/i64\t$dst, $src", "f32.convert_u/i64", + 0xb5>; +defm F64_CONVERT_S_I64 : I<(outs F64:$dst), (ins I64:$src), (outs), (ins), + [(set F64:$dst, (sint_to_fp I64:$src))], + "f64.convert_s/i64\t$dst, $src", "f64.convert_s/i64", + 0xb9>; +defm F64_CONVERT_U_I64 : I<(outs F64:$dst), (ins I64:$src), (outs), (ins), + [(set F64:$dst, (uint_to_fp I64:$src))], + "f64.convert_u/i64\t$dst, $src", "f64.convert_u/i64", + 0xba>; -def F64_PROMOTE_F32 : I<(outs F64:$dst), (ins F32:$src), - [(set F64:$dst, (fpextend F32:$src))], - "f64.promote/f32\t$dst, $src", 0xbb>; -def F32_DEMOTE_F64 : I<(outs F32:$dst), (ins F64:$src), - [(set F32:$dst, (fpround F64:$src))], - "f32.demote/f64\t$dst, $src", 0xb6>; +defm F64_PROMOTE_F32 : I<(outs F64:$dst), (ins F32:$src), (outs), (ins), + [(set F64:$dst, (fpextend F32:$src))], + "f64.promote/f32\t$dst, $src", "f64.promote/f32", + 0xbb>; +defm F32_DEMOTE_F64 : I<(outs F32:$dst), (ins F64:$src), (outs), (ins), + [(set F32:$dst, (fpround F64:$src))], + "f32.demote/f64\t$dst, $src", "f32.demote/f64", + 0xb6>; -def I32_REINTERPRET_F32 : I<(outs I32:$dst), (ins F32:$src), - [(set I32:$dst, (bitconvert F32:$src))], - "i32.reinterpret/f32\t$dst, $src", 0xbc>; -def F32_REINTERPRET_I32 : I<(outs F32:$dst), (ins I32:$src), - [(set F32:$dst, (bitconvert I32:$src))], - "f32.reinterpret/i32\t$dst, $src", 0xbe>; -def I64_REINTERPRET_F64 : I<(outs I64:$dst), (ins F64:$src), - [(set I64:$dst, (bitconvert F64:$src))], - "i64.reinterpret/f64\t$dst, $src", 0xbd>; -def F64_REINTERPRET_I64 : I<(outs F64:$dst), (ins I64:$src), - [(set F64:$dst, (bitconvert I64:$src))], - "f64.reinterpret/i64\t$dst, $src", 0xbf>; +defm I32_REINTERPRET_F32 : I<(outs I32:$dst), (ins F32:$src), (outs), (ins), + [(set I32:$dst, (bitconvert F32:$src))], + "i32.reinterpret/f32\t$dst, $src", + "i32.reinterpret/f32", 0xbc>; +defm F32_REINTERPRET_I32 : I<(outs F32:$dst), (ins I32:$src), (outs), (ins), + [(set F32:$dst, (bitconvert I32:$src))], + "f32.reinterpret/i32\t$dst, $src", + "f32.reinterpret/i32", 0xbe>; +defm I64_REINTERPRET_F64 : I<(outs I64:$dst), (ins F64:$src), (outs), (ins), + [(set I64:$dst, (bitconvert F64:$src))], + "i64.reinterpret/f64\t$dst, $src", + "i64.reinterpret/f64", 0xbd>; +defm F64_REINTERPRET_I64 : I<(outs F64:$dst), (ins I64:$src), (outs), (ins), + [(set F64:$dst, (bitconvert I64:$src))], + "f64.reinterpret/i64\t$dst, $src", + "f64.reinterpret/i64", 0xbf>; } // Defs = [ARGUMENTS] diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrExceptRef.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrExceptRef.td index 80f7c7aaa59..41b39f69e51 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrExceptRef.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrExceptRef.td @@ -14,12 +14,14 @@ let Defs = [ARGUMENTS] in { -def SELECT_EXCEPT_REF : I<(outs EXCEPT_REF:$dst), - (ins EXCEPT_REF:$lhs, EXCEPT_REF:$rhs, I32:$cond), - [(set EXCEPT_REF:$dst, - (select I32:$cond, EXCEPT_REF:$lhs, - EXCEPT_REF:$rhs))], - "except_ref.select\t$dst, $lhs, $rhs, $cond", 0x1b>; +defm SELECT_EXCEPT_REF : I<(outs EXCEPT_REF:$dst), + (ins EXCEPT_REF:$lhs, EXCEPT_REF:$rhs, I32:$cond), + (outs), (ins), + [(set EXCEPT_REF:$dst, + (select I32:$cond, EXCEPT_REF:$lhs, + EXCEPT_REF:$rhs))], + "except_ref.select\t$dst, $lhs, $rhs, $cond", + "except_ref.select", 0x1b>; } // Defs = [ARGUMENTS] diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td index aff96da0919..8db75d38942 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td @@ -77,12 +77,14 @@ def : Pat<(setge f64:$lhs, f64:$rhs), (GE_F64 f64:$lhs, f64:$rhs)>; let Defs = [ARGUMENTS] in { -def SELECT_F32 : I<(outs F32:$dst), (ins F32:$lhs, F32:$rhs, I32:$cond), - [(set F32:$dst, (select I32:$cond, F32:$lhs, F32:$rhs))], - "f32.select\t$dst, $lhs, $rhs, $cond", 0x1b>; -def SELECT_F64 : I<(outs F64:$dst), (ins F64:$lhs, F64:$rhs, I32:$cond), - [(set F64:$dst, (select I32:$cond, F64:$lhs, F64:$rhs))], - "f64.select\t$dst, $lhs, $rhs, $cond", 0x1b>; +defm SELECT_F32 : I<(outs F32:$dst), (ins F32:$lhs, F32:$rhs, I32:$cond), + (outs), (ins), + [(set F32:$dst, (select I32:$cond, F32:$lhs, F32:$rhs))], + "f32.select\t$dst, $lhs, $rhs, $cond", "f32.select", 0x1b>; +defm SELECT_F64 : I<(outs F64:$dst), (ins F64:$lhs, F64:$rhs, I32:$cond), + (outs), (ins), + [(set F64:$dst, (select I32:$cond, F64:$lhs, F64:$rhs))], + "f64.select\t$dst, $lhs, $rhs, $cond", "f64.select", 0x1b>; } // Defs = [ARGUMENTS] diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrFormats.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrFormats.td index 68d44b8e885..403152c8066 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrFormats.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrFormats.td @@ -13,94 +13,155 @@ //===----------------------------------------------------------------------===// // WebAssembly Instruction Format. -class WebAssemblyInst<bits<32> inst, string asmstr> : Instruction { +// We instantiate 2 of these for every actual instruction (register based +// and stack based), see below. +class WebAssemblyInst<bits<32> inst, string asmstr, bit stack> : Instruction { field bits<32> Inst = inst; // Instruction encoding. + field bit StackBased = stack; let Namespace = "WebAssembly"; let Pattern = []; let AsmString = asmstr; } -// Normal instructions. -class I<dag oops, dag iops, list<dag> pattern, string asmstr = "", bits<32> inst = -1> - : WebAssemblyInst<inst, asmstr> { +// Normal instructions. Default instantiation of a WebAssemblyInst. +class NI<dag oops, dag iops, list<dag> pattern, bit stack, string asmstr = "", + bits<32> inst = -1> + : WebAssemblyInst<inst, asmstr, stack> { dag OutOperandList = oops; dag InOperandList = iops; let Pattern = pattern; } -class SIMD_I<dag oops, dag iops, list<dag> pattern, - string asmstr = "", bits<32> inst = -1> - : I<oops, iops, pattern, asmstr, inst>, Requires<[HasSIMD128]>; +// Generates both register and stack based versions of one actual instruction. +// We have 2 sets of operands (oops & iops) for the register and stack +// based version of this instruction, as well as the corresponding asmstr. +// The register versions have virtual-register operands which correspond to wasm +// locals or stack locations. Each use and def of the register corresponds to an +// implicit get_local / set_local or access of stack operands in wasm. These +// instructions are used for ISel and all MI passes. The stack versions of the +// instructions do not have register operands (they implicitly operate on the +// stack), and get_locals and set_locals are explicit. The register instructions +// are converted to their corresponding stack instructions before lowering to +// MC. +// Every instruction should want to be based on this multi-class to guarantee +// there is always an equivalent pair of instructions. +multiclass I<dag oops_r, dag iops_r, dag oops_s, dag iops_s, + list<dag> pattern_r, string asmstr_r = "", string asmstr_s = "", + bits<32> inst = -1> { + def "" : NI<oops_r, iops_r, pattern_r, 0, asmstr_r, inst>; + def _S : NI<oops_s, iops_s, [], 1, asmstr_s, inst>; +} + +// For instructions that have no register ops, so both sets are the same. +multiclass NRI<dag oops, dag iops, list<dag> pattern, string asmstr = "", + bits<32> inst = -1> { + defm "": I<oops, iops, oops, iops, pattern, asmstr, asmstr, inst>; +} -class ATOMIC_I<dag oops, dag iops, list<dag> pattern, - string asmstr = "", bits<32> inst = -1> - : I<oops, iops, pattern, asmstr, inst>, Requires<[HasAtomics]>; +multiclass SIMD_I<dag oops_r, dag iops_r, dag oops_s, dag iops_s, + list<dag> pattern_r, string asmstr_r = "", + string asmstr_s = "", bits<32> inst = -1> { + defm "" : I<oops_r, iops_r, oops_s, iops_s, pattern_r, asmstr_r, asmstr_s, + inst>, + Requires<[HasSIMD128]>; +} + +multiclass ATOMIC_I<dag oops_r, dag iops_r, dag oops_s, dag iops_s, + list<dag> pattern_r, string asmstr_r = "", + string asmstr_s = "", bits<32> inst = -1> { + defm "" : I<oops_r, iops_r, oops_s, iops_s, pattern_r, asmstr_r, asmstr_s, + inst>, + Requires<[HasAtomics]>; +} // Unary and binary instructions, for the local types that WebAssembly supports. -multiclass UnaryInt<SDNode node, string name, bits<32> i32Inst, bits<32> i64Inst> { - def _I32 : I<(outs I32:$dst), (ins I32:$src), - [(set I32:$dst, (node I32:$src))], - !strconcat("i32.", !strconcat(name, "\t$dst, $src")), i32Inst>; - def _I64 : I<(outs I64:$dst), (ins I64:$src), - [(set I64:$dst, (node I64:$src))], - !strconcat("i64.", !strconcat(name, "\t$dst, $src")), i64Inst>; +multiclass UnaryInt<SDNode node, string name, bits<32> i32Inst, + bits<32> i64Inst> { + defm _I32 : I<(outs I32:$dst), (ins I32:$src), (outs), (ins), + [(set I32:$dst, (node I32:$src))], + !strconcat("i32.", !strconcat(name, "\t$dst, $src")), + !strconcat("i32.", name), i32Inst>; + defm _I64 : I<(outs I64:$dst), (ins I64:$src), (outs), (ins), + [(set I64:$dst, (node I64:$src))], + !strconcat("i64.", !strconcat(name, "\t$dst, $src")), + !strconcat("i64.", name), i64Inst>; } -multiclass BinaryInt<SDNode node, string name, bits<32> i32Inst, bits<32> i64Inst> { - def _I32 : I<(outs I32:$dst), (ins I32:$lhs, I32:$rhs), - [(set I32:$dst, (node I32:$lhs, I32:$rhs))], - !strconcat("i32.", !strconcat(name, "\t$dst, $lhs, $rhs")), i32Inst>; - def _I64 : I<(outs I64:$dst), (ins I64:$lhs, I64:$rhs), - [(set I64:$dst, (node I64:$lhs, I64:$rhs))], - !strconcat("i64.", !strconcat(name, "\t$dst, $lhs, $rhs")), i64Inst>; +multiclass BinaryInt<SDNode node, string name, bits<32> i32Inst, + bits<32> i64Inst> { + defm _I32 : I<(outs I32:$dst), (ins I32:$lhs, I32:$rhs), (outs), (ins), + [(set I32:$dst, (node I32:$lhs, I32:$rhs))], + !strconcat("i32.", !strconcat(name, "\t$dst, $lhs, $rhs")), + !strconcat("i32.", name), i32Inst>; + defm _I64 : I<(outs I64:$dst), (ins I64:$lhs, I64:$rhs), (outs), (ins), + [(set I64:$dst, (node I64:$lhs, I64:$rhs))], + !strconcat("i64.", !strconcat(name, "\t$dst, $lhs, $rhs")), + !strconcat("i64.", name), i64Inst>; } -multiclass UnaryFP<SDNode node, string name, bits<32> f32Inst, bits<32> f64Inst> { - def _F32 : I<(outs F32:$dst), (ins F32:$src), - [(set F32:$dst, (node F32:$src))], - !strconcat("f32.", !strconcat(name, "\t$dst, $src")), f32Inst>; - def _F64 : I<(outs F64:$dst), (ins F64:$src), - [(set F64:$dst, (node F64:$src))], - !strconcat("f64.", !strconcat(name, "\t$dst, $src")), f64Inst>; +multiclass UnaryFP<SDNode node, string name, bits<32> f32Inst, + bits<32> f64Inst> { + defm _F32 : I<(outs F32:$dst), (ins F32:$src), (outs), (ins), + [(set F32:$dst, (node F32:$src))], + !strconcat("f32.", !strconcat(name, "\t$dst, $src")), + !strconcat("f32.", name), f32Inst>; + defm _F64 : I<(outs F64:$dst), (ins F64:$src), (outs), (ins), + [(set F64:$dst, (node F64:$src))], + !strconcat("f64.", !strconcat(name, "\t$dst, $src")), + !strconcat("f64.", name), f64Inst>; } -multiclass BinaryFP<SDNode node, string name, bits<32> f32Inst, bits<32> f64Inst> { - def _F32 : I<(outs F32:$dst), (ins F32:$lhs, F32:$rhs), - [(set F32:$dst, (node F32:$lhs, F32:$rhs))], - !strconcat("f32.", !strconcat(name, "\t$dst, $lhs, $rhs")), f32Inst>; - def _F64 : I<(outs F64:$dst), (ins F64:$lhs, F64:$rhs), - [(set F64:$dst, (node F64:$lhs, F64:$rhs))], - !strconcat("f64.", !strconcat(name, "\t$dst, $lhs, $rhs")), f64Inst>; +multiclass BinaryFP<SDNode node, string name, bits<32> f32Inst, + bits<32> f64Inst> { + defm _F32 : I<(outs F32:$dst), (ins F32:$lhs, F32:$rhs), (outs), (ins), + [(set F32:$dst, (node F32:$lhs, F32:$rhs))], + !strconcat("f32.", !strconcat(name, "\t$dst, $lhs, $rhs")), + !strconcat("f32.", name), f32Inst>; + defm _F64 : I<(outs F64:$dst), (ins F64:$lhs, F64:$rhs), (outs), (ins), + [(set F64:$dst, (node F64:$lhs, F64:$rhs))], + !strconcat("f64.", !strconcat(name, "\t$dst, $lhs, $rhs")), + !strconcat("f64.", name), f64Inst>; } multiclass SIMDBinary<SDNode node, SDNode fnode, string name> { - def _I8x16 : SIMD_I<(outs V128:$dst), (ins V128:$lhs, V128:$rhs), - [(set (v16i8 V128:$dst), (node V128:$lhs, V128:$rhs))], - !strconcat("i8x16.", !strconcat(name, "\t$dst, $lhs, $rhs"))>; - def _I16x8 : SIMD_I<(outs V128:$dst), (ins V128:$lhs, V128:$rhs), - [(set (v8i16 V128:$dst), (node V128:$lhs, V128:$rhs))], - !strconcat("i16x8.", !strconcat(name, "\t$dst, $lhs, $rhs"))>; - def _I32x4 : SIMD_I<(outs V128:$dst), (ins V128:$lhs, V128:$rhs), - [(set (v4i32 V128:$dst), (node V128:$lhs, V128:$rhs))], - !strconcat("i32x4.", !strconcat(name, "\t$dst, $lhs, $rhs"))>; - def _F32x4 : SIMD_I<(outs V128:$dst), (ins V128:$lhs, V128:$rhs), - [(set (v4f32 V128:$dst), (fnode V128:$lhs, V128:$rhs))], - !strconcat("f32x4.", !strconcat(name, "\t$dst, $lhs, $rhs"))>; - + defm _I8x16 : SIMD_I<(outs V128:$dst), (ins V128:$lhs, V128:$rhs), + (outs), (ins), + [(set (v16i8 V128:$dst), (node V128:$lhs, V128:$rhs))], + !strconcat("i8x16.", + !strconcat(name, "\t$dst, $lhs, $rhs")), + !strconcat("i8x16.", name)>; + defm _I16x8 : SIMD_I<(outs V128:$dst), (ins V128:$lhs, V128:$rhs), + (outs), (ins), + [(set (v8i16 V128:$dst), (node V128:$lhs, V128:$rhs))], + !strconcat("i16x8.", + !strconcat(name, "\t$dst, $lhs, $rhs")), + !strconcat("i16x8.", name)>; + defm _I32x4 : SIMD_I<(outs V128:$dst), (ins V128:$lhs, V128:$rhs), + (outs), (ins), + [(set (v4i32 V128:$dst), (node V128:$lhs, V128:$rhs))], + !strconcat("i32x4.", + !strconcat(name, "\t$dst, $lhs, $rhs")), + !strconcat("i32x4.", name)>; + defm _F32x4 : SIMD_I<(outs V128:$dst), (ins V128:$lhs, V128:$rhs), + (outs), (ins), + [(set (v4f32 V128:$dst), (fnode V128:$lhs, V128:$rhs))], + !strconcat("f32x4.", + !strconcat(name, "\t$dst, $lhs, $rhs")), + !strconcat("f32x4.", name)>; } multiclass ComparisonInt<CondCode cond, string name, bits<32> i32Inst, bits<32> i64Inst> { - def _I32 : I<(outs I32:$dst), (ins I32:$lhs, I32:$rhs), - [(set I32:$dst, (setcc I32:$lhs, I32:$rhs, cond))], - !strconcat("i32.", !strconcat(name, "\t$dst, $lhs, $rhs")), - i32Inst>; - def _I64 : I<(outs I32:$dst), (ins I64:$lhs, I64:$rhs), - [(set I32:$dst, (setcc I64:$lhs, I64:$rhs, cond))], - !strconcat("i64.", !strconcat(name, "\t$dst, $lhs, $rhs")), - i64Inst>; + defm _I32 : I<(outs I32:$dst), (ins I32:$lhs, I32:$rhs), (outs), (ins), + [(set I32:$dst, (setcc I32:$lhs, I32:$rhs, cond))], + !strconcat("i32.", !strconcat(name, "\t$dst, $lhs, $rhs")), + !strconcat("i32.", name), i32Inst>; + defm _I64 : I<(outs I32:$dst), (ins I64:$lhs, I64:$rhs), (outs), (ins), + [(set I32:$dst, (setcc I64:$lhs, I64:$rhs, cond))], + !strconcat("i64.", !strconcat(name, "\t$dst, $lhs, $rhs")), + !strconcat("i64.", name), i64Inst>; } multiclass ComparisonFP<CondCode cond, string name, bits<32> f32Inst, bits<32> f64Inst> { - def _F32 : I<(outs I32:$dst), (ins F32:$lhs, F32:$rhs), - [(set I32:$dst, (setcc F32:$lhs, F32:$rhs, cond))], - !strconcat("f32.", !strconcat(name, "\t$dst, $lhs, $rhs")), - f32Inst>; - def _F64 : I<(outs I32:$dst), (ins F64:$lhs, F64:$rhs), - [(set I32:$dst, (setcc F64:$lhs, F64:$rhs, cond))], - !strconcat("f64.", !strconcat(name, "\t$dst, $lhs, $rhs")), - f64Inst>; + defm _F32 : I<(outs I32:$dst), (ins F32:$lhs, F32:$rhs), (outs), (ins), + [(set I32:$dst, (setcc F32:$lhs, F32:$rhs, cond))], + !strconcat("f32.", !strconcat(name, "\t$dst, $lhs, $rhs")), + !strconcat("f32.", name), f32Inst>; + defm _F64 : I<(outs I32:$dst), (ins F64:$lhs, F64:$rhs), (outs), (ins), + [(set I32:$dst, (setcc F64:$lhs, F64:$rhs, cond))], + !strconcat("f64.", !strconcat(name, "\t$dst, $lhs, $rhs")), + !strconcat("f64.", name), f64Inst>; } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td index ccd254e40df..aeb282a7feb 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td @@ -153,13 +153,15 @@ include "WebAssemblyInstrFormats.td" multiclass ARGUMENT<WebAssemblyRegClass vt> { let hasSideEffects = 1, Uses = [ARGUMENTS], isCodeGenOnly = 1 in - def ARGUMENT_#vt : I<(outs vt:$res), (ins i32imm:$argno), - [(set vt:$res, (WebAssemblyargument timm:$argno))]>; + defm ARGUMENT_#vt : I<(outs vt:$res), (ins i32imm:$argno), + (outs), (ins i32imm:$argno), + [(set vt:$res, (WebAssemblyargument timm:$argno))]>; } multiclass SIMD_ARGUMENT<ValueType vt> { let hasSideEffects = 1, Uses = [ARGUMENTS], isCodeGenOnly = 1 in - def ARGUMENT_#vt : SIMD_I<(outs V128:$res), (ins i32imm:$argno), - [(set (vt V128:$res), + defm ARGUMENT_#vt : SIMD_I<(outs V128:$res), (ins i32imm:$argno), + (outs), (ins i32imm:$argno), + [(set (vt V128:$res), (WebAssemblyargument timm:$argno))]>; } defm "": ARGUMENT<I32>; @@ -184,47 +186,56 @@ let hasSideEffects = 0 in { // and set_local. COPYs are eliminated (and replaced with // get_local/set_local) in the ExplicitLocals pass. let isAsCheapAsAMove = 1, isCodeGenOnly = 1 in - def COPY_#vt : I<(outs vt:$res), (ins vt:$src), [], "copy_local\t$res, $src">; + defm COPY_#vt : I<(outs vt:$res), (ins vt:$src), (outs), (ins), [], + "copy_local\t$res, $src", "copy_local">; // TEE is similar to COPY, but writes two copies of its result. Typically // this would be used to stackify one result and write the other result to a // local. let isAsCheapAsAMove = 1, isCodeGenOnly = 1 in - def TEE_#vt : I<(outs vt:$res, vt:$also), (ins vt:$src), [], - "tee_local\t$res, $also, $src">; + defm TEE_#vt : I<(outs vt:$res, vt:$also), (ins vt:$src), (outs), (ins), [], + "tee_local\t$res, $also, $src", "tee_local">; // This is the actual get_local instruction in wasm. These are made explicit // by the ExplicitLocals pass. It has mayLoad because it reads from a wasm // local, which is a side effect not otherwise modeled in LLVM. let mayLoad = 1, isAsCheapAsAMove = 1 in - def GET_LOCAL_#vt : I<(outs vt:$res), (ins local_op:$local), [], - "get_local\t$res, $local", 0x20>; + defm GET_LOCAL_#vt : I<(outs vt:$res), (ins local_op:$local), + (outs), (ins local_op:$local), [], + "get_local\t$res, $local", "get_local\t$local", 0x20>; // This is the actual set_local instruction in wasm. These are made explicit // by the ExplicitLocals pass. It has mayStore because it writes to a wasm // local, which is a side effect not otherwise modeled in LLVM. let mayStore = 1, isAsCheapAsAMove = 1 in - def SET_LOCAL_#vt : I<(outs), (ins local_op:$local, vt:$src), [], - "set_local\t$local, $src", 0x21>; + defm SET_LOCAL_#vt : I<(outs), (ins local_op:$local, vt:$src), + (outs), (ins local_op:$local), [], + "set_local\t$local, $src", "set_local\t$local", 0x21>; // This is the actual tee_local instruction in wasm. TEEs are turned into // TEE_LOCALs by the ExplicitLocals pass. It has mayStore for the same reason // as SET_LOCAL. let mayStore = 1, isAsCheapAsAMove = 1 in - def TEE_LOCAL_#vt : I<(outs vt:$res), (ins local_op:$local, vt:$src), [], - "tee_local\t$res, $local, $src", 0x22>; + defm TEE_LOCAL_#vt : I<(outs vt:$res), (ins local_op:$local, vt:$src), + (outs), (ins local_op:$local), [], + "tee_local\t$res, $local, $src", "tee_local\t$local", + 0x22>; // Unused values must be dropped in some contexts. - def DROP_#vt : I<(outs), (ins vt:$src), [], - "drop\t$src", 0x1a>; + defm DROP_#vt : I<(outs), (ins vt:$src), (outs), (ins), [], + "drop\t$src", "drop", 0x1a>; let mayLoad = 1 in - def GET_GLOBAL_#vt : I<(outs vt:$res), (ins global_op:$local), [], - "get_global\t$res, $local", 0x23>; + defm GET_GLOBAL_#vt : I<(outs vt:$res), (ins global_op:$local), + (outs), (ins global_op:$local), [], + "get_global\t$res, $local", "get_global\t$local", + 0x23>; let mayStore = 1 in - def SET_GLOBAL_#vt : I<(outs), (ins global_op:$local, vt:$src), [], - "set_global\t$local, $src", 0x24>; + defm SET_GLOBAL_#vt : I<(outs), (ins global_op:$local, vt:$src), + (outs), (ins global_op:$local), [], + "set_global\t$local, $src", "set_global\t$local", + 0x24>; } // hasSideEffects = 0 } @@ -236,18 +247,22 @@ defm "" : LOCAL<V128>, Requires<[HasSIMD128]>; defm "" : LOCAL<EXCEPT_REF>, Requires<[HasExceptionHandling]>; let isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1 in { -def CONST_I32 : I<(outs I32:$res), (ins i32imm_op:$imm), - [(set I32:$res, imm:$imm)], - "i32.const\t$res, $imm", 0x41>; -def CONST_I64 : I<(outs I64:$res), (ins i64imm_op:$imm), - [(set I64:$res, imm:$imm)], - "i64.const\t$res, $imm", 0x42>; -def CONST_F32 : I<(outs F32:$res), (ins f32imm_op:$imm), - [(set F32:$res, fpimm:$imm)], - "f32.const\t$res, $imm", 0x43>; -def CONST_F64 : I<(outs F64:$res), (ins f64imm_op:$imm), - [(set F64:$res, fpimm:$imm)], - "f64.const\t$res, $imm", 0x44>; +defm CONST_I32 : I<(outs I32:$res), (ins i32imm_op:$imm), + (outs), (ins i32imm_op:$imm), + [(set I32:$res, imm:$imm)], + "i32.const\t$res, $imm", "i32.const\t$imm", 0x41>; +defm CONST_I64 : I<(outs I64:$res), (ins i64imm_op:$imm), + (outs), (ins i64imm_op:$imm), + [(set I64:$res, imm:$imm)], + "i64.const\t$res, $imm", "i64.const\t$imm", 0x42>; +defm CONST_F32 : I<(outs F32:$res), (ins f32imm_op:$imm), + (outs), (ins f32imm_op:$imm), + [(set F32:$res, fpimm:$imm)], + "f32.const\t$res, $imm", "f32.const\t$imm", 0x43>; +defm CONST_F64 : I<(outs F64:$res), (ins f64imm_op:$imm), + (outs), (ins f64imm_op:$imm), + [(set F64:$res, fpimm:$imm)], + "f64.const\t$res, $imm", "f64.const\t$imm", 0x44>; } // isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1 } // Defs = [ARGUMENTS] diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td index 2b5b0795087..f9f21fd1d75 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td @@ -56,12 +56,12 @@ defm CLZ : UnaryInt<ctlz, "clz ", 0x67, 0x79>; defm CTZ : UnaryInt<cttz, "ctz ", 0x68, 0x7a>; defm POPCNT : UnaryInt<ctpop, "popcnt", 0x69, 0x7b>; -def EQZ_I32 : I<(outs I32:$dst), (ins I32:$src), - [(set I32:$dst, (setcc I32:$src, 0, SETEQ))], - "i32.eqz \t$dst, $src", 0x45>; -def EQZ_I64 : I<(outs I32:$dst), (ins I64:$src), - [(set I32:$dst, (setcc I64:$src, 0, SETEQ))], - "i64.eqz \t$dst, $src", 0x50>; +defm EQZ_I32 : I<(outs I32:$dst), (ins I32:$src), (outs), (ins), + [(set I32:$dst, (setcc I32:$src, 0, SETEQ))], + "i32.eqz \t$dst, $src", "i32.eqz", 0x45>; +defm EQZ_I64 : I<(outs I32:$dst), (ins I64:$src), (outs), (ins), + [(set I32:$dst, (setcc I64:$src, 0, SETEQ))], + "i64.eqz \t$dst, $src", "i64.eqz", 0x50>; } // Defs = [ARGUMENTS] @@ -73,12 +73,14 @@ def : Pat<(rotr I64:$lhs, (and I64:$rhs, 63)), (ROTR_I64 I64:$lhs, I64:$rhs)>; let Defs = [ARGUMENTS] in { -def SELECT_I32 : I<(outs I32:$dst), (ins I32:$lhs, I32:$rhs, I32:$cond), - [(set I32:$dst, (select I32:$cond, I32:$lhs, I32:$rhs))], - "i32.select\t$dst, $lhs, $rhs, $cond", 0x1b>; -def SELECT_I64 : I<(outs I64:$dst), (ins I64:$lhs, I64:$rhs, I32:$cond), - [(set I64:$dst, (select I32:$cond, I64:$lhs, I64:$rhs))], - "i64.select\t$dst, $lhs, $rhs, $cond", 0x1b>; +defm SELECT_I32 : I<(outs I32:$dst), (ins I32:$lhs, I32:$rhs, I32:$cond), + (outs), (ins), + [(set I32:$dst, (select I32:$cond, I32:$lhs, I32:$rhs))], + "i32.select\t$dst, $lhs, $rhs, $cond", "i32.select", 0x1b>; +defm SELECT_I64 : I<(outs I64:$dst), (ins I64:$lhs, I64:$rhs, I32:$cond), + (outs), (ins), + [(set I64:$dst, (select I32:$cond, I64:$lhs, I64:$rhs))], + "i64.select\t$dst, $lhs, $rhs, $cond", "i64.select", 0x1b>; } // Defs = [ARGUMENTS] diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td index 70abc058118..e97e34b183d 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td @@ -56,23 +56,26 @@ def regPlusGA : PatFrag<(ops node:$addr, node:$off), let Defs = [ARGUMENTS] in { // Defines atomic and non-atomic loads, regular and extending. -class WebAssemblyLoad<WebAssemblyRegClass rc, string Name, int Opcode> : - I<(outs rc:$dst), - (ins P2Align:$p2align, offset32_op:$off, I32:$addr), - [], !strconcat(Name, "\t$dst, ${off}(${addr})${p2align}"), Opcode>; +multiclass WebAssemblyLoad<WebAssemblyRegClass rc, string Name, int Opcode> { + defm "": I<(outs rc:$dst), + (ins P2Align:$p2align, offset32_op:$off, I32:$addr), + (outs), (ins P2Align:$p2align, offset32_op:$off), + [], !strconcat(Name, "\t$dst, ${off}(${addr})${p2align}"), + !strconcat(Name, "\t${off}, ${p2align}"), Opcode>; +} // Basic load. // FIXME: When we can break syntax compatibility, reorder the fields in the // asmstrings to match the binary encoding. -def LOAD_I32 : WebAssemblyLoad<I32, "i32.load", 0x28>; -def LOAD_I64 : WebAssemblyLoad<I64, "i64.load", 0x29>; -def LOAD_F32 : WebAssemblyLoad<F32, "f32.load", 0x2a>; -def LOAD_F64 : WebAssemblyLoad<F64, "f64.load", 0x2b>; +defm LOAD_I32 : WebAssemblyLoad<I32, "i32.load", 0x28>; +defm LOAD_I64 : WebAssemblyLoad<I64, "i64.load", 0x29>; +defm LOAD_F32 : WebAssemblyLoad<F32, "f32.load", 0x2a>; +defm LOAD_F64 : WebAssemblyLoad<F64, "f64.load", 0x2b>; } // Defs = [ARGUMENTS] // Select loads with no constant offset. -class LoadPatNoOffset<ValueType ty, PatFrag node, I inst> : +class LoadPatNoOffset<ValueType ty, PatFrag node, NI inst> : Pat<(ty (node I32:$addr)), (inst 0, 0, $addr)>; def : LoadPatNoOffset<i32, load, LOAD_I32>; @@ -84,7 +87,7 @@ def : LoadPatNoOffset<f64, load, LOAD_F64>; // Select loads with a constant offset. // Pattern with address + immediate offset -class LoadPatImmOff<ValueType ty, PatFrag loadkind, PatFrag operand, I inst> : +class LoadPatImmOff<ValueType ty, PatFrag loadkind, PatFrag operand, NI inst> : Pat<(ty (loadkind (operand I32:$addr, imm:$off))), (inst 0, imm:$off, $addr)>; @@ -97,7 +100,7 @@ def : LoadPatImmOff<i64, load, or_is_add, LOAD_I64>; def : LoadPatImmOff<f32, load, or_is_add, LOAD_F32>; def : LoadPatImmOff<f64, load, or_is_add, LOAD_F64>; -class LoadPatGlobalAddr<ValueType ty, PatFrag loadkind, I inst> : +class LoadPatGlobalAddr<ValueType ty, PatFrag loadkind, NI inst> : Pat<(ty (loadkind (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)))), (inst 0, tglobaladdr:$off, $addr)>; @@ -106,7 +109,7 @@ def : LoadPatGlobalAddr<i64, load, LOAD_I64>; def : LoadPatGlobalAddr<f32, load, LOAD_F32>; def : LoadPatGlobalAddr<f64, load, LOAD_F64>; -class LoadPatExternalSym<ValueType ty, PatFrag loadkind, I inst> : +class LoadPatExternalSym<ValueType ty, PatFrag loadkind, NI inst> : Pat<(ty (loadkind (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), (inst 0, texternalsym:$off, $addr)>; def : LoadPatExternalSym<i32, load, LOAD_I32>; @@ -116,7 +119,7 @@ def : LoadPatExternalSym<f64, load, LOAD_F64>; // Select loads with just a constant offset. -class LoadPatOffsetOnly<ValueType ty, PatFrag loadkind, I inst> : +class LoadPatOffsetOnly<ValueType ty, PatFrag loadkind, NI inst> : Pat<(ty (loadkind imm:$off)), (inst 0, imm:$off, (CONST_I32 0))>; def : LoadPatOffsetOnly<i32, load, LOAD_I32>; @@ -124,7 +127,7 @@ def : LoadPatOffsetOnly<i64, load, LOAD_I64>; def : LoadPatOffsetOnly<f32, load, LOAD_F32>; def : LoadPatOffsetOnly<f64, load, LOAD_F64>; -class LoadPatGlobalAddrOffOnly<ValueType ty, PatFrag loadkind, I inst> : +class LoadPatGlobalAddrOffOnly<ValueType ty, PatFrag loadkind, NI inst> : Pat<(ty (loadkind (WebAssemblywrapper tglobaladdr:$off))), (inst 0, tglobaladdr:$off, (CONST_I32 0))>; @@ -133,7 +136,7 @@ def : LoadPatGlobalAddrOffOnly<i64, load, LOAD_I64>; def : LoadPatGlobalAddrOffOnly<f32, load, LOAD_F32>; def : LoadPatGlobalAddrOffOnly<f64, load, LOAD_F64>; -class LoadPatExternSymOffOnly<ValueType ty, PatFrag loadkind, I inst> : +class LoadPatExternSymOffOnly<ValueType ty, PatFrag loadkind, NI inst> : Pat<(ty (loadkind (WebAssemblywrapper texternalsym:$off))), (inst 0, texternalsym:$off, (CONST_I32 0))>; def : LoadPatExternSymOffOnly<i32, load, LOAD_I32>; @@ -144,16 +147,16 @@ def : LoadPatExternSymOffOnly<f64, load, LOAD_F64>; let Defs = [ARGUMENTS] in { // Extending load. -def LOAD8_S_I32 : WebAssemblyLoad<I32, "i32.load8_s", 0x2c>; -def LOAD8_U_I32 : WebAssemblyLoad<I32, "i32.load8_u", 0x2d>; -def LOAD16_S_I32 : WebAssemblyLoad<I32, "i32.load16_s", 0x2e>; -def LOAD16_U_I32 : WebAssemblyLoad<I32, "i32.load16_u", 0x2f>; -def LOAD8_S_I64 : WebAssemblyLoad<I64, "i64.load8_s", 0x30>; -def LOAD8_U_I64 : WebAssemblyLoad<I64, "i64.load8_u", 0x31>; -def LOAD16_S_I64 : WebAssemblyLoad<I64, "i64.load16_s", 0x32>; -def LOAD16_U_I64 : WebAssemblyLoad<I64, "i64.load16_u", 0x33>; -def LOAD32_S_I64 : WebAssemblyLoad<I64, "i64.load32_s", 0x34>; -def LOAD32_U_I64 : WebAssemblyLoad<I64, "i64.load32_u", 0x35>; +defm LOAD8_S_I32 : WebAssemblyLoad<I32, "i32.load8_s", 0x2c>; +defm LOAD8_U_I32 : WebAssemblyLoad<I32, "i32.load8_u", 0x2d>; +defm LOAD16_S_I32 : WebAssemblyLoad<I32, "i32.load16_s", 0x2e>; +defm LOAD16_U_I32 : WebAssemblyLoad<I32, "i32.load16_u", 0x2f>; +defm LOAD8_S_I64 : WebAssemblyLoad<I64, "i64.load8_s", 0x30>; +defm LOAD8_U_I64 : WebAssemblyLoad<I64, "i64.load8_u", 0x31>; +defm LOAD16_S_I64 : WebAssemblyLoad<I64, "i64.load16_s", 0x32>; +defm LOAD16_U_I64 : WebAssemblyLoad<I64, "i64.load16_u", 0x33>; +defm LOAD32_S_I64 : WebAssemblyLoad<I64, "i64.load32_s", 0x34>; +defm LOAD32_U_I64 : WebAssemblyLoad<I64, "i64.load32_u", 0x35>; } // Defs = [ARGUMENTS] @@ -304,20 +307,25 @@ def : LoadPatExternSymOffOnly<i64, extloadi32, LOAD32_U_I64>; let Defs = [ARGUMENTS] in { // Defines atomic and non-atomic stores, regular and truncating -class WebAssemblyStore<WebAssemblyRegClass rc, string Name, int Opcode> : - I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr, rc:$val), [], - !strconcat(Name, "\t${off}(${addr})${p2align}, $val"), Opcode>; +multiclass WebAssemblyStore<WebAssemblyRegClass rc, string Name, int Opcode> { + defm "" : I<(outs), + (ins P2Align:$p2align, offset32_op:$off, I32:$addr, rc:$val), + (outs), + (ins P2Align:$p2align, offset32_op:$off), [], + !strconcat(Name, "\t${off}(${addr})${p2align}, $val"), + !strconcat(Name, "\t${off}, ${p2align}"), Opcode>; +} // Basic store. // Note: WebAssembly inverts SelectionDAG's usual operand order. -def STORE_I32 : WebAssemblyStore<I32, "i32.store", 0x36>; -def STORE_I64 : WebAssemblyStore<I64, "i64.store", 0x37>; -def STORE_F32 : WebAssemblyStore<F32, "f32.store", 0x38>; -def STORE_F64 : WebAssemblyStore<F64, "f64.store", 0x39>; +defm STORE_I32 : WebAssemblyStore<I32, "i32.store", 0x36>; +defm STORE_I64 : WebAssemblyStore<I64, "i64.store", 0x37>; +defm STORE_F32 : WebAssemblyStore<F32, "f32.store", 0x38>; +defm STORE_F64 : WebAssemblyStore<F64, "f64.store", 0x39>; } // Defs = [ARGUMENTS] // Select stores with no constant offset. -class StorePatNoOffset<ValueType ty, PatFrag node, I inst> : +class StorePatNoOffset<ValueType ty, PatFrag node, NI inst> : Pat<(node ty:$val, I32:$addr), (inst 0, 0, $addr, $val)>; def : StorePatNoOffset<i32, store, STORE_I32>; @@ -326,7 +334,7 @@ def : StorePatNoOffset<f32, store, STORE_F32>; def : StorePatNoOffset<f64, store, STORE_F64>; // Select stores with a constant offset. -class StorePatImmOff<ValueType ty, PatFrag storekind, PatFrag operand, I inst> : +class StorePatImmOff<ValueType ty, PatFrag storekind, PatFrag operand, NI inst> : Pat<(storekind ty:$val, (operand I32:$addr, imm:$off)), (inst 0, imm:$off, $addr, ty:$val)>; @@ -339,7 +347,7 @@ def : StorePatImmOff<i64, store, or_is_add, STORE_I64>; def : StorePatImmOff<f32, store, or_is_add, STORE_F32>; def : StorePatImmOff<f64, store, or_is_add, STORE_F64>; -class StorePatGlobalAddr<ValueType ty, PatFrag storekind, I inst> : +class StorePatGlobalAddr<ValueType ty, PatFrag storekind, NI inst> : Pat<(storekind ty:$val, (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off))), (inst 0, tglobaladdr:$off, I32:$addr, ty:$val)>; @@ -348,7 +356,7 @@ def : StorePatGlobalAddr<i64, store, STORE_I64>; def : StorePatGlobalAddr<f32, store, STORE_F32>; def : StorePatGlobalAddr<f64, store, STORE_F64>; -class StorePatExternalSym<ValueType ty, PatFrag storekind, I inst> : +class StorePatExternalSym<ValueType ty, PatFrag storekind, NI inst> : Pat<(storekind ty:$val, (add I32:$addr, (WebAssemblywrapper texternalsym:$off))), (inst 0, texternalsym:$off, I32:$addr, ty:$val)>; @@ -358,7 +366,7 @@ def : StorePatExternalSym<f32, store, STORE_F32>; def : StorePatExternalSym<f64, store, STORE_F64>; // Select stores with just a constant offset. -class StorePatOffsetOnly<ValueType ty, PatFrag storekind, I inst> : +class StorePatOffsetOnly<ValueType ty, PatFrag storekind, NI inst> : Pat<(storekind ty:$val, imm:$off), (inst 0, imm:$off, (CONST_I32 0), ty:$val)>; def : StorePatOffsetOnly<i32, store, STORE_I32>; @@ -366,7 +374,7 @@ def : StorePatOffsetOnly<i64, store, STORE_I64>; def : StorePatOffsetOnly<f32, store, STORE_F32>; def : StorePatOffsetOnly<f64, store, STORE_F64>; -class StorePatGlobalAddrOffOnly<ValueType ty, PatFrag storekind, I inst> : +class StorePatGlobalAddrOffOnly<ValueType ty, PatFrag storekind, NI inst> : Pat<(storekind ty:$val, (WebAssemblywrapper tglobaladdr:$off)), (inst 0, tglobaladdr:$off, (CONST_I32 0), ty:$val)>; def : StorePatGlobalAddrOffOnly<i32, store, STORE_I32>; @@ -374,7 +382,7 @@ def : StorePatGlobalAddrOffOnly<i64, store, STORE_I64>; def : StorePatGlobalAddrOffOnly<f32, store, STORE_F32>; def : StorePatGlobalAddrOffOnly<f64, store, STORE_F64>; -class StorePatExternSymOffOnly<ValueType ty, PatFrag storekind, I inst> : +class StorePatExternSymOffOnly<ValueType ty, PatFrag storekind, NI inst> : Pat<(storekind ty:$val, (WebAssemblywrapper texternalsym:$off)), (inst 0, texternalsym:$off, (CONST_I32 0), ty:$val)>; def : StorePatExternSymOffOnly<i32, store, STORE_I32>; @@ -386,11 +394,11 @@ def : StorePatExternSymOffOnly<f64, store, STORE_F64>; let Defs = [ARGUMENTS] in { // Truncating store. -def STORE8_I32 : WebAssemblyStore<I32, "i32.store8", 0x3a>; -def STORE16_I32 : WebAssemblyStore<I32, "i32.store16", 0x3b>; -def STORE8_I64 : WebAssemblyStore<I64, "i64.store8", 0x3c>; -def STORE16_I64 : WebAssemblyStore<I64, "i64.store16", 0x3d>; -def STORE32_I64 : WebAssemblyStore<I64, "i64.store32", 0x3e>; +defm STORE8_I32 : WebAssemblyStore<I32, "i32.store8", 0x3a>; +defm STORE16_I32 : WebAssemblyStore<I32, "i32.store16", 0x3b>; +defm STORE8_I64 : WebAssemblyStore<I64, "i64.store8", 0x3c>; +defm STORE16_I64 : WebAssemblyStore<I64, "i64.store16", 0x3d>; +defm STORE32_I64 : WebAssemblyStore<I64, "i64.store32", 0x3e>; } // Defs = [ARGUMENTS] @@ -444,34 +452,47 @@ def : StorePatExternSymOffOnly<i64, truncstorei32, STORE32_I64>; let Defs = [ARGUMENTS] in { // Current memory size. -def MEMORY_SIZE_I32 : I<(outs I32:$dst), (ins i32imm:$flags), - [(set I32:$dst, (int_wasm_memory_size (i32 imm:$flags)))], - "memory.size\t$dst, $flags", 0x3f>, - Requires<[HasAddr32]>; -def MEM_SIZE_I32 : I<(outs I32:$dst), (ins i32imm:$flags), - [(set I32:$dst, (int_wasm_mem_size (i32 imm:$flags)))], - "mem.size\t$dst, $flags", 0x3f>, - Requires<[HasAddr32]>; -def CURRENT_MEMORY_I32 : I<(outs I32:$dst), (ins i32imm:$flags), - [], - "current_memory\t$dst", 0x3f>, - Requires<[HasAddr32]>; +defm MEMORY_SIZE_I32 : I<(outs I32:$dst), (ins i32imm:$flags), + (outs), (ins i32imm:$flags), + [(set I32:$dst, + (int_wasm_memory_size (i32 imm:$flags)))], + "memory.size\t$dst, $flags", "memory.size\t$flags", + 0x3f>, + Requires<[HasAddr32]>; +defm MEM_SIZE_I32 : I<(outs I32:$dst), (ins i32imm:$flags), + (outs), (ins i32imm:$flags), + [(set I32:$dst, (int_wasm_mem_size (i32 imm:$flags)))], + "mem.size\t$dst, $flags", "mem.size\t$flags", 0x3f>, + Requires<[HasAddr32]>; +defm CURRENT_MEMORY_I32 : I<(outs I32:$dst), (ins i32imm:$flags), + (outs), (ins i32imm:$flags), + [], + "current_memory\t$dst", + "current_memory\t$flags", 0x3f>, + Requires<[HasAddr32]>; // Grow memory. -def MEMORY_GROW_I32 : I<(outs I32:$dst), (ins i32imm:$flags, I32:$delta), - [(set I32:$dst, - (int_wasm_memory_grow (i32 imm:$flags), I32:$delta))], - "memory.grow\t$dst, $flags, $delta", 0x3f>, - Requires<[HasAddr32]>; -def MEM_GROW_I32 : I<(outs I32:$dst), (ins i32imm:$flags, I32:$delta), - [(set I32:$dst, - (int_wasm_mem_grow (i32 imm:$flags), I32:$delta))], - "mem.grow\t$dst, $flags, $delta", 0x3f>, - Requires<[HasAddr32]>; -def GROW_MEMORY_I32 : I<(outs I32:$dst), (ins i32imm:$flags, I32:$delta), - [], - "grow_memory\t$dst, $delta", 0x40>, - Requires<[HasAddr32]>; +defm MEMORY_GROW_I32 : I<(outs I32:$dst), (ins i32imm:$flags, I32:$delta), + (outs), (ins i32imm:$flags, I32:$delta), + [(set I32:$dst, + (int_wasm_memory_grow (i32 imm:$flags), + I32:$delta))], + "memory.grow\t$dst, $flags, $delta", + "memory.grow\t$flags, $delta", 0x3f>, + Requires<[HasAddr32]>; +defm MEM_GROW_I32 : I<(outs I32:$dst), (ins i32imm:$flags, I32:$delta), + (outs), (ins i32imm:$flags), + [(set I32:$dst, + (int_wasm_mem_grow (i32 imm:$flags), I32:$delta))], + "mem.grow\t$dst, $flags, $delta", "mem.grow\t$flags", + 0x3f>, + Requires<[HasAddr32]>; +defm GROW_MEMORY_I32 : I<(outs I32:$dst), (ins i32imm:$flags, I32:$delta), + (outs), (ins i32imm:$flags), + [], + "grow_memory\t$dst, $delta", "grow_memory\t$flags", + 0x40>, + Requires<[HasAddr32]>; } // Defs = [ARGUMENTS] diff --git a/llvm/test/MC/Disassembler/WebAssembly/wasm.txt b/llvm/test/MC/Disassembler/WebAssembly/wasm.txt index d6229f69700..63c9bb183c8 100644 --- a/llvm/test/MC/Disassembler/WebAssembly/wasm.txt +++ b/llvm/test/MC/Disassembler/WebAssembly/wasm.txt @@ -5,14 +5,14 @@ # CHECK: nop 0x01 -# CHECK: i32.add $0=, $0, $0 -# NOTE: registers are meaningless, as there is no context for what they are. +# CHECK: i32.add 0x6a -# CHECK: i64.const $0=, -1 +# CHECK: i64.const -1 0x42 0x7F -# CHECK: i64.load32_u $0=, 16($0):p2align=1 +# CHECK: i64.load32_u 16, :p2align=1 +# FIXME: fix p2align output in WebAssemblyInstPrinter 0x35 0x01 0x10 # CHECK: block @@ -25,9 +25,9 @@ # FIXME: WebAssemblyInstPrinter does not print immediates. 0x11 0x80 0x01 0x00 -# CHECK: get_local $0=, 128 +# CHECK: get_local 128 0x20 0x80 0x01 # Prefix byte example: -# CHECK: i64.trunc_u:sat/f64 $0=, $0 +# CHECK: i64.trunc_u:sat/f64 0xFC 0x07 |

