1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -verify-machineinstrs < %s -mtriple=armv7-apple-ios | FileCheck --check-prefix=CHECK-APPLE %s 3; RUN: llc -verify-machineinstrs -O0 < %s -mtriple=armv7-apple-ios | FileCheck --check-prefix=CHECK-O0 %s 4; RUN: llc -verify-machineinstrs < %s -mtriple=armv7-linux-androideabi | FileCheck --check-prefix=CHECK-ANDROID %s 5 6declare ptr @malloc(i64) 7declare void @free(ptr) 8%swift_error = type { i64, i8 } 9%struct.S = type { i32, i32, i32, i32, i32, i32 } 10 11; This tests the basic usage of a swifterror parameter. "foo" is the function 12; that takes a swifterror parameter and "caller" is the caller of "foo". 13define float @foo(ptr swifterror %error_ptr_ref) { 14; CHECK-APPLE-LABEL: foo: 15; CHECK-APPLE: @ %bb.0: @ %entry 16; CHECK-APPLE-NEXT: push {lr} 17; CHECK-APPLE-NEXT: mov r0, #16 18; CHECK-APPLE-NEXT: mov r1, #0 19; CHECK-APPLE-NEXT: bl _malloc 20; CHECK-APPLE-NEXT: mov r8, r0 21; CHECK-APPLE-NEXT: mov r0, #1 22; CHECK-APPLE-NEXT: strb r0, [r8, #8] 23; CHECK-APPLE-NEXT: mov r0, #1065353216 24; CHECK-APPLE-NEXT: pop {lr} 25; CHECK-APPLE-NEXT: bx lr 26; 27; CHECK-O0-LABEL: foo: 28; CHECK-O0: @ %bb.0: @ %entry 29; CHECK-O0-NEXT: push {r7, lr} 30; CHECK-O0-NEXT: mov r7, sp 31; CHECK-O0-NEXT: mov r0, #16 32; CHECK-O0-NEXT: mov r1, #0 33; CHECK-O0-NEXT: bl _malloc 34; CHECK-O0-NEXT: mov r1, r0 35; CHECK-O0-NEXT: mov r8, r1 36; CHECK-O0-NEXT: mov r0, #1 37; CHECK-O0-NEXT: strb r0, [r1, #8] 38; CHECK-O0-NEXT: mov r0, #1065353216 39; CHECK-O0-NEXT: pop {r7, pc} 40; 41; CHECK-ANDROID-LABEL: foo: 42; CHECK-ANDROID: @ %bb.0: @ %entry 43; CHECK-ANDROID-NEXT: .save {r11, lr} 44; CHECK-ANDROID-NEXT: push {r11, lr} 45; CHECK-ANDROID-NEXT: mov r0, #16 46; CHECK-ANDROID-NEXT: mov r1, #0 47; CHECK-ANDROID-NEXT: bl malloc 48; CHECK-ANDROID-NEXT: mov r8, r0 49; CHECK-ANDROID-NEXT: mov r0, #1 50; CHECK-ANDROID-NEXT: strb r0, [r8, #8] 51; CHECK-ANDROID-NEXT: mov r0, #1065353216 52; CHECK-ANDROID-NEXT: pop {r11, pc} 53 54entry: 55 %call = call ptr @malloc(i64 16) 56 store ptr %call, ptr %error_ptr_ref 57 %tmp = getelementptr inbounds i8, ptr %call, i64 8 58 store i8 1, ptr %tmp 59 ret float 1.0 60} 61 62; "caller" calls "foo" that takes a swifterror parameter. 63define float @caller(ptr %error_ref) { 64; CHECK-APPLE-LABEL: caller: 65; CHECK-APPLE: @ %bb.0: @ %entry 66; CHECK-APPLE-NEXT: push {r4, r8, lr} 67; CHECK-APPLE-NEXT: sub sp, sp, #4 68; CHECK-APPLE-NEXT: mov r8, #0 69; CHECK-APPLE-NEXT: mov r4, r0 70; CHECK-APPLE-NEXT: bl _foo 71; CHECK-APPLE-NEXT: mov r0, r8 72; CHECK-APPLE-NEXT: cmp r8, #0 73; CHECK-APPLE-NEXT: ldrbeq r1, [r0, #8] 74; CHECK-APPLE-NEXT: strbeq r1, [r4] 75; CHECK-APPLE-NEXT: bl _free 76; CHECK-APPLE-NEXT: mov r0, #1065353216 77; CHECK-APPLE-NEXT: add sp, sp, #4 78; CHECK-APPLE-NEXT: pop {r4, r8, pc} 79; 80; CHECK-O0-LABEL: caller: 81; CHECK-O0: @ %bb.0: @ %entry 82; CHECK-O0-NEXT: push {r7, r8, lr} 83; CHECK-O0-NEXT: add r7, sp, #4 84; CHECK-O0-NEXT: sub sp, sp, #12 85; CHECK-O0-NEXT: @ implicit-def: $r1 86; CHECK-O0-NEXT: str r0, [sp] @ 4-byte Spill 87; CHECK-O0-NEXT: mov r8, #0 88; CHECK-O0-NEXT: bl _foo 89; CHECK-O0-NEXT: str r8, [sp, #4] @ 4-byte Spill 90; CHECK-O0-NEXT: movw r0, #0 91; CHECK-O0-NEXT: cmp r8, r0 92; CHECK-O0-NEXT: bne LBB1_2 93; CHECK-O0-NEXT: @ %bb.1: @ %cont 94; CHECK-O0-NEXT: ldr r1, [sp] @ 4-byte Reload 95; CHECK-O0-NEXT: ldr r0, [sp, #4] @ 4-byte Reload 96; CHECK-O0-NEXT: ldrb r0, [r0, #8] 97; CHECK-O0-NEXT: strb r0, [r1] 98; CHECK-O0-NEXT: LBB1_2: @ %handler 99; CHECK-O0-NEXT: ldr r0, [sp, #4] @ 4-byte Reload 100; CHECK-O0-NEXT: bl _free 101; CHECK-O0-NEXT: mov r0, #1065353216 102; CHECK-O0-NEXT: sub sp, r7, #4 103; CHECK-O0-NEXT: pop {r7, r8, pc} 104; 105; CHECK-ANDROID-LABEL: caller: 106; CHECK-ANDROID: @ %bb.0: @ %entry 107; CHECK-ANDROID-NEXT: .save {r4, r8, r11, lr} 108; CHECK-ANDROID-NEXT: push {r4, r8, r11, lr} 109; CHECK-ANDROID-NEXT: .pad #8 110; CHECK-ANDROID-NEXT: sub sp, sp, #8 111; CHECK-ANDROID-NEXT: mov r8, #0 112; CHECK-ANDROID-NEXT: mov r4, r0 113; CHECK-ANDROID-NEXT: bl foo 114; CHECK-ANDROID-NEXT: mov r0, r8 115; CHECK-ANDROID-NEXT: cmp r8, #0 116; CHECK-ANDROID-NEXT: ldrbeq r1, [r0, #8] 117; CHECK-ANDROID-NEXT: strbeq r1, [r4] 118; CHECK-ANDROID-NEXT: bl free 119; CHECK-ANDROID-NEXT: mov r0, #1065353216 120; CHECK-ANDROID-NEXT: add sp, sp, #8 121; CHECK-ANDROID-NEXT: pop {r4, r8, r11, pc} 122; Access part of the error object and save it to error_ref 123 124; spill r0 125; reload r0 126entry: 127 %error_ptr_ref = alloca swifterror ptr 128 store ptr null, ptr %error_ptr_ref 129 %call = call float @foo(ptr swifterror %error_ptr_ref) 130 %error_from_foo = load ptr, ptr %error_ptr_ref 131 %had_error_from_foo = icmp ne ptr %error_from_foo, null 132 br i1 %had_error_from_foo, label %handler, label %cont 133cont: 134 %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1 135 %t = load i8, ptr %v1 136 store i8 %t, ptr %error_ref 137 br label %handler 138handler: 139 call void @free(ptr %error_from_foo) 140 ret float 1.0 141} 142 143; "caller2" is the caller of "foo", it calls "foo" inside a loop. 144define float @caller2(ptr %error_ref) { 145; CHECK-APPLE-LABEL: caller2: 146; CHECK-APPLE: @ %bb.0: @ %entry 147; CHECK-APPLE-NEXT: push {r4, r8, lr} 148; CHECK-APPLE-NEXT: vpush {d8} 149; CHECK-APPLE-NEXT: sub sp, sp, #4 150; CHECK-APPLE-NEXT: vmov.f32 s16, #1.000000e+00 151; CHECK-APPLE-NEXT: mov r4, r0 152; CHECK-APPLE-NEXT: LBB2_1: @ %bb_loop 153; CHECK-APPLE-NEXT: @ =>This Inner Loop Header: Depth=1 154; CHECK-APPLE-NEXT: mov r8, #0 155; CHECK-APPLE-NEXT: bl _foo 156; CHECK-APPLE-NEXT: cmp r8, #0 157; CHECK-APPLE-NEXT: bne LBB2_4 158; CHECK-APPLE-NEXT: @ %bb.2: @ %cont 159; CHECK-APPLE-NEXT: @ in Loop: Header=BB2_1 Depth=1 160; CHECK-APPLE-NEXT: vmov s0, r0 161; CHECK-APPLE-NEXT: vcmp.f32 s0, s16 162; CHECK-APPLE-NEXT: vmrs APSR_nzcv, fpscr 163; CHECK-APPLE-NEXT: ble LBB2_1 164; CHECK-APPLE-NEXT: @ %bb.3: @ %bb_end 165; CHECK-APPLE-NEXT: ldrb r0, [r8, #8] 166; CHECK-APPLE-NEXT: strb r0, [r4] 167; CHECK-APPLE-NEXT: LBB2_4: @ %handler 168; CHECK-APPLE-NEXT: mov r0, r8 169; CHECK-APPLE-NEXT: bl _free 170; CHECK-APPLE-NEXT: mov r0, #1065353216 171; CHECK-APPLE-NEXT: add sp, sp, #4 172; CHECK-APPLE-NEXT: vpop {d8} 173; CHECK-APPLE-NEXT: pop {r4, r8, pc} 174; 175; CHECK-O0-LABEL: caller2: 176; CHECK-O0: @ %bb.0: @ %entry 177; CHECK-O0-NEXT: push {r7, r8, lr} 178; CHECK-O0-NEXT: add r7, sp, #4 179; CHECK-O0-NEXT: sub sp, sp, #16 180; CHECK-O0-NEXT: @ implicit-def: $r1 181; CHECK-O0-NEXT: str r0, [sp, #8] @ 4-byte Spill 182; CHECK-O0-NEXT: LBB2_1: @ %bb_loop 183; CHECK-O0-NEXT: @ =>This Inner Loop Header: Depth=1 184; CHECK-O0-NEXT: mov r8, #0 185; CHECK-O0-NEXT: bl _foo 186; CHECK-O0-NEXT: vmov s0, r0 187; CHECK-O0-NEXT: vstr s0, [sp] @ 4-byte Spill 188; CHECK-O0-NEXT: str r8, [sp, #4] @ 4-byte Spill 189; CHECK-O0-NEXT: movw r0, #0 190; CHECK-O0-NEXT: cmp r8, r0 191; CHECK-O0-NEXT: bne LBB2_4 192; CHECK-O0-NEXT: @ %bb.2: @ %cont 193; CHECK-O0-NEXT: @ in Loop: Header=BB2_1 Depth=1 194; CHECK-O0-NEXT: vldr s0, [sp] @ 4-byte Reload 195; CHECK-O0-NEXT: vmov.f32 s2, #1.000000e+00 196; CHECK-O0-NEXT: vcmp.f32 s0, s2 197; CHECK-O0-NEXT: vmrs APSR_nzcv, fpscr 198; CHECK-O0-NEXT: ble LBB2_1 199; CHECK-O0-NEXT: @ %bb.3: @ %bb_end 200; CHECK-O0-NEXT: ldr r1, [sp, #8] @ 4-byte Reload 201; CHECK-O0-NEXT: ldr r0, [sp, #4] @ 4-byte Reload 202; CHECK-O0-NEXT: ldrb r0, [r0, #8] 203; CHECK-O0-NEXT: strb r0, [r1] 204; CHECK-O0-NEXT: LBB2_4: @ %handler 205; CHECK-O0-NEXT: ldr r0, [sp, #4] @ 4-byte Reload 206; CHECK-O0-NEXT: bl _free 207; CHECK-O0-NEXT: mov r0, #1065353216 208; CHECK-O0-NEXT: sub sp, r7, #4 209; CHECK-O0-NEXT: pop {r7, r8, pc} 210; 211; CHECK-ANDROID-LABEL: caller2: 212; CHECK-ANDROID: @ %bb.0: @ %entry 213; CHECK-ANDROID-NEXT: .save {r4, r8, r11, lr} 214; CHECK-ANDROID-NEXT: push {r4, r8, r11, lr} 215; CHECK-ANDROID-NEXT: .vsave {d8} 216; CHECK-ANDROID-NEXT: vpush {d8} 217; CHECK-ANDROID-NEXT: .pad #8 218; CHECK-ANDROID-NEXT: sub sp, sp, #8 219; CHECK-ANDROID-NEXT: vmov.f32 s16, #1.000000e+00 220; CHECK-ANDROID-NEXT: mov r4, r0 221; CHECK-ANDROID-NEXT: .LBB2_1: @ %bb_loop 222; CHECK-ANDROID-NEXT: @ =>This Inner Loop Header: Depth=1 223; CHECK-ANDROID-NEXT: mov r8, #0 224; CHECK-ANDROID-NEXT: bl foo 225; CHECK-ANDROID-NEXT: cmp r8, #0 226; CHECK-ANDROID-NEXT: bne .LBB2_4 227; CHECK-ANDROID-NEXT: @ %bb.2: @ %cont 228; CHECK-ANDROID-NEXT: @ in Loop: Header=BB2_1 Depth=1 229; CHECK-ANDROID-NEXT: vmov s0, r0 230; CHECK-ANDROID-NEXT: vcmp.f32 s0, s16 231; CHECK-ANDROID-NEXT: vmrs APSR_nzcv, fpscr 232; CHECK-ANDROID-NEXT: ble .LBB2_1 233; CHECK-ANDROID-NEXT: @ %bb.3: @ %bb_end 234; CHECK-ANDROID-NEXT: ldrb r0, [r8, #8] 235; CHECK-ANDROID-NEXT: strb r0, [r4] 236; CHECK-ANDROID-NEXT: .LBB2_4: @ %handler 237; CHECK-ANDROID-NEXT: mov r0, r8 238; CHECK-ANDROID-NEXT: bl free 239; CHECK-ANDROID-NEXT: mov r0, #1065353216 240; CHECK-ANDROID-NEXT: add sp, sp, #8 241; CHECK-ANDROID-NEXT: vpop {d8} 242; CHECK-ANDROID-NEXT: pop {r4, r8, r11, pc} 243; Access part of the error object and save it to error_ref 244 245; spill r0 246; reload r0 247entry: 248 %error_ptr_ref = alloca swifterror ptr 249 br label %bb_loop 250bb_loop: 251 store ptr null, ptr %error_ptr_ref 252 %call = call float @foo(ptr swifterror %error_ptr_ref) 253 %error_from_foo = load ptr, ptr %error_ptr_ref 254 %had_error_from_foo = icmp ne ptr %error_from_foo, null 255 br i1 %had_error_from_foo, label %handler, label %cont 256cont: 257 %cmp = fcmp ogt float %call, 1.000000e+00 258 br i1 %cmp, label %bb_end, label %bb_loop 259bb_end: 260 %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1 261 %t = load i8, ptr %v1 262 store i8 %t, ptr %error_ref 263 br label %handler 264handler: 265 call void @free(ptr %error_from_foo) 266 ret float 1.0 267} 268 269; "foo_if" is a function that takes a swifterror parameter, it sets swifterror 270; under a certain condition. 271define float @foo_if(ptr swifterror %error_ptr_ref, i32 %cc) { 272; CHECK-APPLE-LABEL: foo_if: 273; CHECK-APPLE: @ %bb.0: @ %entry 274; CHECK-APPLE-NEXT: cmp r0, #0 275; CHECK-APPLE-NEXT: vldreq s0, LCPI3_0 276; CHECK-APPLE-NEXT: vmoveq r0, s0 277; CHECK-APPLE-NEXT: bxeq lr 278; CHECK-APPLE-NEXT: LBB3_1: @ %gen_error 279; CHECK-APPLE-NEXT: push {lr} 280; CHECK-APPLE-NEXT: mov r0, #16 281; CHECK-APPLE-NEXT: mov r1, #0 282; CHECK-APPLE-NEXT: bl _malloc 283; CHECK-APPLE-NEXT: mov r8, r0 284; CHECK-APPLE-NEXT: mov r0, #1 285; CHECK-APPLE-NEXT: vmov.f32 s0, #1.000000e+00 286; CHECK-APPLE-NEXT: strb r0, [r8, #8] 287; CHECK-APPLE-NEXT: pop {lr} 288; CHECK-APPLE-NEXT: vmov r0, s0 289; CHECK-APPLE-NEXT: bx lr 290; CHECK-APPLE-NEXT: .p2align 2 291; CHECK-APPLE-NEXT: @ %bb.2: 292; CHECK-APPLE-NEXT: .data_region 293; CHECK-APPLE-NEXT: LCPI3_0: 294; CHECK-APPLE-NEXT: .long 0x00000000 @ float 0 295; CHECK-APPLE-NEXT: .end_data_region 296; 297; CHECK-O0-LABEL: foo_if: 298; CHECK-O0: @ %bb.0: @ %entry 299; CHECK-O0-NEXT: push {r7, lr} 300; CHECK-O0-NEXT: mov r7, sp 301; CHECK-O0-NEXT: sub sp, sp, #4 302; CHECK-O0-NEXT: str r8, [sp] @ 4-byte Spill 303; CHECK-O0-NEXT: cmp r0, #0 304; CHECK-O0-NEXT: beq LBB3_2 305; CHECK-O0-NEXT: @ %bb.1: @ %gen_error 306; CHECK-O0-NEXT: mov r0, #16 307; CHECK-O0-NEXT: mov r1, #0 308; CHECK-O0-NEXT: bl _malloc 309; CHECK-O0-NEXT: mov r1, r0 310; CHECK-O0-NEXT: mov r8, r1 311; CHECK-O0-NEXT: mov r0, #1 312; CHECK-O0-NEXT: strb r0, [r1, #8] 313; CHECK-O0-NEXT: mov r0, #1065353216 314; CHECK-O0-NEXT: mov sp, r7 315; CHECK-O0-NEXT: pop {r7, pc} 316; CHECK-O0-NEXT: LBB3_2: @ %normal 317; CHECK-O0-NEXT: ldr r8, [sp] @ 4-byte Reload 318; CHECK-O0-NEXT: mov r0, #0 319; CHECK-O0-NEXT: mov sp, r7 320; CHECK-O0-NEXT: pop {r7, pc} 321; 322; CHECK-ANDROID-LABEL: foo_if: 323; CHECK-ANDROID: @ %bb.0: @ %entry 324; CHECK-ANDROID-NEXT: cmp r0, #0 325; CHECK-ANDROID-NEXT: vldreq s0, .LCPI3_0 326; CHECK-ANDROID-NEXT: vmoveq r0, s0 327; CHECK-ANDROID-NEXT: bxeq lr 328; CHECK-ANDROID-NEXT: .LBB3_1: @ %gen_error 329; CHECK-ANDROID-NEXT: .save {r11, lr} 330; CHECK-ANDROID-NEXT: push {r11, lr} 331; CHECK-ANDROID-NEXT: mov r0, #16 332; CHECK-ANDROID-NEXT: mov r1, #0 333; CHECK-ANDROID-NEXT: bl malloc 334; CHECK-ANDROID-NEXT: mov r8, r0 335; CHECK-ANDROID-NEXT: mov r0, #1 336; CHECK-ANDROID-NEXT: vmov.f32 s0, #1.000000e+00 337; CHECK-ANDROID-NEXT: strb r0, [r8, #8] 338; CHECK-ANDROID-NEXT: pop {r11, lr} 339; CHECK-ANDROID-NEXT: vmov r0, s0 340; CHECK-ANDROID-NEXT: bx lr 341; CHECK-ANDROID-NEXT: .p2align 2 342; CHECK-ANDROID-NEXT: @ %bb.2: 343; CHECK-ANDROID-NEXT: .LCPI3_0: 344; CHECK-ANDROID-NEXT: .long 0x00000000 @ float 0 345 346; spill to stack 347; reload from stack 348entry: 349 %cond = icmp ne i32 %cc, 0 350 br i1 %cond, label %gen_error, label %normal 351 352gen_error: 353 %call = call ptr @malloc(i64 16) 354 store ptr %call, ptr %error_ptr_ref 355 %tmp = getelementptr inbounds i8, ptr %call, i64 8 356 store i8 1, ptr %tmp 357 ret float 1.0 358 359normal: 360 ret float 0.0 361} 362 363; "foo_loop" is a function that takes a swifterror parameter, it sets swifterror 364; under a certain condition inside a loop. 365define float @foo_loop(ptr swifterror %error_ptr_ref, i32 %cc, float %cc2) { 366; CHECK-APPLE-LABEL: foo_loop: 367; CHECK-APPLE: @ %bb.0: @ %entry 368; CHECK-APPLE-NEXT: push {r4, r5, lr} 369; CHECK-APPLE-NEXT: vpush {d8, d9} 370; CHECK-APPLE-NEXT: vmov.f32 s18, #1.000000e+00 371; CHECK-APPLE-NEXT: mov r4, r0 372; CHECK-APPLE-NEXT: vmov s16, r1 373; CHECK-APPLE-NEXT: mov r5, #1 374; CHECK-APPLE-NEXT: b LBB4_2 375; CHECK-APPLE-NEXT: LBB4_1: @ %bb_cont 376; CHECK-APPLE-NEXT: @ in Loop: Header=BB4_2 Depth=1 377; CHECK-APPLE-NEXT: vcmp.f32 s16, s18 378; CHECK-APPLE-NEXT: vmrs APSR_nzcv, fpscr 379; CHECK-APPLE-NEXT: bgt LBB4_4 380; CHECK-APPLE-NEXT: LBB4_2: @ %bb_loop 381; CHECK-APPLE-NEXT: @ =>This Inner Loop Header: Depth=1 382; CHECK-APPLE-NEXT: cmp r4, #0 383; CHECK-APPLE-NEXT: beq LBB4_1 384; CHECK-APPLE-NEXT: @ %bb.3: @ %gen_error 385; CHECK-APPLE-NEXT: @ in Loop: Header=BB4_2 Depth=1 386; CHECK-APPLE-NEXT: mov r0, #16 387; CHECK-APPLE-NEXT: mov r1, #0 388; CHECK-APPLE-NEXT: bl _malloc 389; CHECK-APPLE-NEXT: mov r8, r0 390; CHECK-APPLE-NEXT: strb r5, [r0, #8] 391; CHECK-APPLE-NEXT: b LBB4_1 392; CHECK-APPLE-NEXT: LBB4_4: @ %bb_end 393; CHECK-APPLE-NEXT: mov r0, #0 394; CHECK-APPLE-NEXT: vpop {d8, d9} 395; CHECK-APPLE-NEXT: pop {r4, r5, pc} 396; 397; CHECK-O0-LABEL: foo_loop: 398; CHECK-O0: @ %bb.0: @ %entry 399; CHECK-O0-NEXT: push {r7, lr} 400; CHECK-O0-NEXT: mov r7, sp 401; CHECK-O0-NEXT: sub sp, sp, #20 402; CHECK-O0-NEXT: str r0, [sp, #8] @ 4-byte Spill 403; CHECK-O0-NEXT: vmov s0, r1 404; CHECK-O0-NEXT: vstr s0, [r7, #-8] @ 4-byte Spill 405; CHECK-O0-NEXT: str r8, [r7, #-4] @ 4-byte Spill 406; CHECK-O0-NEXT: b LBB4_1 407; CHECK-O0-NEXT: LBB4_1: @ %bb_loop 408; CHECK-O0-NEXT: @ =>This Inner Loop Header: Depth=1 409; CHECK-O0-NEXT: ldr r1, [sp, #8] @ 4-byte Reload 410; CHECK-O0-NEXT: ldr r0, [r7, #-4] @ 4-byte Reload 411; CHECK-O0-NEXT: cmp r1, #0 412; CHECK-O0-NEXT: str r0, [sp, #4] @ 4-byte Spill 413; CHECK-O0-NEXT: beq LBB4_3 414; CHECK-O0-NEXT: @ %bb.2: @ %gen_error 415; CHECK-O0-NEXT: @ in Loop: Header=BB4_1 Depth=1 416; CHECK-O0-NEXT: mov r0, #16 417; CHECK-O0-NEXT: mov r1, #0 418; CHECK-O0-NEXT: bl _malloc 419; CHECK-O0-NEXT: mov r2, r0 420; CHECK-O0-NEXT: movw r1, #1 421; CHECK-O0-NEXT: strb r1, [r2, #8] 422; CHECK-O0-NEXT: str r0, [sp, #4] @ 4-byte Spill 423; CHECK-O0-NEXT: LBB4_3: @ %bb_cont 424; CHECK-O0-NEXT: @ in Loop: Header=BB4_1 Depth=1 425; CHECK-O0-NEXT: vldr s0, [r7, #-8] @ 4-byte Reload 426; CHECK-O0-NEXT: ldr r0, [sp, #4] @ 4-byte Reload 427; CHECK-O0-NEXT: str r0, [sp] @ 4-byte Spill 428; CHECK-O0-NEXT: vmov.f32 s2, #1.000000e+00 429; CHECK-O0-NEXT: vcmp.f32 s0, s2 430; CHECK-O0-NEXT: vmrs APSR_nzcv, fpscr 431; CHECK-O0-NEXT: str r0, [r7, #-4] @ 4-byte Spill 432; CHECK-O0-NEXT: ble LBB4_1 433; CHECK-O0-NEXT: @ %bb.4: @ %bb_end 434; CHECK-O0-NEXT: ldr r8, [sp] @ 4-byte Reload 435; CHECK-O0-NEXT: mov r0, #0 436; CHECK-O0-NEXT: mov sp, r7 437; CHECK-O0-NEXT: pop {r7, pc} 438; 439; CHECK-ANDROID-LABEL: foo_loop: 440; CHECK-ANDROID: @ %bb.0: @ %entry 441; CHECK-ANDROID-NEXT: .save {r4, r5, r11, lr} 442; CHECK-ANDROID-NEXT: push {r4, r5, r11, lr} 443; CHECK-ANDROID-NEXT: .vsave {d8, d9} 444; CHECK-ANDROID-NEXT: vpush {d8, d9} 445; CHECK-ANDROID-NEXT: vmov.f32 s18, #1.000000e+00 446; CHECK-ANDROID-NEXT: mov r4, r0 447; CHECK-ANDROID-NEXT: vmov s16, r1 448; CHECK-ANDROID-NEXT: mov r5, #1 449; CHECK-ANDROID-NEXT: b .LBB4_2 450; CHECK-ANDROID-NEXT: .LBB4_1: @ %bb_cont 451; CHECK-ANDROID-NEXT: @ in Loop: Header=BB4_2 Depth=1 452; CHECK-ANDROID-NEXT: vcmp.f32 s16, s18 453; CHECK-ANDROID-NEXT: vmrs APSR_nzcv, fpscr 454; CHECK-ANDROID-NEXT: bgt .LBB4_4 455; CHECK-ANDROID-NEXT: .LBB4_2: @ %bb_loop 456; CHECK-ANDROID-NEXT: @ =>This Inner Loop Header: Depth=1 457; CHECK-ANDROID-NEXT: cmp r4, #0 458; CHECK-ANDROID-NEXT: beq .LBB4_1 459; CHECK-ANDROID-NEXT: @ %bb.3: @ %gen_error 460; CHECK-ANDROID-NEXT: @ in Loop: Header=BB4_2 Depth=1 461; CHECK-ANDROID-NEXT: mov r0, #16 462; CHECK-ANDROID-NEXT: mov r1, #0 463; CHECK-ANDROID-NEXT: bl malloc 464; CHECK-ANDROID-NEXT: mov r8, r0 465; CHECK-ANDROID-NEXT: strb r5, [r0, #8] 466; CHECK-ANDROID-NEXT: b .LBB4_1 467; CHECK-ANDROID-NEXT: .LBB4_4: @ %bb_end 468; CHECK-ANDROID-NEXT: mov r0, #0 469; CHECK-ANDROID-NEXT: vpop {d8, d9} 470; CHECK-ANDROID-NEXT: pop {r4, r5, r11, pc} 471; swifterror is kept in a register 472 473; spill r0 474; reload from stack 475entry: 476 br label %bb_loop 477 478bb_loop: 479 %cond = icmp ne i32 %cc, 0 480 br i1 %cond, label %gen_error, label %bb_cont 481 482gen_error: 483 %call = call ptr @malloc(i64 16) 484 store ptr %call, ptr %error_ptr_ref 485 %tmp = getelementptr inbounds i8, ptr %call, i64 8 486 store i8 1, ptr %tmp 487 br label %bb_cont 488 489bb_cont: 490 %cmp = fcmp ogt float %cc2, 1.000000e+00 491 br i1 %cmp, label %bb_end, label %bb_loop 492bb_end: 493 ret float 0.0 494} 495 496; "foo_sret" is a function that takes a swifterror parameter, it also has a sret 497; parameter. 498define void @foo_sret(ptr sret(%struct.S) %agg.result, i32 %val1, ptr swifterror %error_ptr_ref) { 499; CHECK-APPLE-LABEL: foo_sret: 500; CHECK-APPLE: @ %bb.0: @ %entry 501; CHECK-APPLE-NEXT: push {r4, r5, lr} 502; CHECK-APPLE-NEXT: mov r4, r1 503; CHECK-APPLE-NEXT: mov r5, r0 504; CHECK-APPLE-NEXT: mov r0, #16 505; CHECK-APPLE-NEXT: mov r1, #0 506; CHECK-APPLE-NEXT: bl _malloc 507; CHECK-APPLE-NEXT: mov r1, #1 508; CHECK-APPLE-NEXT: mov r8, r0 509; CHECK-APPLE-NEXT: strb r1, [r0, #8] 510; CHECK-APPLE-NEXT: str r4, [r5, #4] 511; CHECK-APPLE-NEXT: pop {r4, r5, pc} 512; 513; CHECK-O0-LABEL: foo_sret: 514; CHECK-O0: @ %bb.0: @ %entry 515; CHECK-O0-NEXT: push {r7, lr} 516; CHECK-O0-NEXT: mov r7, sp 517; CHECK-O0-NEXT: sub sp, sp, #8 518; CHECK-O0-NEXT: str r1, [sp] @ 4-byte Spill 519; CHECK-O0-NEXT: str r0, [sp, #4] @ 4-byte Spill 520; CHECK-O0-NEXT: mov r0, #16 521; CHECK-O0-NEXT: mov r1, #0 522; CHECK-O0-NEXT: bl _malloc 523; CHECK-O0-NEXT: ldr r1, [sp] @ 4-byte Reload 524; CHECK-O0-NEXT: mov r3, r0 525; CHECK-O0-NEXT: ldr r0, [sp, #4] @ 4-byte Reload 526; CHECK-O0-NEXT: mov r8, r3 527; CHECK-O0-NEXT: mov r2, #1 528; CHECK-O0-NEXT: strb r2, [r3, #8] 529; CHECK-O0-NEXT: str r1, [r0, #4] 530; CHECK-O0-NEXT: mov sp, r7 531; CHECK-O0-NEXT: pop {r7, pc} 532; 533; CHECK-ANDROID-LABEL: foo_sret: 534; CHECK-ANDROID: @ %bb.0: @ %entry 535; CHECK-ANDROID-NEXT: .save {r4, r5, r11, lr} 536; CHECK-ANDROID-NEXT: push {r4, r5, r11, lr} 537; CHECK-ANDROID-NEXT: mov r4, r1 538; CHECK-ANDROID-NEXT: mov r5, r0 539; CHECK-ANDROID-NEXT: mov r0, #16 540; CHECK-ANDROID-NEXT: mov r1, #0 541; CHECK-ANDROID-NEXT: bl malloc 542; CHECK-ANDROID-NEXT: mov r1, #1 543; CHECK-ANDROID-NEXT: mov r8, r0 544; CHECK-ANDROID-NEXT: strb r1, [r0, #8] 545; CHECK-ANDROID-NEXT: str r4, [r5, #4] 546; CHECK-ANDROID-NEXT: pop {r4, r5, r11, pc} 547 548; spill to stack: sret and val1 549; reload from stack: sret and val1 550entry: 551 %call = call ptr @malloc(i64 16) 552 store ptr %call, ptr %error_ptr_ref 553 %tmp = getelementptr inbounds i8, ptr %call, i64 8 554 store i8 1, ptr %tmp 555 %v2 = getelementptr inbounds %struct.S, ptr %agg.result, i32 0, i32 1 556 store i32 %val1, ptr %v2 557 ret void 558} 559 560; "caller3" calls "foo_sret" that takes a swifterror parameter. 561define float @caller3(ptr %error_ref) { 562; CHECK-APPLE-LABEL: caller3: 563; CHECK-APPLE: @ %bb.0: @ %entry 564; CHECK-APPLE-NEXT: push {r4, r7, r8, lr} 565; CHECK-APPLE-NEXT: add r7, sp, #8 566; CHECK-APPLE-NEXT: sub sp, sp, #32 567; CHECK-APPLE-NEXT: bfc sp, #0, #3 568; CHECK-APPLE-NEXT: mov r4, r0 569; CHECK-APPLE-NEXT: add r0, sp, #8 570; CHECK-APPLE-NEXT: mov r1, #1 571; CHECK-APPLE-NEXT: mov r8, #0 572; CHECK-APPLE-NEXT: bl _foo_sret 573; CHECK-APPLE-NEXT: mov r0, r8 574; CHECK-APPLE-NEXT: cmp r8, #0 575; CHECK-APPLE-NEXT: ldrbeq r1, [r0, #8] 576; CHECK-APPLE-NEXT: strbeq r1, [r4] 577; CHECK-APPLE-NEXT: bl _free 578; CHECK-APPLE-NEXT: mov r0, #1065353216 579; CHECK-APPLE-NEXT: sub sp, r7, #8 580; CHECK-APPLE-NEXT: pop {r4, r7, r8, pc} 581; 582; CHECK-O0-LABEL: caller3: 583; CHECK-O0: @ %bb.0: @ %entry 584; CHECK-O0-NEXT: push {r7, r8, lr} 585; CHECK-O0-NEXT: add r7, sp, #4 586; CHECK-O0-NEXT: sub sp, sp, #44 587; CHECK-O0-NEXT: bfc sp, #0, #3 588; CHECK-O0-NEXT: @ implicit-def: $r1 589; CHECK-O0-NEXT: str r0, [sp, #4] @ 4-byte Spill 590; CHECK-O0-NEXT: mov r8, #0 591; CHECK-O0-NEXT: add r0, sp, #16 592; CHECK-O0-NEXT: mov r1, #1 593; CHECK-O0-NEXT: bl _foo_sret 594; CHECK-O0-NEXT: str r8, [sp, #8] @ 4-byte Spill 595; CHECK-O0-NEXT: movw r0, #0 596; CHECK-O0-NEXT: cmp r8, r0 597; CHECK-O0-NEXT: bne LBB6_2 598; CHECK-O0-NEXT: @ %bb.1: @ %cont 599; CHECK-O0-NEXT: ldr r1, [sp, #4] @ 4-byte Reload 600; CHECK-O0-NEXT: ldr r0, [sp, #8] @ 4-byte Reload 601; CHECK-O0-NEXT: ldrb r0, [r0, #8] 602; CHECK-O0-NEXT: strb r0, [r1] 603; CHECK-O0-NEXT: LBB6_2: @ %handler 604; CHECK-O0-NEXT: ldr r0, [sp, #8] @ 4-byte Reload 605; CHECK-O0-NEXT: bl _free 606; CHECK-O0-NEXT: mov r0, #1065353216 607; CHECK-O0-NEXT: sub sp, r7, #4 608; CHECK-O0-NEXT: pop {r7, r8, pc} 609; 610; CHECK-ANDROID-LABEL: caller3: 611; CHECK-ANDROID: @ %bb.0: @ %entry 612; CHECK-ANDROID-NEXT: .save {r4, r8, r11, lr} 613; CHECK-ANDROID-NEXT: push {r4, r8, r11, lr} 614; CHECK-ANDROID-NEXT: .pad #32 615; CHECK-ANDROID-NEXT: sub sp, sp, #32 616; CHECK-ANDROID-NEXT: mov r4, r0 617; CHECK-ANDROID-NEXT: add r0, sp, #8 618; CHECK-ANDROID-NEXT: mov r1, #1 619; CHECK-ANDROID-NEXT: mov r8, #0 620; CHECK-ANDROID-NEXT: bl foo_sret 621; CHECK-ANDROID-NEXT: mov r0, r8 622; CHECK-ANDROID-NEXT: cmp r8, #0 623; CHECK-ANDROID-NEXT: ldrbeq r1, [r0, #8] 624; CHECK-ANDROID-NEXT: strbeq r1, [r4] 625; CHECK-ANDROID-NEXT: bl free 626; CHECK-ANDROID-NEXT: mov r0, #1065353216 627; CHECK-ANDROID-NEXT: add sp, sp, #32 628; CHECK-ANDROID-NEXT: pop {r4, r8, r11, pc} 629; Access part of the error object and save it to error_ref 630 631; Access part of the error object and save it to error_ref 632entry: 633 %s = alloca %struct.S, align 8 634 %error_ptr_ref = alloca swifterror ptr 635 store ptr null, ptr %error_ptr_ref 636 call void @foo_sret(ptr sret(%struct.S) %s, i32 1, ptr swifterror %error_ptr_ref) 637 %error_from_foo = load ptr, ptr %error_ptr_ref 638 %had_error_from_foo = icmp ne ptr %error_from_foo, null 639 br i1 %had_error_from_foo, label %handler, label %cont 640cont: 641 %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1 642 %t = load i8, ptr %v1 643 store i8 %t, ptr %error_ref 644 br label %handler 645handler: 646 call void @free(ptr %error_from_foo) 647 ret float 1.0 648} 649 650; "foo_vararg" is a function that takes a swifterror parameter, it also has 651; variable number of arguments. 652declare void @llvm.va_start(ptr) nounwind 653define float @foo_vararg(ptr swifterror %error_ptr_ref, ...) { 654; CHECK-APPLE-LABEL: foo_vararg: 655; CHECK-APPLE: @ %bb.0: @ %entry 656; CHECK-APPLE-NEXT: sub sp, sp, #16 657; CHECK-APPLE-NEXT: push {r7, lr} 658; CHECK-APPLE-NEXT: mov r7, sp 659; CHECK-APPLE-NEXT: sub sp, sp, #24 660; CHECK-APPLE-NEXT: bfc sp, #0, #3 661; CHECK-APPLE-NEXT: add r8, r7, #8 662; CHECK-APPLE-NEXT: stm r8, {r0, r1, r2, r3} 663; CHECK-APPLE-NEXT: mov r0, #16 664; CHECK-APPLE-NEXT: mov r1, #0 665; CHECK-APPLE-NEXT: bl _malloc 666; CHECK-APPLE-NEXT: mov r8, r0 667; CHECK-APPLE-NEXT: mov r0, #1 668; CHECK-APPLE-NEXT: strb r0, [r8, #8] 669; CHECK-APPLE-NEXT: add r0, r7, #8 670; CHECK-APPLE-NEXT: add r0, r0, #4 671; CHECK-APPLE-NEXT: ldr r2, [r7, #8] 672; CHECK-APPLE-NEXT: ldr r1, [r0], #4 673; CHECK-APPLE-NEXT: ldr r3, [r0], #4 674; CHECK-APPLE-NEXT: str r0, [sp, #16] 675; CHECK-APPLE-NEXT: mov r0, #1065353216 676; CHECK-APPLE-NEXT: str r2, [sp, #12] 677; CHECK-APPLE-NEXT: str r1, [sp, #8] 678; CHECK-APPLE-NEXT: str r3, [sp, #4] 679; CHECK-APPLE-NEXT: mov sp, r7 680; CHECK-APPLE-NEXT: pop {r7, lr} 681; CHECK-APPLE-NEXT: add sp, sp, #16 682; CHECK-APPLE-NEXT: bx lr 683; 684; CHECK-O0-LABEL: foo_vararg: 685; CHECK-O0: @ %bb.0: @ %entry 686; CHECK-O0-NEXT: sub sp, sp, #16 687; CHECK-O0-NEXT: push {r7, lr} 688; CHECK-O0-NEXT: mov r7, sp 689; CHECK-O0-NEXT: sub sp, sp, #24 690; CHECK-O0-NEXT: bfc sp, #0, #3 691; CHECK-O0-NEXT: str r3, [r7, #20] 692; CHECK-O0-NEXT: str r2, [r7, #16] 693; CHECK-O0-NEXT: str r1, [r7, #12] 694; CHECK-O0-NEXT: str r0, [r7, #8] 695; CHECK-O0-NEXT: mov r0, #16 696; CHECK-O0-NEXT: mov r1, #0 697; CHECK-O0-NEXT: bl _malloc 698; CHECK-O0-NEXT: mov r1, r0 699; CHECK-O0-NEXT: mov r8, r1 700; CHECK-O0-NEXT: mov r0, #1 701; CHECK-O0-NEXT: strb r0, [r1, #8] 702; CHECK-O0-NEXT: add r0, r7, #8 703; CHECK-O0-NEXT: str r0, [sp, #16] 704; CHECK-O0-NEXT: ldr r0, [sp, #16] 705; CHECK-O0-NEXT: add r1, r0, #4 706; CHECK-O0-NEXT: str r1, [sp, #16] 707; CHECK-O0-NEXT: ldr r0, [r0] 708; CHECK-O0-NEXT: str r0, [sp, #12] 709; CHECK-O0-NEXT: ldr r0, [sp, #16] 710; CHECK-O0-NEXT: add r1, r0, #4 711; CHECK-O0-NEXT: str r1, [sp, #16] 712; CHECK-O0-NEXT: ldr r0, [r0] 713; CHECK-O0-NEXT: str r0, [sp, #8] 714; CHECK-O0-NEXT: ldr r0, [sp, #16] 715; CHECK-O0-NEXT: add r1, r0, #4 716; CHECK-O0-NEXT: str r1, [sp, #16] 717; CHECK-O0-NEXT: ldr r0, [r0] 718; CHECK-O0-NEXT: str r0, [sp, #4] 719; CHECK-O0-NEXT: mov r0, #1065353216 720; CHECK-O0-NEXT: mov sp, r7 721; CHECK-O0-NEXT: pop {r7, lr} 722; CHECK-O0-NEXT: add sp, sp, #16 723; CHECK-O0-NEXT: bx lr 724; 725; CHECK-ANDROID-LABEL: foo_vararg: 726; CHECK-ANDROID: @ %bb.0: @ %entry 727; CHECK-ANDROID-NEXT: .pad #16 728; CHECK-ANDROID-NEXT: sub sp, sp, #16 729; CHECK-ANDROID-NEXT: .save {r11, lr} 730; CHECK-ANDROID-NEXT: push {r11, lr} 731; CHECK-ANDROID-NEXT: .pad #24 732; CHECK-ANDROID-NEXT: sub sp, sp, #24 733; CHECK-ANDROID-NEXT: add r8, sp, #32 734; CHECK-ANDROID-NEXT: stm r8, {r0, r1, r2, r3} 735; CHECK-ANDROID-NEXT: mov r0, #16 736; CHECK-ANDROID-NEXT: mov r1, #0 737; CHECK-ANDROID-NEXT: bl malloc 738; CHECK-ANDROID-NEXT: mov r8, r0 739; CHECK-ANDROID-NEXT: mov r0, #1 740; CHECK-ANDROID-NEXT: strb r0, [r8, #8] 741; CHECK-ANDROID-NEXT: add r0, sp, #32 742; CHECK-ANDROID-NEXT: orr r0, r0, #4 743; CHECK-ANDROID-NEXT: ldr r2, [sp, #32] 744; CHECK-ANDROID-NEXT: ldr r1, [r0], #4 745; CHECK-ANDROID-NEXT: ldr r3, [r0], #4 746; CHECK-ANDROID-NEXT: str r0, [sp, #16] 747; CHECK-ANDROID-NEXT: mov r0, #1065353216 748; CHECK-ANDROID-NEXT: str r2, [sp, #12] 749; CHECK-ANDROID-NEXT: str r1, [sp, #8] 750; CHECK-ANDROID-NEXT: str r3, [sp, #4] 751; CHECK-ANDROID-NEXT: add sp, sp, #24 752; CHECK-ANDROID-NEXT: pop {r11, lr} 753; CHECK-ANDROID-NEXT: add sp, sp, #16 754; CHECK-ANDROID-NEXT: bx lr 755 756entry: 757 %call = call ptr @malloc(i64 16) 758 store ptr %call, ptr %error_ptr_ref 759 %tmp = getelementptr inbounds i8, ptr %call, i64 8 760 store i8 1, ptr %tmp 761 762 %args = alloca ptr, align 8 763 %a10 = alloca i32, align 4 764 %a11 = alloca i32, align 4 765 %a12 = alloca i32, align 4 766 call void @llvm.va_start(ptr %args) 767 %v11 = va_arg ptr %args, i32 768 store i32 %v11, ptr %a10, align 4 769 %v12 = va_arg ptr %args, i32 770 store i32 %v12, ptr %a11, align 4 771 %v13 = va_arg ptr %args, i32 772 store i32 %v13, ptr %a12, align 4 773 774 ret float 1.0 775} 776 777; "caller4" calls "foo_vararg" that takes a swifterror parameter. 778define float @caller4(ptr %error_ref) { 779; CHECK-APPLE-LABEL: caller4: 780; CHECK-APPLE: @ %bb.0: @ %entry 781; CHECK-APPLE-NEXT: push {r4, r8, lr} 782; CHECK-APPLE-NEXT: sub sp, sp, #16 783; CHECK-APPLE-NEXT: mov r4, r0 784; CHECK-APPLE-NEXT: mov r0, #11 785; CHECK-APPLE-NEXT: str r0, [sp, #4] 786; CHECK-APPLE-NEXT: mov r0, #10 787; CHECK-APPLE-NEXT: str r0, [sp, #8] 788; CHECK-APPLE-NEXT: mov r0, #12 789; CHECK-APPLE-NEXT: str r0, [sp] 790; CHECK-APPLE-NEXT: mov r8, #0 791; CHECK-APPLE-NEXT: mov r0, #10 792; CHECK-APPLE-NEXT: mov r1, #11 793; CHECK-APPLE-NEXT: mov r2, #12 794; CHECK-APPLE-NEXT: bl _foo_vararg 795; CHECK-APPLE-NEXT: mov r0, r8 796; CHECK-APPLE-NEXT: cmp r8, #0 797; CHECK-APPLE-NEXT: ldrbeq r1, [r0, #8] 798; CHECK-APPLE-NEXT: strbeq r1, [r4] 799; CHECK-APPLE-NEXT: bl _free 800; CHECK-APPLE-NEXT: mov r0, #1065353216 801; CHECK-APPLE-NEXT: add sp, sp, #16 802; CHECK-APPLE-NEXT: pop {r4, r8, pc} 803; 804; CHECK-O0-LABEL: caller4: 805; CHECK-O0: @ %bb.0: @ %entry 806; CHECK-O0-NEXT: push {r7, r8, lr} 807; CHECK-O0-NEXT: add r7, sp, #4 808; CHECK-O0-NEXT: sub sp, sp, #24 809; CHECK-O0-NEXT: @ implicit-def: $r1 810; CHECK-O0-NEXT: str r0, [sp] @ 4-byte Spill 811; CHECK-O0-NEXT: mov r8, #0 812; CHECK-O0-NEXT: mov r0, #10 813; CHECK-O0-NEXT: str r0, [r7, #-12] 814; CHECK-O0-NEXT: mov r0, #11 815; CHECK-O0-NEXT: str r0, [sp, #12] 816; CHECK-O0-NEXT: mov r0, #12 817; CHECK-O0-NEXT: str r0, [sp, #8] 818; CHECK-O0-NEXT: ldr r0, [r7, #-12] 819; CHECK-O0-NEXT: ldr r1, [sp, #12] 820; CHECK-O0-NEXT: ldr r2, [sp, #8] 821; CHECK-O0-NEXT: bl _foo_vararg 822; CHECK-O0-NEXT: str r8, [sp, #4] @ 4-byte Spill 823; CHECK-O0-NEXT: movw r0, #0 824; CHECK-O0-NEXT: cmp r8, r0 825; CHECK-O0-NEXT: bne LBB8_2 826; CHECK-O0-NEXT: @ %bb.1: @ %cont 827; CHECK-O0-NEXT: ldr r1, [sp] @ 4-byte Reload 828; CHECK-O0-NEXT: ldr r0, [sp, #4] @ 4-byte Reload 829; CHECK-O0-NEXT: ldrb r0, [r0, #8] 830; CHECK-O0-NEXT: strb r0, [r1] 831; CHECK-O0-NEXT: LBB8_2: @ %handler 832; CHECK-O0-NEXT: ldr r0, [sp, #4] @ 4-byte Reload 833; CHECK-O0-NEXT: bl _free 834; CHECK-O0-NEXT: mov r0, #1065353216 835; CHECK-O0-NEXT: sub sp, r7, #4 836; CHECK-O0-NEXT: pop {r7, r8, pc} 837; 838; CHECK-ANDROID-LABEL: caller4: 839; CHECK-ANDROID: @ %bb.0: @ %entry 840; CHECK-ANDROID-NEXT: .save {r4, r8, r11, lr} 841; CHECK-ANDROID-NEXT: push {r4, r8, r11, lr} 842; CHECK-ANDROID-NEXT: .pad #16 843; CHECK-ANDROID-NEXT: sub sp, sp, #16 844; CHECK-ANDROID-NEXT: mov r4, r0 845; CHECK-ANDROID-NEXT: mov r0, #11 846; CHECK-ANDROID-NEXT: str r0, [sp, #4] 847; CHECK-ANDROID-NEXT: mov r0, #10 848; CHECK-ANDROID-NEXT: str r0, [sp, #8] 849; CHECK-ANDROID-NEXT: mov r0, #12 850; CHECK-ANDROID-NEXT: str r0, [sp] 851; CHECK-ANDROID-NEXT: mov r8, #0 852; CHECK-ANDROID-NEXT: mov r0, #10 853; CHECK-ANDROID-NEXT: mov r1, #11 854; CHECK-ANDROID-NEXT: mov r2, #12 855; CHECK-ANDROID-NEXT: bl foo_vararg 856; CHECK-ANDROID-NEXT: mov r0, r8 857; CHECK-ANDROID-NEXT: cmp r8, #0 858; CHECK-ANDROID-NEXT: ldrbeq r1, [r0, #8] 859; CHECK-ANDROID-NEXT: strbeq r1, [r4] 860; CHECK-ANDROID-NEXT: bl free 861; CHECK-ANDROID-NEXT: mov r0, #1065353216 862; CHECK-ANDROID-NEXT: add sp, sp, #16 863; CHECK-ANDROID-NEXT: pop {r4, r8, r11, pc} 864; Access part of the error object and save it to error_ref 865entry: 866 %error_ptr_ref = alloca swifterror ptr 867 store ptr null, ptr %error_ptr_ref 868 869 %a10 = alloca i32, align 4 870 %a11 = alloca i32, align 4 871 %a12 = alloca i32, align 4 872 store i32 10, ptr %a10, align 4 873 store i32 11, ptr %a11, align 4 874 store i32 12, ptr %a12, align 4 875 %v10 = load i32, ptr %a10, align 4 876 %v11 = load i32, ptr %a11, align 4 877 %v12 = load i32, ptr %a12, align 4 878 879 %call = call float (ptr, ...) @foo_vararg(ptr swifterror %error_ptr_ref, i32 %v10, i32 %v11, i32 %v12) 880 %error_from_foo = load ptr, ptr %error_ptr_ref 881 %had_error_from_foo = icmp ne ptr %error_from_foo, null 882 br i1 %had_error_from_foo, label %handler, label %cont 883 884cont: 885 %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1 886 %t = load i8, ptr %v1 887 store i8 %t, ptr %error_ref 888 br label %handler 889handler: 890 call void @free(ptr %error_from_foo) 891 ret float 1.0 892} 893 894; Check that we don't blow up on tail calling swifterror argument functions. 895define float @tailcallswifterror(ptr swifterror %error_ptr_ref) { 896; CHECK-APPLE-LABEL: tailcallswifterror: 897; CHECK-APPLE: @ %bb.0: @ %entry 898; CHECK-APPLE-NEXT: push {lr} 899; CHECK-APPLE-NEXT: bl _tailcallswifterror 900; CHECK-APPLE-NEXT: pop {lr} 901; CHECK-APPLE-NEXT: bx lr 902; 903; CHECK-O0-LABEL: tailcallswifterror: 904; CHECK-O0: @ %bb.0: @ %entry 905; CHECK-O0-NEXT: push {r7, lr} 906; CHECK-O0-NEXT: mov r7, sp 907; CHECK-O0-NEXT: bl _tailcallswifterror 908; CHECK-O0-NEXT: pop {r7, pc} 909; 910; CHECK-ANDROID-LABEL: tailcallswifterror: 911; CHECK-ANDROID: @ %bb.0: @ %entry 912; CHECK-ANDROID-NEXT: .save {r11, lr} 913; CHECK-ANDROID-NEXT: push {r11, lr} 914; CHECK-ANDROID-NEXT: bl tailcallswifterror 915; CHECK-ANDROID-NEXT: pop {r11, pc} 916entry: 917 %0 = tail call float @tailcallswifterror(ptr swifterror %error_ptr_ref) 918 ret float %0 919} 920define swiftcc float @tailcallswifterror_swiftcc(ptr swifterror %error_ptr_ref) { 921; CHECK-APPLE-LABEL: tailcallswifterror_swiftcc: 922; CHECK-APPLE: @ %bb.0: @ %entry 923; CHECK-APPLE-NEXT: push {lr} 924; CHECK-APPLE-NEXT: bl _tailcallswifterror_swiftcc 925; CHECK-APPLE-NEXT: pop {lr} 926; CHECK-APPLE-NEXT: bx lr 927; 928; CHECK-O0-LABEL: tailcallswifterror_swiftcc: 929; CHECK-O0: @ %bb.0: @ %entry 930; CHECK-O0-NEXT: push {r7, lr} 931; CHECK-O0-NEXT: mov r7, sp 932; CHECK-O0-NEXT: bl _tailcallswifterror_swiftcc 933; CHECK-O0-NEXT: pop {r7, pc} 934; 935; CHECK-ANDROID-LABEL: tailcallswifterror_swiftcc: 936; CHECK-ANDROID: @ %bb.0: @ %entry 937; CHECK-ANDROID-NEXT: .save {r11, lr} 938; CHECK-ANDROID-NEXT: push {r11, lr} 939; CHECK-ANDROID-NEXT: bl tailcallswifterror_swiftcc 940; CHECK-ANDROID-NEXT: pop {r11, pc} 941entry: 942 %0 = tail call swiftcc float @tailcallswifterror_swiftcc(ptr swifterror %error_ptr_ref) 943 ret float %0 944} 945 946define swiftcc void @swifterror_clobber(ptr nocapture swifterror %err) { 947; CHECK-APPLE-LABEL: swifterror_clobber: 948; CHECK-APPLE: @ %bb.0: 949; CHECK-APPLE-NEXT: mov r0, r8 950; CHECK-APPLE-NEXT: @ InlineAsm Start 951; CHECK-APPLE-NEXT: nop 952; CHECK-APPLE-NEXT: @ InlineAsm End 953; CHECK-APPLE-NEXT: mov r8, r0 954; CHECK-APPLE-NEXT: bx lr 955; 956; CHECK-O0-LABEL: swifterror_clobber: 957; CHECK-O0: @ %bb.0: 958; CHECK-O0-NEXT: sub sp, sp, #4 959; CHECK-O0-NEXT: str r8, [sp] @ 4-byte Spill 960; CHECK-O0-NEXT: @ InlineAsm Start 961; CHECK-O0-NEXT: nop 962; CHECK-O0-NEXT: @ InlineAsm End 963; CHECK-O0-NEXT: ldr r8, [sp] @ 4-byte Reload 964; CHECK-O0-NEXT: add sp, sp, #4 965; CHECK-O0-NEXT: bx lr 966; 967; CHECK-ANDROID-LABEL: swifterror_clobber: 968; CHECK-ANDROID: @ %bb.0: 969; CHECK-ANDROID-NEXT: mov r0, r8 970; CHECK-ANDROID-NEXT: @APP 971; CHECK-ANDROID-NEXT: nop 972; CHECK-ANDROID-NEXT: @NO_APP 973; CHECK-ANDROID-NEXT: mov r8, r0 974; CHECK-ANDROID-NEXT: bx lr 975 call void asm sideeffect "nop", "~{r8}"() 976 ret void 977} 978 979define swiftcc void @swifterror_reg_clobber(ptr nocapture %err) { 980; CHECK-APPLE-LABEL: swifterror_reg_clobber: 981; CHECK-APPLE: @ %bb.0: 982; CHECK-APPLE-NEXT: push {r8, lr} 983; CHECK-APPLE-NEXT: @ InlineAsm Start 984; CHECK-APPLE-NEXT: nop 985; CHECK-APPLE-NEXT: @ InlineAsm End 986; CHECK-APPLE-NEXT: pop {r8, pc} 987; 988; CHECK-O0-LABEL: swifterror_reg_clobber: 989; CHECK-O0: @ %bb.0: 990; CHECK-O0-NEXT: push {r7, r8, lr} 991; CHECK-O0-NEXT: add r7, sp, #4 992; CHECK-O0-NEXT: @ InlineAsm Start 993; CHECK-O0-NEXT: nop 994; CHECK-O0-NEXT: @ InlineAsm End 995; CHECK-O0-NEXT: pop {r7, r8, pc} 996; 997; CHECK-ANDROID-LABEL: swifterror_reg_clobber: 998; CHECK-ANDROID: @ %bb.0: 999; CHECK-ANDROID-NEXT: .save {r8, lr} 1000; CHECK-ANDROID-NEXT: push {r8, lr} 1001; CHECK-ANDROID-NEXT: @APP 1002; CHECK-ANDROID-NEXT: nop 1003; CHECK-ANDROID-NEXT: @NO_APP 1004; CHECK-ANDROID-NEXT: pop {r8, pc} 1005 call void asm sideeffect "nop", "~{r8}"() 1006 ret void 1007} 1008 1009define swiftcc void @params_in_reg(i32, i32, i32, i32, ptr swiftself, ptr nocapture swifterror %err) { 1010; CHECK-APPLE-LABEL: params_in_reg: 1011; CHECK-APPLE: @ %bb.0: 1012; CHECK-APPLE-NEXT: push {r4, r5, r6, r7, r10, r11, lr} 1013; CHECK-APPLE-NEXT: add r7, sp, #20 1014; CHECK-APPLE-NEXT: sub sp, sp, #12 1015; CHECK-APPLE-NEXT: bfc sp, #0, #3 1016; CHECK-APPLE-NEXT: str r8, [sp, #4] @ 4-byte Spill 1017; CHECK-APPLE-NEXT: mov r6, r3 1018; CHECK-APPLE-NEXT: str r10, [sp] @ 4-byte Spill 1019; CHECK-APPLE-NEXT: mov r4, r2 1020; CHECK-APPLE-NEXT: mov r11, r1 1021; CHECK-APPLE-NEXT: mov r5, r0 1022; CHECK-APPLE-NEXT: mov r0, #1 1023; CHECK-APPLE-NEXT: mov r1, #2 1024; CHECK-APPLE-NEXT: mov r2, #3 1025; CHECK-APPLE-NEXT: mov r3, #4 1026; CHECK-APPLE-NEXT: mov r10, #0 1027; CHECK-APPLE-NEXT: mov r8, #0 1028; CHECK-APPLE-NEXT: bl _params_in_reg2 1029; CHECK-APPLE-NEXT: ldr r10, [sp] @ 4-byte Reload 1030; CHECK-APPLE-NEXT: mov r0, r5 1031; CHECK-APPLE-NEXT: ldr r8, [sp, #4] @ 4-byte Reload 1032; CHECK-APPLE-NEXT: mov r1, r11 1033; CHECK-APPLE-NEXT: mov r2, r4 1034; CHECK-APPLE-NEXT: mov r3, r6 1035; CHECK-APPLE-NEXT: bl _params_in_reg2 1036; CHECK-APPLE-NEXT: sub sp, r7, #20 1037; CHECK-APPLE-NEXT: pop {r4, r5, r6, r7, r10, r11, pc} 1038; 1039; CHECK-O0-LABEL: params_in_reg: 1040; CHECK-O0: @ %bb.0: 1041; CHECK-O0-NEXT: push {r7, r10, lr} 1042; CHECK-O0-NEXT: add r7, sp, #4 1043; CHECK-O0-NEXT: sub sp, sp, #28 1044; CHECK-O0-NEXT: bfc sp, #0, #3 1045; CHECK-O0-NEXT: str r8, [sp, #20] @ 4-byte Spill 1046; CHECK-O0-NEXT: str r10, [sp] @ 4-byte Spill 1047; CHECK-O0-NEXT: str r3, [sp, #16] @ 4-byte Spill 1048; CHECK-O0-NEXT: str r2, [sp, #12] @ 4-byte Spill 1049; CHECK-O0-NEXT: str r1, [sp, #8] @ 4-byte Spill 1050; CHECK-O0-NEXT: str r0, [sp, #4] @ 4-byte Spill 1051; CHECK-O0-NEXT: @ implicit-def: $r0 1052; CHECK-O0-NEXT: mov r8, #0 1053; CHECK-O0-NEXT: mov r0, #1 1054; CHECK-O0-NEXT: mov r1, #2 1055; CHECK-O0-NEXT: mov r2, #3 1056; CHECK-O0-NEXT: mov r3, #4 1057; CHECK-O0-NEXT: mov r10, r8 1058; CHECK-O0-NEXT: bl _params_in_reg2 1059; CHECK-O0-NEXT: ldr r10, [sp] @ 4-byte Reload 1060; CHECK-O0-NEXT: ldr r0, [sp, #4] @ 4-byte Reload 1061; CHECK-O0-NEXT: ldr r1, [sp, #8] @ 4-byte Reload 1062; CHECK-O0-NEXT: ldr r2, [sp, #12] @ 4-byte Reload 1063; CHECK-O0-NEXT: ldr r3, [sp, #16] @ 4-byte Reload 1064; CHECK-O0-NEXT: mov r9, r8 1065; CHECK-O0-NEXT: ldr r8, [sp, #20] @ 4-byte Reload 1066; CHECK-O0-NEXT: bl _params_in_reg2 1067; CHECK-O0-NEXT: sub sp, r7, #4 1068; CHECK-O0-NEXT: pop {r7, r10, pc} 1069; 1070; CHECK-ANDROID-LABEL: params_in_reg: 1071; CHECK-ANDROID: @ %bb.0: 1072; CHECK-ANDROID-NEXT: .save {r4, r5, r6, r7, r9, r10, r11, lr} 1073; CHECK-ANDROID-NEXT: push {r4, r5, r6, r7, r9, r10, r11, lr} 1074; CHECK-ANDROID-NEXT: .pad #8 1075; CHECK-ANDROID-NEXT: sub sp, sp, #8 1076; CHECK-ANDROID-NEXT: mov r9, r8 1077; CHECK-ANDROID-NEXT: mov r11, r10 1078; CHECK-ANDROID-NEXT: mov r6, r3 1079; CHECK-ANDROID-NEXT: mov r7, r2 1080; CHECK-ANDROID-NEXT: mov r4, r1 1081; CHECK-ANDROID-NEXT: mov r5, r0 1082; CHECK-ANDROID-NEXT: mov r0, #1 1083; CHECK-ANDROID-NEXT: mov r1, #2 1084; CHECK-ANDROID-NEXT: mov r2, #3 1085; CHECK-ANDROID-NEXT: mov r3, #4 1086; CHECK-ANDROID-NEXT: mov r10, #0 1087; CHECK-ANDROID-NEXT: mov r8, #0 1088; CHECK-ANDROID-NEXT: bl params_in_reg2 1089; CHECK-ANDROID-NEXT: mov r0, r5 1090; CHECK-ANDROID-NEXT: mov r1, r4 1091; CHECK-ANDROID-NEXT: mov r2, r7 1092; CHECK-ANDROID-NEXT: mov r3, r6 1093; CHECK-ANDROID-NEXT: mov r10, r11 1094; CHECK-ANDROID-NEXT: mov r8, r9 1095; CHECK-ANDROID-NEXT: bl params_in_reg2 1096; CHECK-ANDROID-NEXT: add sp, sp, #8 1097; CHECK-ANDROID-NEXT: pop {r4, r5, r6, r7, r9, r10, r11, pc} 1098 %error_ptr_ref = alloca swifterror ptr, align 8 1099 store ptr null, ptr %error_ptr_ref 1100 call swiftcc void @params_in_reg2(i32 1, i32 2, i32 3, i32 4, ptr swiftself null, ptr nocapture swifterror %error_ptr_ref) 1101 call swiftcc void @params_in_reg2(i32 %0, i32 %1, i32 %2, i32 %3, ptr swiftself %4, ptr nocapture swifterror %err) 1102 ret void 1103} 1104declare swiftcc void @params_in_reg2(i32, i32, i32, i32, ptr swiftself, ptr nocapture swifterror %err) 1105 1106define swiftcc { i32, i32, i32, i32} @params_and_return_in_reg(i32, i32, i32, i32, ptr swiftself, ptr nocapture swifterror %err) { 1107; CHECK-APPLE-LABEL: params_and_return_in_reg: 1108; CHECK-APPLE: @ %bb.0: 1109; CHECK-APPLE-NEXT: push {r4, r5, r6, r7, r10, r11, lr} 1110; CHECK-APPLE-NEXT: add r7, sp, #20 1111; CHECK-APPLE-NEXT: sub sp, sp, #20 1112; CHECK-APPLE-NEXT: bfc sp, #0, #3 1113; CHECK-APPLE-NEXT: mov r6, r8 1114; CHECK-APPLE-NEXT: str r10, [sp, #12] @ 4-byte Spill 1115; CHECK-APPLE-NEXT: str r3, [sp, #8] @ 4-byte Spill 1116; CHECK-APPLE-NEXT: mov r4, r2 1117; CHECK-APPLE-NEXT: mov r11, r1 1118; CHECK-APPLE-NEXT: mov r5, r0 1119; CHECK-APPLE-NEXT: mov r0, #1 1120; CHECK-APPLE-NEXT: mov r1, #2 1121; CHECK-APPLE-NEXT: mov r2, #3 1122; CHECK-APPLE-NEXT: mov r3, #4 1123; CHECK-APPLE-NEXT: mov r10, #0 1124; CHECK-APPLE-NEXT: mov r8, #0 1125; CHECK-APPLE-NEXT: bl _params_in_reg2 1126; CHECK-APPLE-NEXT: ldr r3, [sp, #8] @ 4-byte Reload 1127; CHECK-APPLE-NEXT: mov r0, r5 1128; CHECK-APPLE-NEXT: ldr r10, [sp, #12] @ 4-byte Reload 1129; CHECK-APPLE-NEXT: mov r1, r11 1130; CHECK-APPLE-NEXT: str r8, [sp, #4] @ 4-byte Spill 1131; CHECK-APPLE-NEXT: mov r2, r4 1132; CHECK-APPLE-NEXT: mov r8, r6 1133; CHECK-APPLE-NEXT: bl _params_and_return_in_reg2 1134; CHECK-APPLE-NEXT: str r8, [sp, #12] @ 4-byte Spill 1135; CHECK-APPLE-NEXT: mov r4, r0 1136; CHECK-APPLE-NEXT: ldr r8, [sp, #4] @ 4-byte Reload 1137; CHECK-APPLE-NEXT: mov r5, r1 1138; CHECK-APPLE-NEXT: mov r6, r2 1139; CHECK-APPLE-NEXT: mov r11, r3 1140; CHECK-APPLE-NEXT: mov r0, #1 1141; CHECK-APPLE-NEXT: mov r1, #2 1142; CHECK-APPLE-NEXT: mov r2, #3 1143; CHECK-APPLE-NEXT: mov r3, #4 1144; CHECK-APPLE-NEXT: mov r10, #0 1145; CHECK-APPLE-NEXT: bl _params_in_reg2 1146; CHECK-APPLE-NEXT: mov r0, r4 1147; CHECK-APPLE-NEXT: mov r1, r5 1148; CHECK-APPLE-NEXT: mov r2, r6 1149; CHECK-APPLE-NEXT: mov r3, r11 1150; CHECK-APPLE-NEXT: ldr r8, [sp, #12] @ 4-byte Reload 1151; CHECK-APPLE-NEXT: sub sp, r7, #20 1152; CHECK-APPLE-NEXT: pop {r4, r5, r6, r7, r10, r11, pc} 1153; 1154; CHECK-O0-LABEL: params_and_return_in_reg: 1155; CHECK-O0: @ %bb.0: 1156; CHECK-O0-NEXT: push {r7, r10, lr} 1157; CHECK-O0-NEXT: add r7, sp, #4 1158; CHECK-O0-NEXT: sub sp, sp, #76 1159; CHECK-O0-NEXT: bfc sp, #0, #3 1160; CHECK-O0-NEXT: str r8, [sp, #24] @ 4-byte Spill 1161; CHECK-O0-NEXT: str r10, [sp, #4] @ 4-byte Spill 1162; CHECK-O0-NEXT: str r3, [sp, #20] @ 4-byte Spill 1163; CHECK-O0-NEXT: str r2, [sp, #16] @ 4-byte Spill 1164; CHECK-O0-NEXT: str r1, [sp, #12] @ 4-byte Spill 1165; CHECK-O0-NEXT: str r0, [sp, #8] @ 4-byte Spill 1166; CHECK-O0-NEXT: @ implicit-def: $r0 1167; CHECK-O0-NEXT: mov r8, #0 1168; CHECK-O0-NEXT: str r8, [sp, #28] @ 4-byte Spill 1169; CHECK-O0-NEXT: mov r0, #1 1170; CHECK-O0-NEXT: str r0, [sp, #32] @ 4-byte Spill 1171; CHECK-O0-NEXT: mov r1, #2 1172; CHECK-O0-NEXT: str r1, [sp, #36] @ 4-byte Spill 1173; CHECK-O0-NEXT: mov r2, #3 1174; CHECK-O0-NEXT: str r2, [sp, #40] @ 4-byte Spill 1175; CHECK-O0-NEXT: mov r3, #4 1176; CHECK-O0-NEXT: str r3, [sp, #44] @ 4-byte Spill 1177; CHECK-O0-NEXT: mov r10, r8 1178; CHECK-O0-NEXT: bl _params_in_reg2 1179; CHECK-O0-NEXT: ldr r10, [sp, #4] @ 4-byte Reload 1180; CHECK-O0-NEXT: ldr r0, [sp, #8] @ 4-byte Reload 1181; CHECK-O0-NEXT: ldr r1, [sp, #12] @ 4-byte Reload 1182; CHECK-O0-NEXT: ldr r2, [sp, #16] @ 4-byte Reload 1183; CHECK-O0-NEXT: ldr r3, [sp, #20] @ 4-byte Reload 1184; CHECK-O0-NEXT: mov r9, r8 1185; CHECK-O0-NEXT: ldr r8, [sp, #24] @ 4-byte Reload 1186; CHECK-O0-NEXT: str r9, [sp, #48] @ 4-byte Spill 1187; CHECK-O0-NEXT: bl _params_and_return_in_reg2 1188; CHECK-O0-NEXT: ldr r10, [sp, #28] @ 4-byte Reload 1189; CHECK-O0-NEXT: mov r9, r0 1190; CHECK-O0-NEXT: ldr r0, [sp, #32] @ 4-byte Reload 1191; CHECK-O0-NEXT: str r9, [sp, #52] @ 4-byte Spill 1192; CHECK-O0-NEXT: mov r9, r1 1193; CHECK-O0-NEXT: ldr r1, [sp, #36] @ 4-byte Reload 1194; CHECK-O0-NEXT: str r9, [sp, #56] @ 4-byte Spill 1195; CHECK-O0-NEXT: mov r9, r2 1196; CHECK-O0-NEXT: ldr r2, [sp, #40] @ 4-byte Reload 1197; CHECK-O0-NEXT: str r9, [sp, #60] @ 4-byte Spill 1198; CHECK-O0-NEXT: mov r9, r3 1199; CHECK-O0-NEXT: ldr r3, [sp, #44] @ 4-byte Reload 1200; CHECK-O0-NEXT: str r9, [sp, #64] @ 4-byte Spill 1201; CHECK-O0-NEXT: mov r9, r8 1202; CHECK-O0-NEXT: ldr r8, [sp, #48] @ 4-byte Reload 1203; CHECK-O0-NEXT: str r9, [sp, #68] @ 4-byte Spill 1204; CHECK-O0-NEXT: bl _params_in_reg2 1205; CHECK-O0-NEXT: ldr r0, [sp, #52] @ 4-byte Reload 1206; CHECK-O0-NEXT: ldr r1, [sp, #56] @ 4-byte Reload 1207; CHECK-O0-NEXT: ldr r2, [sp, #60] @ 4-byte Reload 1208; CHECK-O0-NEXT: ldr r3, [sp, #64] @ 4-byte Reload 1209; CHECK-O0-NEXT: mov r9, r8 1210; CHECK-O0-NEXT: ldr r8, [sp, #68] @ 4-byte Reload 1211; CHECK-O0-NEXT: sub sp, r7, #4 1212; CHECK-O0-NEXT: pop {r7, r10, pc} 1213; 1214; CHECK-ANDROID-LABEL: params_and_return_in_reg: 1215; CHECK-ANDROID: @ %bb.0: 1216; CHECK-ANDROID-NEXT: .save {r4, r5, r6, r7, r9, r10, r11, lr} 1217; CHECK-ANDROID-NEXT: push {r4, r5, r6, r7, r9, r10, r11, lr} 1218; CHECK-ANDROID-NEXT: .pad #16 1219; CHECK-ANDROID-NEXT: sub sp, sp, #16 1220; CHECK-ANDROID-NEXT: str r8, [sp, #4] @ 4-byte Spill 1221; CHECK-ANDROID-NEXT: mov r11, r10 1222; CHECK-ANDROID-NEXT: mov r6, r3 1223; CHECK-ANDROID-NEXT: mov r7, r2 1224; CHECK-ANDROID-NEXT: mov r4, r1 1225; CHECK-ANDROID-NEXT: mov r5, r0 1226; CHECK-ANDROID-NEXT: mov r0, #1 1227; CHECK-ANDROID-NEXT: mov r1, #2 1228; CHECK-ANDROID-NEXT: mov r2, #3 1229; CHECK-ANDROID-NEXT: mov r3, #4 1230; CHECK-ANDROID-NEXT: mov r10, #0 1231; CHECK-ANDROID-NEXT: mov r8, #0 1232; CHECK-ANDROID-NEXT: bl params_in_reg2 1233; CHECK-ANDROID-NEXT: mov r9, r8 1234; CHECK-ANDROID-NEXT: ldr r8, [sp, #4] @ 4-byte Reload 1235; CHECK-ANDROID-NEXT: mov r0, r5 1236; CHECK-ANDROID-NEXT: mov r1, r4 1237; CHECK-ANDROID-NEXT: mov r2, r7 1238; CHECK-ANDROID-NEXT: mov r3, r6 1239; CHECK-ANDROID-NEXT: mov r10, r11 1240; CHECK-ANDROID-NEXT: bl params_and_return_in_reg2 1241; CHECK-ANDROID-NEXT: mov r4, r0 1242; CHECK-ANDROID-NEXT: mov r5, r1 1243; CHECK-ANDROID-NEXT: mov r6, r2 1244; CHECK-ANDROID-NEXT: mov r7, r3 1245; CHECK-ANDROID-NEXT: mov r11, r8 1246; CHECK-ANDROID-NEXT: mov r0, #1 1247; CHECK-ANDROID-NEXT: mov r1, #2 1248; CHECK-ANDROID-NEXT: mov r2, #3 1249; CHECK-ANDROID-NEXT: mov r3, #4 1250; CHECK-ANDROID-NEXT: mov r10, #0 1251; CHECK-ANDROID-NEXT: mov r8, r9 1252; CHECK-ANDROID-NEXT: bl params_in_reg2 1253; CHECK-ANDROID-NEXT: mov r0, r4 1254; CHECK-ANDROID-NEXT: mov r1, r5 1255; CHECK-ANDROID-NEXT: mov r2, r6 1256; CHECK-ANDROID-NEXT: mov r3, r7 1257; CHECK-ANDROID-NEXT: mov r8, r11 1258; CHECK-ANDROID-NEXT: add sp, sp, #16 1259; CHECK-ANDROID-NEXT: pop {r4, r5, r6, r7, r9, r10, r11, pc} 1260 %error_ptr_ref = alloca swifterror ptr, align 8 1261 store ptr null, ptr %error_ptr_ref 1262 call swiftcc void @params_in_reg2(i32 1, i32 2, i32 3, i32 4, ptr swiftself null, ptr nocapture swifterror %error_ptr_ref) 1263 %val = call swiftcc { i32, i32, i32, i32 } @params_and_return_in_reg2(i32 %0, i32 %1, i32 %2, i32 %3, ptr swiftself %4, ptr nocapture swifterror %err) 1264 call swiftcc void @params_in_reg2(i32 1, i32 2, i32 3, i32 4, ptr swiftself null, ptr nocapture swifterror %error_ptr_ref) 1265 ret { i32, i32, i32, i32 }%val 1266} 1267 1268declare swiftcc { i32, i32, i32, i32 } @params_and_return_in_reg2(i32, i32, i32, i32, ptr swiftself, ptr nocapture swifterror %err) 1269 1270 1271declare void @acallee(ptr) 1272 1273; Make sure we don't tail call if the caller returns a swifterror value. We 1274; would have to move into the swifterror register before the tail call. 1275define swiftcc void @tailcall_from_swifterror(ptr swifterror %error_ptr_ref) { 1276; CHECK-APPLE-LABEL: tailcall_from_swifterror: 1277; CHECK-APPLE: @ %bb.0: @ %entry 1278; CHECK-APPLE-NEXT: push {r4, lr} 1279; CHECK-APPLE-NEXT: mov r0, #0 1280; CHECK-APPLE-NEXT: mov r4, r8 1281; CHECK-APPLE-NEXT: bl _acallee 1282; CHECK-APPLE-NEXT: mov r8, r4 1283; CHECK-APPLE-NEXT: pop {r4, pc} 1284; 1285; CHECK-O0-LABEL: tailcall_from_swifterror: 1286; CHECK-O0: @ %bb.0: @ %entry 1287; CHECK-O0-NEXT: push {r7, lr} 1288; CHECK-O0-NEXT: mov r7, sp 1289; CHECK-O0-NEXT: sub sp, sp, #4 1290; CHECK-O0-NEXT: str r8, [sp] @ 4-byte Spill 1291; CHECK-O0-NEXT: mov r0, #0 1292; CHECK-O0-NEXT: bl _acallee 1293; CHECK-O0-NEXT: ldr r8, [sp] @ 4-byte Reload 1294; CHECK-O0-NEXT: mov sp, r7 1295; CHECK-O0-NEXT: pop {r7, pc} 1296; 1297; CHECK-ANDROID-LABEL: tailcall_from_swifterror: 1298; CHECK-ANDROID: @ %bb.0: @ %entry 1299; CHECK-ANDROID-NEXT: .save {r4, lr} 1300; CHECK-ANDROID-NEXT: push {r4, lr} 1301; CHECK-ANDROID-NEXT: mov r0, #0 1302; CHECK-ANDROID-NEXT: mov r4, r8 1303; CHECK-ANDROID-NEXT: bl acallee 1304; CHECK-ANDROID-NEXT: mov r8, r4 1305; CHECK-ANDROID-NEXT: pop {r4, pc} 1306entry: 1307 tail call void @acallee(ptr null) 1308 ret void 1309} 1310 1311 1312declare swiftcc void @foo2(ptr swifterror) 1313 1314; Make sure we properly assign registers during fast-isel. 1315define swiftcc ptr @testAssign(ptr %error_ref) { 1316; CHECK-APPLE-LABEL: testAssign: 1317; CHECK-APPLE: @ %bb.0: @ %entry 1318; CHECK-APPLE-NEXT: push {r8, lr} 1319; CHECK-APPLE-NEXT: sub sp, sp, #4 1320; CHECK-APPLE-NEXT: mov r8, #0 1321; CHECK-APPLE-NEXT: bl _foo2 1322; CHECK-APPLE-NEXT: mov r0, r8 1323; CHECK-APPLE-NEXT: add sp, sp, #4 1324; CHECK-APPLE-NEXT: pop {r8, pc} 1325; 1326; CHECK-O0-LABEL: testAssign: 1327; CHECK-O0: @ %bb.0: @ %entry 1328; CHECK-O0-NEXT: push {r7, r8, lr} 1329; CHECK-O0-NEXT: add r7, sp, #4 1330; CHECK-O0-NEXT: sub sp, sp, #8 1331; CHECK-O0-NEXT: @ implicit-def: $r1 1332; CHECK-O0-NEXT: mov r8, #0 1333; CHECK-O0-NEXT: bl _foo2 1334; CHECK-O0-NEXT: str r8, [sp] @ 4-byte Spill 1335; CHECK-O0-NEXT: @ %bb.1: @ %a 1336; CHECK-O0-NEXT: ldr r0, [sp] @ 4-byte Reload 1337; CHECK-O0-NEXT: sub sp, r7, #4 1338; CHECK-O0-NEXT: pop {r7, r8, pc} 1339; 1340; CHECK-ANDROID-LABEL: testAssign: 1341; CHECK-ANDROID: @ %bb.0: @ %entry 1342; CHECK-ANDROID-NEXT: .save {r8, lr} 1343; CHECK-ANDROID-NEXT: push {r8, lr} 1344; CHECK-ANDROID-NEXT: .pad #8 1345; CHECK-ANDROID-NEXT: sub sp, sp, #8 1346; CHECK-ANDROID-NEXT: mov r8, #0 1347; CHECK-ANDROID-NEXT: bl foo2 1348; CHECK-ANDROID-NEXT: mov r0, r8 1349; CHECK-ANDROID-NEXT: add sp, sp, #8 1350; CHECK-ANDROID-NEXT: pop {r8, pc} 1351entry: 1352 %error_ptr = alloca swifterror ptr 1353 store ptr null, ptr %error_ptr 1354 call swiftcc void @foo2(ptr swifterror %error_ptr) 1355 br label %a 1356 1357a: 1358 %error = load ptr, ptr %error_ptr 1359 ret ptr %error 1360} 1361