1; RUN: llc -fast-isel-sink-local-values -verify-machineinstrs < %s -mtriple=armv7-apple-ios | FileCheck --check-prefix=CHECK-APPLE --check-prefix=CHECK-ARMV7 %s 2; RUN: llc -fast-isel-sink-local-values -verify-machineinstrs -O0 < %s -mtriple=armv7-apple-ios | FileCheck --check-prefix=CHECK-O0 %s 3; RUN: llc -fast-isel-sink-local-values -verify-machineinstrs < %s -mtriple=armv7-linux-androideabi | FileCheck --check-prefix=CHECK-ANDROID %s 4 5declare i8* @malloc(i64) 6declare void @free(i8*) 7%swift_error = type { i64, i8 } 8%struct.S = type { i32, i32, i32, i32, i32, i32 } 9 10; This tests the basic usage of a swifterror parameter. "foo" is the function 11; that takes a swifterror parameter and "caller" is the caller of "foo". 12define float @foo(%swift_error** swifterror %error_ptr_ref) { 13; CHECK-APPLE-LABEL: foo: 14; CHECK-APPLE: mov r0, #16 15; CHECK-APPLE: malloc 16; CHECK-APPLE-DAG: mov [[ID:r[0-9]+]], #1 17; CHECK-APPLE-DAG: mov r8, r{{.*}} 18; CHECK-APPLE-DAG: strb [[ID]], [r{{.*}}, #8] 19 20; CHECK-O0-LABEL: foo: 21; CHECK-O0: mov r{{.*}}, #16 22; CHECK-O0: malloc 23; CHECK-O0: mov [[ID2:r[0-9]+]], r0 24; CHECK-O0: mov [[ID:r[0-9]+]], #1 25; CHECK-O0: strb [[ID]], [r0, #8] 26; CHECK-O0: mov r8, [[ID2]] 27entry: 28 %call = call i8* @malloc(i64 16) 29 %call.0 = bitcast i8* %call to %swift_error* 30 store %swift_error* %call.0, %swift_error** %error_ptr_ref 31 %tmp = getelementptr inbounds i8, i8* %call, i64 8 32 store i8 1, i8* %tmp 33 ret float 1.0 34} 35 36; "caller" calls "foo" that takes a swifterror parameter. 37define float @caller(i8* %error_ref) { 38; CHECK-APPLE-LABEL: caller: 39; CHECK-APPLE-DAG: mov [[ID:r[0-9]+]], r0 40; CHECK-APPLE-DAG: mov r8, #0 41; CHECK-APPLE: bl {{.*}}foo 42; CHECK-APPLE: mov r0, r8 43; CHECK-APPLE: cmp r8, #0 44; Access part of the error object and save it to error_ref 45; CHECK-APPLE: ldrbeq [[CODE:r[0-9]+]], [r0, #8] 46; CHECK-APPLE: strbeq [[CODE]], [{{.*}}[[ID]]] 47; CHECK-APPLE: bl {{.*}}free 48 49; CHECK-O0-LABEL: caller: 50; spill r0 51; CHECK-O0-DAG: mov r8, #0 52; CHECK-O0-DAG: str r0, [sp, [[SLOT:#[0-9]+]] 53; CHECK-O0: bl {{.*}}foo 54; CHECK-O0: mov [[TMP:r[0-9]+]], r8 55; CHECK-O0: str [[TMP]], [sp] 56; CHECK-O0: bne 57; CHECK-O0: ldrb [[CODE:r[0-9]+]], [r0, #8] 58; CHECK-O0: ldr [[ID:r[0-9]+]], [sp, [[SLOT]]] 59; CHECK-O0: strb [[CODE]], [{{.*}}[[ID]]] 60; reload r0 61; CHECK-O0: ldr r0, [sp] 62; CHECK-O0: free 63entry: 64 %error_ptr_ref = alloca swifterror %swift_error* 65 store %swift_error* null, %swift_error** %error_ptr_ref 66 %call = call float @foo(%swift_error** swifterror %error_ptr_ref) 67 %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref 68 %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null 69 %tmp = bitcast %swift_error* %error_from_foo to i8* 70 br i1 %had_error_from_foo, label %handler, label %cont 71cont: 72 %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1 73 %t = load i8, i8* %v1 74 store i8 %t, i8* %error_ref 75 br label %handler 76handler: 77 call void @free(i8* %tmp) 78 ret float 1.0 79} 80 81; "caller2" is the caller of "foo", it calls "foo" inside a loop. 82define float @caller2(i8* %error_ref) { 83; CHECK-APPLE-LABEL: caller2: 84; CHECK-APPLE-DAG: mov [[ID:r[0-9]+]], r0 85; CHECK-APPLE-DAG: mov r8, #0 86; CHECK-APPLE: bl {{.*}}foo 87; CHECK-APPLE: cmp r8, #0 88; CHECK-APPLE: bne 89; Access part of the error object and save it to error_ref 90; CHECK-APPLE: ldrb [[CODE:r[0-9]+]], [r8, #8] 91; CHECK-APPLE: strb [[CODE]], [{{.*}}[[ID]]] 92; CHECK-APPLE: mov r0, r8 93; CHECK-APPLE: bl {{.*}}free 94 95; CHECK-O0-LABEL: caller2: 96; spill r0 97; CHECK-O0-DAG: str r0, 98; CHECK-O0-DAG: mov r8, #0 99; CHECK-O0: bl {{.*}}foo 100; CHECK-O0: mov r{{.*}}, r8 101; CHECK-O0: str r0, [sp] 102; CHECK-O0: bne 103; CHECK-O0: ble 104; CHECK-O0: ldrb [[CODE:r[0-9]+]], [r0, #8] 105; reload r0 106; CHECK-O0: ldr [[ID:r[0-9]+]], 107; CHECK-O0: strb [[CODE]], [{{.*}}[[ID]]] 108; CHECK-O0: ldr r0, [sp] 109; CHECK-O0: free 110entry: 111 %error_ptr_ref = alloca swifterror %swift_error* 112 br label %bb_loop 113bb_loop: 114 store %swift_error* null, %swift_error** %error_ptr_ref 115 %call = call float @foo(%swift_error** swifterror %error_ptr_ref) 116 %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref 117 %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null 118 %tmp = bitcast %swift_error* %error_from_foo to i8* 119 br i1 %had_error_from_foo, label %handler, label %cont 120cont: 121 %cmp = fcmp ogt float %call, 1.000000e+00 122 br i1 %cmp, label %bb_end, label %bb_loop 123bb_end: 124 %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1 125 %t = load i8, i8* %v1 126 store i8 %t, i8* %error_ref 127 br label %handler 128handler: 129 call void @free(i8* %tmp) 130 ret float 1.0 131} 132 133; "foo_if" is a function that takes a swifterror parameter, it sets swifterror 134; under a certain condition. 135define float @foo_if(%swift_error** swifterror %error_ptr_ref, i32 %cc) { 136; CHECK-APPLE-LABEL: foo_if: 137; CHECK-APPLE: cmp r0, #0 138; CHECK-APPLE: eq 139; CHECK-APPLE: mov r0, #16 140; CHECK-APPLE: malloc 141; CHECK-APPLE-DAG: mov [[ID:r[0-9]+]], #1 142; CHECK-APPLE-DAG: mov r8, r{{.*}} 143; CHECK-APPLE-DAG: strb [[ID]], [r{{.*}}, #8] 144 145; CHECK-O0-LABEL: foo_if: 146; CHECK-O0: cmp r0, #0 147; spill to stack 148; CHECK-O0: str r8 149; CHECK-O0: beq 150; CHECK-O0: mov r0, #16 151; CHECK-O0: malloc 152; CHECK-O0: mov [[ID:r[0-9]+]], r0 153; CHECK-O0: mov [[ID2:[a-z0-9]+]], #1 154; CHECK-O0: strb [[ID2]], [r0, #8] 155; CHECK-O0: mov r8, [[ID]] 156; reload from stack 157; CHECK-O0: ldr r8 158entry: 159 %cond = icmp ne i32 %cc, 0 160 br i1 %cond, label %gen_error, label %normal 161 162gen_error: 163 %call = call i8* @malloc(i64 16) 164 %call.0 = bitcast i8* %call to %swift_error* 165 store %swift_error* %call.0, %swift_error** %error_ptr_ref 166 %tmp = getelementptr inbounds i8, i8* %call, i64 8 167 store i8 1, i8* %tmp 168 ret float 1.0 169 170normal: 171 ret float 0.0 172} 173 174; "foo_loop" is a function that takes a swifterror parameter, it sets swifterror 175; under a certain condition inside a loop. 176define float @foo_loop(%swift_error** swifterror %error_ptr_ref, i32 %cc, float %cc2) { 177; CHECK-APPLE-LABEL: foo_loop: 178; CHECK-APPLE: mov [[CODE:r[0-9]+]], r0 179; swifterror is kept in a register 180; CHECK-APPLE: cmp [[CODE]], #0 181; CHECK-APPLE: beq 182; CHECK-APPLE: mov r0, #16 183; CHECK-APPLE: malloc 184; CHECK-APPLE: strb r{{.*}}, [r0, #8] 185; CHECK-APPLE: ble 186 187; CHECK-O0-LABEL: foo_loop: 188; CHECK-O0: mov r{{.*}}, r8 189; CHECK-O0: cmp r{{.*}}, #0 190; CHECK-O0: beq 191; CHECK-O0: mov r0, #16 192; CHECK-O0: malloc 193; CHECK-O0-DAG: mov [[ID:r[0-9]+]], r0 194; CHECK-O0-DAG: movw [[ID2:.*]], #1 195; CHECK-O0: strb [[ID2]], [{{.*}}[[ID]], #8] 196; spill r0 197; CHECK-O0: str r0, [sp{{.*}}] 198; CHECK-O0: vcmpe 199; CHECK-O0: ble 200; reload from stack 201; CHECK-O0: ldr r8 202entry: 203 br label %bb_loop 204 205bb_loop: 206 %cond = icmp ne i32 %cc, 0 207 br i1 %cond, label %gen_error, label %bb_cont 208 209gen_error: 210 %call = call i8* @malloc(i64 16) 211 %call.0 = bitcast i8* %call to %swift_error* 212 store %swift_error* %call.0, %swift_error** %error_ptr_ref 213 %tmp = getelementptr inbounds i8, i8* %call, i64 8 214 store i8 1, i8* %tmp 215 br label %bb_cont 216 217bb_cont: 218 %cmp = fcmp ogt float %cc2, 1.000000e+00 219 br i1 %cmp, label %bb_end, label %bb_loop 220bb_end: 221 ret float 0.0 222} 223 224; "foo_sret" is a function that takes a swifterror parameter, it also has a sret 225; parameter. 226define void @foo_sret(%struct.S* sret %agg.result, i32 %val1, %swift_error** swifterror %error_ptr_ref) { 227; CHECK-APPLE-LABEL: foo_sret: 228; CHECK-APPLE: mov [[SRET:r[0-9]+]], r0 229; CHECK-APPLE: mov r0, #16 230; CHECK-APPLE: malloc 231; CHECK-APPLE: mov [[REG:r[0-9]+]], #1 232; CHECK-APPLE-DAG: mov r8, r0 233; CHECK-APPLE-DAG: strb [[REG]], [r0, #8] 234; CHECK-APPLE-DAG: str r{{.*}}, [{{.*}}[[SRET]], #4] 235 236; CHECK-O0-LABEL: foo_sret: 237; CHECK-O0: mov r{{.*}}, #16 238; spill to stack: sret and val1 239; CHECK-O0-DAG: str r0 240; CHECK-O0-DAG: str r1 241; CHECK-O0: malloc 242; CHECK-O0: mov [[ID:r[0-9]+]], #1 243; CHECK-O0: strb [[ID]], [r0, #8] 244; reload from stack: sret and val1 245; CHECK-O0: ldr 246; CHECK-O0: ldr 247; CHECK-O0: str r{{.*}}, [{{.*}}, #4] 248; CHECK-O0: mov r8 249entry: 250 %call = call i8* @malloc(i64 16) 251 %call.0 = bitcast i8* %call to %swift_error* 252 store %swift_error* %call.0, %swift_error** %error_ptr_ref 253 %tmp = getelementptr inbounds i8, i8* %call, i64 8 254 store i8 1, i8* %tmp 255 %v2 = getelementptr inbounds %struct.S, %struct.S* %agg.result, i32 0, i32 1 256 store i32 %val1, i32* %v2 257 ret void 258} 259 260; "caller3" calls "foo_sret" that takes a swifterror parameter. 261define float @caller3(i8* %error_ref) { 262; CHECK-APPLE-LABEL: caller3: 263; CHECK-APPLE: mov [[ID:r[0-9]+]], r0 264; CHECK-APPLE: mov r8, #0 265; CHECK-APPLE: bl {{.*}}foo_sret 266; CHECK-APPLE: mov r0, r8 267; CHECK-APPLE: cmp r8, #0 268; Access part of the error object and save it to error_ref 269; CHECK-APPLE: ldrbeq [[CODE:r[0-9]+]], [r0, #8] 270; CHECK-APPLE: strbeq [[CODE]], [{{.*}}[[ID]]] 271; CHECK-APPLE: bl {{.*}}free 272 273; CHECK-O0-LABEL: caller3: 274; CHECK-O0-DAG: mov r8, #0 275; CHECK-O0-DAG: mov r0 276; CHECK-O0-DAG: mov r1 277; CHECK-O0: bl {{.*}}foo_sret 278; CHECK-O0: mov [[ID2:r[0-9]+]], r8 279; CHECK-O0: cmp r8 280; CHECK-O0: str [[ID2]], [sp[[SLOT:.*]]] 281; CHECK-O0: bne 282; Access part of the error object and save it to error_ref 283; CHECK-O0: ldrb [[CODE:r[0-9]+]] 284; CHECK-O0: ldr [[ID:r[0-9]+]] 285; CHECK-O0: strb [[CODE]], [{{.*}}[[ID]]] 286; CHECK-O0: ldr r0, [sp[[SLOT]] 287; CHECK-O0: bl {{.*}}free 288entry: 289 %s = alloca %struct.S, align 8 290 %error_ptr_ref = alloca swifterror %swift_error* 291 store %swift_error* null, %swift_error** %error_ptr_ref 292 call void @foo_sret(%struct.S* sret %s, i32 1, %swift_error** swifterror %error_ptr_ref) 293 %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref 294 %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null 295 %tmp = bitcast %swift_error* %error_from_foo to i8* 296 br i1 %had_error_from_foo, label %handler, label %cont 297cont: 298 %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1 299 %t = load i8, i8* %v1 300 store i8 %t, i8* %error_ref 301 br label %handler 302handler: 303 call void @free(i8* %tmp) 304 ret float 1.0 305} 306 307; "foo_vararg" is a function that takes a swifterror parameter, it also has 308; variable number of arguments. 309declare void @llvm.va_start(i8*) nounwind 310define float @foo_vararg(%swift_error** swifterror %error_ptr_ref, ...) { 311; CHECK-APPLE-LABEL: foo_vararg: 312; CHECK-APPLE: mov r0, #16 313; CHECK-APPLE: malloc 314; CHECK-APPLE: mov r8, r0 315; CHECK-APPLE: mov [[ID:r[0-9]+]], #1 316; CHECK-APPLE-DAG: strb [[ID]], [r8, #8] 317 318entry: 319 %call = call i8* @malloc(i64 16) 320 %call.0 = bitcast i8* %call to %swift_error* 321 store %swift_error* %call.0, %swift_error** %error_ptr_ref 322 %tmp = getelementptr inbounds i8, i8* %call, i64 8 323 store i8 1, i8* %tmp 324 325 %args = alloca i8*, align 8 326 %a10 = alloca i32, align 4 327 %a11 = alloca i32, align 4 328 %a12 = alloca i32, align 4 329 %v10 = bitcast i8** %args to i8* 330 call void @llvm.va_start(i8* %v10) 331 %v11 = va_arg i8** %args, i32 332 store i32 %v11, i32* %a10, align 4 333 %v12 = va_arg i8** %args, i32 334 store i32 %v12, i32* %a11, align 4 335 %v13 = va_arg i8** %args, i32 336 store i32 %v13, i32* %a12, align 4 337 338 ret float 1.0 339} 340 341; "caller4" calls "foo_vararg" that takes a swifterror parameter. 342define float @caller4(i8* %error_ref) { 343; CHECK-APPLE-LABEL: caller4: 344; CHECK-APPLE: mov [[ID:r[0-9]+]], r0 345; CHECK-APPLE: mov r8, #0 346; CHECK-APPLE: bl {{.*}}foo_vararg 347; CHECK-APPLE: mov r0, r8 348; CHECK-APPLE: cmp r8, #0 349; Access part of the error object and save it to error_ref 350; CHECK-APPLE: ldrbeq [[CODE:r[0-9]+]], [r0, #8] 351; CHECK-APPLE: strbeq [[CODE]], [{{.*}}[[ID]]] 352; CHECK-APPLE: bl {{.*}}free 353entry: 354 %error_ptr_ref = alloca swifterror %swift_error* 355 store %swift_error* null, %swift_error** %error_ptr_ref 356 357 %a10 = alloca i32, align 4 358 %a11 = alloca i32, align 4 359 %a12 = alloca i32, align 4 360 store i32 10, i32* %a10, align 4 361 store i32 11, i32* %a11, align 4 362 store i32 12, i32* %a12, align 4 363 %v10 = load i32, i32* %a10, align 4 364 %v11 = load i32, i32* %a11, align 4 365 %v12 = load i32, i32* %a12, align 4 366 367 %call = call float (%swift_error**, ...) @foo_vararg(%swift_error** swifterror %error_ptr_ref, i32 %v10, i32 %v11, i32 %v12) 368 %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref 369 %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null 370 %tmp = bitcast %swift_error* %error_from_foo to i8* 371 br i1 %had_error_from_foo, label %handler, label %cont 372 373cont: 374 %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1 375 %t = load i8, i8* %v1 376 store i8 %t, i8* %error_ref 377 br label %handler 378handler: 379 call void @free(i8* %tmp) 380 ret float 1.0 381} 382 383; Check that we don't blow up on tail calling swifterror argument functions. 384define float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref) { 385entry: 386 %0 = tail call float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref) 387 ret float %0 388} 389define swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref) { 390entry: 391 %0 = tail call swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref) 392 ret float %0 393} 394 395; CHECK-APPLE-LABEL: swifterror_clobber 396; CHECK-APPLE: mov [[REG:r[0-9]+]], r8 397; CHECK-APPLE: nop 398; CHECK-APPLE: mov r8, [[REG]] 399define swiftcc void @swifterror_clobber(%swift_error** nocapture swifterror %err) { 400 call void asm sideeffect "nop", "~{r8}"() 401 ret void 402} 403 404; CHECK-APPLE-LABEL: swifterror_reg_clobber 405; CHECK-APPLE: push {{.*}}r8 406; CHECK-APPLE: nop 407; CHECK-APPLE: pop {{.*}}r8 408define swiftcc void @swifterror_reg_clobber(%swift_error** nocapture %err) { 409 call void asm sideeffect "nop", "~{r8}"() 410 ret void 411} 412 413; CHECK-ARMV7-LABEL: _params_in_reg 414; Store callee saved registers excluding swifterror. 415; CHECK-ARMV7: push {r4, r5, r6, r7, r10, r11, lr} 416; Store swiftself (r10) and swifterror (r8). 417; CHECK-ARMV7-DAG: str r8, [s[[STK1:.*]]] 418; CHECK-ARMV7-DAG: str r10, [s[[STK2:.*]]] 419; Store arguments. 420; CHECK-ARMV7-DAG: mov r6, r3 421; CHECK-ARMV7-DAG: mov r4, r2 422; CHECK-ARMV7-DAG: mov r11, r1 423; CHECK-ARMV7-DAG: mov r5, r0 424; Setup call. 425; CHECK-ARMV7: mov r0, #1 426; CHECK-ARMV7: mov r1, #2 427; CHECK-ARMV7: mov r2, #3 428; CHECK-ARMV7: mov r3, #4 429; CHECK-ARMV7: mov r10, #0 430; CHECK-ARMV7: mov r8, #0 431; CHECK-ARMV7: bl _params_in_reg2 432; Restore original arguments. 433; CHECK-ARMV7-DAG: ldr r10, [s[[STK2]]] 434; CHECK-ARMV7-DAG: ldr r8, [s[[STK1]]] 435; CHECK-ARMV7-DAG: mov r0, r5 436; CHECK-ARMV7-DAG: mov r1, r11 437; CHECK-ARMV7-DAG: mov r2, r4 438; CHECK-ARMV7-DAG: mov r3, r6 439; CHECK-ARMV7: bl _params_in_reg2 440; CHECK-ARMV7: pop {r4, r5, r6, r7, r10, r11, pc} 441define swiftcc void @params_in_reg(i32, i32, i32, i32, i8* swiftself, %swift_error** nocapture swifterror %err) { 442 %error_ptr_ref = alloca swifterror %swift_error*, align 8 443 store %swift_error* null, %swift_error** %error_ptr_ref 444 call swiftcc void @params_in_reg2(i32 1, i32 2, i32 3, i32 4, i8* swiftself null, %swift_error** nocapture swifterror %error_ptr_ref) 445 call swiftcc void @params_in_reg2(i32 %0, i32 %1, i32 %2, i32 %3, i8* swiftself %4, %swift_error** nocapture swifterror %err) 446 ret void 447} 448declare swiftcc void @params_in_reg2(i32, i32, i32, i32, i8* swiftself, %swift_error** nocapture swifterror %err) 449 450; CHECK-ARMV7-LABEL: params_and_return_in_reg 451; CHECK-ARMV7: push {r4, r5, r6, r7, r10, r11, lr} 452; Store swifterror and swiftself 453; CHECK-ARMV7: mov r6, r8 454; CHECK-ARMV7: str r10, [s[[STK1:.*]]] 455; Store arguments. 456; CHECK-ARMV7: str r3, [s[[STK2:.*]]] 457; CHECK-ARMV7: mov r4, r2 458; CHECK-ARMV7: mov r11, r1 459; CHECK-ARMV7: mov r5, r0 460; Setup call. 461; CHECK-ARMV7: mov r0, #1 462; CHECK-ARMV7: mov r1, #2 463; CHECK-ARMV7: mov r2, #3 464; CHECK-ARMV7: mov r3, #4 465; CHECK-ARMV7: mov r10, #0 466; CHECK-ARMV7: mov r8, #0 467; CHECK-ARMV7: bl _params_in_reg2 468; Restore original arguments. 469; CHECK-ARMV7-DAG: ldr r3, [s[[STK2]]] 470; CHECK-ARMV7-DAG: ldr r10, [s[[STK1]]] 471; Store %error_ptr_ref; 472; CHECK-ARMV7-DAG: str r8, [s[[STK3:.*]]] 473; Restore original arguments. 474; CHECK-ARMV7-DAG: mov r0, r5 475; CHECK-ARMV7-DAG: mov r1, r11 476; CHECK-ARMV7-DAG: mov r2, r4 477; CHECK-ARMV7-DAG: mov r8, r6 478; CHECK-ARMV7: bl _params_and_return_in_reg2 479; Store swifterror return %err; 480; CHECK-ARMV7-DAG: str r8, [s[[STK1]]] 481; Load swifterror value %error_ptr_ref. 482; CHECK-ARMV7-DAG: ldr r8, [s[[STK3]]] 483; Save return values. 484; CHECK-ARMV7-DAG: mov r4, r0 485; CHECK-ARMV7-DAG: mov r5, r1 486; CHECK-ARMV7-DAG: mov r6, r2 487; CHECK-ARMV7-DAG: mov r11, r3 488; Setup call. 489; CHECK-ARMV7: mov r0, #1 490; CHECK-ARMV7: mov r1, #2 491; CHECK-ARMV7: mov r2, #3 492; CHECK-ARMV7: mov r3, #4 493; CHECK-ARMV7: mov r10, #0 494; CHECK-ARMV7: bl _params_in_reg2 495; Load swifterror %err; 496; CHECK-ARMV7-DAG: ldr r8, [s[[STK1]]] 497; Restore return values for returning. 498; CHECK-ARMV7-DAG: mov r0, r4 499; CHECK-ARMV7-DAG: mov r1, r5 500; CHECK-ARMV7-DAG: mov r2, r6 501; CHECK-ARMV7-DAG: mov r3, r11 502; CHECK-ARMV7: pop {r4, r5, r6, r7, r10, r11, pc} 503 504; CHECK-ANDROID-LABEL: params_and_return_in_reg 505; CHECK-ANDROID: push {r4, r5, r6, r7, r9, r10, r11, lr} 506; CHECK-ANDROID: sub sp, sp, #16 507; CHECK-ANDROID: str r8, [sp, #4] @ 4-byte Spill 508; CHECK-ANDROID: mov r11, r10 509; CHECK-ANDROID: mov r6, r3 510; CHECK-ANDROID: mov r7, r2 511; CHECK-ANDROID: mov r4, r1 512; CHECK-ANDROID: mov r5, r0 513; CHECK-ANDROID: mov r0, #1 514; CHECK-ANDROID: mov r1, #2 515; CHECK-ANDROID: mov r2, #3 516; CHECK-ANDROID: mov r3, #4 517; CHECK-ANDROID: mov r10, #0 518; CHECK-ANDROID: mov r8, #0 519; CHECK-ANDROID: bl params_in_reg2 520; CHECK-ANDROID: mov r9, r8 521; CHECK-ANDROID: ldr r8, [sp, #4] @ 4-byte Reload 522; CHECK-ANDROID: mov r0, r5 523; CHECK-ANDROID: mov r1, r4 524; CHECK-ANDROID: mov r2, r7 525; CHECK-ANDROID: mov r3, r6 526; CHECK-ANDROID: mov r10, r11 527; CHECK-ANDROID: bl params_and_return_in_reg2 528; CHECK-ANDROID: mov r4, r0 529; CHECK-ANDROID: mov r5, r1 530; CHECK-ANDROID: mov r6, r2 531; CHECK-ANDROID: mov r7, r3 532; CHECK-ANDROID: mov r11, r8 533; CHECK-ANDROID: mov r0, #1 534; CHECK-ANDROID: mov r1, #2 535; CHECK-ANDROID: mov r2, #3 536; CHECK-ANDROID: mov r3, #4 537; CHECK-ANDROID: mov r10, #0 538; CHECK-ANDROID: mov r8, r9 539; CHECK-ANDROID: bl params_in_reg2 540; CHECK-ANDROID: mov r0, r4 541; CHECK-ANDROID: mov r1, r5 542; CHECK-ANDROID: mov r2, r6 543; CHECK-ANDROID: mov r3, r7 544; CHECK-ANDROID: mov r8, r11 545; CHECK-ANDROID: add sp, sp, #16 546; CHECK-ANDROID: pop {r4, r5, r6, r7, r9, r10, r11, pc} 547 548define swiftcc { i32, i32, i32, i32} @params_and_return_in_reg(i32, i32, i32, i32, i8* swiftself, %swift_error** nocapture swifterror %err) { 549 %error_ptr_ref = alloca swifterror %swift_error*, align 8 550 store %swift_error* null, %swift_error** %error_ptr_ref 551 call swiftcc void @params_in_reg2(i32 1, i32 2, i32 3, i32 4, i8* swiftself null, %swift_error** nocapture swifterror %error_ptr_ref) 552 %val = call swiftcc { i32, i32, i32, i32 } @params_and_return_in_reg2(i32 %0, i32 %1, i32 %2, i32 %3, i8* swiftself %4, %swift_error** nocapture swifterror %err) 553 call swiftcc void @params_in_reg2(i32 1, i32 2, i32 3, i32 4, i8* swiftself null, %swift_error** nocapture swifterror %error_ptr_ref) 554 ret { i32, i32, i32, i32 }%val 555} 556 557declare swiftcc { i32, i32, i32, i32 } @params_and_return_in_reg2(i32, i32, i32, i32, i8* swiftself, %swift_error** nocapture swifterror %err) 558 559 560declare void @acallee(i8*) 561 562; Make sure we don't tail call if the caller returns a swifterror value. We 563; would have to move into the swifterror register before the tail call. 564; CHECK-APPLE: tailcall_from_swifterror: 565; CHECK-APPLE-NOT: b _acallee 566; CHECK-APPLE: bl _acallee 567; CHECK-ANDROID: tailcall_from_swifterror: 568; CHECK-ANDROID-NOT: b acallee 569; CHECK-ANDROID: bl acallee 570 571define swiftcc void @tailcall_from_swifterror(%swift_error** swifterror %error_ptr_ref) { 572entry: 573 tail call void @acallee(i8* null) 574 ret void 575} 576 577 578declare swiftcc void @foo2(%swift_error** swifterror) 579 580; Make sure we properly assign registers during fast-isel. 581; CHECK-O0-LABEL: testAssign 582; CHECK-O0: mov r8, #0 583; CHECK-O0: bl _foo2 584; CHECK-O0: str r8, [s[[STK:p.*]]] 585; CHECK-O0: ldr r0, [s[[STK]]] 586; CHECK-O0: pop 587 588; CHECK-APPLE-LABEL: testAssign 589; CHECK-APPLE: mov r8, #0 590; CHECK-APPLE: bl _foo2 591; CHECK-APPLE: mov r0, r8 592 593; CHECK-ANDROID-LABEL: testAssign 594; CHECK-ANDROID: mov r8, #0 595; CHECK-ANDROID: bl foo2 596; CHECK-ANDROID: mov r0, r8 597 598define swiftcc %swift_error* @testAssign(i8* %error_ref) { 599entry: 600 %error_ptr = alloca swifterror %swift_error* 601 store %swift_error* null, %swift_error** %error_ptr 602 call swiftcc void @foo2(%swift_error** swifterror %error_ptr) 603 br label %a 604 605a: 606 %error = load %swift_error*, %swift_error** %error_ptr 607 ret %swift_error* %error 608} 609