From f227621036351c8f0e142e938d4a597480443650 Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Wed, 26 Dec 2018 22:55:26 +0000 Subject: [PATCH] [WebAssembly] Added basic support for if/else/end_if in MC layer. Summary: These instructions are currently unused in our backend, but for completeness it is good to support them, so they can be used with the assembler in hand-written code. Tests are very basic, signature support missing much like other blocks. Reviewers: dschuff, aheejin Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits Differential Revision: https://reviews.llvm.org/D55973 llvm-svn: 350079 --- .../AsmParser/WebAssemblyAsmParser.cpp | 3 ++- .../WebAssembly/WebAssemblyInstrControl.td | 14 +++++++++---- llvm/test/MC/WebAssembly/basic-assembly.s | 20 +++++++++---------- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp index 62229d390b3c..d997190aa366 100644 --- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp +++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp @@ -488,7 +488,8 @@ public: // assembly, so we add a dummy one explicitly (since we have no control // over signature tables here, we assume these will be regenerated when // the wasm module is generated). - if (BaseName == "block" || BaseName == "loop" || BaseName == "try") { + if (BaseName == "block" || BaseName == "loop" || BaseName == "try" || + BaseName == "if") { Operands.push_back(make_unique( WebAssemblyOperand::Integer, NameLoc, NameLoc, WebAssemblyOperand::IntOp{-1})); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td index a7fc75640090..021f95feec8d 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td @@ -75,13 +75,19 @@ defm NOP : NRI<(outs), (ins), [], "nop", 0x01>; // 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 { -defm BLOCK : NRI<(outs), (ins Signature:$sig), [], "block \t$sig", 0x02>; -defm LOOP : NRI<(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. +defm IF : I<(outs), (ins Signature:$sig, I32:$cond), + (outs), (ins Signature:$sig), + [], "if \t$sig, $cond", "if \t$sig", 0x04>; +defm ELSE : NRI<(outs), (ins), [], "else", 0x05>; + +// END_BLOCK, END_LOOP, END_IF and END_FUNCTION are represented with the same +// opcode in wasm. 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>; 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/test/MC/WebAssembly/basic-assembly.s b/llvm/test/MC/WebAssembly/basic-assembly.s index e29e47d80aa9..684d40debfe7 100644 --- a/llvm/test/MC/WebAssembly/basic-assembly.s +++ b/llvm/test/MC/WebAssembly/basic-assembly.s @@ -59,11 +59,11 @@ test0: end_block # default jumps here. i32.const 3 end_block # "switch" exit. - #if # These are not in tablegen defs yet.. - #if - #end_if - #else - #end_if + if + if + end_if + else + end_if f32x4.add # Test correct parsing of instructions with / and : in them: # TODO: enable once instruction has been added. @@ -134,11 +134,11 @@ test0: # CHECK-NEXT: end_block # label3: # CHECK-NEXT: i32.const 3 # CHECK-NEXT: end_block # label2: -# DONT-CHECK-NEXT: if -# DONT-CHECK-NEXT: if -# DONT-CHECK-NEXT: end_if -# DONT-CHECK-NEXT: else -# DONT-CHECK-NEXT: end_if +# CHECK-NEXT: if +# CHECK-NEXT: if +# CHECK-NEXT: end_if +# CHECK-NEXT: else +# CHECK-NEXT: end_if # CHECK-NEXT: f32x4.add # CHECK-NEXT: i32.trunc_s/f32 # CHECK-NEXT: try