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 ; RUN: llc -verify-machineinstrs < %s -mtriple=i386-apple-darwin | FileCheck --check-prefix=CHECK-i386 %s 4 5 declare i8* @malloc(i64) 6 declare void @free(i8*) 7 %swift_error = type {i64, i8} 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: movl $16, %edi 14 ; CHECK-APPLE: malloc 15 ; CHECK-APPLE: movb $1, 8(%rax) 16 ; CHECK-APPLE: movq %rax, %r12 17 18 ; CHECK-O0-LABEL: foo: 19 ; CHECK-O0: movl $16 20 ; CHECK-O0: malloc 21 ; CHECK-O0: movb $1, 8(%rax) 22 ; CHECK-O0: movq %{{.*}}, %r12 23 entry: 24 %call = call i8* @malloc(i64 16) 25 %call.0 = bitcast i8* %call to %swift_error* 26 store %swift_error* %call.0, %swift_error** %error_ptr_ref 27 %tmp = getelementptr inbounds i8, i8* %call, i64 8 28 store i8 1, i8* %tmp 29 ret float 1.0 30 } 31 32 ; "caller" calls "foo" that takes a swifterror parameter. 33 define float @caller(i8* %error_ref) { 34 ; CHECK-APPLE-LABEL: caller: 35 ; CHECK-APPLE: xorl %r12d, %r12d 36 ; CHECK-APPLE: callq {{.*}}foo 37 ; CHECK-APPLE: testq %r12, %r12 38 ; CHECK-APPLE: jne 39 ; Access part of the error object and save it to error_ref 40 ; CHECK-APPLE: movb 8(%r12) 41 ; CHECK-APPLE: movq %r12, %rdi 42 ; CHECK-APPLE: callq {{.*}}free 43 44 ; CHECK-O0-LABEL: caller: 45 ; CHECK-O0: xorl 46 ; CHECK-O0: movl %{{.*}}, %r12d 47 ; CHECK-O0: callq {{.*}}foo 48 ; CHECK-O0: jne 49 entry: 50 %error_ptr_ref = alloca swifterror %swift_error* 51 store %swift_error* null, %swift_error** %error_ptr_ref 52 %call = call float @foo(%swift_error** swifterror %error_ptr_ref) 53 %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref 54 %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null 55 %tmp = bitcast %swift_error* %error_from_foo to i8* 56 br i1 %had_error_from_foo, label %handler, label %cont 57 cont: 58 %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1 59 %t = load i8, i8* %v1 60 store i8 %t, i8* %error_ref 61 br label %handler 62 handler: 63 call void @free(i8* %tmp) 64 ret float 1.0 65 } 66 67 ; "caller2" is the caller of "foo", it calls "foo" inside a loop. 68 define float @caller2(i8* %error_ref) { 69 ; CHECK-APPLE-LABEL: caller2: 70 ; CHECK-APPLE: xorl %r12d, %r12d 71 ; CHECK-APPLE: callq {{.*}}foo 72 ; CHECK-APPLE: testq %r12, %r12 73 ; CHECK-APPLE: jne 74 ; CHECK-APPLE: ucomiss 75 ; CHECK-APPLE: jbe 76 ; Access part of the error object and save it to error_ref 77 ; CHECK-APPLE: movb 8(%r12) 78 ; CHECK-APPLE: movq %r12, %rdi 79 ; CHECK-APPLE: callq {{.*}}free 80 81 ; CHECK-O0-LABEL: caller2: 82 ; CHECK-O0: xorl 83 ; CHECK-O0: movl %{{.*}}, %r12d 84 ; CHECK-O0: callq {{.*}}foo 85 ; CHECK-O0: movq %r12, [[ID:%[a-z]+]] 86 ; CHECK-O0: cmpq $0, %r12 87 ; CHECK-O0: jne 88 entry: 89 %error_ptr_ref = alloca swifterror %swift_error* 90 br label %bb_loop 91 bb_loop: 92 store %swift_error* null, %swift_error** %error_ptr_ref 93 %call = call float @foo(%swift_error** swifterror %error_ptr_ref) 94 %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref 95 %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null 96 %tmp = bitcast %swift_error* %error_from_foo to i8* 97 br i1 %had_error_from_foo, label %handler, label %cont 98 cont: 99 %cmp = fcmp ogt float %call, 1.000000e+00 100 br i1 %cmp, label %bb_end, label %bb_loop 101 bb_end: 102 %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1 103 %t = load i8, i8* %v1 104 store i8 %t, i8* %error_ref 105 br label %handler 106 handler: 107 call void @free(i8* %tmp) 108 ret float 1.0 109 } 110 111 ; "foo_if" is a function that takes a swifterror parameter, it sets swifterror 112 ; under a certain condition. 113 define float @foo_if(%swift_error** swifterror %error_ptr_ref, i32 %cc) { 114 ; CHECK-APPLE-LABEL: foo_if: 115 ; CHECK-APPLE: testl %edi, %edi 116 ; CHECK-APPLE: je 117 ; CHECK-APPLE: movl $16, %edi 118 ; CHECK-APPLE: malloc 119 ; CHECK-APPLE: movb $1, 8(%rax) 120 ; CHECK-APPLE: movq %rax, %r12 121 ; CHECK-APPLE-NOT: %r12 122 ; CHECK-APPLE: ret 123 124 ; CHECK-O0-LABEL: foo_if: 125 ; CHECK-O0: cmpl $0 126 ; spill to stack 127 ; CHECK-O0: movq %r12, {{.*}}(%rsp) 128 ; CHECK-O0: je 129 ; CHECK-O0: movl $16, 130 ; CHECK-O0: malloc 131 ; CHECK-O0: movq %rax, [[ID:%[a-z]+]] 132 ; CHECK-O0-DAG: movb $1, 8(%rax) 133 ; CHECK-O0-DAG: movq [[ID]], %r12 134 ; CHECK-O0: ret 135 ; reload from stack 136 ; CHECK-O0: movq {{.*}}(%rsp), [[REG:%[a-z]+]] 137 ; CHECK-O0: movq [[REG]], %r12 138 ; CHECK-O0: ret 139 entry: 140 %cond = icmp ne i32 %cc, 0 141 br i1 %cond, label %gen_error, label %normal 142 143 gen_error: 144 %call = call i8* @malloc(i64 16) 145 %call.0 = bitcast i8* %call to %swift_error* 146 store %swift_error* %call.0, %swift_error** %error_ptr_ref 147 %tmp = getelementptr inbounds i8, i8* %call, i64 8 148 store i8 1, i8* %tmp 149 ret float 1.0 150 151 normal: 152 ret float 0.0 153 } 154 155 ; "foo_loop" is a function that takes a swifterror parameter, it sets swifterror 156 ; under a certain condition inside a loop. 157 define float @foo_loop(%swift_error** swifterror %error_ptr_ref, i32 %cc, float %cc2) { 158 ; CHECK-APPLE-LABEL: foo_loop: 159 ; CHECK-APPLE: movq %r12, %rax 160 ; CHECK-APPLE: testl 161 ; CHECK-APPLE: je 162 ; CHECK-APPLE: movl $16, %edi 163 ; CHECK-APPLE: malloc 164 ; CHECK-APPLE: movb $1, 8(%rax) 165 ; CHECK-APPLE: ucomiss 166 ; CHECK-APPLE: jbe 167 ; CHECK-APPLE: movq %rax, %r12 168 ; CHECK-APPLE: ret 169 170 ; CHECK-O0-LABEL: foo_loop: 171 ; spill to stack 172 ; CHECK-O0: movq %r12, {{.*}}(%rsp) 173 ; CHECK-O0: cmpl $0 174 ; CHECK-O0: je 175 ; CHECK-O0: movl $16, 176 ; CHECK-O0: malloc 177 ; CHECK-O0: movq %rax, [[ID:%[a-z0-9]+]] 178 ; CHECK-O0: movb $1, 8([[ID]]) 179 ; CHECK-O0: jbe 180 ; reload from stack 181 ; CHECK-O0: movq {{.*}}(%rsp), [[REG:%[a-z0-9]+]] 182 ; CHECK-O0: movq [[REG]], %r12 183 ; CHECK-O0: ret 184 entry: 185 br label %bb_loop 186 187 bb_loop: 188 %cond = icmp ne i32 %cc, 0 189 br i1 %cond, label %gen_error, label %bb_cont 190 191 gen_error: 192 %call = call i8* @malloc(i64 16) 193 %call.0 = bitcast i8* %call to %swift_error* 194 store %swift_error* %call.0, %swift_error** %error_ptr_ref 195 %tmp = getelementptr inbounds i8, i8* %call, i64 8 196 store i8 1, i8* %tmp 197 br label %bb_cont 198 199 bb_cont: 200 %cmp = fcmp ogt float %cc2, 1.000000e+00 201 br i1 %cmp, label %bb_end, label %bb_loop 202 bb_end: 203 ret float 0.0 204 } 205 206 %struct.S = type { i32, i32, i32, i32, i32, i32 } 207 208 ; "foo_sret" is a function that takes a swifterror parameter, it also has a sret 209 ; parameter. 210 define void @foo_sret(%struct.S* sret %agg.result, i32 %val1, %swift_error** swifterror %error_ptr_ref) { 211 ; CHECK-APPLE-LABEL: foo_sret: 212 ; CHECK-APPLE: movq %rdi, %{{.*}} 213 ; CHECK-APPLE: movl $16, %edi 214 ; CHECK-APPLE: malloc 215 ; CHECK-APPLE: movb $1, 8(%rax) 216 ; CHECK-APPLE: movl %{{.*}}, 4(%{{.*}}) 217 ; CHECK-APPLE: movq %rax, %r12 218 ; CHECK-APPLE: movq %{{.*}}, %rax 219 ; CHECK-APPLE-NOT: x19 220 221 ; CHECK-O0-LABEL: foo_sret: 222 ; CHECK-O0: movl $16, 223 ; spill sret to stack 224 ; CHECK-O0: movq %rdi, 225 ; CHECK-O0: movq {{.*}}, %rdi 226 ; CHECK-O0: malloc 227 ; CHECK-O0: movb $1, 8(%rax) 228 ; CHECK-O0: movl %{{.*}}, 4(%{{.*}}) 229 ; CHECK-O0: movq %{{.*}}, %r12 230 ; reload sret from stack 231 ; CHECK-O0: movq {{.*}}(%rsp), %rax 232 ; CHECK-O0: ret 233 entry: 234 %call = call i8* @malloc(i64 16) 235 %call.0 = bitcast i8* %call to %swift_error* 236 store %swift_error* %call.0, %swift_error** %error_ptr_ref 237 %tmp = getelementptr inbounds i8, i8* %call, i64 8 238 store i8 1, i8* %tmp 239 %v2 = getelementptr inbounds %struct.S, %struct.S* %agg.result, i32 0, i32 1 240 store i32 %val1, i32* %v2 241 ret void 242 } 243 244 ; "caller3" calls "foo_sret" that takes a swifterror parameter. 245 define float @caller3(i8* %error_ref) { 246 ; CHECK-APPLE-LABEL: caller3: 247 ; CHECK-APPLE: movl $1, %esi 248 ; CHECK-APPLE: xorl %r12d, %r12d 249 ; CHECK-APPLE: callq {{.*}}foo_sret 250 ; CHECK-APPLE: testq %r12, %r12 251 ; CHECK-APPLE: jne 252 ; Access part of the error object and save it to error_ref 253 ; CHECK-APPLE: movb 8(%r12), 254 ; CHECK-APPLE: movb %{{.*}}, 255 ; CHECK-APPLE: movq %r12, %rdi 256 ; CHECK-APPLE: callq {{.*}}free 257 258 ; CHECK-O0-LABEL: caller3: 259 ; CHECK-O0: xorl 260 ; CHECK-O0: movl {{.*}}, %r12d 261 ; CHECK-O0: movl $1, %esi 262 ; CHECK-O0: movq {{.*}}, %rdi 263 ; CHECK-O0: callq {{.*}}foo_sret 264 ; CHECK-O0: movq %r12, 265 ; CHECK-O0: cmpq $0 266 ; CHECK-O0: jne 267 ; Access part of the error object and save it to error_ref 268 ; CHECK-O0: movb 8(%{{.*}}), 269 ; CHECK-O0: movb %{{.*}}, 270 ; reload from stack 271 ; CHECK-O0: movq {{.*}}(%rsp), %rdi 272 ; CHECK-O0: callq {{.*}}free 273 entry: 274 %s = alloca %struct.S, align 8 275 %error_ptr_ref = alloca swifterror %swift_error* 276 store %swift_error* null, %swift_error** %error_ptr_ref 277 call void @foo_sret(%struct.S* sret %s, i32 1, %swift_error** swifterror %error_ptr_ref) 278 %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref 279 %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null 280 %tmp = bitcast %swift_error* %error_from_foo to i8* 281 br i1 %had_error_from_foo, label %handler, label %cont 282 cont: 283 %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1 284 %t = load i8, i8* %v1 285 store i8 %t, i8* %error_ref 286 br label %handler 287 handler: 288 call void @free(i8* %tmp) 289 ret float 1.0 290 } 291 292 ; This is a caller with multiple swifterror values, it calls "foo" twice, each 293 ; time with a different swifterror value, from "alloca swifterror". 294 define float @caller_with_multiple_swifterror_values(i8* %error_ref, i8* %error_ref2) { 295 ; CHECK-APPLE-LABEL: caller_with_multiple_swifterror_values: 296 297 ; The first swifterror value: 298 ; CHECK-APPLE: xorl %r12d, %r12d 299 ; CHECK-APPLE: callq {{.*}}foo 300 ; CHECK-APPLE: testq %r12, %r12 301 ; CHECK-APPLE: jne 302 ; Access part of the error object and save it to error_ref 303 ; CHECK-APPLE: movb 8(%r12) 304 ; CHECK-APPLE: movq %r12, %rdi 305 ; CHECK-APPLE: callq {{.*}}free 306 307 ; The second swifterror value: 308 ; CHECK-APPLE: xorl %r12d, %r12d 309 ; CHECK-APPLE: callq {{.*}}foo 310 ; CHECK-APPLE: testq %r12, %r12 311 ; CHECK-APPLE: jne 312 ; Access part of the error object and save it to error_ref 313 ; CHECK-APPLE: movb 8(%r12) 314 ; CHECK-APPLE: movq %r12, %rdi 315 ; CHECK-APPLE: callq {{.*}}free 316 317 ; CHECK-O0-LABEL: caller_with_multiple_swifterror_values: 318 319 ; The first swifterror value: 320 ; CHECK-O0: xorl 321 ; CHECK-O0: movl %{{.*}}, %r12d 322 ; CHECK-O0: callq {{.*}}foo 323 ; CHECK-O0: jne 324 325 ; The second swifterror value: 326 ; CHECK-O0: xorl 327 ; CHECK-O0: movl %{{.*}}, %r12d 328 ; CHECK-O0: callq {{.*}}foo 329 ; CHECK-O0: jne 330 entry: 331 %error_ptr_ref = alloca swifterror %swift_error* 332 store %swift_error* null, %swift_error** %error_ptr_ref 333 %call = call float @foo(%swift_error** swifterror %error_ptr_ref) 334 %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref 335 %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null 336 %tmp = bitcast %swift_error* %error_from_foo to i8* 337 br i1 %had_error_from_foo, label %handler, label %cont 338 cont: 339 %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1 340 %t = load i8, i8* %v1 341 store i8 %t, i8* %error_ref 342 br label %handler 343 handler: 344 call void @free(i8* %tmp) 345 346 %error_ptr_ref2 = alloca swifterror %swift_error* 347 store %swift_error* null, %swift_error** %error_ptr_ref2 348 %call2 = call float @foo(%swift_error** swifterror %error_ptr_ref2) 349 %error_from_foo2 = load %swift_error*, %swift_error** %error_ptr_ref2 350 %had_error_from_foo2 = icmp ne %swift_error* %error_from_foo2, null 351 %bitcast2 = bitcast %swift_error* %error_from_foo2 to i8* 352 br i1 %had_error_from_foo2, label %handler2, label %cont2 353 cont2: 354 %v2 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo2, i64 0, i32 1 355 %t2 = load i8, i8* %v2 356 store i8 %t2, i8* %error_ref2 357 br label %handler2 358 handler2: 359 call void @free(i8* %bitcast2) 360 361 ret float 1.0 362 } 363 364 %swift.refcounted = type opaque 365 366 ; This test checks that we don't create bad phi nodes as part of swifterror 367 ; isel. We used to fail machine ir verification. 368 ; CHECK-APPLE: _swifterror_isel 369 ; CHECK-O0: _swifterror_isel 370 define void @swifterror_isel(%swift.refcounted*) { 371 entry: 372 %swifterror = alloca swifterror %swift_error*, align 8 373 br i1 undef, label %5, label %1 374 375 %2 = phi i16 [ %4, %1 ], [ undef, %entry ] 376 %3 = call i1 undef(i16 %2, %swift.refcounted* swiftself %0, %swift_error** nocapture swifterror %swifterror) 377 %4 = load i16, i16* undef, align 2 378 br label %1 379 380 ret void 381 } 382 383 ; This tests the basic usage of a swifterror parameter with swiftcc. 384 define swiftcc float @foo_swiftcc(%swift_error** swifterror %error_ptr_ref) { 385 ; CHECK-APPLE-LABEL: foo_swiftcc: 386 ; CHECK-APPLE: movl $16, %edi 387 ; CHECK-APPLE: malloc 388 ; CHECK-APPLE: movb $1, 8(%rax) 389 ; CHECK-APPLE: movq %rax, %r12 390 391 ; CHECK-O0-LABEL: foo_swiftcc: 392 ; CHECK-O0: movl $16 393 ; CHECK-O0: malloc 394 ; CHECK-O0: movb $1, 8(%rax) 395 ; CHECK-O0: movq %{{.*}}, %r12 396 entry: 397 %call = call i8* @malloc(i64 16) 398 %call.0 = bitcast i8* %call to %swift_error* 399 store %swift_error* %call.0, %swift_error** %error_ptr_ref 400 %tmp = getelementptr inbounds i8, i8* %call, i64 8 401 store i8 1, i8* %tmp 402 ret float 1.0 403 } 404 405 declare swiftcc float @moo(%swift_error** swifterror) 406 407 ; Test parameter forwarding. 408 define swiftcc float @forward_swifterror(%swift_error** swifterror %error_ptr_ref) { 409 ; CHECK-APPLE-LABEL: forward_swifterror: 410 ; CHECK-APPLE: pushq %rax 411 ; CHECK-APPLE: callq _moo 412 ; CHECK-APPLE: popq %rax 413 ; CHECK-APPLE: retq 414 415 ; CHECK-O0-LABEL: forward_swifterror: 416 ; CHECK-O0: pushq %rax 417 ; CHECK-O0: callq _moo 418 ; CHECK-O0: popq %rax 419 ; CHECK-O0: retq 420 421 entry: 422 %call = call swiftcc float @moo(%swift_error** swifterror %error_ptr_ref) 423 ret float %call 424 } 425 426 define swiftcc float @conditionally_forward_swifterror(%swift_error** swifterror %error_ptr_ref, i32 %cc) { 427 ; CHECK-APPLE-LABEL: conditionally_forward_swifterror: 428 ; CHECK-APPLE: pushq %rax 429 ; CHECK-APPLE: testl %edi, %edi 430 ; CHECK-APPLE: je 431 432 ; CHECK-APPLE: callq _moo 433 ; CHECK-APPLE: popq %rax 434 ; CHECK-APPLE: retq 435 436 ; CHECK-APPLE: xorps %xmm0, %xmm0 437 ; CHECK-APPLE: popq %rax 438 ; CHECK-APPLE: retq 439 440 ; CHECK-O0-LABEL: conditionally_forward_swifterror: 441 ; CHECK-O0: subq $24, %rsp 442 ; CHECK-O0: movq %r12, [[REG1:%[a-z0-9]+]] 443 ; CHECK-O0: cmpl $0, %edi 444 ; CHECK-O0-DAG: movq [[REG1]], [[STK:[0-9]+]](%rsp) 445 ; CHECK-O0-DAG: movq %r12, [[STK2:[0-9]+]](%rsp) 446 ; CHECK-O0: je 447 448 ; CHECK-O0: movq [[STK2]](%rsp), [[REG:%[a-z0-9]+]] 449 ; CHECK-O0: movq [[REG]], %r12 450 ; CHECK-O0: callq _moo 451 ; CHECK-O0: addq $24, %rsp 452 ; CHECK-O0: retq 453 454 ; CHECK-O0: movq [[STK2]](%rsp), [[REG:%[a-z0-9]+]] 455 ; CHECK-O0: xorps %xmm0, %xmm0 456 ; CHECK-O0: movq [[REG]], %r12 457 ; CHECK-O0: addq $24, %rsp 458 ; CHECK-O0: retq 459 entry: 460 %cond = icmp ne i32 %cc, 0 461 br i1 %cond, label %gen_error, label %normal 462 463 gen_error: 464 %call = call swiftcc float @moo(%swift_error** swifterror %error_ptr_ref) 465 ret float %call 466 467 normal: 468 ret float 0.0 469 } 470 471 ; Check that we don't blow up on tail calling swifterror argument functions. 472 define float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref) { 473 entry: 474 %0 = tail call float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref) 475 ret float %0 476 } 477 define swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref) { 478 entry: 479 %0 = tail call swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref) 480 ret float %0 481 } 482 483 ; Check that we can handle an empty function with swifterror argument. 484 ; CHECK-i386-LABEL: empty_swiftcc: 485 ; CHECK-i386: movl 4(%esp), %eax 486 ; CHECK-i386: movl 8(%esp), %edx 487 ; CHECK-i386: movl 12(%esp), %ecx 488 ; CHECK-i386: retl 489 ; CHECK-APPLE-LABEL: empty_swiftcc: 490 ; CHECK-APPLE: movl %edx, %ecx 491 ; CHECK-APPLE: movl %edi, %eax 492 ; CHECK-APPLE: movl %esi, %edx 493 ; CHECK-APPLE: retq 494 define swiftcc {i32, i32, i32} @empty_swiftcc({i32, i32, i32} , %swift_error** swifterror %error_ptr_ref) { 495 entry: 496 ret {i32, i32, i32} %0 497 } 498 499 ; Make sure we can handle the case when isel generates new machine basic blocks. 500 ; CHECK-APPLE-LABEL: dont_crash_on_new_isel_blocks: 501 ; CHECK-APPLE: pushq %rax 502 ; CHECK-APPLE: xorl %eax, %eax 503 ; CHECK-APPLE: testb %al, %al 504 ; CHECK-APPLE: jne 505 ; CHECK-APPLE: callq *%rax 506 ; CHECK-APPLE: popq %rax 507 ; CHECK-APPLE: ret 508 509 define swiftcc void @dont_crash_on_new_isel_blocks(%swift_error** nocapture swifterror, i1, i8**) { 510 entry: 511 %3 = or i1 false, %1 512 br i1 %3, label %cont, label %falsebb 513 514 falsebb: 515 %4 = load i8*, i8** %2, align 8 516 br label %cont 517 518 cont: 519 tail call swiftcc void undef(%swift_error** nocapture swifterror %0) 520 ret void 521 } 522 523 ; CHECK-APPLE-LABEL: swifterror_clobber 524 ; CHECK-APPLE: movq %r12, [[REG:%.*]] 525 ; CHECK-APPLE: nop 526 ; CHECK-APPLE: movq [[REG]], %r12 527 define swiftcc void @swifterror_clobber(%swift_error** nocapture swifterror %err) { 528 call void asm sideeffect "nop", "~{r12}"() 529 ret void 530 } 531 532 ; CHECK-APPLE-LABEL: swifterror_reg_clobber 533 ; CHECK-APPLE: pushq %r12 534 ; CHECK-APPLE: nop 535 ; CHECK-APPLE: popq %r12 536 define swiftcc void @swifterror_reg_clobber(%swift_error** nocapture %err) { 537 call void asm sideeffect "nop", "~{r12}"() 538 ret void 539 } 540 541 ; CHECK-APPLE-LABEL: params_in_reg 542 ; Save callee save registers to store clobbered arugments. 543 ; CHECK-APPLE: pushq %rbp 544 ; CHECK-APPLE: pushq %r15 545 ; CHECK-APPLE: pushq %r14 546 ; Clobbered swiftself register. 547 ; CHECK-APPLE: pushq %r13 548 ; CHECK-APPLE: pushq %rbx 549 ; CHECK-APPLE: subq $48, %rsp 550 ; Save arguments. 551 ; CHECK-APPLE: movq %r12, 32(%rsp) 552 ; CHECK-APPLE: movq %r13, 24(%rsp) 553 ; CHECK-APPLE: movq %r9, 16(%rsp) 554 ; CHECK-APPLE: movq %r8, 8(%rsp) 555 ; CHECK-APPLE: movq %rcx, %r14 556 ; CHECK-APPLE: movq %rdx, %r15 557 ; CHECK-APPLE: movq %rsi, %rbx 558 ; CHECK-APPLE: movq %rdi, %rbp 559 ; Setup call. 560 ; CHECK-APPLE: movl $1, %edi 561 ; CHECK-APPLE: movl $2, %esi 562 ; CHECK-APPLE: movl $3, %edx 563 ; CHECK-APPLE: movl $4, %ecx 564 ; CHECK-APPLE: movl $5, %r8d 565 ; CHECK-APPLE: movl $6, %r9d 566 ; CHECK-APPLE: xorl %r13d, %r13d 567 ; CHECK-APPLE: xorl %r12d, %r12d 568 ; CHECK-APPLE: callq _params_in_reg2 569 ; Setup second call with stored arguments. 570 ; CHECK-APPLE: movq %rbp, %rdi 571 ; CHECK-APPLE: movq %rbx, %rsi 572 ; CHECK-APPLE: movq %r15, %rdx 573 ; CHECK-APPLE: movq %r14, %rcx 574 ; CHECK-APPLE: movq 8(%rsp), %r8 575 ; CHECK-APPLE: movq 16(%rsp), %r9 576 ; CHECK-APPLE: movq 24(%rsp), %r13 577 ; CHECK-APPLE: movq 32(%rsp), %r12 578 ; CHECK-APPLE: callq _params_in_reg2 579 ; CHECK-APPLE: addq $48, %rsp 580 ; CHECK-APPLE: popq %rbx 581 ; CHECK-APPLE: popq %r13 582 ; CHECK-APPLE: popq %r14 583 ; CHECK-APPLE: popq %r15 584 ; CHECK-APPLE: popq %rbp 585 define swiftcc void @params_in_reg(i64, i64, i64, i64, i64, i64, i8* swiftself, %swift_error** nocapture swifterror %err) { 586 %error_ptr_ref = alloca swifterror %swift_error*, align 8 587 store %swift_error* null, %swift_error** %error_ptr_ref 588 call swiftcc void @params_in_reg2(i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i8* swiftself null, %swift_error** nocapture swifterror %error_ptr_ref) 589 call swiftcc void @params_in_reg2(i64 %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5, i8* swiftself %6, %swift_error** nocapture swifterror %err) 590 ret void 591 } 592 declare swiftcc void @params_in_reg2(i64, i64, i64, i64, i64, i64, i8* swiftself, %swift_error** nocapture swifterror %err) 593 594 ; CHECK-APPLE-LABEL: params_and_return_in_reg 595 ; CHECK-APPLE: pushq %rbp 596 ; CHECK-APPLE: pushq %r15 597 ; CHECK-APPLE: pushq %r14 598 ; CHECK-APPLE: pushq %r13 599 ; CHECK-APPLE: pushq %rbx 600 ; CHECK-APPLE: subq $48, %rsp 601 ; Store arguments. 602 ; CHECK-APPLE: movq %r12, %r14 603 ; CHECK-APPLE: movq %r13, (%rsp) 604 ; CHECK-APPLE: movq %r9, 32(%rsp) 605 ; CHECK-APPLE: movq %r8, 24(%rsp) 606 ; CHECK-APPLE: movq %rcx, 16(%rsp) 607 ; CHECK-APPLE: movq %rdx, %r15 608 ; CHECK-APPLE: movq %rsi, %rbx 609 ; CHECK-APPLE: movq %rdi, %rbp 610 ; Setup call that clobbers all argument registers. 611 ; CHECK-APPLE: movl $1, %edi 612 ; CHECK-APPLE: movl $2, %esi 613 ; CHECK-APPLE: movl $3, %edx 614 ; CHECK-APPLE: movl $4, %ecx 615 ; CHECK-APPLE: movl $5, %r8d 616 ; CHECK-APPLE: movl $6, %r9d 617 ; CHECK-APPLE: xorl %r13d, %r13d 618 ; CHECK-APPLE: xorl %r12d, %r12d 619 ; CHECK-APPLE: callq _params_in_reg2 620 ; Store error_ptr_ref for later use. 621 ; CHECK-APPLE: movq %r12, 8(%rsp) 622 ; Restore original arguments. 623 ; CHECK-APPLE: movq %rbp, %rdi 624 ; CHECK-APPLE: movq %rbx, %rsi 625 ; CHECK-APPLE: movq %r15, %rdx 626 ; CHECK-APPLE: movq 16(%rsp), %rcx 627 ; CHECK-APPLE: movq 24(%rsp), %r8 628 ; CHECK-APPLE: movq 32(%rsp), %r9 629 ; CHECK-APPLE: movq (%rsp), %r13 630 ; CHECK-APPLE: movq %r14, %r12 631 ; CHECK-APPLE: callq _params_and_return_in_reg2 632 ; Store return values in callee saved registers. 633 ; CHECK-APPLE: movq %rax, %rbx 634 ; CHECK-APPLE: movq %rdx, %rbp 635 ; CHECK-APPLE: movq %rcx, %r15 636 ; CHECK-APPLE: movq %r8, %r14 637 ; Store the swifterror return value (%err). 638 ; CHECK-APPLE: movq %r12, (%rsp) 639 ; Setup call. 640 ; CHECK-APPLE: movl $1, %edi 641 ; CHECK-APPLE: movl $2, %esi 642 ; CHECK-APPLE: movl $3, %edx 643 ; CHECK-APPLE: movl $4, %ecx 644 ; CHECK-APPLE: movl $5, %r8d 645 ; CHECK-APPLE: movl $6, %r9d 646 ; CHECK-APPLE: xorl %r13d, %r13d 647 ; Restore the swifterror value of error_ptr_ref. 648 ; CHECK-APPLE: movq 8(%rsp), %r12 649 ; CHECK-APPLE: callq _params_in_reg2 650 ; Restore the return values of _params_and_return_in_reg2. 651 ; CHECK-APPLE: movq %rbx, %rax 652 ; CHECK-APPLE: movq %rbp, %rdx 653 ; CHECK-APPLE: movq %r15, %rcx 654 ; CHECK-APPLE: movq %r14, %r8 655 ; Restore the swiferror value of err. 656 ; CHECK-APPLE: movq (%rsp), %r12 657 ; CHECK-APPLE: addq $48, %rsp 658 ; CHECK-APPLE: popq %rbx 659 ; CHECK-APPLE: popq %r13 660 ; CHECK-APPLE: popq %r14 661 ; CHECK-APPLE: popq %r15 662 ; CHECK-APPLE: popq %rbp 663 define swiftcc { i64, i64, i64, i64} @params_and_return_in_reg(i64, i64, i64, i64, i64, i64, i8* swiftself, %swift_error** nocapture swifterror %err) { 664 %error_ptr_ref = alloca swifterror %swift_error*, align 8 665 store %swift_error* null, %swift_error** %error_ptr_ref 666 call swiftcc void @params_in_reg2(i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i8* swiftself null, %swift_error** nocapture swifterror %error_ptr_ref) 667 %val = call swiftcc { i64, i64, i64, i64 } @params_and_return_in_reg2(i64 %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5, i8* swiftself %6, %swift_error** nocapture swifterror %err) 668 call swiftcc void @params_in_reg2(i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i8* swiftself null, %swift_error** nocapture swifterror %error_ptr_ref) 669 ret { i64, i64, i64, i64 }%val 670 } 671 672 declare swiftcc { i64, i64, i64, i64 } @params_and_return_in_reg2(i64, i64, i64, i64, i64, i64, i8* swiftself, %swift_error** nocapture swifterror %err) 673 674 675 declare void @acallee(i8*) 676 677 ; Make sure we don't tail call if the caller returns a swifterror value. We 678 ; would have to move into the swifterror register before the tail call. 679 ; CHECK-APPLE: tailcall_from_swifterror: 680 ; CHECK-APPLE-NOT: jmp _acallee 681 ; CHECK-APPLE: callq _acallee 682 683 define swiftcc void @tailcall_from_swifterror(%swift_error** swifterror %error_ptr_ref) { 684 entry: 685 tail call void @acallee(i8* null) 686 ret void 687 } 688 689 ; Make sure we don't crash on this function during -O0. 690 ; We used to crash because we would insert an IMPLICIT_DEF for the swifterror at 691 ; beginning of the machine basic block but did not inform FastISel of the 692 ; inserted instruction. When computing the InsertPoint in the entry block 693 ; FastISel would choose an insertion point before the IMPLICIT_DEF causing a 694 ; crash later on. 695 declare hidden swiftcc i8* @testFunA() 696 697 %TSb = type <{ i1 }> 698 699 define swiftcc void @dontCrash() { 700 entry: 701 %swifterror = alloca swifterror %swift_error*, align 8 702 store %swift_error* null, %swift_error** %swifterror, align 8 703 %a = call i8* @testFunA() 704 %b = bitcast i8* %a to %TSb* 705 %._value = getelementptr inbounds %TSb, %TSb* %b, i32 0, i32 0 706 %c = load i1, i1* %._value, align 1 707 br i1 %c, label %trueBB, label %falseBB 708 709 trueBB: 710 ret void 711 712 falseBB: 713 ret void 714 } 715 716 717 declare swiftcc void @foo2(%swift_error** swifterror) 718 719 ; Make sure we properly assign registers during fast-isel. 720 ; CHECK-O0-LABEL: testAssign 721 ; CHECK-O0: pushq %r12 722 ; CHECK-O0: xorl [[ZERO:%[a-z0-9]+]], [[ZERO]] 723 ; CHECK-O0: movl [[ZERO]], %r12d 724 ; CHECK-O0: callq _foo2 725 ; CHECK-O0: movq %r12, [[SLOT:[-a-z0-9\(\)\%]*]] 726 ; 727 ; CHECK-O0: movq [[SLOT]], %rax 728 ; CHECK-O0: popq %r12 729 ; CHECK-O0: retq 730 731 ; CHECK-APPLE-LABEL: testAssign 732 ; CHECK-APPLE: pushq %r12 733 ; CHECK-APPLE: xorl %r12d, %r12d 734 ; CHECK-APPLE: callq _foo2 735 ; CHECK-APPLE: movq %r12, %rax 736 ; CHECK-APPLE: popq %r12 737 ; CHECK-APPLE: retq 738 739 define swiftcc %swift_error* @testAssign(i8* %error_ref) { 740 entry: 741 %error_ptr = alloca swifterror %swift_error* 742 store %swift_error* null, %swift_error** %error_ptr 743 call swiftcc void @foo2(%swift_error** swifterror %error_ptr) 744 br label %a 745 746 a: 747 %error = load %swift_error*, %swift_error** %error_ptr 748 ret %swift_error* %error 749 } 750 751 ; CHECK-O0-LABEL: testAssign2 752 ; CHECK-O0: movq %r12, {{.*}} 753 ; CHECK-O0: movq %r12, [[SLOT:[-a-z0-9\(\)\%]*]] 754 ; CHECK-O0: jmp 755 ; CHECK-O0: movq [[SLOT]], %rax 756 ; CHECK-O0: movq %rax, [[SLOT2:[-a-z0-9\(\)\%]*]] 757 ; CHECK-O0: movq [[SLOT2]], %r12 758 ; CHECK-O0: retq 759 760 ; CHECK-APPLE-LABEL: testAssign2 761 ; CHECK-APPLE: movq %r12, %rax 762 ; CHECK-APPLE: retq 763 define swiftcc %swift_error* @testAssign2(i8* %error_ref, %swift_error** swifterror %err) { 764 entry: 765 br label %a 766 767 a: 768 %error = load %swift_error*, %swift_error** %err 769 ret %swift_error* %error 770 } 771 772 ; CHECK-O0-LABEL: testAssign3 773 ; CHECK-O0: callq _foo2 774 ; CHECK-O0: movq %r12, [[SLOT:[-a-z0-9\(\)\%]*]] 775 ; CHECK-O0: movq [[SLOT]], %rax 776 ; CHECK-O0: movq %rax, [[SLOT2:[-a-z0-9\(\)\%]*]] 777 ; CHECK-O0: movq [[SLOT2]], %r12 778 ; CHECK-O0: addq $24, %rsp 779 ; CHECK-O0: retq 780 781 ; CHECK-APPLE-LABEL: testAssign3 782 ; CHECK-APPLE: callq _foo2 783 ; CHECK-APPLE: movq %r12, %rax 784 ; CHECK-APPLE: retq 785 786 define swiftcc %swift_error* @testAssign3(i8* %error_ref, %swift_error** swifterror %err) { 787 entry: 788 call swiftcc void @foo2(%swift_error** swifterror %err) 789 br label %a 790 791 a: 792 %error = load %swift_error*, %swift_error** %err 793 ret %swift_error* %error 794 } 795 796 797 ; CHECK-O0-LABEL: testAssign4 798 ; CHECK-O0: callq _foo2 799 ; CHECK-O0: xorl %ecx, %ecx 800 ; CHECK-O0: movl %ecx, %eax 801 ; CHECK-O0: movq %rax, [[SLOT:[-a-z0-9\(\)\%]*]] 802 ; CHECK-O0: movq [[SLOT]], %rax 803 ; CHECK-O0: movq %rax, [[SLOT2:[-a-z0-9\(\)\%]*]] 804 ; CHECK-O0: movq [[SLOT2]], %r12 805 ; CHECK-O0: retq 806 807 ; CHECK-APPLE-LABEL: testAssign4 808 ; CHECK-APPLE: callq _foo2 809 ; CHECK-APPLE: xorl %eax, %eax 810 ; CHECK-APPLE: xorl %r12d, %r12d 811 ; CHECK-APPLE: retq 812 813 define swiftcc %swift_error* @testAssign4(i8* %error_ref, %swift_error** swifterror %err) { 814 entry: 815 call swiftcc void @foo2(%swift_error** swifterror %err) 816 store %swift_error* null, %swift_error** %err 817 br label %a 818 819 a: 820 %error = load %swift_error*, %swift_error** %err 821 ret %swift_error* %error 822 } 823