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