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