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