1292915Sdim//===- WebAssemblyInstrControl.td-WebAssembly control-flow ------*- tablegen -*- 2292915Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6292915Sdim// 7292915Sdim//===----------------------------------------------------------------------===// 8292915Sdim/// 9292915Sdim/// \file 10341825Sdim/// WebAssembly control-flow code-gen constructs. 11292915Sdim/// 12292915Sdim//===----------------------------------------------------------------------===// 13292915Sdim 14292915Sdimlet isBranch = 1, isTerminator = 1, hasCtrlDep = 1 in { 15292915Sdim// The condition operand is a boolean value which WebAssembly represents as i32. 16341825Sdimdefm BR_IF : I<(outs), (ins bb_op:$dst, I32:$cond), 17341825Sdim (outs), (ins bb_op:$dst), 18341825Sdim [(brcond I32:$cond, bb:$dst)], 19341825Sdim "br_if \t$dst, $cond", "br_if \t$dst", 0x0d>; 20292915Sdimlet isCodeGenOnly = 1 in 21341825Sdimdefm BR_UNLESS : I<(outs), (ins bb_op:$dst, I32:$cond), 22341825Sdim (outs), (ins bb_op:$dst), []>; 23353358Sdimlet isBarrier = 1 in 24341825Sdimdefm BR : NRI<(outs), (ins bb_op:$dst), 25341825Sdim [(br bb:$dst)], 26341825Sdim "br \t$dst", 0x0c>; 27292915Sdim} // isBranch = 1, isTerminator = 1, hasCtrlDep = 1 28292915Sdim 29292915Sdimdef : Pat<(brcond (i32 (setne I32:$cond, 0)), bb:$dst), 30309124Sdim (BR_IF bb_op:$dst, I32:$cond)>; 31292915Sdimdef : Pat<(brcond (i32 (seteq I32:$cond, 0)), bb:$dst), 32309124Sdim (BR_UNLESS bb_op:$dst, I32:$cond)>; 33292915Sdim 34344779Sdim// A list of branch targets enclosed in {} and separated by comma. 35344779Sdim// Used by br_table only. 36344779Sdimdef BrListAsmOperand : AsmOperandClass { let Name = "BrList"; } 37353358Sdimlet OperandNamespace = "WebAssembly", OperandType = "OPERAND_BRLIST" in 38344779Sdimdef brlist : Operand<i32> { 39344779Sdim let ParserMatchClass = BrListAsmOperand; 40344779Sdim let PrintMethod = "printBrList"; 41344779Sdim} 42292915Sdim 43292915Sdim// TODO: SelectionDAG's lowering insists on using a pointer as the index for 44309124Sdim// jump tables, so in practice we don't ever use BR_TABLE_I64 in wasm32 mode 45292915Sdim// currently. 46292915Sdimlet isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 in { 47344779Sdimdefm BR_TABLE_I32 : I<(outs), (ins I32:$index, variable_ops), 48344779Sdim (outs), (ins brlist:$brl), 49344779Sdim [(WebAssemblybr_table I32:$index)], 50344779Sdim "br_table \t$index", "br_table \t$brl", 51344779Sdim 0x0e>; 52344779Sdimdefm BR_TABLE_I64 : I<(outs), (ins I64:$index, variable_ops), 53344779Sdim (outs), (ins brlist:$brl), 54344779Sdim [(WebAssemblybr_table I64:$index)], 55344779Sdim "br_table \t$index", "br_table \t$brl", 56344779Sdim 0x0e>; 57292915Sdim} // isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 58292915Sdim 59341825Sdim// This is technically a control-flow instruction, since all it affects is the 60341825Sdim// IP. 61341825Sdimdefm NOP : NRI<(outs), (ins), [], "nop", 0x01>; 62341825Sdim 63341825Sdim// Placemarkers to indicate the start or end of a block or loop scope. 64321369Sdim// These use/clobber VALUE_STACK to prevent them from being moved into the 65321369Sdim// middle of an expression tree. 66314564Sdimlet Uses = [VALUE_STACK], Defs = [VALUE_STACK] in { 67344779Sdimdefm BLOCK : NRI<(outs), (ins Signature:$sig), [], "block \t$sig", 0x02>; 68344779Sdimdefm LOOP : NRI<(outs), (ins Signature:$sig), [], "loop \t$sig", 0x03>; 69292915Sdim 70344779Sdimdefm IF : I<(outs), (ins Signature:$sig, I32:$cond), 71344779Sdim (outs), (ins Signature:$sig), 72344779Sdim [], "if \t$sig, $cond", "if \t$sig", 0x04>; 73344779Sdimdefm ELSE : NRI<(outs), (ins), [], "else", 0x05>; 74344779Sdim 75344779Sdim// END_BLOCK, END_LOOP, END_IF and END_FUNCTION are represented with the same 76344779Sdim// opcode in wasm. 77341825Sdimdefm END_BLOCK : NRI<(outs), (ins), [], "end_block", 0x0b>; 78341825Sdimdefm END_LOOP : NRI<(outs), (ins), [], "end_loop", 0x0b>; 79344779Sdimdefm END_IF : NRI<(outs), (ins), [], "end_if", 0x0b>; 80353358Sdim// Generic instruction, for disassembler. 81353358Sdimlet IsCanonical = 1 in 82353358Sdimdefm END : NRI<(outs), (ins), [], "end", 0x0b>; 83321369Sdimlet isTerminator = 1, isBarrier = 1 in 84341825Sdimdefm END_FUNCTION : NRI<(outs), (ins), [], "end_function", 0x0b>; 85314564Sdim} // Uses = [VALUE_STACK], Defs = [VALUE_STACK] 86314564Sdim 87292915Sdim 88292915Sdimlet isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 in { 89314564Sdim 90292915Sdimlet isReturn = 1 in { 91309124Sdim 92360784Sdimdefm RETURN : I<(outs), (ins variable_ops), (outs), (ins), 93360784Sdim [(WebAssemblyreturn)], 94360784Sdim "return", "return", 0x0f>; 95360784Sdim// Equivalent to RETURN, for use at the end of a function when wasm 96360784Sdim// semantics return by falling off the end of the block. 97360784Sdimlet isCodeGenOnly = 1 in 98360784Sdimdefm FALLTHROUGH_RETURN : I<(outs), (ins variable_ops), (outs), (ins), []>; 99314564Sdim 100292915Sdim} // isReturn = 1 101314564Sdim 102341825Sdimdefm UNREACHABLE : NRI<(outs), (ins), [(trap)], "unreachable", 0x00>; 103341825Sdim} // isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 104314564Sdim 105341825Sdim//===----------------------------------------------------------------------===// 106341825Sdim// Exception handling instructions 107341825Sdim//===----------------------------------------------------------------------===// 108321369Sdim 109341825Sdimlet Predicates = [HasExceptionHandling] in { 110341825Sdim 111341825Sdim// Throwing an exception: throw / rethrow 112341825Sdimlet isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 in { 113353358Sdimdefm THROW : I<(outs), (ins event_op:$tag, variable_ops), 114353358Sdim (outs), (ins event_op:$tag), 115353358Sdim [(WebAssemblythrow (WebAssemblywrapper texternalsym:$tag))], 116353358Sdim "throw \t$tag", "throw \t$tag", 0x08>; 117353358Sdimdefm RETHROW : I<(outs), (ins EXNREF:$exn), (outs), (ins), [], 118353358Sdim "rethrow \t$exn", "rethrow", 0x09>; 119353358Sdim// Pseudo instruction to be the lowering target of int_wasm_rethrow_in_catch 120353358Sdim// intrinsic. Will be converted to the real rethrow instruction later. 121353358Sdimlet isPseudo = 1 in 122353358Sdimdefm RETHROW_IN_CATCH : NRI<(outs), (ins), [(int_wasm_rethrow_in_catch)], 123353358Sdim "rethrow_in_catch", 0>; 124292915Sdim} // isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 125292915Sdim 126341825Sdim// Region within which an exception is caught: try / end_try 127341825Sdimlet Uses = [VALUE_STACK], Defs = [VALUE_STACK] in { 128341825Sdimdefm TRY : NRI<(outs), (ins Signature:$sig), [], "try \t$sig", 0x06>; 129341825Sdimdefm END_TRY : NRI<(outs), (ins), [], "end_try", 0x0b>; 130341825Sdim} // Uses = [VALUE_STACK], Defs = [VALUE_STACK] 131341825Sdim 132353358Sdim// Catching an exception: catch / extract_exception 133353358Sdimlet hasCtrlDep = 1, hasSideEffects = 1 in 134353358Sdimdefm CATCH : I<(outs EXNREF:$dst), (ins), (outs), (ins), [], 135353358Sdim "catch \t$dst", "catch", 0x07>; 136341825Sdim 137353358Sdim// Querying / extracing exception: br_on_exn 138353358Sdim// br_on_exn queries an exnref to see if it matches the corresponding exception 139353358Sdim// tag index. If true it branches to the given label and pushes the 140353358Sdim// corresponding argument values of the exception onto the stack. 141353358Sdimlet isBranch = 1, isTerminator = 1, hasCtrlDep = 1 in 142353358Sdimdefm BR_ON_EXN : I<(outs), (ins bb_op:$dst, event_op:$tag, EXNREF:$exn), 143353358Sdim (outs), (ins bb_op:$dst, event_op:$tag), [], 144353358Sdim "br_on_exn \t$dst, $tag, $exn", "br_on_exn \t$dst, $tag", 145353358Sdim 0x0a>; 146353358Sdim// This is a pseudo instruction that simulates popping a value from stack, which 147353358Sdim// has been pushed by br_on_exn 148353358Sdimlet isCodeGenOnly = 1, hasSideEffects = 1 in 149353358Sdimdefm EXTRACT_EXCEPTION_I32 : NRI<(outs I32:$dst), (ins), 150353358Sdim [(set I32:$dst, (int_wasm_extract_exception))], 151353358Sdim "extract_exception\t$dst">; 152353358Sdim 153341825Sdim// Pseudo instructions: cleanupret / catchret 154341825Sdimlet isTerminator = 1, hasSideEffects = 1, isBarrier = 1, hasCtrlDep = 1, 155353358Sdim isPseudo = 1, isEHScopeReturn = 1 in { 156353358Sdim defm CLEANUPRET : NRI<(outs), (ins), [(cleanupret)], "cleanupret", 0>; 157341825Sdim defm CATCHRET : NRI<(outs), (ins bb_op:$dst, bb_op:$from), 158353358Sdim [(catchret bb:$dst, bb:$from)], "catchret", 0>; 159353358Sdim} // isTerminator = 1, hasSideEffects = 1, isBarrier = 1, hasCtrlDep = 1, 160353358Sdim // isPseudo = 1, isEHScopeReturn = 1 161353358Sdim} // Predicates = [HasExceptionHandling] 162