1; RUN: llc < %s -asm-verbose=false | FileCheck %s
2
3; Test that basic call operations assemble as expected.
4
5target datalayout = "e-p:32:32-i64:64-n32:64-S128"
6target triple = "wasm32-unknown-unknown"
7
8declare i32 @i32_nullary()
9declare i32 @i32_unary(i32)
10declare i32 @i32_binary(i32, i32)
11declare i64 @i64_nullary()
12declare float @float_nullary()
13declare double @double_nullary()
14declare void @void_nullary()
15
16; CHECK-LABEL: call_i32_nullary:
17; CHECK-NEXT: .result i32
18; CHECK-NEXT: .local i32
19; CHECK-NEXT: call $i32_nullary, push{{$}}
20; CHECK-NEXT: set_local 0, pop
21; CHECK-NEXT: return (get_local 0)
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: .local i64
30; CHECK-NEXT: call $i64_nullary, push{{$}}
31; CHECK-NEXT: set_local 0, pop
32; CHECK-NEXT: return (get_local 0)
33define i64 @call_i64_nullary() {
34  %r = call i64 @i64_nullary()
35  ret i64 %r
36}
37
38; CHECK-LABEL: call_float_nullary:
39; CHECK-NEXT: .result f32
40; CHECK-NEXT: .local f32
41; CHECK-NEXT: call $float_nullary, push{{$}}
42; CHECK-NEXT: set_local 0, pop
43; CHECK-NEXT: return (get_local 0)
44define float @call_float_nullary() {
45  %r = call float @float_nullary()
46  ret float %r
47}
48
49; CHECK-LABEL: call_double_nullary:
50; CHECK-NEXT: .result f64
51; CHECK-NEXT: .local f64
52; CHECK-NEXT: call $double_nullary, push{{$}}
53; CHECK-NEXT: set_local 0, pop
54; CHECK-NEXT: return (get_local 0)
55define double @call_double_nullary() {
56  %r = call double @double_nullary()
57  ret double %r
58}
59
60; CHECK-LABEL: call_void_nullary:
61; CHECK-NEXT: call $void_nullary{{$}}
62; CHECK-NEXT: return
63define void @call_void_nullary() {
64  call void @void_nullary()
65  ret void
66}
67
68; CHECK-LABEL: call_i32_unary:
69; CHECK-NEXT: .param i32
70; CHECK-NEXT: .result i32
71; CHECK-NEXT: .local i32, i32
72; CHECK-NEXT: get_local push, 0
73; CHECK-NEXT: set_local 1, pop
74; CHECK-NEXT: call $i32_unary, push, (get_local 1){{$}}
75; CHECK-NEXT: set_local 2, pop
76; CHECK-NEXT: return (get_local 2)
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
84; CHECK-NEXT: .param i32
85; CHECK-NEXT: .result i32
86; CHECK-NEXT: .local i32, i32, i32
87; CHECK-NEXT: get_local push, 1
88; CHECK-NEXT: set_local 2, pop
89; CHECK-NEXT: get_local push, 0
90; CHECK-NEXT: set_local 3, pop
91; CHECK-NEXT: call $i32_binary, push, (get_local 3), (get_local 2){{$}}
92; CHECK-NEXT: set_local 4, pop
93; CHECK-NEXT: return (get_local 4)
94define i32 @call_i32_binary(i32 %a, i32 %b) {
95  %r = call i32 @i32_binary(i32 %a, i32 %b)
96  ret i32 %r
97}
98
99; CHECK-LABEL: call_indirect_void:
100; CHECK-NEXT: .param i32
101; CHECK-NEXT: .local i32
102; CHECK-NEXT: get_local push, 0
103; CHECK-NEXT: set_local 1, pop
104; CHECK-NEXT: call_indirect (get_local 1){{$}}
105; CHECK-NEXT: return
106define void @call_indirect_void(void ()* %callee) {
107  call void %callee()
108  ret void
109}
110
111; CHECK-LABEL: call_indirect_i32:
112; CHECK-NEXT: .param i32
113; CHECK-NEXT: .result i32
114; CHECK-NEXT: .local i32, i32
115; CHECK-NEXT: get_local push, 0
116; CHECK-NEXT: set_local 1, pop
117; CHECK-NEXT: call_indirect (get_local 1), push{{$}}
118; CHECK-NEXT: set_local 2, pop
119; CHECK-NEXT: return (get_local 2)
120define i32 @call_indirect_i32(i32 ()* %callee) {
121  %t = call i32 %callee()
122  ret i32 %t
123}
124
125; CHECK-LABEL: tail_call_void_nullary:
126; CHECK-NEXT: call $void_nullary{{$}}
127; CHECK-NEXT: return{{$}}
128define void @tail_call_void_nullary() {
129  tail call void @void_nullary()
130  ret void
131}
132
133; CHECK-LABEL: fastcc_tail_call_void_nullary:
134; CHECK-NEXT: call $void_nullary{{$}}
135; CHECK-NEXT: return{{$}}
136define void @fastcc_tail_call_void_nullary() {
137  tail call fastcc void @void_nullary()
138  ret void
139}
140
141; CHECK-LABEL: coldcc_tail_call_void_nullary:
142; CHECK-NEXT: call $void_nullary
143; CHECK-NEXT: return{{$}}
144define void @coldcc_tail_call_void_nullary() {
145  tail call coldcc void @void_nullary()
146  ret void
147}
148
149; FIXME test the following:
150;  - More argument combinations.
151;  - Tail call.
152;  - Interesting returns (struct, multiple).
153;  - Vararg.
154