xref: /llvm-project/llvm/test/CodeGen/AArch64/arm64ec-exit-thunks.ll (revision 2c9c22c6e295b1176225b63ae4cbbceb216da55e)
1; RUN: llc -mtriple=arm64ec-pc-windows-msvc < %s | FileCheck %s
2
3declare void @no_op() nounwind;
4; CHECK-LABEL:    .def    $iexit_thunk$cdecl$v$v;
5; CHECK:          .section        .wowthk$aa,"xr",discard,$iexit_thunk$cdecl$v$v
6; CHECK:          // %bb.0:
7; CHECK-NEXT:     sub     sp, sp, #48
8; CHECK-NEXT:     .seh_stackalloc 48
9; CHECK-NEXT:     stp     x29, x30, [sp, #32]             // 16-byte Folded Spill
10; CHECK-NEXT:     .seh_save_fplr  32
11; CHECK-NEXT:     add     x29, sp, #32
12; CHECK-NEXT:     .seh_add_fp     32
13; CHECK-NEXT:     .seh_endprologue
14; CHECK-NEXT:     adrp    x8, __os_arm64x_dispatch_call_no_redirect
15; CHECK-NEXT:     ldr     x16, [x8, :lo12:__os_arm64x_dispatch_call_no_redirect]
16; CHECK-NEXT:     blr     x16
17; CHECK-NEXT:     .seh_startepilogue
18; CHECK-NEXT:     ldp     x29, x30, [sp, #32]             // 16-byte Folded Reload
19; CHECK-NEXT:     .seh_save_fplr  32
20; CHECK-NEXT:     add     sp, sp, #48
21; CHECK-NEXT:     .seh_stackalloc 48
22; CHECK-NEXT:     .seh_endepilogue
23; CHECK-NEXT:     ret
24; CHECK-NEXT:     .seh_endfunclet
25; CHECK-NEXT:     .seh_endproc
26; CHECK-LABEL:    .def    "#no_op$exit_thunk";
27; CHECK:          .section        .wowthk$aa,"xr",discard,"#no_op$exit_thunk"
28; CHECK:          .weak_anti_dep  no_op
29; CHECK:          .weak_anti_dep  "#no_op"
30; CHECK:          // %bb.0:
31; CHECK-NEXT:     str     x30, [sp, #-16]!                // 8-byte Folded Spill
32; CHECK-NEXT:     .seh_save_reg_x x30, 16
33; CHECK-NEXT:     .seh_endprologue
34; CHECK-NEXT:     adrp    x8, __os_arm64x_check_icall
35; CHECK-NEXT:     adrp    x11, no_op
36; CHECK-NEXT:     add     x11, x11, :lo12:no_op
37; CHECK-NEXT:     ldr     x8, [x8, :lo12:__os_arm64x_check_icall]
38; CHECK-NEXT:     adrp    x10, ($iexit_thunk$cdecl$v$v)
39; CHECK-NEXT:     add     x10, x10, :lo12:($iexit_thunk$cdecl$v$v)
40; CHECK-NEXT:     blr     x8
41; CHECK-NEXT:     .seh_startepilogue
42; CHECK-NEXT:     ldr     x30, [sp], #16                  // 8-byte Folded Reload
43; CHECK-NEXT:     .seh_save_reg_x x30, 16
44; CHECK-NEXT:     .seh_endepilogue
45; CHECK-NEXT:     br      x11
46; CHECK-NEXT:     .seh_endfunclet
47; CHECK-NEXT:     .seh_endproc
48
49declare i64 @simple_integers(i8, i16, i32, i64) nounwind;
50; CHECK-LABEL:    .def    $iexit_thunk$cdecl$i8$i8i8i8i8;
51; CHECK:          .section        .wowthk$aa,"xr",discard,$iexit_thunk$cdecl$i8$i8i8i8i8
52; CHECK:          // %bb.0:
53; CHECK-NEXT:     sub     sp, sp, #48
54; CHECK-NEXT:     .seh_stackalloc 48
55; CHECK-NEXT:     stp     x29, x30, [sp, #32]             // 16-byte Folded Spill
56; CHECK-NEXT:     .seh_save_fplr  32
57; CHECK-NEXT:     add     x29, sp, #32
58; CHECK-NEXT:     .seh_add_fp     32
59; CHECK-NEXT:     .seh_endprologue
60; CHECK-NEXT:     adrp    x8, __os_arm64x_dispatch_call_no_redirect
61; CHECK-NEXT:     ldr     x16, [x8, :lo12:__os_arm64x_dispatch_call_no_redirect]
62; CHECK-NEXT:     blr     x16
63; CHECK-NEXT:     mov     x0, x8
64; CHECK-NEXT:     .seh_startepilogue
65; CHECK-NEXT:     ldp     x29, x30, [sp, #32]             // 16-byte Folded Reload
66; CHECK-NEXT:     .seh_save_fplr  32
67; CHECK-NEXT:     add     sp, sp, #48
68; CHECK-NEXT:     .seh_stackalloc 48
69; CHECK-NEXT:     .seh_endepilogue
70; CHECK-NEXT:     ret
71; CHECK-NEXT:     .seh_endfunclet
72; CHECK-NEXT:     .seh_endproc
73; CHECK-LABEL:    .def    "#simple_integers$exit_thunk";
74; CHECK:          .section        .wowthk$aa,"xr",discard,"#simple_integers$exit_thunk"
75; CHECK:          .weak_anti_dep  simple_integers
76; CHECK:          .weak_anti_dep  "#simple_integers"
77; CHECK:          // %bb.0:
78; CHECK-NEXT:     str     x30, [sp, #-16]!                // 8-byte Folded Spill
79; CHECK-NEXT:     .seh_save_reg_x x30, 16
80; CHECK-NEXT:     .seh_endprologue
81; CHECK-NEXT:     adrp    x8, __os_arm64x_check_icall
82; CHECK-NEXT:     adrp    x11, simple_integers
83; CHECK-NEXT:     add     x11, x11, :lo12:simple_integers
84; CHECK-NEXT:     ldr     x8, [x8, :lo12:__os_arm64x_check_icall]
85; CHECK-NEXT:     adrp    x10, ($iexit_thunk$cdecl$i8$i8i8i8i8)
86; CHECK-NEXT:     add     x10, x10, :lo12:($iexit_thunk$cdecl$i8$i8i8i8i8)
87; CHECK-NEXT:     blr     x8
88; CHECK-NEXT:     .seh_startepilogue
89; CHECK-NEXT:     ldr     x30, [sp], #16                  // 8-byte Folded Reload
90; CHECK-NEXT:     .seh_save_reg_x x30, 16
91; CHECK-NEXT:     .seh_endepilogue
92; CHECK-NEXT:     br      x11
93; CHECK-NEXT:     .seh_endfunclet
94; CHECK-NEXT:     .seh_endproc
95
96; NOTE: Only float and double are supported.
97declare double @simple_floats(float, double) nounwind;
98; CHECK-LABEL:    .def    $iexit_thunk$cdecl$d$fd;
99; CHECK:          .section        .wowthk$aa,"xr",discard,$iexit_thunk$cdecl$d$fd
100; CHECK:          // %bb.0:
101; CHECK-NEXT:     sub     sp, sp, #48
102; CHECK-NEXT:     .seh_stackalloc 48
103; CHECK-NEXT:     stp     x29, x30, [sp, #32]             // 16-byte Folded Spill
104; CHECK-NEXT:     .seh_save_fplr  32
105; CHECK-NEXT:     add     x29, sp, #32
106; CHECK-NEXT:     .seh_add_fp     32
107; CHECK-NEXT:     .seh_endprologue
108; CHECK-NEXT:     adrp    x8, __os_arm64x_dispatch_call_no_redirect
109; CHECK-NEXT:     ldr     x16, [x8, :lo12:__os_arm64x_dispatch_call_no_redirect]
110; CHECK-NEXT:     blr     x16
111; CHECK-NEXT:     .seh_startepilogue
112; CHECK-NEXT:     ldp     x29, x30, [sp, #32]             // 16-byte Folded Reload
113; CHECK-NEXT:     .seh_save_fplr  32
114; CHECK-NEXT:     add     sp, sp, #48
115; CHECK-NEXT:     .seh_stackalloc 48
116; CHECK-NEXT:     .seh_endepilogue
117; CHECK-NEXT:     ret
118; CHECK-NEXT:     .seh_endfunclet
119; CHECK-NEXT:     .seh_endproc
120; CHECK-LABEL:    .def    "#simple_floats$exit_thunk";
121; CHECK:          .section        .wowthk$aa,"xr",discard,"#simple_floats$exit_thunk"
122; CHECK:          .weak_anti_dep  simple_floats
123; CHECK:          .weak_anti_dep  "#simple_floats"
124; CHECK:          // %bb.0:
125; CHECK-NEXT:     str     x30, [sp, #-16]!                // 8-byte Folded Spill
126; CHECK-NEXT:     .seh_save_reg_x x30, 16
127; CHECK-NEXT:     .seh_endprologue
128; CHECK-NEXT:     adrp    x8, __os_arm64x_check_icall
129; CHECK-NEXT:     adrp    x11, simple_floats
130; CHECK-NEXT:     add     x11, x11, :lo12:simple_floats
131; CHECK-NEXT:     ldr     x8, [x8, :lo12:__os_arm64x_check_icall]
132; CHECK-NEXT:     adrp    x10, ($iexit_thunk$cdecl$d$fd)
133; CHECK-NEXT:     add     x10, x10, :lo12:($iexit_thunk$cdecl$d$fd)
134; CHECK-NEXT:     blr     x8
135; CHECK-NEXT:     .seh_startepilogue
136; CHECK-NEXT:     ldr     x30, [sp], #16                  // 8-byte Folded Reload
137; CHECK-NEXT:     .seh_save_reg_x x30, 16
138; CHECK-NEXT:     .seh_endepilogue
139; CHECK-NEXT:     br      x11
140; CHECK-NEXT:     .seh_endfunclet
141; CHECK-NEXT:     .seh_endproc
142
143declare void @has_varargs(...) nounwind;
144; CHECK-LABEL:    .def    $iexit_thunk$cdecl$v$varargs;
145; CHECK:          .section        .wowthk$aa,"xr",discard,$iexit_thunk$cdecl$v$varargs
146; CHECK:          // %bb.0:
147; CHECK-NEXT:     sub     sp, sp, #64
148; CHECK-NEXT:     .seh_stackalloc 64
149; CHECK-NEXT:     stp     x29, x30, [sp, #48]             // 16-byte Folded Spill
150; CHECK-NEXT:     .seh_save_fplr  48
151; CHECK-NEXT:     add     x29, sp, #48
152; CHECK-NEXT:     .seh_add_fp     48
153; CHECK-NEXT:     .seh_endprologue
154; CHECK-NEXT:     adrp    x8, __os_arm64x_dispatch_call_no_redirect
155; CHECK-NEXT:     stp     x4, x5, [sp, #32]
156; CHECK-NEXT:     ldr     x16, [x8, :lo12:__os_arm64x_dispatch_call_no_redirect]
157; CHECK-NEXT:     blr     x16
158; CHECK-NEXT:     .seh_startepilogue
159; CHECK-NEXT:     ldp     x29, x30, [sp, #48]             // 16-byte Folded Reload
160; CHECK-NEXT:     .seh_save_fplr  48
161; CHECK-NEXT:     add     sp, sp, #64
162; CHECK-NEXT:     .seh_stackalloc 64
163; CHECK-NEXT:     .seh_endepilogue
164; CHECK-NEXT:     ret
165; CHECK-NEXT:     .seh_endfunclet
166; CHECK-NEXT:     .seh_endproc
167; CHECK-LABEL:    .def    "#has_varargs$exit_thunk";
168; CHECK:          .section        .wowthk$aa,"xr",discard,"#has_varargs$exit_thunk"
169; CHECK:          .weak_anti_dep  has_varargs
170; CHECK:          .weak_anti_dep  "#has_varargs"
171; CHECK:          // %bb.0:
172; CHECK-NEXT:     str     x30, [sp, #-16]!                // 8-byte Folded Spill
173; CHECK-NEXT:     .seh_save_reg_x x30, 16
174; CHECK-NEXT:     .seh_endprologue
175; CHECK-NEXT:     adrp    x8, __os_arm64x_check_icall
176; CHECK-NEXT:     adrp    x11, has_varargs
177; CHECK-NEXT:     add     x11, x11, :lo12:has_varargs
178; CHECK-NEXT:     ldr     x8, [x8, :lo12:__os_arm64x_check_icall]
179; CHECK-NEXT:     adrp    x10, ($iexit_thunk$cdecl$v$varargs)
180; CHECK-NEXT:     add     x10, x10, :lo12:($iexit_thunk$cdecl$v$varargs)
181; CHECK-NEXT:     blr     x8
182; CHECK-NEXT:     .seh_startepilogue
183; CHECK-NEXT:     ldr     x30, [sp], #16                  // 8-byte Folded Reload
184; CHECK-NEXT:     .seh_save_reg_x x30, 16
185; CHECK-NEXT:     .seh_endepilogue
186; CHECK-NEXT:     br      x11
187; CHECK-NEXT:     .seh_endfunclet
188; CHECK-NEXT:     .seh_endproc
189
190declare void @has_sret(ptr sret([100 x i8])) nounwind;
191; CHECK-LABEL:    .def    $iexit_thunk$cdecl$m100$v;
192; CHECK:          .section        .wowthk$aa,"xr",discard,$iexit_thunk$cdecl$m100$v
193; CHECK:          // %bb.0:
194; CHECK-NEXT:     sub     sp, sp, #48
195; CHECK-NEXT:     .seh_stackalloc 48
196; CHECK-NEXT:     stp     x29, x30, [sp, #32]             // 16-byte Folded Spill
197; CHECK-NEXT:     .seh_save_fplr  32
198; CHECK-NEXT:     add     x29, sp, #32
199; CHECK-NEXT:     .seh_add_fp     32
200; CHECK-NEXT:     .seh_endprologue
201; CHECK-NEXT:     mov     x0, x8
202; CHECK-NEXT:     adrp    x8, __os_arm64x_dispatch_call_no_redirect
203; CHECK-NEXT:     ldr     x16, [x8, :lo12:__os_arm64x_dispatch_call_no_redirect]
204; CHECK-NEXT:     blr     x16
205; CHECK-NEXT:     .seh_startepilogue
206; CHECK-NEXT:     ldp     x29, x30, [sp, #32]             // 16-byte Folded Reload
207; CHECK-NEXT:     .seh_save_fplr  32
208; CHECK-NEXT:     add     sp, sp, #48
209; CHECK-NEXT:     .seh_stackalloc 48
210; CHECK-NEXT:     .seh_endepilogue
211; CHECK-NEXT:     ret
212; CHECK-NEXT:     .seh_endfunclet
213; CHECK-NEXT:     .seh_endproc
214; CHECK-LABEL:    .def    "#has_sret$exit_thunk";
215; CHECK:          .section        .wowthk$aa,"xr",discard,"#has_sret$exit_thunk"
216; CHECK:          .weak_anti_dep  has_sret
217; CHECK:          .weak_anti_dep  "#has_sret"
218; CHECK:          // %bb.0:
219; CHECK-NEXT:     str     x30, [sp, #-16]!                // 8-byte Folded Spill
220; CHECK-NEXT:     .seh_save_reg_x x30, 16
221; CHECK-NEXT:     .seh_endprologue
222; CHECK-NEXT:     adrp    x9, __os_arm64x_check_icall
223; CHECK-NEXT:     adrp    x11, has_sret
224; CHECK-NEXT:     add     x11, x11, :lo12:has_sret
225; CHECK-NEXT:     ldr     x9, [x9, :lo12:__os_arm64x_check_icall]
226; CHECK-NEXT:     adrp    x10, ($iexit_thunk$cdecl$m100$v)
227; CHECK-NEXT:     add     x10, x10, :lo12:($iexit_thunk$cdecl$m100$v)
228; CHECK-NEXT:     blr     x9
229; CHECK-NEXT:     .seh_startepilogue
230; CHECK-NEXT:     ldr     x30, [sp], #16                  // 8-byte Folded Reload
231; CHECK-NEXT:     .seh_save_reg_x x30, 16
232; CHECK-NEXT:     .seh_endepilogue
233; CHECK-NEXT:     br      x11
234; CHECK-NEXT:     .seh_endfunclet
235; CHECK-NEXT:     .seh_endproc
236
237%TSRet = type { i64, i64 }
238declare void @has_aligned_sret(ptr align 32 sret(%TSRet)) nounwind;
239; CHECK-LABEL:    .def    $iexit_thunk$cdecl$m16$v;
240; CHECK:          .section        .wowthk$aa,"xr",discard,$iexit_thunk$cdecl$m16$v
241; CHECK:          // %bb.0:
242; CHECK-NEXT:     sub     sp, sp, #48
243; CHECK-NEXT:     .seh_stackalloc 48
244; CHECK-NEXT:     stp     x29, x30, [sp, #32]             // 16-byte Folded Spill
245; CHECK-NEXT:     .seh_save_fplr  32
246; CHECK-NEXT:     add     x29, sp, #32
247; CHECK-NEXT:     .seh_add_fp     32
248; CHECK-NEXT:     .seh_endprologue
249; CHECK-NEXT:     mov     x0, x8
250; CHECK-NEXT:     adrp    x8, __os_arm64x_dispatch_call_no_redirect
251; CHECK-NEXT:     ldr     x16, [x8, :lo12:__os_arm64x_dispatch_call_no_redirect]
252; CHECK-NEXT:     blr     x16
253; CHECK-NEXT:     .seh_startepilogue
254; CHECK-NEXT:     ldp     x29, x30, [sp, #32]             // 16-byte Folded Reload
255; CHECK-NEXT:     .seh_save_fplr  32
256; CHECK-NEXT:     add     sp, sp, #48
257; CHECK-NEXT:     .seh_stackalloc 48
258; CHECK-NEXT:     .seh_endepilogue
259; CHECK-NEXT:     ret
260; CHECK-NEXT:     .seh_endfunclet
261; CHECK-NEXT:     .seh_endproc
262; CHECK-LABEL:    .def    "#has_aligned_sret$exit_thunk";
263; CHECK:          .section        .wowthk$aa,"xr",discard,"#has_aligned_sret$exit_thunk"
264; CHECK:          .weak_anti_dep  has_aligned_sret
265; CHECK:          .weak_anti_dep  "#has_aligned_sret"
266; CHECK:          // %bb.0:
267; CHECK:          str     x30, [sp, #-16]!                // 8-byte Folded Spill
268; CHECK:          .seh_save_reg_x x30, 16
269; CHECK:          .seh_endprologue
270; CHECK:          adrp    x9, __os_arm64x_check_icall
271; CHECK:          adrp    x11, has_aligned_sret
272; CHECK:          add     x11, x11, :lo12:has_aligned_sret
273; CHECK:          ldr     x9, [x9, :lo12:__os_arm64x_check_icall]
274; CHECK:          adrp    x10, ($iexit_thunk$cdecl$m16$v)
275; CHECK:          add     x10, x10, :lo12:($iexit_thunk$cdecl$m16$v)
276; CHECK:          blr     x9
277; CHECK:          .seh_startepilogue
278; CHECK:          ldr     x30, [sp], #16                  // 8-byte Folded Reload
279; CHECK:          .seh_save_reg_x x30, 16
280; CHECK:          .seh_endepilogue
281; CHECK:          br      x11
282; CHECK:          .seh_endfunclet
283; CHECK:          .seh_endproc
284
285declare [2 x i8] @small_array([2 x i8], [2 x float]) nounwind;
286; CHECK-LABEL:    .def    $iexit_thunk$cdecl$m2$m2F8;
287; CHECK:          .section        .wowthk$aa,"xr",discard,$iexit_thunk$cdecl$m2$m2F8
288; CHECK:          // %bb.0:
289; CHECK-NEXT:     sub     sp, sp, #64
290; CHECK-NEXT:     .seh_stackalloc 64
291; CHECK-NEXT:     stp     x29, x30, [sp, #48]             // 16-byte Folded Spill
292; CHECK-NEXT:     .seh_save_fplr  48
293; CHECK-NEXT:     add     x29, sp, #48
294; CHECK-NEXT:     .seh_add_fp     48
295; CHECK-NEXT:     .seh_endprologue
296; CHECK-NEXT:     sturb   w1, [x29, #-1]
297; CHECK-NEXT:     adrp    x8, __os_arm64x_dispatch_call_no_redirect
298; CHECK-NEXT:     sturb   w0, [x29, #-2]
299; CHECK-NEXT:     ldr     x16, [x8, :lo12:__os_arm64x_dispatch_call_no_redirect]
300; CHECK-NEXT:     stp     s0, s1, [x29, #-12]
301; CHECK-NEXT:     ldurh   w0, [x29, #-2]
302; CHECK-NEXT:     ldur    x1, [x29, #-12]
303; CHECK-NEXT:     blr     x16
304; CHECK-NEXT:     mov     w0, w8
305; CHECK-NEXT:     sturh   w8, [x29, #-14]
306; CHECK-NEXT:     ubfx    w1, w8, #8, #8
307; CHECK-NEXT:     .seh_startepilogue
308; CHECK-NEXT:     ldp     x29, x30, [sp, #48]             // 16-byte Folded Reload
309; CHECK-NEXT:     .seh_save_fplr  48
310; CHECK-NEXT:     add     sp, sp, #64
311; CHECK-NEXT:     .seh_stackalloc 64
312; CHECK-NEXT:     .seh_endepilogue
313; CHECK-NEXT:     ret
314; CHECK-NEXT:     .seh_endfunclet
315; CHECK-NEXT:     .seh_endproc
316; CHECK-LABEL:    .def    "#small_array$exit_thunk";
317; CHECK:          .section        .wowthk$aa,"xr",discard,"#small_array$exit_thunk"
318; CHECK:          .weak_anti_dep  small_array
319; CHECK:          .weak_anti_dep  "#small_array"
320; CHECK:          // %bb.0:
321; CHECK-NEXT:     str     x30, [sp, #-16]!                // 8-byte Folded Spill
322; CHECK-NEXT:     .seh_save_reg_x x30, 16
323; CHECK-NEXT:     .seh_endprologue
324; CHECK-NEXT:     adrp    x8, __os_arm64x_check_icall
325; CHECK-NEXT:     adrp    x11, small_array
326; CHECK-NEXT:     add     x11, x11, :lo12:small_array
327; CHECK-NEXT:     ldr     x8, [x8, :lo12:__os_arm64x_check_icall]
328; CHECK-NEXT:     adrp    x10, ($iexit_thunk$cdecl$m2$m2F8)
329; CHECK-NEXT:     add     x10, x10, :lo12:($iexit_thunk$cdecl$m2$m2F8)
330; CHECK-NEXT:     blr     x8
331; CHECK-NEXT:     .seh_startepilogue
332; CHECK-NEXT:     ldr     x30, [sp], #16                  // 8-byte Folded Reload
333; CHECK-NEXT:     .seh_save_reg_x x30, 16
334; CHECK-NEXT:     .seh_endepilogue
335; CHECK-NEXT:     br      x11
336; CHECK-NEXT:     .seh_endfunclet
337; CHECK-NEXT:     .seh_endproc
338
339declare [3 x i64] @large_array([3 x i64], [2 x double], [2 x [2 x i64]]) nounwind;
340; CHECK-LABEL:    .def    $iexit_thunk$cdecl$m24$m24D16m32;
341; CHECK:          .section        .wowthk$aa,"xr",discard,$iexit_thunk$cdecl$m24$m24D16m32
342; CHECK:          // %bb.0:
343; CHECK-NEXT:     sub     sp, sp, #144
344; CHECK-NEXT:     .seh_stackalloc 144
345; CHECK-NEXT:     stp     x29, x30, [sp, #128]            // 16-byte Folded Spill
346; CHECK-NEXT:     .seh_save_fplr  128
347; CHECK-NEXT:     add     x29, sp, #128
348; CHECK-NEXT:     .seh_add_fp     128
349; CHECK-NEXT:     .seh_endprologue
350; CHECK-NEXT:     adrp    x8, __os_arm64x_dispatch_call_no_redirect
351; CHECK-NEXT:     stp     x0, x1, [x29, #-48]
352; CHECK-NEXT:     sub     x0, x29, #24
353; CHECK-NEXT:     ldr     x16, [x8, :lo12:__os_arm64x_dispatch_call_no_redirect]
354; CHECK-NEXT:     stur    x2, [x29, #-32]
355; CHECK-NEXT:     sub     x1, x29, #48
356; CHECK-NEXT:     stp     x3, x4, [sp, #32]
357; CHECK-NEXT:     add     x2, sp, #64
358; CHECK-NEXT:     add     x3, sp, #32
359; CHECK-NEXT:     stp     d0, d1, [sp, #64]
360; CHECK-NEXT:     stp     x5, x6, [sp, #48]
361; CHECK-NEXT:     blr     x16
362; CHECK-NEXT:     ldp     x0, x1, [x29, #-24]
363; CHECK-NEXT:     ldur    x2, [x29, #-8]
364; CHECK-NEXT:     .seh_startepilogue
365; CHECK-NEXT:     ldp     x29, x30, [sp, #128]            // 16-byte Folded Reload
366; CHECK-NEXT:     .seh_save_fplr  128
367; CHECK-NEXT:     add     sp, sp, #144
368; CHECK-NEXT:     .seh_stackalloc 144
369; CHECK-NEXT:     .seh_endepilogue
370; CHECK-NEXT:     ret
371; CHECK-NEXT:     .seh_endfunclet
372; CHECK-NEXT:     .seh_endproc
373; CHECK-LABEL:    .def    "#large_array$exit_thunk";
374; CHECK:          .section        .wowthk$aa,"xr",discard,"#large_array$exit_thunk"
375; CHECK:          .weak_anti_dep  large_array
376; CHECK:          .weak_anti_dep  "#large_array"
377; CHECK:          // %bb.0:
378; CHECK-NEXT:     str     x30, [sp, #-16]!                // 8-byte Folded Spill
379; CHECK-NEXT:     .seh_save_reg_x x30, 16
380; CHECK-NEXT:     .seh_endprologue
381; CHECK-NEXT:     adrp    x8, __os_arm64x_check_icall
382; CHECK-NEXT:     adrp    x11, large_array
383; CHECK-NEXT:     add     x11, x11, :lo12:large_array
384; CHECK-NEXT:     ldr     x8, [x8, :lo12:__os_arm64x_check_icall]
385; CHECK-NEXT:     adrp    x10, ($iexit_thunk$cdecl$m24$m24D16m32)
386; CHECK-NEXT:     add     x10, x10, :lo12:($iexit_thunk$cdecl$m24$m24D16m32)
387; CHECK-NEXT:     blr     x8
388; CHECK-NEXT:     .seh_startepilogue
389; CHECK-NEXT:     ldr     x30, [sp], #16                  // 8-byte Folded Reload
390; CHECK-NEXT:     .seh_save_reg_x x30, 16
391; CHECK-NEXT:     .seh_endepilogue
392; CHECK-NEXT:     br      x11
393; CHECK-NEXT:     .seh_endfunclet
394; CHECK-NEXT:     .seh_endproc
395
396%T1 = type { i16 }
397%T2 = type { i32, float }
398%T3 = type { i64, double }
399%T4 = type { i64, double, i8 }
400declare %T2 @simple_struct(%T1, %T2, %T3, %T4) nounwind;
401; CHECK-LABEL:    .def    $iexit_thunk$cdecl$m8$i8m8m16m24;
402; CHECK:          .section        .wowthk$aa,"xr",discard,$iexit_thunk$cdecl$m8$i8m8m16m24
403; CHECK:          // %bb.0:
404; CHECK-NEXT:     sub     sp, sp, #112
405; CHECK-NEXT:     .seh_stackalloc 112
406; CHECK-NEXT:     stp     x29, x30, [sp, #96]             // 16-byte Folded Spill
407; CHECK-NEXT:     .seh_save_fplr  96
408; CHECK-NEXT:     add     x29, sp, #96
409; CHECK-NEXT:     .seh_add_fp     96
410; CHECK-NEXT:     .seh_endprologue
411; CHECK-NEXT:     stur    w1, [x29, #-8]
412; CHECK-NEXT:     adrp    x8, __os_arm64x_dispatch_call_no_redirect
413; CHECK-NEXT:     stur    s0, [x29, #-4]
414; CHECK-NEXT:     ldr     x16, [x8, :lo12:__os_arm64x_dispatch_call_no_redirect]
415; CHECK-NEXT:     ldur    x1, [x29, #-8]
416; CHECK-NEXT:     stur    x2, [x29, #-24]
417; CHECK-NEXT:     sub     x2, x29, #24
418; CHECK-NEXT:     str     x3, [sp, #48]
419; CHECK-NEXT:     add     x3, sp, #48
420; CHECK-NEXT:     stur    d1, [x29, #-16]
421; CHECK-NEXT:     str     d2, [sp, #56]
422; CHECK-NEXT:     strb    w4, [sp, #64]
423; CHECK-NEXT:     blr     x16
424; CHECK-NEXT:     str     x8, [sp, #40]
425; CHECK-NEXT:     mov     x0, x8
426; CHECK-NEXT:     ldr     s0, [sp, #44]
427; CHECK-NEXT:                                     // kill: def $w0 killed $w0 killed $x0
428; CHECK-NEXT:     .seh_startepilogue
429; CHECK-NEXT:     ldp     x29, x30, [sp, #96]             // 16-byte Folded Reload
430; CHECK-NEXT:     .seh_save_fplr  96
431; CHECK-NEXT:     add     sp, sp, #112
432; CHECK-NEXT:     .seh_stackalloc 112
433; CHECK-NEXT:     .seh_endepilogue
434; CHECK-NEXT:     ret
435; CHECK-NEXT:     .seh_endfunclet
436; CHECK-NEXT:     .seh_endproc
437; CHECK-LABEL:    .def    "#simple_struct$exit_thunk";
438; CHECK:          .section        .wowthk$aa,"xr",discard,"#simple_struct$exit_thunk"
439; CHECK:          .weak_anti_dep  simple_struct
440; CHECK:          .weak_anti_dep  "#simple_struct"
441; CHECK:          // %bb.0:
442; CHECK-NEXT:     str     x30, [sp, #-16]!                // 8-byte Folded Spill
443; CHECK-NEXT:     .seh_save_reg_x x30, 16
444; CHECK-NEXT:     .seh_endprologue
445; CHECK-NEXT:     adrp    x8, __os_arm64x_check_icall
446; CHECK-NEXT:     adrp    x11, simple_struct
447; CHECK-NEXT:     add     x11, x11, :lo12:simple_struct
448; CHECK-NEXT:     ldr     x8, [x8, :lo12:__os_arm64x_check_icall]
449; CHECK-NEXT:     adrp    x10, ($iexit_thunk$cdecl$m8$i8m8m16m24)
450; CHECK-NEXT:     add     x10, x10, :lo12:($iexit_thunk$cdecl$m8$i8m8m16m24)
451; CHECK-NEXT:     blr     x8
452; CHECK-NEXT:     .seh_startepilogue
453; CHECK-NEXT:     ldr     x30, [sp], #16                  // 8-byte Folded Reload
454; CHECK-NEXT:     .seh_save_reg_x x30, 16
455; CHECK-NEXT:     .seh_endepilogue
456; CHECK-NEXT:     br      x11
457; CHECK-NEXT:     .seh_endfunclet
458; CHECK-NEXT:     .seh_endproc
459
460declare <4 x i8> @small_vector(<4 x i8> %0) nounwind;
461; CHECK-LABEL:    .def	$iexit_thunk$cdecl$m$m;
462; CHECK:          .section	.wowthk$aa,"xr",discard,$iexit_thunk$cdecl$m$m
463; CHECK:          // %bb.0:
464; CHECK-NEXT:     sub	sp, sp, #64
465; CHECK-NEXT:     .seh_stackalloc	64
466; CHECK-NEXT:     stp	x29, x30, [sp, #48]             // 16-byte Folded Spill
467; CHECK-NEXT:     .seh_save_fplr	48
468; CHECK-NEXT:     add	x29, sp, #48
469; CHECK-NEXT:     .seh_add_fp	48
470; CHECK-NEXT:     .seh_endprologue
471; CHECK-NEXT:     uzp1	v0.8b, v0.8b, v0.8b
472; CHECK-NEXT:     adrp	x8, __os_arm64x_dispatch_call_no_redirect
473; CHECK-NEXT:     ldr	x16, [x8, :lo12:__os_arm64x_dispatch_call_no_redirect]
474; CHECK-NEXT:     fmov	w0, s0
475; CHECK-NEXT:     stur	s0, [x29, #-4]
476; CHECK-NEXT:     blr	x16
477; CHECK-NEXT:     stur	w8, [x29, #-8]
478; CHECK-NEXT:     ldur	s0, [x29, #-8]
479; CHECK-NEXT:     ushll	v0.8h, v0.8b, #0
480; CHECK-NEXT:                                           // kill: def $d0 killed $d0 killed $q0
481; CHECK-NEXT:     .seh_startepilogue
482; CHECK-NEXT:     ldp	x29, x30, [sp, #48]             // 16-byte Folded Reload
483; CHECK-NEXT:     .seh_save_fplr	48
484; CHECK-NEXT:     add	sp, sp, #64
485; CHECK-NEXT:     .seh_stackalloc	64
486; CHECK-NEXT:     .seh_endepilogue
487; CHECK-NEXT:     ret
488; CHECK-NEXT:     .seh_endfunclet
489; CHECK-NEXT:     .seh_endproc
490; CHECK-LABEL:    .def	"#small_vector$exit_thunk";
491; CHECK:          .section	.wowthk$aa,"xr",discard,"#small_vector$exit_thunk"
492; CHECK:          .weak_anti_dep	small_vector
493; CHECK:          .weak_anti_dep	"#small_vector"
494; CHECK:          // %bb.0:
495; CHECK-NEXT:     str	x30, [sp, #-16]!                // 8-byte Folded Spill
496; CHECK-NEXT:     .seh_save_reg_x	x30, 16
497; CHECK-NEXT:     .seh_endprologue
498; CHECK-NEXT:     adrp	x8, __os_arm64x_check_icall
499; CHECK-NEXT:     adrp	x11, small_vector
500; CHECK-NEXT:     add	x11, x11, :lo12:small_vector
501; CHECK-NEXT:     ldr	x8, [x8, :lo12:__os_arm64x_check_icall]
502; CHECK-NEXT:     adrp	x10, ($iexit_thunk$cdecl$m$m)
503; CHECK-NEXT:     add	x10, x10, :lo12:($iexit_thunk$cdecl$m$m)
504; CHECK-NEXT:     blr	x8
505; CHECK-NEXT:     .seh_startepilogue
506; CHECK-NEXT:     ldr	x30, [sp], #16                  // 8-byte Folded Reload
507; CHECK-NEXT:     .seh_save_reg_x	x30, 16
508; CHECK-NEXT:     .seh_endepilogue
509; CHECK-NEXT:     br	x11
510; CHECK-NEXT:     .seh_endfunclet
511; CHECK-NEXT:     .seh_endproc
512
513declare <8 x i16> @large_vector(<8 x i16> %0) nounwind;
514; CHECK-LABEL:    .def	$iexit_thunk$cdecl$m16$m16;
515; CHECK:          .section	.wowthk$aa,"xr",discard,$iexit_thunk$cdecl$m16$m16
516; CHECK:          // %bb.0:
517; CHECK-NEXT:     sub	sp, sp, #80
518; CHECK-NEXT:     .seh_stackalloc	80
519; CHECK-NEXT:     stp	x29, x30, [sp, #64]             // 16-byte Folded Spill
520; CHECK-NEXT:     .seh_save_fplr	64
521; CHECK-NEXT:     add	x29, sp, #64
522; CHECK-NEXT:     .seh_add_fp	64
523; CHECK-NEXT:     .seh_endprologue
524; CHECK-NEXT:     adrp	x8, __os_arm64x_dispatch_call_no_redirect
525; CHECK-NEXT:     sub	x0, x29, #16
526; CHECK-NEXT:     add	x1, sp, #32
527; CHECK-NEXT:     ldr	x16, [x8, :lo12:__os_arm64x_dispatch_call_no_redirect]
528; CHECK-NEXT:     str	q0, [sp, #32]
529; CHECK-NEXT:     blr	x16
530; CHECK-NEXT:     ldur	q0, [x29, #-16]
531; CHECK-NEXT:     .seh_startepilogue
532; CHECK-NEXT:     ldp	x29, x30, [sp, #64]             // 16-byte Folded Reload
533; CHECK-NEXT:     .seh_save_fplr	64
534; CHECK-NEXT:     add	sp, sp, #80
535; CHECK-NEXT:     .seh_stackalloc	80
536; CHECK-NEXT:     .seh_endepilogue
537; CHECK-NEXT:     ret
538; CHECK-NEXT:     .seh_endfunclet
539; CHECK-NEXT:     .seh_endproc
540; CHECK-LABEL:    .def	"#large_vector$exit_thunk";
541; CHECK:          .section	.wowthk$aa,"xr",discard,"#large_vector$exit_thunk"
542; CHECK:          .weak_anti_dep	large_vector
543; CHECK:          .weak_anti_dep	"#large_vector"
544; CHECK:          // %bb.0:
545; CHECK-NEXT:     str	x30, [sp, #-16]!                // 8-byte Folded Spill
546; CHECK-NEXT:     .seh_save_reg_x	x30, 16
547; CHECK-NEXT:     .seh_endprologue
548; CHECK-NEXT:     adrp	x8, __os_arm64x_check_icall
549; CHECK-NEXT:     adrp	x11, large_vector
550; CHECK-NEXT:     add	x11, x11, :lo12:large_vector
551; CHECK-NEXT:     ldr	x8, [x8, :lo12:__os_arm64x_check_icall]
552; CHECK-NEXT:     adrp	x10, ($iexit_thunk$cdecl$m16$m16)
553; CHECK-NEXT:     add	x10, x10, :lo12:($iexit_thunk$cdecl$m16$m16)
554; CHECK-NEXT:     blr	x8
555; CHECK-NEXT:     .seh_startepilogue
556; CHECK-NEXT:     ldr	x30, [sp], #16                  // 8-byte Folded Reload
557; CHECK-NEXT:     .seh_save_reg_x	x30, 16
558; CHECK-NEXT:     .seh_endepilogue
559; CHECK-NEXT:     br	x11
560; CHECK-NEXT:     .seh_endfunclet
561; CHECK-NEXT:     .seh_endproc
562
563; CHECK-LABEL:    .section        .hybmp$x,"yi"
564; CHECK-NEXT:     .symidx "#func_caller"
565; CHECK-NEXT:     .symidx $ientry_thunk$cdecl$v$v
566; CHECK-NEXT:     .word   1
567; CHECK-NEXT:     .symidx no_op
568; CHECK-NEXT:     .symidx $iexit_thunk$cdecl$v$v
569; CHECK-NEXT:     .word   4
570; CHECK-NEXT:     .symidx "#no_op$exit_thunk"
571; CHECK-NEXT:     .symidx no_op
572; CHECK-NEXT:     .word   0
573; CHECK-NEXT:     .symidx simple_integers
574; CHECK-NEXT:     .symidx $iexit_thunk$cdecl$i8$i8i8i8i8
575; CHECK-NEXT:     .word   4
576; CHECK-NEXT:     .symidx "#simple_integers$exit_thunk"
577; CHECK-NEXT:     .symidx simple_integers
578; CHECK-NEXT:     .word   0
579; CHECK-NEXT:     .symidx simple_floats
580; CHECK-NEXT:     .symidx $iexit_thunk$cdecl$d$fd
581; CHECK-NEXT:     .word   4
582; CHECK-NEXT:     .symidx "#simple_floats$exit_thunk"
583; CHECK-NEXT:     .symidx simple_floats
584; CHECK-NEXT:     .word   0
585; CHECK-NEXT:     .symidx has_varargs
586; CHECK-NEXT:     .symidx $iexit_thunk$cdecl$v$varargs
587; CHECK-NEXT:     .word   4
588; CHECK-NEXT:     .symidx "#has_varargs$exit_thunk"
589; CHECK-NEXT:     .symidx has_varargs
590; CHECK-NEXT:     .word 0
591; CHECK-NEXT:     .symidx has_sret
592; CHECK-NEXT:     .symidx $iexit_thunk$cdecl$m100$v
593; CHECK-NEXT:     .word   4
594; CHECK-NEXT:     .symidx "#has_sret$exit_thunk"
595; CHECK-NEXT:     .symidx has_sret
596; CHECK-NEXT:     .word   0
597; CHECK-NEXT:     .symidx has_aligned_sret
598; CHECK-NEXT:     .symidx $iexit_thunk$cdecl$m16$v
599; CHECK-NEXT:     .word   4
600; CHECK-NEXT:     .symidx "#has_aligned_sret$exit_thunk"
601; CHECK-NEXT:     .symidx has_aligned_sret
602; CHECK-NEXT:     .word   0
603; CHECK-NEXT:     .symidx small_array
604; CHECK-NEXT:     .symidx $iexit_thunk$cdecl$m2$m2F8
605; CHECK-NEXT:     .word   4
606; CHECK-NEXT:     .symidx "#small_array$exit_thunk"
607; CHECK-NEXT:     .symidx small_array
608; CHECK-NEXT:     .word   0
609; CHECK-NEXT:     .symidx large_array
610; CHECK-NEXT:     .symidx $iexit_thunk$cdecl$m24$m24D16m32
611; CHECK-NEXT:     .word   4
612; CHECK-NEXT:     .symidx "#large_array$exit_thunk"
613; CHECK-NEXT:     .symidx large_array
614; CHECK-NEXT:     .word   0
615; CHECK-NEXT:     .symidx simple_struct
616; CHECK-NEXT:     .symidx $iexit_thunk$cdecl$m8$i8m8m16m24
617; CHECK-NEXT:     .word   4
618; CHECK-NEXT:     .symidx "#simple_struct$exit_thunk"
619; CHECK-NEXT:     .symidx simple_struct
620; CHECK-NEXT:     .word   0
621; CHECK-NEXT:     .symidx	small_vector
622; CHECK-NEXT:     .symidx	$iexit_thunk$cdecl$m$m
623; CHECK-NEXT:     .word	4
624; CHECK-NEXT:     .symidx	"#small_vector$exit_thunk"
625; CHECK-NEXT:     .symidx	small_vector
626; CHECK-NEXT:     .word	0
627; CHECK-NEXT:     .symidx	large_vector
628; CHECK-NEXT:     .symidx	$iexit_thunk$cdecl$m16$m16
629; CHECK-NEXT:     .word	4
630; CHECK-NEXT:     .symidx	"#large_vector$exit_thunk"
631; CHECK-NEXT:     .symidx	large_vector
632; CHECK-NEXT:     .word	0
633
634define void @func_caller() nounwind {
635  call void @no_op()
636  call i64 @simple_integers(i8 0, i16 0, i32 0, i64 0)
637  call double @simple_floats(float 0.0, double 0.0)
638  call void (...) @has_varargs()
639  %c = alloca i8
640  call void @has_sret(ptr sret([100 x i8]) %c)
641  %aligned = alloca %TSRet, align 32
642  store %TSRet { i64 0, i64 0 }, ptr %aligned, align 32
643  call void @has_aligned_sret(ptr align 32 sret(%TSRet) %aligned)
644  call [2 x i8] @small_array([2 x i8] [i8 0, i8 0], [2 x float] [float 0.0, float 0.0])
645  call [3 x i64] @large_array([3 x i64] [i64 0, i64 0, i64 0], [2 x double] [double 0.0, double 0.0], [2 x [2 x i64]] [[2 x i64] [i64 0, i64 0], [2 x i64] [i64 0, i64 0]])
646  call %T2 @simple_struct(%T1 { i16 0 }, %T2 { i32 0, float 0.0 }, %T3 { i64 0, double 0.0 }, %T4 { i64 0, double 0.0, i8 0 })
647  call <4 x i8> @small_vector(<4 x i8> <i8 0, i8 0, i8 0, i8 0>)
648  call <8 x i16> @large_vector(<8 x i16> <i16 0, i16 0, i16 0, i16 0, i16 0, i16 0, i16 0, i16 0>)
649  ret void
650}
651