1600aee98SJF Bastien//===- WebAssemblyInstrControl.td-WebAssembly control-flow ------*- tablegen -*- 2600aee98SJF Bastien// 32946cd70SChandler Carruth// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth// See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6600aee98SJF Bastien// 7600aee98SJF Bastien//===----------------------------------------------------------------------===// 8600aee98SJF Bastien/// 9600aee98SJF Bastien/// \file 105f8f34e4SAdrian Prantl/// WebAssembly control-flow code-gen constructs. 11600aee98SJF Bastien/// 12600aee98SJF Bastien//===----------------------------------------------------------------------===// 13600aee98SJF Bastien 14950a13cfSDan Gohmanlet isBranch = 1, isTerminator = 1, hasCtrlDep = 1 in { 15f0b165a7SDan Gohman// The condition operand is a boolean value which WebAssembly represents as i32. 1648dac310SWouter van Oortmerssendefm BR_IF : I<(outs), (ins bb_op:$dst, I32:$cond), 1748dac310SWouter van Oortmerssen (outs), (ins bb_op:$dst), 18f0b165a7SDan Gohman [(brcond I32:$cond, bb:$dst)], 1948dac310SWouter van Oortmerssen "br_if \t$dst, $cond", "br_if \t$dst", 0x0d>; 20f0b165a7SDan Gohmanlet isCodeGenOnly = 1 in 2148dac310SWouter van Oortmerssendefm BR_UNLESS : I<(outs), (ins bb_op:$dst, I32:$cond), 2248dac310SWouter van Oortmerssen (outs), (ins bb_op:$dst), []>; 234367587fSHeejin Ahnlet isBarrier = 1 in 2448dac310SWouter van Oortmerssendefm BR : NRI<(outs), (ins bb_op:$dst), 25af29bd4fSDan Gohman [(br bb:$dst)], 26c968297bSDan Gohman "br \t$dst", 0x0c>; 27950a13cfSDan Gohman} // isBranch = 1, isTerminator = 1, hasCtrlDep = 1 28950a13cfSDan Gohman 29f0b165a7SDan Gohmandef : Pat<(brcond (i32 (setne I32:$cond, 0)), bb:$dst), 3006b49582SDan Gohman (BR_IF bb_op:$dst, I32:$cond)>; 31f0b165a7SDan Gohmandef : Pat<(brcond (i32 (seteq I32:$cond, 0)), bb:$dst), 3206b49582SDan Gohman (BR_UNLESS bb_op:$dst, I32:$cond)>; 3392e77714SSam Parkerdef : Pat<(brcond (i32 (xor bool_node:$cond, (i32 1))), bb:$dst), 3492e77714SSam Parker (BR_UNLESS bb_op:$dst, I32:$cond)>; 35f0b165a7SDan Gohman 36d3c544aaSWouter van Oortmerssen// A list of branch targets enclosed in {} and separated by comma. 37d3c544aaSWouter van Oortmerssen// Used by br_table only. 38d3c544aaSWouter van Oortmerssendef BrListAsmOperand : AsmOperandClass { let Name = "BrList"; } 394367587fSHeejin Ahnlet OperandNamespace = "WebAssembly", OperandType = "OPERAND_BRLIST" in 40d3c544aaSWouter van Oortmerssendef brlist : Operand<i32> { 41d3c544aaSWouter van Oortmerssen let ParserMatchClass = BrListAsmOperand; 42d3c544aaSWouter van Oortmerssen let PrintMethod = "printBrList"; 43d3c544aaSWouter van Oortmerssen} 44d3c544aaSWouter van Oortmerssen 45c5d01234SThomas Lively// Duplicating a BR_TABLE is almost never a good idea. In particular, it can 46c5d01234SThomas Lively// lead to some nasty irreducibility due to tail merging when the br_table is in 47c5d01234SThomas Lively// a loop. 48c5d01234SThomas Livelylet isTerminator = 1, hasCtrlDep = 1, isBarrier = 1, isNotDuplicable = 1 in { 49c5d01234SThomas Lively 508e2bac8eSHeejin Ahndefm BR_TABLE_I32 : I<(outs), (ins I32:$index, variable_ops), 518e2bac8eSHeejin Ahn (outs), (ins brlist:$brl), 528e2bac8eSHeejin Ahn [(WebAssemblybr_table I32:$index)], 538e2bac8eSHeejin Ahn "br_table \t$index", "br_table \t$brl", 548e2bac8eSHeejin Ahn 0x0e>; 55c5d01234SThomas Lively// TODO: SelectionDAG's lowering insists on using a pointer as the index for 56c5d01234SThomas Lively// jump tables, so in practice we don't ever use BR_TABLE_I64 in wasm32 mode 57c5d01234SThomas Lively// currently. 588e2bac8eSHeejin Ahndefm BR_TABLE_I64 : I<(outs), (ins I64:$index, variable_ops), 598e2bac8eSHeejin Ahn (outs), (ins brlist:$brl), 608e2bac8eSHeejin Ahn [(WebAssemblybr_table I64:$index)], 618e2bac8eSHeejin Ahn "br_table \t$index", "br_table \t$brl", 628e2bac8eSHeejin Ahn 0x0e>; 63c5d01234SThomas Lively} // isTerminator = 1, hasCtrlDep = 1, isBarrier = 1, isNotDuplicable = 1 64950a13cfSDan Gohman 6516c16827SSam Clegg// This is technically a control-flow instruction, since all it affects is the 6616c16827SSam Clegg// IP. 6748dac310SWouter van Oortmerssendefm NOP : NRI<(outs), (ins), [], "nop", 0x01>; 6816c16827SSam Clegg 69e4a8deeaSHeejin Ahn// Placemarkers to indicate the start or end of a block or loop scope. 70ac62b05dSHeejin Ahn// These use/clobber VALUE_STACK to prevent them from being moved into the 71ac62b05dSHeejin Ahn// middle of an expression tree. 72e040533eSDan Gohmanlet Uses = [VALUE_STACK], Defs = [VALUE_STACK] in { 7348dac310SWouter van Oortmerssendefm BLOCK : NRI<(outs), (ins Signature:$sig), [], "block \t$sig", 0x02>; 7448dac310SWouter van Oortmerssendefm LOOP : NRI<(outs), (ins Signature:$sig), [], "loop \t$sig", 0x03>; 754becc585SDan Gohman 76f2276210SWouter van Oortmerssendefm IF : I<(outs), (ins Signature:$sig, I32:$cond), 77f2276210SWouter van Oortmerssen (outs), (ins Signature:$sig), 78f2276210SWouter van Oortmerssen [], "if \t$sig, $cond", "if \t$sig", 0x04>; 79f2276210SWouter van Oortmerssendefm ELSE : NRI<(outs), (ins), [], "else", 0x05>; 80f2276210SWouter van Oortmerssen 81f2276210SWouter van Oortmerssen// END_BLOCK, END_LOOP, END_IF and END_FUNCTION are represented with the same 82f2276210SWouter van Oortmerssen// opcode in wasm. 8348dac310SWouter van Oortmerssendefm END_BLOCK : NRI<(outs), (ins), [], "end_block", 0x0b>; 8448dac310SWouter van Oortmerssendefm END_LOOP : NRI<(outs), (ins), [], "end_loop", 0x0b>; 85f2276210SWouter van Oortmerssendefm END_IF : NRI<(outs), (ins), [], "end_if", 0x0b>; 861a91cb04SWouter van Oortmerssen// Generic instruction, for disassembler. 874367587fSHeejin Ahnlet IsCanonical = 1 in 881a91cb04SWouter van Oortmerssendefm END : NRI<(outs), (ins), [], "end", 0x0b>; 89d934cb88SDan Gohmanlet isTerminator = 1, isBarrier = 1 in 9048dac310SWouter van Oortmerssendefm END_FUNCTION : NRI<(outs), (ins), [], "end_function", 0x0b>; 91e040533eSDan Gohman} // Uses = [VALUE_STACK], Defs = [VALUE_STACK] 92950a13cfSDan Gohman 9339bf39f3SDerek Schuff 94a07c08f7SThomas Livelylet hasCtrlDep = 1, isBarrier = 1 in { 95a07c08f7SThomas Livelylet isTerminator = 1 in { 96ffa143ceSDerek Schufflet isReturn = 1 in { 9739bf39f3SDerek Schuff 9800f9e5aaSThomas Livelydefm RETURN : I<(outs), (ins variable_ops), (outs), (ins), 9900f9e5aaSThomas Lively [(WebAssemblyreturn)], 10000f9e5aaSThomas Lively "return", "return", 0x0f>; 10100f9e5aaSThomas Lively// Equivalent to RETURN, for use at the end of a function when wasm 10200f9e5aaSThomas Lively// semantics return by falling off the end of the block. 103b7c2400fSDan Gohmanlet isCodeGenOnly = 1 in 10400f9e5aaSThomas Livelydefm FALLTHROUGH_RETURN : I<(outs), (ins variable_ops), (outs), (ins), []>; 10500f9e5aaSThomas Lively 106ffa143ceSDerek Schuff} // isReturn = 1 1079850e877SDan Gohman 1084252f300SDominic Chenlet IsCanonical = 1, isTrap = 1 in 10948dac310SWouter van Oortmerssendefm UNREACHABLE : NRI<(outs), (ins), [(trap)], "unreachable", 0x00>; 110a07c08f7SThomas Lively 111a07c08f7SThomas Lively} // isTerminator = 1 112a07c08f7SThomas Lively 113a07c08f7SThomas Lively// debugtrap explicitly returns despite trapping because it is supposed to just 114a07c08f7SThomas Lively// get the attention of the debugger. Unfortunately, because UNREACHABLE is a 115a07c08f7SThomas Lively// terminator, lowering debugtrap to UNREACHABLE can create an invalid 116a07c08f7SThomas Lively// MachineBasicBlock when there is additional code after it. Lower it to this 117a07c08f7SThomas Lively// non-terminator version instead. 118a07c08f7SThomas Lively// TODO: Actually execute the debugger statement when running on the Web 119a07c08f7SThomas Livelylet isTrap = 1 in 120a07c08f7SThomas Livelydefm DEBUG_UNREACHABLE : NRI<(outs), (ins), [(debugtrap)], "unreachable", 0x00>; 121a07c08f7SThomas Lively 122a07c08f7SThomas Lively} // hasCtrlDep = 1, isBarrier = 1 1239850e877SDan Gohman 124e4a8deeaSHeejin Ahn//===----------------------------------------------------------------------===// 125e4a8deeaSHeejin Ahn// Exception handling instructions 126e4a8deeaSHeejin Ahn//===----------------------------------------------------------------------===// 127e4a8deeaSHeejin Ahn 12847068a42SHeejin Ahnlet Predicates = [HasExceptionHandling] in { 12947068a42SHeejin Ahn 130e4a8deeaSHeejin Ahn// Throwing an exception: throw / rethrow 131e4a8deeaSHeejin Ahnlet isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 in { 1321d891d44SHeejin Ahndefm THROW : I<(outs), (ins tag_op:$tag, variable_ops), 133*31a71a39SHeejin Ahn (outs), (ins tag_op:$tag), [], 134d6f48786SHeejin Ahn "throw \t$tag", "throw \t$tag", 0x08>; 1359e4eadebSHeejin Ahndefm RETHROW : NRI<(outs), (ins i32imm:$depth), [], "rethrow \t$depth", 0x09>; 136ffa143ceSDerek Schuff} // isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 13735f5f797SHeejin Ahn// The depth argument will be computed in CFGStackify. We set it to 0 here for 13835f5f797SHeejin Ahn// now. 1399e4eadebSHeejin Ahndef : Pat<(int_wasm_rethrow), (RETHROW 0)>; 140fb3e0594SDan Gohman 141e4a8deeaSHeejin Ahn// Region within which an exception is caught: try / end_try 142e4a8deeaSHeejin Ahnlet Uses = [VALUE_STACK], Defs = [VALUE_STACK] in { 14348dac310SWouter van Oortmerssendefm TRY : NRI<(outs), (ins Signature:$sig), [], "try \t$sig", 0x06>; 14448dac310SWouter van Oortmerssendefm END_TRY : NRI<(outs), (ins), [], "end_try", 0x0b>; 145e4a8deeaSHeejin Ahn} // Uses = [VALUE_STACK], Defs = [VALUE_STACK] 146e4a8deeaSHeejin Ahn 1479e4eadebSHeejin Ahn// Catching an exception: catch / catch_all 1489e4eadebSHeejin Ahnlet hasCtrlDep = 1, hasSideEffects = 1 in { 149*31a71a39SHeejin Ahnlet variadicOpsAreDefs = 1 in 150*31a71a39SHeejin Ahndefm CATCH : I<(outs), (ins tag_op:$tag, variable_ops), 151*31a71a39SHeejin Ahn (outs), (ins tag_op:$tag), [], 152*31a71a39SHeejin Ahn "catch", "catch \t$tag", 0x07>; 1537c594babSHeejin Ahndefm CATCH_ALL : NRI<(outs), (ins), [], "catch_all", 0x19>; 1549e4eadebSHeejin Ahn} 155d6f48786SHeejin Ahn 156ed41945fSHeejin Ahn// Delegating an exception: delegate 157ed41945fSHeejin Ahnlet isTerminator = 1, hasCtrlDep = 1, hasSideEffects = 1 in 158ed41945fSHeejin Ahndefm DELEGATE : NRI<(outs), (ins bb_op:$dst), [], "delegate \t $dst", 0x18>; 159ed41945fSHeejin Ahn 1605ef4d5f9SHeejin Ahn// Pseudo instructions: cleanupret / catchret 1615ef4d5f9SHeejin Ahnlet isTerminator = 1, hasSideEffects = 1, isBarrier = 1, hasCtrlDep = 1, 162d6f48786SHeejin Ahn isPseudo = 1, isEHScopeReturn = 1 in { 163d6f48786SHeejin Ahn defm CLEANUPRET : NRI<(outs), (ins), [(cleanupret)], "cleanupret", 0>; 16448dac310SWouter van Oortmerssen defm CATCHRET : NRI<(outs), (ins bb_op:$dst, bb_op:$from), 165d6f48786SHeejin Ahn [(catchret bb:$dst, bb:$from)], "catchret", 0>; 166d6f48786SHeejin Ahn} // isTerminator = 1, hasSideEffects = 1, isBarrier = 1, hasCtrlDep = 1, 167d6f48786SHeejin Ahn // isPseudo = 1, isEHScopeReturn = 1 1684367587fSHeejin Ahn} // Predicates = [HasExceptionHandling] 169