Home | History | Annotate | Download | only in ARM
      1 ; RUN: llc -verify-machineinstrs < %s -mtriple=armv7-apple-ios | FileCheck --check-prefix=CHECK-APPLE %s
      2 ; RUN: llc -verify-machineinstrs -O0 < %s -mtriple=armv7-apple-ios | FileCheck --check-prefix=CHECK-O0 %s
      3 
      4 declare i8* @malloc(i64)
      5 declare void @free(i8*)
      6 %swift_error = type { i64, i8 }
      7 %struct.S = type { i32, i32, i32, i32, i32, i32 }
      8 
      9 ; This tests the basic usage of a swifterror parameter. "foo" is the function
     10 ; that takes a swifterror parameter and "caller" is the caller of "foo".
     11 define float @foo(%swift_error** swifterror %error_ptr_ref) {
     12 ; CHECK-APPLE-LABEL: foo:
     13 ; CHECK-APPLE: mov r0, #16
     14 ; CHECK-APPLE: malloc
     15 ; CHECK-APPLE-DAG: mov [[ID:r[0-9]+]], #1
     16 ; CHECK-APPLE-DAG: mov r6, r{{.*}}
     17 ; CHECK-APPLE-DAG: strb [[ID]], [r{{.*}}, #8]
     18 
     19 ; CHECK-O0-LABEL: foo:
     20 ; CHECK-O0: mov r{{.*}}, #16
     21 ; CHECK-O0: malloc
     22 ; CHECK-O0: mov [[ID2:r[0-9]+]], r0
     23 ; CHECK-O0: mov [[ID:r[0-9]+]], #1
     24 ; CHECK-O0: strb [[ID]], [r0, #8]
     25 ; CHECK-O0: mov r6, [[ID2]]
     26 entry:
     27   %call = call i8* @malloc(i64 16)
     28   %call.0 = bitcast i8* %call to %swift_error*
     29   store %swift_error* %call.0, %swift_error** %error_ptr_ref
     30   %tmp = getelementptr inbounds i8, i8* %call, i64 8
     31   store i8 1, i8* %tmp
     32   ret float 1.0
     33 }
     34 
     35 ; "caller" calls "foo" that takes a swifterror parameter.
     36 define float @caller(i8* %error_ref) {
     37 ; CHECK-APPLE-LABEL: caller:
     38 ; CHECK-APPLE-DAG: mov [[ID:r[0-9]+]], r0
     39 ; CHECK-APPLE-DAG: mov r6, #0
     40 ; CHECK-APPLE: bl {{.*}}foo
     41 ; CHECK-APPLE: cmp r6, #0
     42 ; Access part of the error object and save it to error_ref
     43 ; CHECK-APPLE: ldrbeq [[CODE:r[0-9]+]], [r6, #8]
     44 ; CHECK-APPLE: strbeq [[CODE]], [{{.*}}[[ID]]]
     45 ; CHECK-APPLE: mov r0, r6
     46 ; CHECK_APPLE: bl {{.*}}free
     47 
     48 ; CHECK-O0-LABEL: caller:
     49 ; spill r0
     50 ; CHECK-O0-DAG: str r0,
     51 ; CHECK-O0-DAG: mov r6, #0
     52 ; CHECK-O0: bl {{.*}}foo
     53 ; CHECK-O0: mov r{{.*}}, r6
     54 ; CHECK-O0: bne
     55 ; CHECK-O0: ldrb [[CODE:r[0-9]+]], [r0, #8]
     56 ; reload r0
     57 ; CHECK-O0: ldr [[ID:r[0-9]+]],
     58 ; CHECK-O0: strb [[CODE]], [{{.*}}[[ID]]]
     59 ; CHECK-O0: mov r0,
     60 ; CHECK-O0: free
     61 entry:
     62   %error_ptr_ref = alloca swifterror %swift_error*
     63   store %swift_error* null, %swift_error** %error_ptr_ref
     64   %call = call float @foo(%swift_error** swifterror %error_ptr_ref)
     65   %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
     66   %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
     67   %tmp = bitcast %swift_error* %error_from_foo to i8*
     68   br i1 %had_error_from_foo, label %handler, label %cont
     69 cont:
     70   %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
     71   %t = load i8, i8* %v1
     72   store i8 %t, i8* %error_ref
     73   br label %handler
     74 handler:
     75   call void @free(i8* %tmp)
     76   ret float 1.0
     77 }
     78 
     79 ; "caller2" is the caller of "foo", it calls "foo" inside a loop.
     80 define float @caller2(i8* %error_ref) {
     81 ; CHECK-APPLE-LABEL: caller2:
     82 ; CHECK-APPLE-DAG: mov [[ID:r[0-9]+]], r0
     83 ; CHECK-APPLE-DAG: mov r6, #0
     84 ; CHECK-APPLE: bl {{.*}}foo
     85 ; CHECK-APPLE: cmp r6, #0
     86 ; CHECK-APPLE: bne
     87 ; Access part of the error object and save it to error_ref
     88 ; CHECK-APPLE: ldrb [[CODE:r[0-9]+]], [r6, #8]
     89 ; CHECK-APPLE: strb [[CODE]], [{{.*}}[[ID]]]
     90 ; CHECK-APPLE: mov r0, r6
     91 ; CHECK_APPLE: bl {{.*}}free
     92 
     93 ; CHECK-O0-LABEL: caller2:
     94 ; spill r0
     95 ; CHECK-O0-DAG: str r0,
     96 ; CHECK-O0-DAG: mov r6, #0
     97 ; CHECK-O0: bl {{.*}}foo
     98 ; CHECK-O0: mov r{{.*}}, r6
     99 ; CHECK-O0: bne
    100 ; CHECK-O0: ble
    101 ; CHECK-O0: ldrb [[CODE:r[0-9]+]], [r0, #8]
    102 ; reload r0
    103 ; CHECK-O0: ldr [[ID:r[0-9]+]],
    104 ; CHECK-O0: strb [[CODE]], [{{.*}}[[ID]]]
    105 ; CHECK-O0: mov r0,
    106 ; CHECK-O0: free
    107 entry:
    108   %error_ptr_ref = alloca swifterror %swift_error*
    109   br label %bb_loop
    110 bb_loop:
    111   store %swift_error* null, %swift_error** %error_ptr_ref
    112   %call = call float @foo(%swift_error** swifterror %error_ptr_ref)
    113   %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
    114   %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
    115   %tmp = bitcast %swift_error* %error_from_foo to i8*
    116   br i1 %had_error_from_foo, label %handler, label %cont
    117 cont:
    118   %cmp = fcmp ogt float %call, 1.000000e+00
    119   br i1 %cmp, label %bb_end, label %bb_loop
    120 bb_end:
    121   %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
    122   %t = load i8, i8* %v1
    123   store i8 %t, i8* %error_ref
    124   br label %handler
    125 handler:
    126   call void @free(i8* %tmp)
    127   ret float 1.0
    128 }
    129 
    130 ; "foo_if" is a function that takes a swifterror parameter, it sets swifterror
    131 ; under a certain condition.
    132 define float @foo_if(%swift_error** swifterror %error_ptr_ref, i32 %cc) {
    133 ; CHECK-APPLE-LABEL: foo_if:
    134 ; CHECK-APPLE: cmp r0, #0
    135 ; CHECK-APPLE: eq
    136 ; CHECK-APPLE: mov r0, #16
    137 ; CHECK-APPLE: malloc
    138 ; CHECK-APPLE: mov [[ID:r[0-9]+]], #1
    139 ; CHECK-APPLE-DAG: mov r6, r{{.*}}
    140 ; CHECK-APPLE-DAG: strb [[ID]], [r{{.*}}, #8]
    141 
    142 ; CHECK-O0-LABEL: foo_if:
    143 ; CHECK-O0: cmp r0, #0
    144 ; spill to stack
    145 ; CHECK-O0: str r6
    146 ; CHECK-O0: beq
    147 ; CHECK-O0: mov r0, #16
    148 ; CHECK-O0: malloc
    149 ; CHECK-O0: mov [[ID:r[0-9]+]], r0
    150 ; CHECK-O0: mov [[ID2:[a-z0-9]+]], #1
    151 ; CHECK-O0: strb [[ID2]], [r0, #8]
    152 ; CHECK-O0: mov r6, [[ID]]
    153 ; reload from stack
    154 ; CHECK-O0: ldr r6
    155 entry:
    156   %cond = icmp ne i32 %cc, 0
    157   br i1 %cond, label %gen_error, label %normal
    158 
    159 gen_error:
    160   %call = call i8* @malloc(i64 16)
    161   %call.0 = bitcast i8* %call to %swift_error*
    162   store %swift_error* %call.0, %swift_error** %error_ptr_ref
    163   %tmp = getelementptr inbounds i8, i8* %call, i64 8
    164   store i8 1, i8* %tmp
    165   ret float 1.0
    166 
    167 normal:
    168   ret float 0.0
    169 }
    170 
    171 ; "foo_loop" is a function that takes a swifterror parameter, it sets swifterror
    172 ; under a certain condition inside a loop.
    173 define float @foo_loop(%swift_error** swifterror %error_ptr_ref, i32 %cc, float %cc2) {
    174 ; CHECK-APPLE-LABEL: foo_loop:
    175 ; CHECK-APPLE: mov [[CODE:r[0-9]+]], r0
    176 ; swifterror is kept in a register
    177 ; CHECK-APPLE: mov [[ID:r[0-9]+]], r6
    178 ; CHECK-APPLE: cmp [[CODE]], #0
    179 ; CHECK-APPLE: beq
    180 ; CHECK-APPLE: mov r0, #16
    181 ; CHECK-APPLE: malloc
    182 ; CHECK-APPLE: strb r{{.*}}, [{{.*}}[[ID]], #8]
    183 ; CHECK-APPLE: ble
    184 ; CHECK-APPLE: mov r6, [[ID]]
    185 
    186 ; CHECK-O0-LABEL: foo_loop:
    187 ; CHECK-O0: mov r{{.*}}, r6
    188 ; CHECK-O0: cmp r{{.*}}, #0
    189 ; CHECK-O0: beq
    190 ; CHECK-O0-DAG: movw r{{.*}}, #1
    191 ; CHECK-O0-DAG: mov r{{.*}}, #16
    192 ; CHECK-O0: malloc
    193 ; CHECK-O0-DAG: mov [[ID:r[0-9]+]], r0
    194 ; CHECK-O0-DAG: ldr [[ID2:r[0-9]+]], [sp{{.*}}]
    195 ; CHECK-O0: strb [[ID2]], [{{.*}}[[ID]], #8]
    196 ; spill r0
    197 ; CHECK-O0: str r0, [sp{{.*}}]
    198 ; CHECK-O0: vcmpe
    199 ; CHECK-O0: ble
    200 ; reload from stack
    201 ; CHECK-O0: ldr r6
    202 entry:
    203   br label %bb_loop
    204 
    205 bb_loop:
    206   %cond = icmp ne i32 %cc, 0
    207   br i1 %cond, label %gen_error, label %bb_cont
    208 
    209 gen_error:
    210   %call = call i8* @malloc(i64 16)
    211   %call.0 = bitcast i8* %call to %swift_error*
    212   store %swift_error* %call.0, %swift_error** %error_ptr_ref
    213   %tmp = getelementptr inbounds i8, i8* %call, i64 8
    214   store i8 1, i8* %tmp
    215   br label %bb_cont
    216 
    217 bb_cont:
    218   %cmp = fcmp ogt float %cc2, 1.000000e+00
    219   br i1 %cmp, label %bb_end, label %bb_loop
    220 bb_end:
    221   ret float 0.0
    222 }
    223 
    224 ; "foo_sret" is a function that takes a swifterror parameter, it also has a sret
    225 ; parameter.
    226 define void @foo_sret(%struct.S* sret %agg.result, i32 %val1, %swift_error** swifterror %error_ptr_ref) {
    227 ; CHECK-APPLE-LABEL: foo_sret:
    228 ; CHECK-APPLE: mov [[SRET:r[0-9]+]], r0
    229 ; CHECK-APPLE: mov r0, #16
    230 ; CHECK-APPLE: malloc
    231 ; CHECK-APPLE: mov [[REG:r[0-9]+]], #1
    232 ; CHECK-APPLE-DAG: mov r6, r0
    233 ; CHECK-APPLE-DAG: strb [[REG]], [r0, #8]
    234 ; CHECK-APPLE-DAG: str r{{.*}}, [{{.*}}[[SRET]], #4]
    235 
    236 ; CHECK-O0-LABEL: foo_sret:
    237 ; CHECK-O0: mov r{{.*}}, #16
    238 ; spill to stack: sret and val1
    239 ; CHECK-O0-DAG: str r0
    240 ; CHECK-O0-DAG: str r1
    241 ; CHECK-O0: malloc
    242 ; CHECK-O0: mov [[ID:r[0-9]+]], #1
    243 ; CHECK-O0: strb [[ID]], [r0, #8]
    244 ; reload from stack: sret and val1
    245 ; CHECK-O0: ldr
    246 ; CHECK-O0: ldr
    247 ; CHECK-O0: str r{{.*}}, [{{.*}}, #4]
    248 ; CHECK-O0: mov r6
    249 entry:
    250   %call = call i8* @malloc(i64 16)
    251   %call.0 = bitcast i8* %call to %swift_error*
    252   store %swift_error* %call.0, %swift_error** %error_ptr_ref
    253   %tmp = getelementptr inbounds i8, i8* %call, i64 8
    254   store i8 1, i8* %tmp
    255   %v2 = getelementptr inbounds %struct.S, %struct.S* %agg.result, i32 0, i32 1
    256   store i32 %val1, i32* %v2
    257   ret void
    258 }
    259 
    260 ; "caller3" calls "foo_sret" that takes a swifterror parameter.
    261 define float @caller3(i8* %error_ref) {
    262 ; CHECK-APPLE-LABEL: caller3:
    263 ; CHECK-APPLE: mov [[ID:r[0-9]+]], r0
    264 ; CHECK-APPLE: mov r6, #0
    265 ; CHECK-APPLE: bl {{.*}}foo_sret
    266 ; CHECK-APPLE: cmp r6, #0
    267 ; Access part of the error object and save it to error_ref
    268 ; CHECK-APPLE: ldrbeq [[CODE:r[0-9]+]], [r6, #8]
    269 ; CHECK-APPLE: strbeq [[CODE]], [{{.*}}[[ID]]]
    270 ; CHECK-APPLE: mov r0, r6
    271 ; CHECK_APPLE: bl {{.*}}free
    272 
    273 ; CHECK-O0-LABEL: caller3:
    274 ; CHECK-O0-DAG: mov r6, #0
    275 ; CHECK-O0-DAG: mov r0
    276 ; CHECK-O0-DAG: mov r1
    277 ; CHECK-O0: bl {{.*}}foo_sret
    278 ; CHECK-O0: mov [[ID2:r[0-9]+]], r6
    279 ; CHECK-O0: cmp [[ID2]]
    280 ; CHECK-O0: bne
    281 ; Access part of the error object and save it to error_ref
    282 ; CHECK-O0: ldrb [[CODE:r[0-9]+]]
    283 ; CHECK-O0: ldr [[ID:r[0-9]+]]
    284 ; CHECK-O0: strb [[CODE]], [{{.*}}[[ID]]]
    285 ; CHECK-O0: mov r0,
    286 ; CHECK_O0: bl {{.*}}free
    287 entry:
    288   %s = alloca %struct.S, align 8
    289   %error_ptr_ref = alloca swifterror %swift_error*
    290   store %swift_error* null, %swift_error** %error_ptr_ref
    291   call void @foo_sret(%struct.S* sret %s, i32 1, %swift_error** swifterror %error_ptr_ref)
    292   %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
    293   %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
    294   %tmp = bitcast %swift_error* %error_from_foo to i8*
    295   br i1 %had_error_from_foo, label %handler, label %cont
    296 cont:
    297   %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
    298   %t = load i8, i8* %v1
    299   store i8 %t, i8* %error_ref
    300   br label %handler
    301 handler:
    302   call void @free(i8* %tmp)
    303   ret float 1.0
    304 }
    305 
    306 ; "foo_vararg" is a function that takes a swifterror parameter, it also has
    307 ; variable number of arguments.
    308 declare void @llvm.va_start(i8*) nounwind
    309 define float @foo_vararg(%swift_error** swifterror %error_ptr_ref, ...) {
    310 ; CHECK-APPLE-LABEL: foo_vararg:
    311 ; CHECK-APPLE: mov r0, #16
    312 ; CHECK-APPLE: malloc
    313 ; CHECK-APPLE: mov [[REG:r[0-9]+]], r0
    314 ; CHECK-APPLE: mov [[ID:r[0-9]+]], #1
    315 ; CHECK-APPLE-DAG: strb [[ID]], [{{.*}}[[REG]], #8]
    316 ; CHECK-APPLE-DAG: mov r6, [[REG]]
    317 
    318 entry:
    319   %call = call i8* @malloc(i64 16)
    320   %call.0 = bitcast i8* %call to %swift_error*
    321   store %swift_error* %call.0, %swift_error** %error_ptr_ref
    322   %tmp = getelementptr inbounds i8, i8* %call, i64 8
    323   store i8 1, i8* %tmp
    324 
    325   %args = alloca i8*, align 8
    326   %a10 = alloca i32, align 4
    327   %a11 = alloca i32, align 4
    328   %a12 = alloca i32, align 4
    329   %v10 = bitcast i8** %args to i8*
    330   call void @llvm.va_start(i8* %v10)
    331   %v11 = va_arg i8** %args, i32
    332   store i32 %v11, i32* %a10, align 4
    333   %v12 = va_arg i8** %args, i32
    334   store i32 %v12, i32* %a11, align 4
    335   %v13 = va_arg i8** %args, i32
    336   store i32 %v13, i32* %a12, align 4
    337 
    338   ret float 1.0
    339 }
    340 
    341 ; "caller4" calls "foo_vararg" that takes a swifterror parameter.
    342 define float @caller4(i8* %error_ref) {
    343 ; CHECK-APPLE-LABEL: caller4:
    344 ; CHECK-APPLE: mov [[ID:r[0-9]+]], r0
    345 ; CHECK-APPLE: mov r6, #0
    346 ; CHECK-APPLE: bl {{.*}}foo_vararg
    347 ; CHECK-APPLE: cmp r6, #0
    348 ; Access part of the error object and save it to error_ref
    349 ; CHECK-APPLE: ldrbeq [[CODE:r[0-9]+]], [r6, #8]
    350 ; CHECK-APPLE: strbeq [[CODE]], [{{.*}}[[ID]]]
    351 ; CHECK-APPLE: mov r0, r6
    352 ; CHECK_APPLE: bl {{.*}}free
    353 entry:
    354   %error_ptr_ref = alloca swifterror %swift_error*
    355   store %swift_error* null, %swift_error** %error_ptr_ref
    356 
    357   %a10 = alloca i32, align 4
    358   %a11 = alloca i32, align 4
    359   %a12 = alloca i32, align 4
    360   store i32 10, i32* %a10, align 4
    361   store i32 11, i32* %a11, align 4
    362   store i32 12, i32* %a12, align 4
    363   %v10 = load i32, i32* %a10, align 4
    364   %v11 = load i32, i32* %a11, align 4
    365   %v12 = load i32, i32* %a12, align 4
    366 
    367   %call = call float (%swift_error**, ...) @foo_vararg(%swift_error** swifterror %error_ptr_ref, i32 %v10, i32 %v11, i32 %v12)
    368   %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
    369   %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
    370   %tmp = bitcast %swift_error* %error_from_foo to i8*
    371   br i1 %had_error_from_foo, label %handler, label %cont
    372 
    373 cont:
    374   %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
    375   %t = load i8, i8* %v1
    376   store i8 %t, i8* %error_ref
    377   br label %handler
    378 handler:
    379   call void @free(i8* %tmp)
    380   ret float 1.0
    381 }
    382