1; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -wasm-temporary-workarounds=false -mattr=+sign-ext,+simd128 | FileCheck %s 2; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -fast-isel -fast-isel-abort=1 -wasm-temporary-workarounds=false -mattr=+sign-ext,+simd128 | 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 <16 x i8> @v128_nullary() 16declare void @void_nullary() 17 18; CHECK-LABEL: call_i32_nullary: 19; CHECK-NEXT: .result i32{{$}} 20; CHECK-NEXT: {{^}} i32.call $push[[NUM:[0-9]+]]=, i32_nullary@FUNCTION{{$}} 21; CHECK-NEXT: return $pop[[NUM]]{{$}} 22define i32 @call_i32_nullary() { 23 %r = call i32 @i32_nullary() 24 ret i32 %r 25} 26 27; CHECK-LABEL: call_i64_nullary: 28; CHECK-NEXT: .result i64{{$}} 29; CHECK-NEXT: {{^}} i64.call $push[[NUM:[0-9]+]]=, i64_nullary@FUNCTION{{$}} 30; CHECK-NEXT: return $pop[[NUM]]{{$}} 31define i64 @call_i64_nullary() { 32 %r = call i64 @i64_nullary() 33 ret i64 %r 34} 35 36; CHECK-LABEL: call_float_nullary: 37; CHECK-NEXT: .result f32{{$}} 38; CHECK-NEXT: {{^}} f32.call $push[[NUM:[0-9]+]]=, float_nullary@FUNCTION{{$}} 39; CHECK-NEXT: return $pop[[NUM]]{{$}} 40define float @call_float_nullary() { 41 %r = call float @float_nullary() 42 ret float %r 43} 44 45; CHECK-LABEL: call_double_nullary: 46; CHECK-NEXT: .result f64{{$}} 47; CHECK-NEXT: {{^}} f64.call $push[[NUM:[0-9]+]]=, double_nullary@FUNCTION{{$}} 48; CHECK-NEXT: return $pop[[NUM]]{{$}} 49define double @call_double_nullary() { 50 %r = call double @double_nullary() 51 ret double %r 52} 53 54; CHECK-LABEL: call_v128_nullary: 55; CHECK-NEXT: .result v128{{$}} 56; CHECK-NEXT: {{^}} v128.call $push[[NUM:[0-9]+]]=, v128_nullary@FUNCTION{{$}} 57; CHECK-NEXT: return $pop[[NUM]]{{$}} 58define <16 x i8> @call_v128_nullary() { 59 %r = call <16 x i8> @v128_nullary() 60 ret <16 x i8> %r 61} 62 63; CHECK-LABEL: call_void_nullary: 64; CHECK-NEXT: {{^}} call void_nullary@FUNCTION{{$}} 65; CHECK-NEXT: return{{$}} 66define void @call_void_nullary() { 67 call void @void_nullary() 68 ret void 69} 70 71; CHECK-LABEL: call_i32_unary: 72; CHECK-NEXT: .param i32{{$}} 73; CHECK-NEXT: .result i32{{$}} 74; CHECK-NEXT: get_local $push[[L0:[0-9]+]]=, 0{{$}} 75; CHECK-NEXT: {{^}} i32.call $push[[NUM:[0-9]+]]=, i32_unary@FUNCTION, $pop[[L0]]{{$}} 76; CHECK-NEXT: return $pop[[NUM]]{{$}} 77define i32 @call_i32_unary(i32 %a) { 78 %r = call i32 @i32_unary(i32 %a) 79 ret i32 %r 80} 81 82; CHECK-LABEL: call_i32_binary: 83; CHECK-NEXT: .param i32, i32{{$}} 84; CHECK-NEXT: .result i32{{$}} 85; CHECK-NEXT: get_local $push[[L0:[0-9]+]]=, 0{{$}} 86; CHECK-NEXT: get_local $push[[L1:[0-9]+]]=, 1{{$}} 87; CHECK-NEXT: {{^}} i32.call $push[[NUM:[0-9]+]]=, i32_binary@FUNCTION, $pop[[L0]], $pop[[L1]]{{$}} 88; CHECK-NEXT: return $pop[[NUM]]{{$}} 89define i32 @call_i32_binary(i32 %a, i32 %b) { 90 %r = call i32 @i32_binary(i32 %a, i32 %b) 91 ret i32 %r 92} 93 94; CHECK-LABEL: call_indirect_void: 95; CHECK-NEXT: .param i32{{$}} 96; CHECK-NEXT: get_local $push[[L0:[0-9]+]]=, 0{{$}} 97; CHECK-NEXT: {{^}} call_indirect $pop[[L0]]{{$}} 98; CHECK-NEXT: return{{$}} 99define void @call_indirect_void(void ()* %callee) { 100 call void %callee() 101 ret void 102} 103 104; CHECK-LABEL: call_indirect_i32: 105; CHECK-NEXT: .param i32{{$}} 106; CHECK-NEXT: .result i32{{$}} 107; CHECK-NEXT: get_local $push[[L0:[0-9]+]]=, 0{{$}} 108; CHECK-NEXT: {{^}} i32.call_indirect $push[[NUM:[0-9]+]]=, $pop[[L0]]{{$}} 109; CHECK-NEXT: return $pop[[NUM]]{{$}} 110define i32 @call_indirect_i32(i32 ()* %callee) { 111 %t = call i32 %callee() 112 ret i32 %t 113} 114 115; CHECK-LABEL: call_indirect_i64: 116; CHECK-NEXT: .param i32{{$}} 117; CHECK-NEXT: .result i64{{$}} 118; CHECK-NEXT: get_local $push[[L0:[0-9]+]]=, 0{{$}} 119; CHECK-NEXT: {{^}} i64.call_indirect $push[[NUM:[0-9]+]]=, $pop[[L0]]{{$}} 120; CHECK-NEXT: return $pop[[NUM]]{{$}} 121define i64 @call_indirect_i64(i64 ()* %callee) { 122 %t = call i64 %callee() 123 ret i64 %t 124} 125 126; CHECK-LABEL: call_indirect_float: 127; CHECK-NEXT: .param i32{{$}} 128; CHECK-NEXT: .result f32{{$}} 129; CHECK-NEXT: get_local $push[[L0:[0-9]+]]=, 0{{$}} 130; CHECK-NEXT: {{^}} f32.call_indirect $push[[NUM:[0-9]+]]=, $pop[[L0]]{{$}} 131; CHECK-NEXT: return $pop[[NUM]]{{$}} 132define float @call_indirect_float(float ()* %callee) { 133 %t = call float %callee() 134 ret float %t 135} 136 137; CHECK-LABEL: call_indirect_double: 138; CHECK-NEXT: .param i32{{$}} 139; CHECK-NEXT: .result f64{{$}} 140; CHECK-NEXT: get_local $push[[L0:[0-9]+]]=, 0{{$}} 141; CHECK-NEXT: {{^}} f64.call_indirect $push[[NUM:[0-9]+]]=, $pop[[L0]]{{$}} 142; CHECK-NEXT: return $pop[[NUM]]{{$}} 143define double @call_indirect_double(double ()* %callee) { 144 %t = call double %callee() 145 ret double %t 146} 147 148; CHECK-LABEL: call_indirect_v128: 149; CHECK-NEXT: .param i32{{$}} 150; CHECK-NEXT: .result v128{{$}} 151; CHECK-NEXT: get_local $push[[L0:[0-9]+]]=, 0{{$}} 152; CHECK-NEXT: {{^}} v128.call_indirect $push[[NUM:[0-9]+]]=, $pop[[L0]]{{$}} 153; CHECK-NEXT: return $pop[[NUM]]{{$}} 154define <16 x i8> @call_indirect_v128(<16 x i8> ()* %callee) { 155 %t = call <16 x i8> %callee() 156 ret <16 x i8> %t 157} 158 159; CHECK-LABEL: call_indirect_arg: 160; CHECK-NEXT: .param i32, i32{{$}} 161; CHECK-NEXT: get_local $push[[L0:[0-9]+]]=, 1{{$}} 162; CHECK-NEXT: get_local $push[[L1:[0-9]+]]=, 0{{$}} 163; CHECK-NEXT: {{^}} call_indirect $pop[[L0]], $pop[[L1]]{{$}} 164; CHECK-NEXT: return{{$}} 165define void @call_indirect_arg(void (i32)* %callee, i32 %arg) { 166 call void %callee(i32 %arg) 167 ret void 168} 169 170; CHECK-LABEL: call_indirect_arg_2: 171; CHECK-NEXT: .param i32, i32, i32{{$}} 172; CHECK-NEXT: get_local $push[[L0:[0-9]+]]=, 1{{$}} 173; CHECK-NEXT: get_local $push[[L1:[0-9]+]]=, 2{{$}} 174; CHECK-NEXT: get_local $push[[L2:[0-9]+]]=, 0{{$}} 175; CHECK-NEXT: {{^}} i32.call_indirect $push[[NUM:[0-9]+]]=, $pop[[L0]], $pop[[L1]], $pop[[L2]]{{$}} 176; CHECK-NEXT: drop $pop[[NUM]]{{$}} 177; CHECK-NEXT: return{{$}} 178define void @call_indirect_arg_2(i32 (i32, i32)* %callee, i32 %arg, i32 %arg2) { 179 call i32 %callee(i32 %arg, i32 %arg2) 180 ret void 181} 182 183; CHECK-LABEL: tail_call_void_nullary: 184; CHECK-NEXT: {{^}} call void_nullary@FUNCTION{{$}} 185; CHECK-NEXT: return{{$}} 186define void @tail_call_void_nullary() { 187 tail call void @void_nullary() 188 ret void 189} 190 191; CHECK-LABEL: fastcc_tail_call_void_nullary: 192; CHECK-NEXT: {{^}} call void_nullary@FUNCTION{{$}} 193; CHECK-NEXT: return{{$}} 194define void @fastcc_tail_call_void_nullary() { 195 tail call fastcc void @void_nullary() 196 ret void 197} 198 199; CHECK-LABEL: coldcc_tail_call_void_nullary: 200; CHECK-NEXT: {{^}} call void_nullary@FUNCTION{{$}} 201; CHECK-NEXT: return{{$}} 202define void @coldcc_tail_call_void_nullary() { 203 tail call coldcc void @void_nullary() 204 ret void 205} 206 207; CHECK-LABEL: call_constexpr: 208; CHECK-NEXT: i32.const $push[[L0:[0-9]+]]=, 2{{$}} 209; CHECK-NEXT: i32.const $push[[L1:[0-9]+]]=, 3{{$}} 210; CHECK-NEXT: call .Lvararg_func_bitcast@FUNCTION, $pop[[L0]], $pop[[L1]]{{$}} 211; CHECK-NEXT: call other_void_nullary@FUNCTION{{$}} 212; CHECK-NEXT: call void_nullary@FUNCTION{{$}} 213; CHECK-NEXT: return{{$}} 214declare void @vararg_func(...) 215declare void @other_void_nullary() 216define void @call_constexpr() { 217bb0: 218 call void bitcast (void (...)* @vararg_func to void (i32, i32)*)(i32 2, i32 3) 219 br label %bb1 220bb1: 221 call void select (i1 0, void ()* @void_nullary, void ()* @other_void_nullary)() 222 br label %bb2 223bb2: 224 call void inttoptr (i32 ptrtoint (void ()* @void_nullary to i32) to void ()*)() 225 ret void 226} 227 228; TODO: test the following: 229; - More argument combinations. 230; - Tail call. 231; - Interesting returns (struct, multiple). 232; - Vararg. 233