1; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -mattr=+multivalue,+tail-call | FileCheck %s
2; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -mattr=+reference-types,+multivalue,+tail-call | FileCheck --check-prefix REF %s
3; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+multivalue,+tail-call | FileCheck %s --check-prefix REGS
4; RUN: llc < %s --filetype=obj -mattr=+multivalue,+tail-call | obj2yaml | FileCheck %s --check-prefix OBJ
5
6; Test that the multivalue calls, returns, function types, and block
7; types work as expected.
8
9target triple = "wasm32-unknown-unknown"
10
11%pair = type { i32, i64 }
12%rpair = type { i64, i32 }
13
14declare void @use_i32(i32)
15declare void @use_i64(i64)
16
17; CHECK-LABEL: pair_const:
18; CHECK-NEXT: .functype pair_const () -> (i32, i64)
19; CHECK-NEXT: i32.const 42{{$}}
20; CHECK-NEXT: i64.const 42{{$}}
21; CHECK-NEXT: end_function{{$}}
22define %pair @pair_const() {
23  ret %pair { i32 42, i64 42 }
24}
25
26; CHECK-LABEL: pair_ident:
27; CHECK-NEXT: .functype pair_ident (i32, i64) -> (i32, i64)
28; CHECK-NEXT: local.get 0{{$}}
29; CHECK-NEXT: local.get 1{{$}}
30; CHECK-NEXT: end_function{{$}}
31define %pair @pair_ident(%pair %p) {
32  ret %pair %p
33}
34
35; CHECK-LABEL: pair_call:
36; CHECK-NEXT: .functype pair_call () -> ()
37; CHECK-NEXT: call pair_const{{$}}
38; CHECK-NEXT: drop{{$}}
39; CHECK-NEXT: drop{{$}}
40; CHECK-NEXT: end_function{{$}}
41; REGS: call $drop=, $drop=, pair_const{{$}}
42define void @pair_call() {
43  %p = call %pair @pair_const()
44  ret void
45}
46
47; CHECK-LABEL: pair_call_return:
48; CHECK-NEXT: .functype pair_call_return () -> (i32, i64)
49; CHECK-NEXT: call pair_const{{$}}
50; CHECK-NEXT: end_function{{$}}
51; REGS: call $push{{[0-9]+}}=, $push{{[0-9]+}}=, pair_const{{$}}
52define %pair @pair_call_return() {
53  %p = call %pair @pair_const()
54  ret %pair %p
55}
56
57; CHECK-LABEL: pair_call_indirect:
58; CHECK-NEXT: .functype pair_call_indirect (i32) -> (i32, i64)
59; CHECK-NEXT: local.get 0{{$}}
60; CHECK-NEXT: call_indirect () -> (i32, i64){{$}}
61; REF:        call_indirect __indirect_function_table, () -> (i32, i64){{$}}
62; CHECK-NEXT: end_function{{$}}
63; REGS: call_indirect $push{{[0-9]+}}=, $push{{[0-9]+}}=, $0{{$}}
64define %pair @pair_call_indirect(%pair()* %f) {
65  %p = call %pair %f()
66  ret %pair %p
67}
68
69; CHECK-LABEL: pair_tail_call:
70; CHECK-NEXT: .functype pair_tail_call () -> (i32, i64)
71; CHECK-NEXT: return_call pair_const{{$}}
72; CHECK-NEXT: end_function{{$}}
73; REGS: return_call pair_const{{$}}
74define %pair @pair_tail_call() {
75  %p = musttail call %pair @pair_const()
76  ret %pair %p
77}
78
79; CHECK-LABEL: pair_call_return_first:
80; CHECK-NEXT: .functype pair_call_return_first () -> (i32)
81; CHECK-NEXT: call pair_const{{$}}
82; CHECK-NEXT: drop{{$}}
83; CHECK-NEXT: end_function{{$}}
84; REGS: call $push{{[0-9]+}}=, $drop=, pair_const{{$}}
85define i32 @pair_call_return_first() {
86  %p = call %pair @pair_const()
87  %v = extractvalue %pair %p, 0
88  ret i32 %v
89}
90
91; CHECK-LABEL: pair_call_return_second:
92; CHECK-NEXT: .functype pair_call_return_second () -> (i64)
93; CHECK-NEXT: .local i64{{$}}
94; CHECK-NEXT: call pair_const{{$}}
95; CHECK-NEXT: local.set 0{{$}}
96; CHECK-NEXT: drop{{$}}
97; CHECK-NEXT: local.get 0{{$}}
98; CHECK-NEXT: end_function{{$}}
99; REGS: call $drop=, $0=, pair_const{{$}}
100define i64 @pair_call_return_second() {
101  %p = call %pair @pair_const()
102  %v = extractvalue %pair %p, 1
103  ret i64 %v
104}
105
106; CHECK-LABEL: pair_call_use_first:
107; CHECK-NEXT: .functype pair_call_use_first () -> ()
108; CHECK-NEXT: call pair_const{{$}}
109; CHECK-NEXT: drop{{$}}
110; CHECK-NEXT: call use_i32{{$}}
111; CHECK-NEXT: end_function{{$}}
112; REGS: call $push{{[0-9]+}}=, $drop=, pair_const{{$}}
113define void @pair_call_use_first() {
114  %p = call %pair @pair_const()
115  %v = extractvalue %pair %p, 0
116  call void @use_i32(i32 %v)
117  ret void
118}
119
120; CHECK-LABEL: pair_call_use_second:
121; CHECK-NEXT: .functype pair_call_use_second () -> ()
122; CHECK-NEXT: .local i64
123; CHECK-NEXT: call pair_const{{$}}
124; CHECK-NEXT: local.set 0{{$}}
125; CHECK-NEXT: drop{{$}}
126; CHECK-NEXT: local.get 0{{$}}
127; CHECK-NEXT: call use_i64{{$}}
128; CHECK-NEXT: end_function{{$}}
129; REGS: call $drop=, $0=, pair_const{{$}}
130define void @pair_call_use_second() {
131  %p = call %pair @pair_const()
132  %v = extractvalue %pair %p, 1
133  call void @use_i64(i64 %v)
134  ret void
135}
136
137; CHECK-LABEL: pair_call_use_first_return_second:
138; CHECK-NEXT: .functype pair_call_use_first_return_second () -> (i64)
139; CHECK-NEXT: .local i64{{$}}
140; CHECK-NEXT: call pair_const{{$}}
141; CHECK-NEXT: local.set 0{{$}}
142; CHECK-NEXT: call use_i32{{$}}
143; CHECK-NEXT: local.get 0{{$}}
144; CHECK-NEXT: end_function{{$}}
145; REGS: call $push{{[0-9]+}}=, $0=, pair_const{{$}}
146define i64 @pair_call_use_first_return_second() {
147  %p = call %pair @pair_const()
148  %v = extractvalue %pair %p, 0
149  call void @use_i32(i32 %v)
150  %r = extractvalue %pair %p, 1
151  ret i64 %r
152}
153
154; CHECK-LABEL: pair_call_use_second_return_first:
155; CHECK-NEXT: .functype pair_call_use_second_return_first () -> (i32)
156; CHECK-NEXT: .local i32, i64{{$}}
157; CHECK-NEXT: call pair_const{{$}}
158; CHECK-NEXT: local.set 1{{$}}
159; CHECK-NEXT: local.set 0{{$}}
160; CHECK-NEXT: local.get 1{{$}}
161; CHECK-NEXT: call use_i64{{$}}
162; CHECK-NEXT: local.get 0{{$}}
163; CHECK-NEXT: end_function{{$}}
164; REGS: call $0=, $1=, pair_const{{$}}
165define i32 @pair_call_use_second_return_first() {
166  %p = call %pair @pair_const()
167  %v = extractvalue %pair %p, 1
168  call void @use_i64(i64 %v)
169  %r = extractvalue %pair %p, 0
170  ret i32 %r
171}
172
173; CHECK-LABEL: pair_pass_through:
174; CHECK-NEXT: .functype pair_pass_through (i32, i64) -> (i32, i64)
175; CHECK-NEXT: local.get 0
176; CHECK-NEXT: local.get 1
177; CHECK-NEXT: call pair_ident{{$}}
178; CHECK-NEXT: end_function{{$}}
179; REGS: call $push{{[0-9]+}}=, $push{{[0-9]+}}=, pair_ident, $0, $1{{$}}
180define %pair @pair_pass_through(%pair %p) {
181  %r = call %pair @pair_ident(%pair %p)
182  ret %pair %r
183}
184
185; CHECK-LABEL: pair_swap:
186; CHECK-NEXT: .functype pair_swap (i32, i64) -> (i64, i32)
187; CHECK-NEXT: local.get 1{{$}}
188; CHECK-NEXT: local.get 0{{$}}
189; CHECK-NEXT: end_function{{$}}
190define %rpair @pair_swap(%pair %p) {
191  %first = extractvalue %pair %p, 0
192  %second = extractvalue %pair %p, 1
193  %r1 = insertvalue %rpair undef, i32 %first, 1
194  %r2 = insertvalue %rpair %r1, i64 %second, 0
195  ret %rpair %r2
196}
197
198; CHECK-LABEL: pair_call_swap:
199; CHECK-NEXT: .functype pair_call_swap () -> (i64, i32)
200; CHECK-NEXT: .local i32, i64{{$}}
201; CHECK-NEXT: call pair_const{{$}}
202; CHECK-NEXT: local.set 1{{$}}
203; CHECK-NEXT: local.set 0{{$}}
204; CHECK-NEXT: local.get 1{{$}}
205; CHECK-NEXT: local.get 0{{$}}
206; CHECK-NEXT: end_function{{$}}
207; REGS: call $0=, $1=, pair_const{{$}}
208define %rpair @pair_call_swap() {
209  %p = call %pair @pair_const()
210  %first = extractvalue %pair %p, 0
211  %second = extractvalue %pair %p, 1
212  %r1 = insertvalue %rpair undef, i32 %first, 1
213  %r2 = insertvalue %rpair %r1, i64 %second, 0
214  ret %rpair %r2
215}
216
217; CHECK-LABEL: pair_pass_through_swap:
218; CHECK-NEXT: .functype pair_pass_through_swap (i32, i64) -> (i64, i32)
219; CHECK-NEXT: local.get 0{{$}}
220; CHECK-NEXT: local.get 1{{$}}
221; CHECK-NEXT: call pair_ident{{$}}
222; CHECK-NEXT: local.set 1{{$}}
223; CHECK-NEXT: local.set 0{{$}}
224; CHECK-NEXT: local.get 1{{$}}
225; CHECK-NEXT: local.get 0{{$}}
226; CHECK-NEXT: end_function{{$}}
227; REGS: call $0=, $1=, pair_ident, $0, $1{{$}}
228define %rpair @pair_pass_through_swap(%pair %p) {
229  %p1 = call %pair @pair_ident(%pair %p)
230  %first = extractvalue %pair %p1, 0
231  %second = extractvalue %pair %p1, 1
232  %r1 = insertvalue %rpair undef, i32 %first, 1
233  %r2 = insertvalue %rpair %r1, i64 %second, 0
234  ret %rpair %r2
235}
236
237; CHECK-LABEL: minimal_loop:
238; CHECK-NEXT: .functype minimal_loop (i32) -> (i32, i64)
239; CHECK-NEXT: .LBB{{[0-9]+}}_1:
240; CHECK-NEXT: loop () -> (i32, i64)
241; CHECK-NEXT: br 0{{$}}
242; CHECK-NEXT: .LBB{{[0-9]+}}_2:
243; CHECK-NEXT: end_loop{{$}}
244; CHECK-NEXT: end_function{{$}}
245define %pair @minimal_loop(i32* %p) {
246entry:
247  br label %loop
248loop:
249  br label %loop
250}
251
252; CHECK-LABEL: .section .custom_section.target_features
253; CHECK-NEXT: .int8 2
254; CHECK-NEXT: .int8 43
255; CHECK-NEXT: .int8 10
256; CHECK-NEXT: .ascii "multivalue"
257; CHECK-NEXT: .int8 43
258; CHECK-NEXT: .int8 9
259; CHECK-NEXT: .ascii "tail-call"
260
261; OBJ-LABEL:  - Type:            TYPE
262; OBJ-NEXT:     Signatures:
263; OBJ-NEXT:       - Index:           0
264; OBJ-NEXT:         ParamTypes:      []
265; OBJ-NEXT:         ReturnTypes:
266; OBJ-NEXT:           - I32
267; OBJ-NEXT:           - I64
268; OBJ-NEXT:       - Index:           1
269; OBJ-NEXT:         ParamTypes:
270; OBJ-NEXT:           - I32
271; OBJ-NEXT:           - I64
272; OBJ-NEXT:         ReturnTypes:
273; OBJ-NEXT:           - I32
274; OBJ-NEXT:           - I64
275; OBJ-NEXT:       - Index:           2
276; OBJ-NEXT:         ParamTypes:      []
277; OBJ-NEXT:         ReturnTypes:     []
278; OBJ-NEXT:       - Index:           3
279; OBJ-NEXT:         ParamTypes:
280; OBJ-NEXT:           - I32
281; OBJ-NEXT:         ReturnTypes:
282; OBJ-NEXT:           - I32
283; OBJ-NEXT:           - I64
284; OBJ-NEXT:       - Index:           4
285; OBJ-NEXT:         ParamTypes:      []
286; OBJ-NEXT:         ReturnTypes:
287; OBJ-NEXT:           - I32
288; OBJ-NEXT:       - Index:           5
289; OBJ-NEXT:         ParamTypes:      []
290; OBJ-NEXT:         ReturnTypes:
291; OBJ-NEXT:           - I64
292; OBJ-NEXT:       - Index:           6
293; OBJ-NEXT:         ParamTypes:
294; OBJ-NEXT:           - I32
295; OBJ-NEXT:         ReturnTypes:     []
296; OBJ-NEXT:       - Index:           7
297; OBJ-NEXT:         ParamTypes:
298; OBJ-NEXT:           - I64
299; OBJ-NEXT:         ReturnTypes:     []
300; OBJ-NEXT:       - Index:           8
301; OBJ-NEXT:         ParamTypes:
302; OBJ-NEXT:           - I32
303; OBJ-NEXT:           - I64
304; OBJ-NEXT:         ReturnTypes:
305; OBJ-NEXT:           - I64
306; OBJ-NEXT:           - I32
307; OBJ-NEXT:       - Index:           9
308; OBJ-NEXT:         ParamTypes:      []
309; OBJ-NEXT:         ReturnTypes:
310; OBJ-NEXT:           - I64
311; OBJ-NEXT:           - I32
312