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