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 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: movb $1, 8(%rax) 22; CHECK-O0: movq %{{.*}}, %r12 23entry: 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. 33define 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 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; 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 139entry: 140 %cond = icmp ne i32 %cc, 0 141 br i1 %cond, label %gen_error, label %normal 142 143gen_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 151normal: 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. 157define 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 184entry: 185 br label %bb_loop 186 187bb_loop: 188 %cond = icmp ne i32 %cc, 0 189 br i1 %cond, label %gen_error, label %bb_cont 190 191gen_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 199bb_cont: 200 %cmp = fcmp ogt float %cc2, 1.000000e+00 201 br i1 %cmp, label %bb_end, label %bb_loop 202bb_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. 210define 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 233entry: 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. 245define 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 273entry: 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 282cont: 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 287handler: 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". 294define 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 330entry: 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 338cont: 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 343handler: 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 353cont2: 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 358handler2: 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 370define void @swifterror_isel(%swift.refcounted*) { 371entry: 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. 384define 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 396entry: 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 405declare swiftcc float @moo(%swift_error** swifterror) 406 407; Test parameter forwarding. 408define 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 421entry: 422 %call = call swiftcc float @moo(%swift_error** swifterror %error_ptr_ref) 423 ret float %call 424} 425 426define 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 459entry: 460 %cond = icmp ne i32 %cc, 0 461 br i1 %cond, label %gen_error, label %normal 462 463gen_error: 464 %call = call swiftcc float @moo(%swift_error** swifterror %error_ptr_ref) 465 ret float %call 466 467normal: 468 ret float 0.0 469} 470 471; Check that we don't blow up on tail calling swifterror argument functions. 472define float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref) { 473entry: 474 %0 = tail call float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref) 475 ret float %0 476} 477define swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref) { 478entry: 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 494define swiftcc {i32, i32, i32} @empty_swiftcc({i32, i32, i32} , %swift_error** swifterror %error_ptr_ref) { 495entry: 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 509define swiftcc void @dont_crash_on_new_isel_blocks(%swift_error** nocapture swifterror, i1, i8**) { 510entry: 511 %3 = or i1 false, %1 512 br i1 %3, label %cont, label %falsebb 513 514falsebb: 515 %4 = load i8*, i8** %2, align 8 516 br label %cont 517 518cont: 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 527define 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 536define 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 585define 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} 592declare 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 663define 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 672declare 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 675declare 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 683define swiftcc void @tailcall_from_swifterror(%swift_error** swifterror %error_ptr_ref) { 684entry: 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. 695declare hidden swiftcc i8* @testFunA() 696 697%TSb = type <{ i1 }> 698 699define swiftcc void @dontCrash() { 700entry: 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 709trueBB: 710 ret void 711 712falseBB: 713 ret void 714} 715