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