Refine the ARM EHABI test cases.
[oota-llvm.git] / test / CodeGen / ARM / ehabi.ll
1 ; ARM EHABI integrated test
2
3 ; This test case checks whether the ARM unwind directives are properly
4 ; generated or not.
5
6 ; The purpose of the test:
7 ; (1) .fnstart and .fnend directives should wrap the function.
8 ; (2) .setfp directive should be available if frame pointer is not eliminated.
9 ; (3) .save directive should come with push instruction.
10 ; (4) .vsave directive should come with vpush instruction.
11 ; (5) .pad directive should come with stack pointer adjustment.
12 ; (6) .cantunwind directive should be available if the function is marked with
13 ;     nounwind function attribute.
14
15 ; We have to check several cases:
16 ; (1) arm with -disable-fp-elim
17 ; (2) arm without -disable-fp-elim
18 ; (3) armv7 with -disable-fp-elim
19 ; (4) armv7 without -disable-fp-elim
20
21 ; RUN: llc -mtriple arm-unknown-linux-gnueabi \
22 ; RUN:     -arm-enable-ehabi -arm-enable-ehabi-descriptors \
23 ; RUN:     -disable-fp-elim -filetype=asm -o - %s \
24 ; RUN:   | FileCheck %s --check-prefix=CHECK-FP
25
26 ; RUN: llc -mtriple arm-unknown-linux-gnueabi \
27 ; RUN:     -arm-enable-ehabi -arm-enable-ehabi-descriptors \
28 ; RUN:     -filetype=asm -o - %s \
29 ; RUN:   | FileCheck %s --check-prefix=CHECK-FP-ELIM
30
31 ; RUN: llc -mtriple armv7-unknown-linux-gnueabi \
32 ; RUN:     -arm-enable-ehabi -arm-enable-ehabi-descriptors \
33 ; RUN:     -disable-fp-elim -filetype=asm -o - %s \
34 ; RUN:   | FileCheck %s --check-prefix=CHECK-V7-FP
35
36 ; RUN: llc -mtriple armv7-unknown-linux-gnueabi \
37 ; RUN:     -arm-enable-ehabi -arm-enable-ehabi-descriptors \
38 ; RUN:     -filetype=asm -o - %s \
39 ; RUN:   | FileCheck %s --check-prefix=CHECK-V7-FP-ELIM
40
41 ;-------------------------------------------------------------------------------
42 ; Test 1
43 ;-------------------------------------------------------------------------------
44 ; This is the LLVM assembly generated from following C++ code:
45 ;
46 ;   extern void print(int, int, int, int, int);
47 ;   extern void print(double, double, double, double, double);
48 ;
49 ;   void test(int a, int b, int c, int d, int e,
50 ;             double m, double n, double p, double q, double r) {
51 ;     try {
52 ;       print(a, b, c, d, e);
53 ;     } catch (...) {
54 ;       print(m, n, p, q, r);
55 ;     }
56 ;   }
57
58 declare void @_Z5printiiiii(i32, i32, i32, i32, i32)
59
60 declare void @_Z5printddddd(double, double, double, double, double)
61
62 define void @_Z4testiiiiiddddd(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e,
63                                double %m, double %n, double %p,
64                                double %q, double %r) {
65 entry:
66   invoke void @_Z5printiiiii(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e)
67           to label %try.cont unwind label %lpad
68
69 lpad:
70   %0 = landingpad { i8*, i32 }
71           personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
72           catch i8* null
73   %1 = extractvalue { i8*, i32 } %0, 0
74   %2 = tail call i8* @__cxa_begin_catch(i8* %1)
75   invoke void @_Z5printddddd(double %m, double %n, double %p,
76                              double %q, double %r)
77           to label %invoke.cont2 unwind label %lpad1
78
79 invoke.cont2:
80   tail call void @__cxa_end_catch()
81   br label %try.cont
82
83 try.cont:
84   ret void
85
86 lpad1:
87   %3 = landingpad { i8*, i32 }
88           personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
89           cleanup
90   invoke void @__cxa_end_catch()
91           to label %eh.resume unwind label %terminate.lpad
92
93 eh.resume:
94   resume { i8*, i32 } %3
95
96 terminate.lpad:
97   %4 = landingpad { i8*, i32 }
98           personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
99           catch i8* null
100   %5 = extractvalue { i8*, i32 } %4, 0
101   tail call void @__clang_call_terminate(i8* %5)
102   unreachable
103 }
104
105 declare void @__clang_call_terminate(i8*)
106
107 declare i32 @__gxx_personality_v0(...)
108
109 declare i8* @__cxa_begin_catch(i8*)
110
111 declare void @__cxa_end_catch()
112
113 declare void @_ZSt9terminatev()
114
115 ; CHECK-FP: _Z4testiiiiiddddd:
116 ; CHECK-FP:   .fnstart
117 ; CHECK-FP:   .save  {r4, r5, r6, r7, r8, r9, r10, r11, lr}
118 ; CHECK-FP:   push   {r4, r5, r6, r7, r8, r9, r10, r11, lr}
119 ; CHECK-FP:   .setfp r11, sp, #28
120 ; CHECK-FP:   add    r11, sp, #28
121 ; CHECK-FP:   .pad   #28
122 ; CHECK-FP:   sub    sp, sp, #28
123 ; CHECK-FP:   .personality __gxx_personality_v0
124 ; CHECK-FP:   .handlerdata
125 ; CHECK-FP:   .fnend
126
127 ; CHECK-FP-ELIM: _Z4testiiiiiddddd:
128 ; CHECK-FP-ELIM:   .fnstart
129 ; CHECK-FP-ELIM:   .save {r4, r5, r6, r7, r8, r9, r10, r11, lr}
130 ; CHECK-FP-ELIM:   push  {r4, r5, r6, r7, r8, r9, r10, r11, lr}
131 ; CHECK-FP-ELIM:   .pad  #28
132 ; CHECK-FP-ELIM:   sub   sp, sp, #28
133 ; CHECK-FP-ELIM:   .personality __gxx_personality_v0
134 ; CHECK-FP-ELIM:   .handlerdata
135 ; CHECK-FP-ELIM:   .fnend
136
137 ; CHECK-V7-FP: _Z4testiiiiiddddd:
138 ; CHECK-V7-FP:   .fnstart
139 ; CHECK-V7-FP:   .save  {r4, r11, lr}
140 ; CHECK-V7-FP:   push   {r4, r11, lr}
141 ; CHECK-V7-FP:   .setfp r11, sp, #4
142 ; CHECK-V7-FP:   add    r11, sp, #4
143 ; CHECK-V7-FP:   .vsave {d8, d9, d10, d11, d12}
144 ; CHECK-V7-FP:   vpush  {d8, d9, d10, d11, d12}
145 ; CHECK-V7-FP:   .pad   #28
146 ; CHECK-V7-FP:   sub    sp, sp, #28
147 ; CHECK-V7-FP:   .personality __gxx_personality_v0
148 ; CHECK-V7-FP:   .handlerdata
149 ; CHECK-V7-FP:   .fnend
150
151 ; CHECK-V7-FP-ELIM: _Z4testiiiiiddddd:
152 ; CHECK-V7-FP-ELIM:   .fnstart
153 ; CHECK-V7-FP-ELIM:   .save  {r4, lr}
154 ; CHECK-V7-FP-ELIM:   push   {r4, lr}
155 ; CHECK-V7-FP-ELIM:   .vsave {d8, d9, d10, d11, d12}
156 ; CHECK-V7-FP-ELIM:   vpush  {d8, d9, d10, d11, d12}
157 ; CHECK-V7-FP-ELIM:   .pad   #24
158 ; CHECK-V7-FP-ELIM:   sub    sp, sp, #24
159 ; CHECK-V7-FP-ELIM:   .personality __gxx_personality_v0
160 ; CHECK-V7-FP-ELIM:   .handlerdata
161 ; CHECK-V7-FP-ELIM:   .fnend
162
163
164 ;-------------------------------------------------------------------------------
165 ; Test 2
166 ;-------------------------------------------------------------------------------
167
168 declare void @throw_exception_2()
169
170 define void @test2() {
171 entry:
172   tail call void @throw_exception_2()
173   ret void
174 }
175
176 ; CHECK-FP: test2:
177 ; CHECK-FP:   .fnstart
178 ; CHECK-FP:   .save  {r11, lr}
179 ; CHECK-FP:   push   {r11, lr}
180 ; CHECK-FP:   .setfp r11, sp
181 ; CHECK-FP:   mov    r11, sp
182 ; CHECK-FP:   pop    {r11, lr}
183 ; CHECK-FP:   mov    pc, lr
184 ; CHECK-FP:   .fnend
185
186 ; CHECK-FP-ELIM: test2:
187 ; CHECK-FP-ELIM:   .fnstart
188 ; CHECK-FP-ELIM:   .save {r11, lr}
189 ; CHECK-FP-ELIM:   push  {r11, lr}
190 ; CHECK-FP-ELIM:   pop   {r11, lr}
191 ; CHECK-FP-ELIM:   mov   pc, lr
192 ; CHECK-FP-ELIM:   .fnend
193
194 ; CHECK-V7-FP: test2:
195 ; CHECK-V7-FP:   .fnstart
196 ; CHECK-V7-FP:   .save  {r11, lr}
197 ; CHECK-V7-FP:   push   {r11, lr}
198 ; CHECK-V7-FP:   .setfp r11, sp
199 ; CHECK-V7-FP:   mov    r11, sp
200 ; CHECK-V7-FP:   pop    {r11, pc}
201 ; CHECK-V7-FP:   .fnend
202
203 ; CHECK-V7-FP-ELIM: test2:
204 ; CHECK-V7-FP-ELIM:   .fnstart
205 ; CHECK-V7-FP-ELIM:   .save {r11, lr}
206 ; CHECK-V7-FP-ELIM:   push  {r11, lr}
207 ; CHECK-V7-FP-ELIM:   pop   {r11, pc}
208 ; CHECK-V7-FP-ELIM:   .fnend
209
210
211 ;-------------------------------------------------------------------------------
212 ; Test 3
213 ;-------------------------------------------------------------------------------
214
215 declare void @throw_exception_3(i32)
216
217 define i32 @test3(i32 %a, i32 %b, i32 %c, i32 %d,
218                   i32 %e, i32 %f, i32 %g, i32 %h) {
219 entry:
220   %add = add nsw i32 %b, %a
221   %add1 = add nsw i32 %add, %c
222   %add2 = add nsw i32 %add1, %d
223   tail call void @throw_exception_3(i32 %add2)
224   %add3 = add nsw i32 %f, %e
225   %add4 = add nsw i32 %add3, %g
226   %add5 = add nsw i32 %add4, %h
227   tail call void @throw_exception_3(i32 %add5)
228   %add6 = add nsw i32 %add5, %add2
229   ret i32 %add6
230 }
231
232 ; CHECK-FP: test3:
233 ; CHECK-FP:   .fnstart
234 ; CHECK-FP:   .save  {r4, r5, r11, lr}
235 ; CHECK-FP:   push   {r4, r5, r11, lr}
236 ; CHECK-FP:   .setfp r11, sp, #8
237 ; CHECK-FP:   add    r11, sp, #8
238 ; CHECK-FP:   pop    {r4, r5, r11, lr}
239 ; CHECK-FP:   mov    pc, lr
240 ; CHECK-FP:   .fnend
241
242 ; CHECK-FP-ELIM: test3:
243 ; CHECK-FP-ELIM:   .fnstart
244 ; CHECK-FP-ELIM:   .save {r4, r5, r11, lr}
245 ; CHECK-FP-ELIM:   push  {r4, r5, r11, lr}
246 ; CHECK-FP-ELIM:   pop   {r4, r5, r11, lr}
247 ; CHECK-FP-ELIM:   mov   pc, lr
248 ; CHECK-FP-ELIM:   .fnend
249
250 ; CHECK-V7-FP: test3:
251 ; CHECK-V7-FP:   .fnstart
252 ; CHECK-V7-FP:   .save  {r4, r5, r11, lr}
253 ; CHECK-V7-FP:   push   {r4, r5, r11, lr}
254 ; CHECK-V7-FP:   .setfp r11, sp, #8
255 ; CHECK-V7-FP:   add    r11, sp, #8
256 ; CHECK-V7-FP:   pop    {r4, r5, r11, pc}
257 ; CHECK-V7-FP:   .fnend
258
259 ; CHECK-V7-FP-ELIM: test3:
260 ; CHECK-V7-FP-ELIM:   .fnstart
261 ; CHECK-V7-FP-ELIM:   .save {r4, r5, r11, lr}
262 ; CHECK-V7-FP-ELIM:   push  {r4, r5, r11, lr}
263 ; CHECK-V7-FP-ELIM:   pop   {r4, r5, r11, pc}
264 ; CHECK-V7-FP-ELIM:   .fnend
265
266
267 ;-------------------------------------------------------------------------------
268 ; Test 4
269 ;-------------------------------------------------------------------------------
270
271 define void @test4() nounwind {
272 entry:
273   ret void
274 }
275
276 ; CHECK-FP: test4:
277 ; CHECK-FP:   .fnstart
278 ; CHECK-FP:   mov pc, lr
279 ; CHECK-FP:   .cantunwind
280 ; CHECK-FP:   .fnend
281
282 ; CHECK-FP-ELIM: test4:
283 ; CHECK-FP-ELIM:   .fnstart
284 ; CHECK-FP-ELIM:   mov pc, lr
285 ; CHECK-FP-ELIM:   .cantunwind
286 ; CHECK-FP-ELIM:   .fnend
287
288 ; CHECK-V7-FP: test4:
289 ; CHECK-V7-FP:   .fnstart
290 ; CHECK-V7-FP:   bx lr
291 ; CHECK-V7-FP:   .cantunwind
292 ; CHECK-V7-FP:   .fnend
293
294 ; CHECK-V7-FP-ELIM: test4:
295 ; CHECK-V7-FP-ELIM:   .fnstart
296 ; CHECK-V7-FP-ELIM:   bx lr
297 ; CHECK-V7-FP-ELIM:   .cantunwind
298 ; CHECK-V7-FP-ELIM:   .fnend