1; RUN: llc < %s -mtriple=i686-pc-linux | FileCheck %s -check-prefix=LINUX -check-prefix=CHECK
2; RUN: llc < %s -mtriple=i686-apple-darwin | FileCheck %s -check-prefix=DARWIN -check-prefix=CHECK
3
4declare i32 @__gxx_personality_v0(...)
5declare void @good(i32 %a, i32 %b, i32 %c, i32 %d)
6declare void @large(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f)
7declare void @empty()
8
9; When we use an invoke, we expect a .cfi_escape GNU_ARGS_SIZE
10; with size 16 before the invocation. Without FP, we also expect
11; .cfi_adjust_cfa_offset after each push.
12; Darwin should not generate pushes in either circumstance.
13; CHECK-LABEL: test1_nofp:
14; LINUX: .cfi_escape 0x2e, 0x10
15; LINUX-NEXT: pushl   $4
16; LINUX-NEXT: .cfi_adjust_cfa_offset 4
17; LINUX-NEXT: pushl   $3
18; LINUX-NEXT: .cfi_adjust_cfa_offset 4
19; LINUX-NEXT: pushl   $2
20; LINUX-NEXT: .cfi_adjust_cfa_offset 4
21; LINUX-NEXT: pushl   $1
22; LINUX-NEXT: .cfi_adjust_cfa_offset 4
23; LINUX-NEXT: call
24; LINUX-NEXT: addl $16, %esp
25; LINUX: .cfi_adjust_cfa_offset -16
26; DARWIN-NOT: .cfi_escape
27; DARWIN-NOT: pushl
28define void @test1_nofp() #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
29entry:
30  invoke void @good(i32 1, i32 2, i32 3, i32 4)
31          to label %continue unwind label %cleanup
32continue:
33  ret void
34cleanup:
35  landingpad { i8*, i32 }
36     cleanup
37  ret void
38}
39
40; CHECK-LABEL: test1_fp:
41; LINUX: .cfi_escape 0x2e, 0x10
42; LINUX-NEXT: pushl   $4
43; LINUX-NEXT: pushl   $3
44; LINUX-NEXT: pushl   $2
45; LINUX-NEXT: pushl   $1
46; LINUX-NEXT: call
47; LINUX-NEXT: addl $16, %esp
48; DARWIN: pushl %ebp
49; DARWIN-NOT: .cfi_escape
50; DARWIN-NOT: pushl
51define void @test1_fp() #1 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
52entry:
53  invoke void @good(i32 1, i32 2, i32 3, i32 4)
54          to label %continue unwind label %cleanup
55continue:
56  ret void
57cleanup:
58  landingpad { i8*, i32 }
59     cleanup
60  ret void
61}
62
63; If the function has no handlers, we don't need to generate GNU_ARGS_SIZE,
64; even if it has an unwind table. Without FP, we still need cfi_adjust_cfa_offset,
65; so darwin should not generate pushes.
66; CHECK-LABEL: test2_nofp:
67; LINUX-NOT: .cfi_escape
68; LINUX: pushl   $4
69; LINUX-NEXT: .cfi_adjust_cfa_offset 4
70; LINUX-NEXT: pushl   $3
71; LINUX-NEXT: .cfi_adjust_cfa_offset 4
72; LINUX-NEXT: pushl   $2
73; LINUX-NEXT: .cfi_adjust_cfa_offset 4
74; LINUX-NEXT: pushl   $1
75; LINUX-NEXT: .cfi_adjust_cfa_offset 4
76; LINUX-NEXT: call
77; LINUX-NEXT: addl $28, %esp
78; LINUX: .cfi_adjust_cfa_offset -28
79; DARWIN-NOT: .cfi_escape
80; DARWIN-NOT: pushl
81define void @test2_nofp() #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
82entry:
83  call void @good(i32 1, i32 2, i32 3, i32 4)
84  ret void
85}
86
87; CHECK-LABEL: test2_fp:
88; CHECK-NOT: .cfi_escape
89; CHECK-NOT: .cfi_adjust_cfa_offset
90; CHECK: pushl   $4
91; CHECK-NEXT: pushl   $3
92; CHECK-NEXT: pushl   $2
93; CHECK-NEXT: pushl   $1
94; CHECK-NEXT: call
95; CHECK-NEXT: addl $24, %esp
96define void @test2_fp() #1 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
97entry:
98  call void @good(i32 1, i32 2, i32 3, i32 4)
99  ret void
100}
101
102; If we did not end up using any pushes, no need for GNU_ARGS_SIZE or
103; cfi_adjust_cfa_offset.
104; CHECK-LABEL: test3_nofp:
105; LINUX-NOT: .cfi_escape
106; LINUX-NOT: .cfi_adjust_cfa_offset
107; LINUX-NOT: pushl
108; LINUX: retl
109define void @test3_nofp() #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
110entry:
111  invoke void @empty()
112          to label %continue unwind label %cleanup
113continue:
114  ret void
115cleanup:
116  landingpad { i8*, i32 }
117     cleanup
118  ret void
119}
120
121; If we did not end up using any pushes, no need for GNU_ARGS_SIZE or
122; cfi_adjust_cfa_offset.
123; CHECK-LABEL: test3_fp:
124; LINUX: pushl %ebp
125; LINUX-NOT: .cfi_escape
126; LINUX-NOT: .cfi_adjust_cfa_offset
127; LINUX-NOT: pushl
128; LINUX: retl
129define void @test3_fp() #1 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
130entry:
131  invoke void @empty()
132          to label %continue unwind label %cleanup
133continue:
134  ret void
135cleanup:
136  landingpad { i8*, i32 }
137     cleanup
138  ret void
139}
140
141; Different sized stacks need different GNU_ARGS_SIZEs
142; CHECK-LABEL: test4:
143; LINUX: .cfi_escape 0x2e, 0x10
144; LINUX-NEXT: pushl   $4
145; LINUX-NEXT: pushl   $3
146; LINUX-NEXT: pushl   $2
147; LINUX-NEXT: pushl   $1
148; LINUX-NEXT: call
149; LINUX-NEXT: addl $16, %esp
150; LINUX: .cfi_escape 0x2e, 0x20
151; LINUX: subl    $8, %esp
152; LINUX-NEXT: pushl   $11
153; LINUX-NEXT: pushl   $10
154; LINUX-NEXT: pushl   $9
155; LINUX-NEXT: pushl   $8
156; LINUX-NEXT: pushl   $7
157; LINUX-NEXT: pushl   $6
158; LINUX-NEXT: calll   large
159; LINUX-NEXT: addl $32, %esp
160define void @test4() #1 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
161entry:
162  invoke void @good(i32 1, i32 2, i32 3, i32 4)
163          to label %continue1 unwind label %cleanup
164continue1:
165  invoke void @large(i32 6, i32 7, i32 8, i32 9, i32 10, i32 11)
166          to label %continue2 unwind label %cleanup
167continue2:
168  ret void
169cleanup:
170  landingpad { i8*, i32 }
171     cleanup
172  ret void
173}
174
175; If we did use pushes, we need to reset GNU_ARGS_SIZE before a call
176; without parameters, but don't need to adjust the cfa offset
177; CHECK-LABEL: test5_nofp:
178; LINUX: .cfi_escape 0x2e, 0x10
179; LINUX-NEXT: pushl   $4
180; LINUX-NEXT: .cfi_adjust_cfa_offset 4
181; LINUX-NEXT: pushl   $3
182; LINUX-NEXT: .cfi_adjust_cfa_offset 4
183; LINUX-NEXT: pushl   $2
184; LINUX-NEXT: .cfi_adjust_cfa_offset 4
185; LINUX-NEXT: pushl   $1
186; LINUX-NEXT: .cfi_adjust_cfa_offset 4
187; LINUX-NEXT: call
188; LINUX-NEXT: addl $16, %esp
189; LINUX: .cfi_adjust_cfa_offset -16
190; LINUX-NOT: .cfi_adjust_cfa_offset
191; LINUX: .cfi_escape 0x2e, 0x00
192; LINUX-NOT: .cfi_adjust_cfa_offset
193; LINUX: call
194define void @test5_nofp() #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
195entry:
196  invoke void @good(i32 1, i32 2, i32 3, i32 4)
197          to label %continue1 unwind label %cleanup
198continue1:
199  invoke void @empty()
200          to label %continue2 unwind label %cleanup
201continue2:
202  ret void
203cleanup:
204  landingpad { i8*, i32 }
205     cleanup
206  ret void
207}
208
209; CHECK-LABEL: test5_fp:
210; LINUX: .cfi_escape 0x2e, 0x10
211; LINUX-NEXT: pushl   $4
212; LINUX-NEXT: pushl   $3
213; LINUX-NEXT: pushl   $2
214; LINUX-NEXT: pushl   $1
215; LINUX-NEXT: call
216; LINUX-NEXT: addl $16, %esp
217; LINUX: .cfi_escape 0x2e, 0x00
218; LINUX-NOT: .cfi_adjust_cfa_offset
219; LINUX: call
220define void @test5_fp() #1 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
221entry:
222  invoke void @good(i32 1, i32 2, i32 3, i32 4)
223          to label %continue1 unwind label %cleanup
224continue1:
225  invoke void @empty()
226          to label %continue2 unwind label %cleanup
227continue2:
228  ret void
229cleanup:
230  landingpad { i8*, i32 }
231     cleanup
232  ret void
233}
234
235; FIXME: This is actually inefficient - we don't need to repeat the .cfi_escape twice.
236; CHECK-LABEL: test6:
237; LINUX: .cfi_escape 0x2e, 0x10
238; LINUX: call
239; LINUX: .cfi_escape 0x2e, 0x10
240; LINUX: call
241define void @test6() #1 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
242entry:
243  invoke void @good(i32 1, i32 2, i32 3, i32 4)
244          to label %continue1 unwind label %cleanup
245continue1:
246  invoke void @good(i32 5, i32 6, i32 7, i32 8)
247          to label %continue2 unwind label %cleanup
248continue2:
249  ret void
250cleanup:
251  landingpad { i8*, i32 }
252     cleanup
253  ret void
254}
255
256; Darwin should generate pushes in the presense of FP and an unwind table,
257; but not FP and invoke.
258; CHECK-LABEL: test7:
259; DARWIN: pushl %ebp
260; DARWIN: movl %esp, %ebp
261; DARWIN: .cfi_def_cfa_register %ebp
262; DARWIN-NOT: .cfi_adjust_cfa_offset
263; DARWIN: pushl   $4
264; DARWIN-NEXT: pushl   $3
265; DARWIN-NEXT: pushl   $2
266; DARWIN-NEXT: pushl   $1
267; DARWIN-NEXT: call
268define void @test7() #1 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
269entry:
270  call void @good(i32 1, i32 2, i32 3, i32 4)
271  ret void
272}
273
274; CHECK-LABEL: test8:
275; DARWIN: pushl %ebp
276; DARWIN: movl %esp, %ebp
277; DARWIN-NOT: .cfi_adjust_cfa_offset
278; DARWIN-NOT: pushl
279define void @test8() #1 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
280entry:
281  invoke void @good(i32 1, i32 2, i32 3, i32 4)
282          to label %continue unwind label %cleanup
283continue:
284  ret void
285cleanup:
286  landingpad { i8*, i32 }
287     cleanup
288  ret void
289}
290
291attributes #0 = { optsize }
292attributes #1 = { optsize "frame-pointer"="all" }
293