1*0b57cec5SDimitry Andric//===- WebAssemblyInstrCall.td-WebAssembly Call codegen support -*- tablegen -*- 2*0b57cec5SDimitry Andric// 3*0b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric// 7*0b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric/// 9*0b57cec5SDimitry Andric/// \file 10*0b57cec5SDimitry Andric/// WebAssembly Call operand code-gen constructs. 11*0b57cec5SDimitry Andric/// 12*0b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 13*0b57cec5SDimitry Andric 14*0b57cec5SDimitry Andric// TODO: addr64: These currently assume the callee address is 32-bit. 15*0b57cec5SDimitry Andric// FIXME: add $type to first call_indirect asmstr (and maybe $flags) 16*0b57cec5SDimitry Andric 17*0b57cec5SDimitry Andric// Call sequence markers. These have an immediate which represents the amount of 18*0b57cec5SDimitry Andric// stack space to allocate or free, which is used for varargs lowering. 19*0b57cec5SDimitry Andriclet Uses = [SP32, SP64], Defs = [SP32, SP64], isCodeGenOnly = 1 in { 20*0b57cec5SDimitry Andricdefm ADJCALLSTACKDOWN : NRI<(outs), (ins i32imm:$amt, i32imm:$amt2), 21*0b57cec5SDimitry Andric [(WebAssemblycallseq_start timm:$amt, timm:$amt2)]>; 22*0b57cec5SDimitry Andricdefm ADJCALLSTACKUP : NRI<(outs), (ins i32imm:$amt, i32imm:$amt2), 23*0b57cec5SDimitry Andric [(WebAssemblycallseq_end timm:$amt, timm:$amt2)]>; 24*0b57cec5SDimitry Andric} // Uses = [SP32, SP64], Defs = [SP32, SP64], isCodeGenOnly = 1 25*0b57cec5SDimitry Andric 26*0b57cec5SDimitry Andricmulticlass CALL<ValueType vt, WebAssemblyRegClass rt, string prefix, 27*0b57cec5SDimitry Andric list<Predicate> preds = []> { 28*0b57cec5SDimitry Andric defm CALL_#vt : 29*0b57cec5SDimitry Andric I<(outs rt:$dst), (ins function32_op:$callee, variable_ops), 30*0b57cec5SDimitry Andric (outs), (ins function32_op:$callee), 31*0b57cec5SDimitry Andric [(set (vt rt:$dst), (WebAssemblycall1 (i32 imm:$callee)))], 32*0b57cec5SDimitry Andric !strconcat(prefix, "call\t$dst, $callee"), 33*0b57cec5SDimitry Andric !strconcat(prefix, "call\t$callee"), 34*0b57cec5SDimitry Andric 0x10>, 35*0b57cec5SDimitry Andric Requires<preds>; 36*0b57cec5SDimitry Andric 37*0b57cec5SDimitry Andric let isCodeGenOnly = 1 in 38*0b57cec5SDimitry Andric defm PCALL_INDIRECT_#vt : 39*0b57cec5SDimitry Andric I<(outs rt:$dst), (ins I32:$callee, variable_ops), 40*0b57cec5SDimitry Andric (outs), (ins I32:$callee), 41*0b57cec5SDimitry Andric [(set (vt rt:$dst), (WebAssemblycall1 I32:$callee))], 42*0b57cec5SDimitry Andric "PSEUDO CALL INDIRECT\t$callee", 43*0b57cec5SDimitry Andric "PSEUDO CALL INDIRECT\t$callee">, 44*0b57cec5SDimitry Andric Requires<preds>; 45*0b57cec5SDimitry Andric 46*0b57cec5SDimitry Andric defm CALL_INDIRECT_#vt : 47*0b57cec5SDimitry Andric I<(outs rt:$dst), 48*0b57cec5SDimitry Andric (ins TypeIndex:$type, i32imm:$flags, variable_ops), 49*0b57cec5SDimitry Andric (outs), (ins TypeIndex:$type, i32imm:$flags), 50*0b57cec5SDimitry Andric [], 51*0b57cec5SDimitry Andric !strconcat(prefix, "call_indirect\t$dst"), 52*0b57cec5SDimitry Andric !strconcat(prefix, "call_indirect\t$type"), 53*0b57cec5SDimitry Andric 0x11>, 54*0b57cec5SDimitry Andric Requires<preds>; 55*0b57cec5SDimitry Andric} 56*0b57cec5SDimitry Andric 57*0b57cec5SDimitry Andriclet Uses = [SP32, SP64], isCall = 1 in { 58*0b57cec5SDimitry Andricdefm "" : CALL<i32, I32, "i32.">; 59*0b57cec5SDimitry Andricdefm "" : CALL<i64, I64, "i64.">; 60*0b57cec5SDimitry Andricdefm "" : CALL<f32, F32, "f32.">; 61*0b57cec5SDimitry Andricdefm "" : CALL<f64, F64, "f64.">; 62*0b57cec5SDimitry Andricdefm "" : CALL<exnref, EXNREF, "exnref.", [HasExceptionHandling]>; 63*0b57cec5SDimitry Andricdefm "" : CALL<v16i8, V128, "v128.", [HasSIMD128]>; 64*0b57cec5SDimitry Andricdefm "" : CALL<v8i16, V128, "v128.", [HasSIMD128]>; 65*0b57cec5SDimitry Andricdefm "" : CALL<v4i32, V128, "v128.", [HasSIMD128]>; 66*0b57cec5SDimitry Andricdefm "" : CALL<v2i64, V128, "v128.", [HasSIMD128]>; 67*0b57cec5SDimitry Andricdefm "" : CALL<v4f32, V128, "v128.", [HasSIMD128]>; 68*0b57cec5SDimitry Andricdefm "" : CALL<v2f64, V128, "v128.", [HasSIMD128]>; 69*0b57cec5SDimitry Andric 70*0b57cec5SDimitry Andriclet IsCanonical = 1 in { 71*0b57cec5SDimitry Andricdefm CALL_VOID : 72*0b57cec5SDimitry Andric I<(outs), (ins function32_op:$callee, variable_ops), 73*0b57cec5SDimitry Andric (outs), (ins function32_op:$callee), 74*0b57cec5SDimitry Andric [(WebAssemblycall0 (i32 imm:$callee))], 75*0b57cec5SDimitry Andric "call \t$callee", "call\t$callee", 0x10>; 76*0b57cec5SDimitry Andric 77*0b57cec5SDimitry Andriclet isReturn = 1 in 78*0b57cec5SDimitry Andricdefm RET_CALL : 79*0b57cec5SDimitry Andric I<(outs), (ins function32_op:$callee, variable_ops), 80*0b57cec5SDimitry Andric (outs), (ins function32_op:$callee), 81*0b57cec5SDimitry Andric [(WebAssemblyretcall (i32 imm:$callee))], 82*0b57cec5SDimitry Andric "return_call \t$callee", "return_call\t$callee", 0x12>, 83*0b57cec5SDimitry Andric Requires<[HasTailCall]>; 84*0b57cec5SDimitry Andric 85*0b57cec5SDimitry Andriclet isCodeGenOnly = 1 in 86*0b57cec5SDimitry Andricdefm PCALL_INDIRECT_VOID : 87*0b57cec5SDimitry Andric I<(outs), (ins I32:$callee, variable_ops), 88*0b57cec5SDimitry Andric (outs), (ins I32:$callee), 89*0b57cec5SDimitry Andric [(WebAssemblycall0 I32:$callee)], 90*0b57cec5SDimitry Andric "PSEUDO CALL INDIRECT\t$callee", 91*0b57cec5SDimitry Andric "PSEUDO CALL INDIRECT\t$callee">; 92*0b57cec5SDimitry Andric 93*0b57cec5SDimitry Andricdefm CALL_INDIRECT_VOID : 94*0b57cec5SDimitry Andric I<(outs), (ins TypeIndex:$type, i32imm:$flags, variable_ops), 95*0b57cec5SDimitry Andric (outs), (ins TypeIndex:$type, i32imm:$flags), 96*0b57cec5SDimitry Andric [], 97*0b57cec5SDimitry Andric "call_indirect\t", "call_indirect\t$type", 98*0b57cec5SDimitry Andric 0x11>; 99*0b57cec5SDimitry Andric 100*0b57cec5SDimitry Andriclet isReturn = 1 in 101*0b57cec5SDimitry Andricdefm RET_CALL_INDIRECT : 102*0b57cec5SDimitry Andric I<(outs), (ins TypeIndex:$type, i32imm:$flags, variable_ops), 103*0b57cec5SDimitry Andric (outs), (ins TypeIndex:$type, i32imm:$flags), 104*0b57cec5SDimitry Andric [], 105*0b57cec5SDimitry Andric "return_call_indirect\t", "return_call_indirect\t$type", 106*0b57cec5SDimitry Andric 0x13>, 107*0b57cec5SDimitry Andric Requires<[HasTailCall]>; 108*0b57cec5SDimitry Andric 109*0b57cec5SDimitry Andriclet isCodeGenOnly = 1, isReturn = 1 in 110*0b57cec5SDimitry Andricdefm PRET_CALL_INDIRECT: 111*0b57cec5SDimitry Andric I<(outs), (ins I32:$callee, variable_ops), 112*0b57cec5SDimitry Andric (outs), (ins I32:$callee), 113*0b57cec5SDimitry Andric [(WebAssemblyretcall I32:$callee)], 114*0b57cec5SDimitry Andric "PSEUDO RET_CALL INDIRECT\t$callee", 115*0b57cec5SDimitry Andric "PSEUDO RET_CALL INDIRECT\t$callee">, 116*0b57cec5SDimitry Andric Requires<[HasTailCall]>; 117*0b57cec5SDimitry Andric 118*0b57cec5SDimitry Andric} // IsCanonical = 1 119*0b57cec5SDimitry Andric} // Uses = [SP32,SP64], isCall = 1 120*0b57cec5SDimitry Andric 121*0b57cec5SDimitry Andric// Patterns for matching a direct call to a global address. 122*0b57cec5SDimitry Andricdef : Pat<(i32 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))), 123*0b57cec5SDimitry Andric (CALL_i32 tglobaladdr:$callee)>; 124*0b57cec5SDimitry Andricdef : Pat<(i64 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))), 125*0b57cec5SDimitry Andric (CALL_i64 tglobaladdr:$callee)>; 126*0b57cec5SDimitry Andricdef : Pat<(f32 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))), 127*0b57cec5SDimitry Andric (CALL_f32 tglobaladdr:$callee)>; 128*0b57cec5SDimitry Andricdef : Pat<(f64 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))), 129*0b57cec5SDimitry Andric (CALL_f64 tglobaladdr:$callee)>; 130*0b57cec5SDimitry Andricdef : Pat<(v16i8 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))), 131*0b57cec5SDimitry Andric (CALL_v16i8 tglobaladdr:$callee)>, Requires<[HasSIMD128]>; 132*0b57cec5SDimitry Andricdef : Pat<(v8i16 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))), 133*0b57cec5SDimitry Andric (CALL_v8i16 tglobaladdr:$callee)>, Requires<[HasSIMD128]>; 134*0b57cec5SDimitry Andricdef : Pat<(v4i32 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))), 135*0b57cec5SDimitry Andric (CALL_v4i32 tglobaladdr:$callee)>, Requires<[HasSIMD128]>; 136*0b57cec5SDimitry Andricdef : Pat<(v2i64 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))), 137*0b57cec5SDimitry Andric (CALL_v2i64 tglobaladdr:$callee)>, Requires<[HasSIMD128]>; 138*0b57cec5SDimitry Andricdef : Pat<(v4f32 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))), 139*0b57cec5SDimitry Andric (CALL_v4f32 tglobaladdr:$callee)>, Requires<[HasSIMD128]>; 140*0b57cec5SDimitry Andricdef : Pat<(v2f64 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))), 141*0b57cec5SDimitry Andric (CALL_v2f64 tglobaladdr:$callee)>, Requires<[HasSIMD128]>; 142*0b57cec5SDimitry Andricdef : Pat<(exnref (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))), 143*0b57cec5SDimitry Andric (CALL_exnref tglobaladdr:$callee)>, 144*0b57cec5SDimitry Andric Requires<[HasExceptionHandling]>; 145*0b57cec5SDimitry Andricdef : Pat<(WebAssemblycall0 (WebAssemblywrapper tglobaladdr:$callee)), 146*0b57cec5SDimitry Andric (CALL_VOID tglobaladdr:$callee)>; 147*0b57cec5SDimitry Andricdef : Pat<(WebAssemblyretcall (WebAssemblywrapper tglobaladdr:$callee)), 148*0b57cec5SDimitry Andric (RET_CALL tglobaladdr:$callee)>, Requires<[HasTailCall]>; 149*0b57cec5SDimitry Andric 150*0b57cec5SDimitry Andric// Patterns for matching a direct call to an external symbol. 151*0b57cec5SDimitry Andricdef : Pat<(i32 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))), 152*0b57cec5SDimitry Andric (CALL_i32 texternalsym:$callee)>; 153*0b57cec5SDimitry Andricdef : Pat<(i64 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))), 154*0b57cec5SDimitry Andric (CALL_i64 texternalsym:$callee)>; 155*0b57cec5SDimitry Andricdef : Pat<(f32 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))), 156*0b57cec5SDimitry Andric (CALL_f32 texternalsym:$callee)>; 157*0b57cec5SDimitry Andricdef : Pat<(f64 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))), 158*0b57cec5SDimitry Andric (CALL_f64 texternalsym:$callee)>; 159*0b57cec5SDimitry Andricdef : Pat<(v16i8 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))), 160*0b57cec5SDimitry Andric (CALL_v16i8 texternalsym:$callee)>, Requires<[HasSIMD128]>; 161*0b57cec5SDimitry Andricdef : Pat<(v8i16 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))), 162*0b57cec5SDimitry Andric (CALL_v8i16 texternalsym:$callee)>, Requires<[HasSIMD128]>; 163*0b57cec5SDimitry Andricdef : Pat<(v4i32 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))), 164*0b57cec5SDimitry Andric (CALL_v4i32 texternalsym:$callee)>, Requires<[HasSIMD128]>; 165*0b57cec5SDimitry Andricdef : Pat<(v2i64 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))), 166*0b57cec5SDimitry Andric (CALL_v2i64 texternalsym:$callee)>, Requires<[HasSIMD128]>; 167*0b57cec5SDimitry Andricdef : Pat<(v4f32 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))), 168*0b57cec5SDimitry Andric (CALL_v4f32 texternalsym:$callee)>, Requires<[HasSIMD128]>; 169*0b57cec5SDimitry Andricdef : Pat<(v2f64 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))), 170*0b57cec5SDimitry Andric (CALL_v2f64 texternalsym:$callee)>, Requires<[HasSIMD128]>; 171*0b57cec5SDimitry Andricdef : Pat<(exnref (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))), 172*0b57cec5SDimitry Andric (CALL_exnref texternalsym:$callee)>, 173*0b57cec5SDimitry Andric Requires<[HasExceptionHandling]>; 174*0b57cec5SDimitry Andricdef : Pat<(WebAssemblycall0 (WebAssemblywrapper texternalsym:$callee)), 175*0b57cec5SDimitry Andric (CALL_VOID texternalsym:$callee)>; 176*0b57cec5SDimitry Andricdef : Pat<(WebAssemblyretcall (WebAssemblywrapper texternalsym:$callee)), 177*0b57cec5SDimitry Andric (RET_CALL texternalsym:$callee)>, Requires<[HasTailCall]>; 178