Home | History | Annotate | Download | only in ARM
      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-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 
    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-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 
    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-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 
    271 define void @test4() nounwind {
    272 entry:
    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