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
58declare void @_Z5printiiiii(i32, i32, i32, i32, i32)
59
60declare void @_Z5printddddd(double, double, double, double, double)
61
62define void @_Z4testiiiiiddddd(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e,
63                               double %m, double %n, double %p,
64                               double %q, double %r) {
65entry:
66  invoke void @_Z5printiiiii(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e)
67          to label %try.cont unwind label %lpad
68
69lpad:
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
79invoke.cont2:
80  tail call void @__cxa_end_catch()
81  br label %try.cont
82
83try.cont:
84  ret void
85
86lpad1:
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
93eh.resume:
94  resume { i8*, i32 } %3
95
96terminate.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
105declare void @__clang_call_terminate(i8*)
106
107declare i32 @__gxx_personality_v0(...)
108
109declare i8* @__cxa_begin_catch(i8*)
110
111declare void @__cxa_end_catch()
112
113declare void @_ZSt9terminatev()
114
115; CHECK-FP-LABEL: _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-LABEL: _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-LABEL: _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-LABEL: _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
168declare void @throw_exception_2()
169
170define void @test2() {
171entry:
172  tail call void @throw_exception_2()
173  ret void
174}
175
176; CHECK-FP-LABEL: 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-LABEL: 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-LABEL: 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-LABEL: 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
215declare void @throw_exception_3(i32)
216
217define i32 @test3(i32 %a, i32 %b, i32 %c, i32 %d,
218                  i32 %e, i32 %f, i32 %g, i32 %h) {
219entry:
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-LABEL: 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-LABEL: 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-LABEL: 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-LABEL: 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
271define void @test4() nounwind {
272entry:
273  ret void
274}
275
276; CHECK-FP-LABEL: test4:
277; CHECK-FP:   .fnstart
278; CHECK-FP:   mov pc, lr
279; CHECK-FP:   .cantunwind
280; CHECK-FP:   .fnend
281
282; CHECK-FP-ELIM-LABEL: 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-LABEL: 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-LABEL: 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
299