xref: /llvm-project/llvm/test/CodeGen/ARM/Windows/wineh-opcodes.ll (revision c5383536cb6824391f99f8f5963fc1427dd1673f)
1;; Check that this produces the expected assembly output
2; RUN: llc -mtriple=thumbv7-windows -o - %s -verify-machineinstrs | FileCheck %s
3;; Also try to write an object file, which verifies that the SEH opcodes
4;; match the actual prologue/epilogue length.
5; RUN: llc -mtriple=thumbv7-windows -filetype=obj -o %t.obj %s -verify-machineinstrs
6
7; CHECK-LABEL: clobberR4Frame:
8; CHECK-NEXT: .seh_proc clobberR4Frame
9; CHECK-NEXT: @ %bb.0:                                @ %entry
10; CHECK-NEXT:         push.w  {r4, r7, r11, lr}
11; CHECK-NEXT:         .seh_save_regs_w        {r4, r7, r11, lr}
12; CHECK-NEXT:         add.w   r11, sp, #8
13; CHECK-NEXT:         .seh_nop_w
14; CHECK-NEXT:         .seh_endprologue
15; CHECK-NEXT:         bl      other
16
17; CHECK:              .seh_startepilogue
18; CHECK-NEXT:         pop.w   {r4, r7, r11, pc}
19; CHECK-NEXT:         .seh_save_regs_w        {r4, r7, r11, lr}
20; CHECK-NEXT:         .seh_endepilogue
21; CHECK-NEXT:         .seh_endproc
22
23define arm_aapcs_vfpcc void @clobberR4Frame() uwtable "frame-pointer"="all" {
24entry:
25  call arm_aapcs_vfpcc void @other()
26  call void asm sideeffect "", "~{r4}"()
27  ret void
28}
29
30; CHECK-LABEL: clobberR4NoFrame:
31; CHECK-NEXT: .seh_proc clobberR4NoFrame
32; CHECK-NEXT: @ %bb.0:                                @ %entry
33; CHECK-NEXT:         push    {r4, lr}
34; CHECK-NEXT:         .seh_save_regs  {r4, lr}
35; CHECK-NEXT:         .seh_endprologue
36; CHECK-NEXT:         bl      other
37
38; CHECK:              .seh_startepilogue
39; CHECK-NEXT:         pop     {r4, pc}
40; CHECK-NEXT:         .seh_save_regs  {r4, lr}
41; CHECK-NEXT:         .seh_endepilogue
42; CHECK-NEXT:         .seh_endproc
43
44define arm_aapcs_vfpcc void @clobberR4NoFrame() uwtable "frame-pointer"="none" {
45entry:
46  call arm_aapcs_vfpcc void @other()
47  call void asm sideeffect "", "~{r4}"()
48  ret void
49}
50
51; CHECK-LABEL: clobberR4Tail:
52; CHECK-NEXT: .seh_proc clobberR4Tail
53; CHECK-NEXT: @ %bb.0:                                @ %entry
54; CHECK-NEXT:         push    {r4, lr}
55; CHECK-NEXT:         .seh_save_regs  {r4, lr}
56; CHECK-NEXT:         .seh_endprologue
57
58; CHECK:              .seh_startepilogue
59; CHECK-NEXT:         pop.w   {r4, lr}
60; CHECK-NEXT:         .seh_save_regs_w        {r4, lr}
61; CHECK-NEXT:         b.w     other
62; CHECK-NEXT:         .seh_nop_w
63; CHECK-NEXT:         .seh_endepilogue
64; CHECK-NEXT:         .seh_endproc
65
66define arm_aapcs_vfpcc void @clobberR4Tail() uwtable "frame-pointer"="none" {
67entry:
68  call void asm sideeffect "", "~{r4}"()
69  tail call arm_aapcs_vfpcc void @other()
70  ret void
71}
72
73; CHECK-LABEL: clobberD8D10:
74; CHECK-NEXT: .seh_proc clobberD8D10
75; CHECK-NEXT: @ %bb.0:                                @ %entry
76; CHECK-NEXT:         vpush   {d8, d9, d10}
77; CHECK-NEXT:         .seh_save_fregs {d8-d10}
78; CHECK-NEXT:         .seh_endprologue
79
80; CHECK:              .seh_startepilogue
81; CHECK-NEXT:         vpop    {d8, d9, d10}
82; CHECK-NEXT:         .seh_save_fregs {d8-d10}
83; CHECK-NEXT:         b.w     other
84; CHECK-NEXT:         .seh_nop_w
85; CHECK-NEXT:         .seh_endepilogue
86; CHECK-NEXT:         .seh_endproc
87
88define arm_aapcs_vfpcc void @clobberD8D10() uwtable "frame-pointer"="none" {
89entry:
90  call void asm sideeffect "", "~{d8},~{d9},~{d10}"()
91  tail call arm_aapcs_vfpcc void @other()
92  ret void
93}
94
95declare arm_aapcs_vfpcc void @other()
96
97; CHECK-LABEL: vararg:
98; CHECK-NEXT: .seh_proc vararg
99; CHECK-NEXT: @ %bb.0:                                @ %entry
100; CHECK-NEXT:         sub     sp, #12
101; CHECK-NEXT:         .seh_stackalloc 12
102; CHECK-NEXT:         push.w  {r11, lr}
103; CHECK-NEXT:         .seh_save_regs_w        {r11, lr}
104; CHECK-NEXT:         sub     sp, #4
105; CHECK-NEXT:         .seh_stackalloc 4
106; CHECK-NEXT:         .seh_endprologue
107
108; CHECK:              .seh_startepilogue
109; CHECK-NEXT:         add     sp, #4
110; CHECK-NEXT:         .seh_stackalloc 4
111; CHECK-NEXT:         pop.w   {r11, lr}
112; CHECK-NEXT:         .seh_save_regs_w        {r11, lr}
113; CHECK-NEXT:         add     sp, #12
114; CHECK-NEXT:         .seh_stackalloc 12
115; CHECK-NEXT:         bx      lr
116; CHECK-NEXT:         .seh_nop
117; CHECK-NEXT:         .seh_endepilogue
118; CHECK-NEXT:         .seh_endproc
119
120define arm_aapcs_vfpcc void @vararg(i32 noundef %a, ...) uwtable "frame-pointer"="none" {
121entry:
122  %ap = alloca ptr, align 4
123  call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %ap)
124  call void @llvm.va_start(ptr nonnull %ap)
125  %0 = load ptr, ptr %ap
126  call arm_aapcs_vfpcc void @useva(ptr noundef %0)
127  call void @llvm.va_end(ptr nonnull %ap)
128  call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %ap)
129  ret void
130}
131
132declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture)
133declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture)
134declare void @llvm.va_start(ptr)
135declare void @llvm.va_end(ptr)
136
137declare arm_aapcs_vfpcc void @useva(ptr noundef)
138
139; CHECK-LABEL: onlystack:
140; CHECK-NEXT: .seh_proc onlystack
141; CHECK-NEXT: @ %bb.0:                                @ %entry
142; CHECK-NEXT:         sub     sp, #4
143; CHECK-NEXT:         .seh_stackalloc 4
144; CHECK-NEXT:         .seh_endprologue
145
146; CHECK:              .seh_startepilogue
147; CHECK-NEXT:         add     sp, #4
148; CHECK-NEXT:         .seh_stackalloc 4
149; CHECK-NEXT:         bx      lr
150; CHECK-NEXT:         .seh_nop
151; CHECK-NEXT:         .seh_endepilogue
152; CHECK-NEXT:         .seh_endproc
153
154define dso_local arm_aapcs_vfpcc void @onlystack() uwtable "frame-pointer"="none" {
155entry:
156  %buf = alloca [4 x i8], align 1
157  call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %buf)
158  call void asm sideeffect "", "r"(ptr nonnull %buf)
159  call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %buf)
160  ret void
161}
162
163; CHECK-LABEL: func50:
164; CHECK-NEXT: .seh_proc func50
165; CHECK-NEXT: @ %bb.0:                                @ %entry
166; CHECK-NEXT:         push.w  {r11, lr}
167; CHECK-NEXT:         .seh_save_regs_w        {r11, lr}
168; CHECK-NEXT:         sub     sp, #56
169; CHECK-NEXT:         .seh_stackalloc 56
170; CHECK-NEXT:         .seh_endprologue
171
172; CHECK:              .seh_startepilogue
173; CHECK-NEXT:         add     sp, #56
174; CHECK-NEXT:         .seh_stackalloc 56
175; CHECK-NEXT:         pop.w   {r11, pc}
176; CHECK-NEXT:         .seh_save_regs_w        {r11, lr}
177; CHECK-NEXT:         .seh_endepilogue
178; CHECK-NEXT:         .seh_endproc
179
180define arm_aapcs_vfpcc void @func50() {
181entry:
182  %buf = alloca [50 x i8], align 1
183  call void @llvm.lifetime.start.p0(i64 50, ptr nonnull %buf)
184  call arm_aapcs_vfpcc void @useptr(ptr noundef nonnull %buf)
185  call void @llvm.lifetime.end.p0(i64 50, ptr nonnull %buf)
186  ret void
187}
188
189; CHECK-LABEL: func4000:
190; CHECK-NEXT: .seh_proc func4000
191; CHECK-NEXT: @ %bb.0:                                @ %entry
192; CHECK-NEXT:         push.w  {r11, lr}
193; CHECK-NEXT:         .seh_save_regs_w        {r11, lr}
194; CHECK-NEXT:         sub.w   sp, sp, #4000
195; CHECK-NEXT:         .seh_stackalloc_w       4000
196; CHECK-NEXT:         .seh_endprologue
197
198; CHECK:              .seh_startepilogue
199; CHECK-NEXT:         add.w   sp, sp, #4000
200; CHECK-NEXT:         .seh_stackalloc_w       4000
201; CHECK-NEXT:         pop.w   {r11, pc}
202; CHECK-NEXT:         .seh_save_regs_w        {r11, lr}
203; CHECK-NEXT:         .seh_endepilogue
204; CHECK-NEXT:         .seh_endproc
205
206define arm_aapcs_vfpcc void @func4000() {
207entry:
208  %buf = alloca [4000 x i8], align 1
209  call void @llvm.lifetime.start.p0(i64 4000, ptr nonnull %buf)
210  call arm_aapcs_vfpcc void @useptr(ptr noundef nonnull %buf)
211  call void @llvm.lifetime.end.p0(i64 4000, ptr nonnull %buf)
212  ret void
213}
214
215; CHECK-LABEL: func5000:
216; CHECK-NEXT: .seh_proc func5000
217; CHECK-NEXT: @ %bb.0:                                @ %entry
218; CHECK-NEXT:         push    {r4, r5, r6, lr}
219; CHECK-NEXT:         .seh_save_regs  {r4-r6, lr}
220; CHECK-NEXT:         movw    r4, #1250
221; CHECK-NEXT:         .seh_nop_w
222; CHECK-NEXT:         bl      __chkstk
223; CHECK-NEXT:         .seh_nop_w
224; CHECK-NEXT:         sub.w   sp, sp, r4
225; CHECK-NEXT:         .seh_stackalloc_w       5000
226; CHECK-NEXT:         .seh_endprologue
227
228; CHECK:              .seh_startepilogue
229; CHECK-NEXT:         add.w   sp, sp, #4992
230; CHECK-NEXT:         .seh_stackalloc_w       4992
231; CHECK-NEXT:         add     sp, #8
232; CHECK-NEXT:         .seh_stackalloc 8
233; CHECK-NEXT:         pop     {r4, r5, r6, pc}
234; CHECK-NEXT:         .seh_save_regs  {r4-r6, lr}
235; CHECK-NEXT:         .seh_endepilogue
236; CHECK-NEXT:         .seh_endproc
237
238define arm_aapcs_vfpcc void @func5000() {
239entry:
240  %buf = alloca [5000 x i8], align 1
241  call void @llvm.lifetime.start.p0(i64 5000, ptr nonnull %buf)
242  call arm_aapcs_vfpcc void @useptr(ptr noundef nonnull %buf)
243  call void @llvm.lifetime.end.p0(i64 5000, ptr nonnull %buf)
244  ret void
245}
246
247; CHECK-LABEL: func262144:
248; CHECK-NEXT: .seh_proc func262144
249; CHECK-NEXT: @ %bb.0:                                @ %entry
250; CHECK-NEXT:         push    {r4, r5, r6, lr}
251; CHECK-NEXT:         .seh_save_regs  {r4-r6, lr}
252; CHECK-NEXT:         movs    r4, #0
253; CHECK-NEXT:         .seh_nop
254; CHECK-NEXT:         movt    r4, #1
255; CHECK-NEXT:         .seh_nop_w
256; CHECK-NEXT:         bl      __chkstk
257; CHECK-NEXT:         .seh_nop_w
258; CHECK-NEXT:         sub.w   sp, sp, r4
259; CHECK-NEXT:         .seh_stackalloc_w       262144
260; CHECK-NEXT:         .seh_endprologue
261
262; CHECK:              .seh_startepilogue
263; CHECK-NEXT:         add.w   sp, sp, #262144
264; CHECK-NEXT:         .seh_stackalloc_w       262144
265; CHECK-NEXT:         pop     {r4, r5, r6, pc}
266; CHECK-NEXT:         .seh_save_regs  {r4-r6, lr}
267; CHECK-NEXT:         .seh_endepilogue
268; CHECK-NEXT:         .seh_endproc
269
270define arm_aapcs_vfpcc void @func262144() {
271entry:
272  %buf = alloca [262144 x i8], align 1
273  call void @llvm.lifetime.start.p0(i64 262144, ptr nonnull %buf)
274  call arm_aapcs_vfpcc void @useptr(ptr noundef nonnull %buf)
275  call void @llvm.lifetime.end.p0(i64 262144, ptr nonnull %buf)
276  ret void
277}
278
279; CHECK-LABEL: func270000:
280; CHECK-NEXT: .seh_proc func270000
281; CHECK-NEXT: @ %bb.0:                                @ %entry
282; CHECK-NEXT:         push    {r4, r5, r6, lr}
283; CHECK-NEXT:         .seh_save_regs  {r4-r6, lr}
284; CHECK-NEXT:         movw    r4, #1964
285; CHECK-NEXT:         .seh_nop_w
286; CHECK-NEXT:         movt    r4, #1
287; CHECK-NEXT:         .seh_nop_w
288; CHECK-NEXT:         bl      __chkstk
289; CHECK-NEXT:         .seh_nop_w
290; CHECK-NEXT:         sub.w   sp, sp, r4
291; CHECK-NEXT:         .seh_stackalloc_w       270000
292; CHECK-NEXT:         .seh_endprologue
293
294; CHECK:              .seh_startepilogue
295; CHECK-NEXT:         add.w   sp, sp, #268288
296; CHECK-NEXT:         .seh_stackalloc_w       268288
297; CHECK-NEXT:         add.w   sp, sp, #1712
298; CHECK-NEXT:         .seh_stackalloc_w       1712
299; CHECK-NEXT:         pop     {r4, r5, r6, pc}
300; CHECK-NEXT:         .seh_save_regs  {r4-r6, lr}
301; CHECK-NEXT:         .seh_endepilogue
302; CHECK-NEXT:         .seh_endproc
303
304define arm_aapcs_vfpcc void @func270000() {
305entry:
306  %buf = alloca [270000 x i8], align 1
307  call void @llvm.lifetime.start.p0(i64 270000, ptr nonnull %buf)
308  call arm_aapcs_vfpcc void @useptr(ptr noundef nonnull %buf)
309  call void @llvm.lifetime.end.p0(i64 270000, ptr nonnull %buf)
310  ret void
311}
312
313declare arm_aapcs_vfpcc void @useptr(ptr noundef)
314
315; CHECK-LABEL: func_fp:
316; CHECK-NEXT: .seh_proc func_fp
317; CHECK-NEXT: @ %bb.0:                                @ %entry
318; CHECK-NEXT:         str     r11, [sp, #-4]!
319; CHECK-NEXT:         .seh_save_regs_w        {r11}
320; CHECK-NEXT:         mov     r11, sp
321; CHECK-NEXT:         .seh_save_sp    r11
322; CHECK-NEXT:         .seh_endprologue
323
324; CHECK-NEXT:         mov     r0, r11
325
326; CHECK-NEXT:         .seh_startepilogue
327; CHECK-NEXT:         ldr     r11, [sp], #4
328; CHECK-NEXT:         .seh_save_regs_w        {r11}
329; CHECK-NEXT:         bx      lr
330; CHECK-NEXT:         .seh_nop
331; CHECK-NEXT:         .seh_endepilogue
332; CHECK-NEXT:         .seh_endproc
333
334define arm_aapcs_vfpcc i32 @func_fp() {
335entry:
336  %0 = tail call ptr @llvm.frameaddress.p0(i32 0)
337  %1 = ptrtoint ptr %0 to i32
338  ret i32 %1
339}
340
341declare ptr @llvm.frameaddress.p0(i32 immarg)
342