1; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-temporary-workarounds=false | FileCheck %s 2; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -fast-isel -fast-isel-abort=1 -wasm-temporary-workarounds=false | FileCheck %s 3 4; Test that basic call operations assemble as expected. 5 6target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" 7target triple = "wasm32-unknown-unknown" 8 9declare i32 @i32_nullary() 10declare i32 @i32_unary(i32) 11declare i32 @i32_binary(i32, i32) 12declare i64 @i64_nullary() 13declare float @float_nullary() 14declare double @double_nullary() 15declare void @void_nullary() 16 17; CHECK-LABEL: call_i32_nullary: 18; CHECK-NEXT: .result i32{{$}} 19; CHECK-NEXT: {{^}} i32.call $push[[NUM:[0-9]+]]=, i32_nullary@FUNCTION{{$}} 20; CHECK-NEXT: return $pop[[NUM]]{{$}} 21define i32 @call_i32_nullary() { 22 %r = call i32 @i32_nullary() 23 ret i32 %r 24} 25 26; CHECK-LABEL: call_i64_nullary: 27; CHECK-NEXT: .result i64{{$}} 28; CHECK-NEXT: {{^}} i64.call $push[[NUM:[0-9]+]]=, i64_nullary@FUNCTION{{$}} 29; CHECK-NEXT: return $pop[[NUM]]{{$}} 30define i64 @call_i64_nullary() { 31 %r = call i64 @i64_nullary() 32 ret i64 %r 33} 34 35; CHECK-LABEL: call_float_nullary: 36; CHECK-NEXT: .result f32{{$}} 37; CHECK-NEXT: {{^}} f32.call $push[[NUM:[0-9]+]]=, float_nullary@FUNCTION{{$}} 38; CHECK-NEXT: return $pop[[NUM]]{{$}} 39define float @call_float_nullary() { 40 %r = call float @float_nullary() 41 ret float %r 42} 43 44; CHECK-LABEL: call_double_nullary: 45; CHECK-NEXT: .result f64{{$}} 46; CHECK-NEXT: {{^}} f64.call $push[[NUM:[0-9]+]]=, double_nullary@FUNCTION{{$}} 47; CHECK-NEXT: return $pop[[NUM]]{{$}} 48define double @call_double_nullary() { 49 %r = call double @double_nullary() 50 ret double %r 51} 52 53; CHECK-LABEL: call_void_nullary: 54; CHECK-NEXT: {{^}} call void_nullary@FUNCTION{{$}} 55; CHECK-NEXT: return{{$}} 56define void @call_void_nullary() { 57 call void @void_nullary() 58 ret void 59} 60 61; CHECK-LABEL: call_i32_unary: 62; CHECK-NEXT: .param i32{{$}} 63; CHECK-NEXT: .result i32{{$}} 64; CHECK-NEXT: get_local $push[[L0:[0-9]+]]=, 0{{$}} 65; CHECK-NEXT: {{^}} i32.call $push[[NUM:[0-9]+]]=, i32_unary@FUNCTION, $pop[[L0]]{{$}} 66; CHECK-NEXT: return $pop[[NUM]]{{$}} 67define i32 @call_i32_unary(i32 %a) { 68 %r = call i32 @i32_unary(i32 %a) 69 ret i32 %r 70} 71 72; CHECK-LABEL: call_i32_binary: 73; CHECK-NEXT: .param i32, i32{{$}} 74; CHECK-NEXT: .result i32{{$}} 75; CHECK-NEXT: get_local $push[[L0:[0-9]+]]=, 0{{$}} 76; CHECK-NEXT: get_local $push[[L1:[0-9]+]]=, 1{{$}} 77; CHECK-NEXT: {{^}} i32.call $push[[NUM:[0-9]+]]=, i32_binary@FUNCTION, $pop[[L0]], $pop[[L1]]{{$}} 78; CHECK-NEXT: return $pop[[NUM]]{{$}} 79define i32 @call_i32_binary(i32 %a, i32 %b) { 80 %r = call i32 @i32_binary(i32 %a, i32 %b) 81 ret i32 %r 82} 83 84; CHECK-LABEL: call_indirect_void: 85; CHECK-NEXT: .param i32{{$}} 86; CHECK-NEXT: get_local $push[[L0:[0-9]+]]=, 0{{$}} 87; CHECK-NEXT: {{^}} call_indirect $pop[[L0]]{{$}} 88; CHECK-NEXT: return{{$}} 89define void @call_indirect_void(void ()* %callee) { 90 call void %callee() 91 ret void 92} 93 94; CHECK-LABEL: call_indirect_i32: 95; CHECK-NEXT: .param i32{{$}} 96; CHECK-NEXT: .result i32{{$}} 97; CHECK-NEXT: get_local $push[[L0:[0-9]+]]=, 0{{$}} 98; CHECK-NEXT: {{^}} i32.call_indirect $push[[NUM:[0-9]+]]=, $pop[[L0]]{{$}} 99; CHECK-NEXT: return $pop[[NUM]]{{$}} 100define i32 @call_indirect_i32(i32 ()* %callee) { 101 %t = call i32 %callee() 102 ret i32 %t 103} 104 105; CHECK-LABEL: call_indirect_arg: 106; CHECK-NEXT: .param i32, i32{{$}} 107; CHECK-NEXT: get_local $push[[L0:[0-9]+]]=, 1{{$}} 108; CHECK-NEXT: get_local $push[[L1:[0-9]+]]=, 0{{$}} 109; CHECK-NEXT: {{^}} call_indirect $pop[[L0]], $pop[[L1]]{{$}} 110; CHECK-NEXT: return{{$}} 111define void @call_indirect_arg(void (i32)* %callee, i32 %arg) { 112 call void %callee(i32 %arg) 113 ret void 114} 115 116; CHECK-LABEL: call_indirect_arg_2: 117; CHECK-NEXT: .param i32, i32, i32{{$}} 118; CHECK-NEXT: get_local $push[[L0:[0-9]+]]=, 1{{$}} 119; CHECK-NEXT: get_local $push[[L1:[0-9]+]]=, 2{{$}} 120; CHECK-NEXT: get_local $push[[L2:[0-9]+]]=, 0{{$}} 121; CHECK-NEXT: {{^}} i32.call_indirect $push[[NUM:[0-9]+]]=, $pop[[L0]], $pop[[L1]], $pop[[L2]]{{$}} 122; CHECK-NEXT: drop $pop[[NUM]]{{$}} 123; CHECK-NEXT: return{{$}} 124define void @call_indirect_arg_2(i32 (i32, i32)* %callee, i32 %arg, i32 %arg2) { 125 call i32 %callee(i32 %arg, i32 %arg2) 126 ret void 127} 128 129; CHECK-LABEL: tail_call_void_nullary: 130; CHECK-NEXT: {{^}} call void_nullary@FUNCTION{{$}} 131; CHECK-NEXT: return{{$}} 132define void @tail_call_void_nullary() { 133 tail call void @void_nullary() 134 ret void 135} 136 137; CHECK-LABEL: fastcc_tail_call_void_nullary: 138; CHECK-NEXT: {{^}} call void_nullary@FUNCTION{{$}} 139; CHECK-NEXT: return{{$}} 140define void @fastcc_tail_call_void_nullary() { 141 tail call fastcc void @void_nullary() 142 ret void 143} 144 145; CHECK-LABEL: coldcc_tail_call_void_nullary: 146; CHECK-NEXT: {{^}} call void_nullary@FUNCTION{{$}} 147; CHECK-NEXT: return{{$}} 148define void @coldcc_tail_call_void_nullary() { 149 tail call coldcc void @void_nullary() 150 ret void 151} 152 153; CHECK-LABEL: call_constexpr: 154; CHECK-NEXT: i32.const $push[[L0:[0-9]+]]=, 2{{$}} 155; CHECK-NEXT: i32.const $push[[L1:[0-9]+]]=, 3{{$}} 156; CHECK-NEXT: call .Lbitcast@FUNCTION, $pop[[L0]], $pop[[L1]]{{$}} 157; CHECK-NEXT: call other_void_nullary@FUNCTION{{$}} 158; CHECK-NEXT: call void_nullary@FUNCTION{{$}} 159; CHECK-NEXT: return{{$}} 160declare void @vararg_func(...) 161declare void @other_void_nullary() 162define void @call_constexpr() { 163bb0: 164 call void bitcast (void (...)* @vararg_func to void (i32, i32)*)(i32 2, i32 3) 165 br label %bb1 166bb1: 167 call void select (i1 0, void ()* @void_nullary, void ()* @other_void_nullary)() 168 br label %bb2 169bb2: 170 call void inttoptr (i32 ptrtoint (void ()* @void_nullary to i32) to void ()*)() 171 ret void 172} 173 174; TODO: test the following: 175; - More argument combinations. 176; - Tail call. 177; - Interesting returns (struct, multiple). 178; - Vararg. 179