1; RUN: llc -mtriple=mips-linux -relocation-model=static < %s \ 2; RUN: | FileCheck --check-prefixes=ALL,O32 %s 3; RUN: llc -mtriple=mipsel-linux -relocation-model=static < %s \ 4; RUN: | FileCheck --check-prefixes=ALL,O32 %s 5 6; RUN-TODO: llc -march=mips64 -relocation-model=static -target-abi o32 < %s \ 7; RUN-TODO: | FileCheck --check-prefixes=ALL,O32 %s 8; RUN-TODO: llc -march=mips64el -relocation-model=static -target-abi o32 < %s \ 9; RUN-TODO: | FileCheck --check-prefixes=ALL,O32 %s 10 11; RUN: llc -mtriple=mips64-linux -relocation-model=static -target-abi n32 < %s \ 12; RUN: | FileCheck --check-prefixes=ALL,NEW,N32,NEW-BE %s 13; RUN: llc -mtriple=mips64el-linux -relocation-model=static -target-abi n32 < %s \ 14; RUN: | FileCheck --check-prefixes=ALL,NEW,N32,NEW-LE %s 15 16; RUN: llc -march=mips64 -relocation-model=static -target-abi n64 < %s \ 17; RUN: | FileCheck --check-prefixes=ALL,NEW,N64,NEW-BE %s 18; RUN: llc -march=mips64el -relocation-model=static -target-abi n64 < %s \ 19; RUN: | FileCheck --check-prefixes=ALL,NEW,N64,NEW-LE %s 20 21@hwords = global [3 x i16] zeroinitializer, align 1 22@words = global [3 x i32] zeroinitializer, align 1 23@dwords = global [3 x i64] zeroinitializer, align 1 24 25define void @fn_i16_dotdotdot_i16(i16 %a, ...) { 26entry: 27; ALL-LABEL: fn_i16_dotdotdot_i16: 28 29; Set up the stack with an 8-byte local area. N32/N64 must also make room for 30; the argument save area (56 bytes). 31; O32: addiu [[SP:\$sp]], $sp, -8 32; N32: addiu [[SP:\$sp]], $sp, -64 33; N64: daddiu [[SP:\$sp]], $sp, -64 34 35; Save variable argument portion on the stack 36; O32-DAG: sw $7, 20([[SP]]) 37; O32-DAG: sw $6, 16([[SP]]) 38; O32-DAG: sw $5, 12([[SP]]) 39 40; NEW-DAG: sd $11, 56([[SP]]) 41; NEW-DAG: sd $10, 48([[SP]]) 42; NEW-DAG: sd $9, 40([[SP]]) 43; NEW-DAG: sd $8, 32([[SP]]) 44; NEW-DAG: sd $7, 24([[SP]]) 45; NEW-DAG: sd $6, 16([[SP]]) 46; NEW-DAG: sd $5, 8([[SP]]) 47 48; Initialize variable argument pointer. 49; For O32, the offset is 12 due to the 4 bytes used to store local variables, 50; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first 51; fixed argument. 52; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 53; space. 54; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 55; O32-DAG: sw [[VA]], 0([[SP]]) 56 57; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 58; N32-DAG: sw [[VA]], 0([[SP]]) 59 60; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 61; N64-DAG: sd [[VA]], 0([[SP]]) 62 63; ALL: teqi $zero, 1 64 65; Increment [[VA]] 66; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 67; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 68; O32-DAG: sw [[VA2]], 0([[SP]]) 69 70; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 71; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 72; N32-DAG: sw [[VA2]], 0([[SP]]) 73 74; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 75; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 76; N64-DAG: sd [[VA2]], 0([[SP]]) 77 78; Load the first argument from the variable portion. 79; This has used the stack pointer directly rather than the [[VA]] we just set 80; up. 81; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 82; order. 83; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 84 85; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 86; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) 87 88; Copy the arg to the global 89; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 90 91; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 92 93; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 94 95; ALL-DAG: sh [[ARG1]], 2([[GV]]) 96 97; ALL: teqi $zero, 2 98 99; Increment [[VA]] again. 100; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 101; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 102; O32-DAG: sw [[VA2]], 0([[SP]]) 103 104; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 105; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 106; N32-DAG: sw [[VA3]], 0([[SP]]) 107 108; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 109; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 110; N64-DAG: sd [[VA3]], 0([[SP]]) 111 112; Load the second argument from the variable portion. 113; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 114 115; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) 116; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) 117 118; Copy the arg to the global 119; ALL-DAG: sh [[ARG2]], 4([[GV]]) 120 121 %ap = alloca i8*, align 8 122 %ap2 = bitcast i8** %ap to i8* 123 call void @llvm.va_start(i8* %ap2) 124 125 call void asm sideeffect "teqi $$zero, 1", ""() 126 %arg1 = va_arg i8** %ap, i16 127 %e1 = getelementptr [3 x i16], [3 x i16]* @hwords, i32 0, i32 1 128 store volatile i16 %arg1, i16* %e1, align 2 129 130 call void asm sideeffect "teqi $$zero, 2", ""() 131 %arg2 = va_arg i8** %ap, i16 132 %e2 = getelementptr [3 x i16], [3 x i16]* @hwords, i32 0, i32 2 133 store volatile i16 %arg2, i16* %e2, align 2 134 135 call void @llvm.va_end(i8* %ap2) 136 137 ret void 138} 139 140define void @fn_i16_dotdotdot_i32(i16 %a, ...) { 141entry: 142; ALL-LABEL: fn_i16_dotdotdot_i32: 143 144; Set up the stack with an 8-byte local area. N32/N64 must also make room for 145; the argument save area (56 bytes). 146; O32: addiu [[SP:\$sp]], $sp, -8 147; N32: addiu [[SP:\$sp]], $sp, -64 148; N64: daddiu [[SP:\$sp]], $sp, -64 149 150; Save variable argument portion on the stack 151; O32-DAG: sw $7, 20([[SP]]) 152; O32-DAG: sw $6, 16([[SP]]) 153; O32-DAG: sw $5, 12([[SP]]) 154 155; NEW-DAG: sd $11, 56([[SP]]) 156; NEW-DAG: sd $10, 48([[SP]]) 157; NEW-DAG: sd $9, 40([[SP]]) 158; NEW-DAG: sd $8, 32([[SP]]) 159; NEW-DAG: sd $7, 24([[SP]]) 160; NEW-DAG: sd $6, 16([[SP]]) 161; NEW-DAG: sd $5, 8([[SP]]) 162 163; Initialize variable argument pointer. 164; For O32, the offset is 12 due to the 4 bytes used to store local variables, 165; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first 166; fixed argument. 167; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 168; space. 169; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 170; O32-DAG: sw [[VA]], 0([[SP]]) 171 172; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 173; N32-DAG: sw [[VA]], 0([[SP]]) 174 175; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 176; N64-DAG: sd [[VA]], 0([[SP]]) 177 178; ALL: teqi $zero, 1 179 180; Increment [[VA]] 181; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 182; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 183; O32-DAG: sw [[VA2]], 0([[SP]]) 184 185; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 186; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 187; N32-DAG: sw [[VA2]], 0([[SP]]) 188 189; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 190; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 191; N64-DAG: sd [[VA2]], 0([[SP]]) 192 193; Load the first argument from the variable portion. 194; This has used the stack pointer directly rather than the [[VA]] we just set 195; up. 196; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 197; order. 198; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 199 200; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 201; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) 202 203; Copy the arg to the global 204; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 205 206; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 207 208; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 209 210; ALL-DAG: sw [[ARG1]], 4([[GV]]) 211 212; ALL: teqi $zero, 2 213 214; Increment [[VA]] again. 215; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 216; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 217; O32-DAG: sw [[VA2]], 0([[SP]]) 218 219; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 220; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 221; N32-DAG: sw [[VA3]], 0([[SP]]) 222 223; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 224; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 225; N64-DAG: sd [[VA3]], 0([[SP]]) 226 227; Load the second argument from the variable portion. 228; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 229 230; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) 231; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) 232 233; Copy the arg to the global 234; ALL-DAG: sw [[ARG2]], 8([[GV]]) 235 236 %ap = alloca i8*, align 8 237 %ap2 = bitcast i8** %ap to i8* 238 call void @llvm.va_start(i8* %ap2) 239 240 call void asm sideeffect "teqi $$zero, 1", ""() 241 %arg1 = va_arg i8** %ap, i32 242 %e1 = getelementptr [3 x i32], [3 x i32]* @words, i32 0, i32 1 243 store volatile i32 %arg1, i32* %e1, align 4 244 245 call void asm sideeffect "teqi $$zero, 2", ""() 246 %arg2 = va_arg i8** %ap, i32 247 %e2 = getelementptr [3 x i32], [3 x i32]* @words, i32 0, i32 2 248 store volatile i32 %arg2, i32* %e2, align 4 249 250 call void @llvm.va_end(i8* %ap2) 251 252 ret void 253} 254 255define void @fn_i16_dotdotdot_i64(i16 %a, ...) { 256entry: 257; ALL-LABEL: fn_i16_dotdotdot_i64: 258 259; Set up the stack with an 8-byte local area. N32/N64 must also make room for 260; the argument save area (56 bytes). 261; O32: addiu [[SP:\$sp]], $sp, -8 262; N32: addiu [[SP:\$sp]], $sp, -64 263; N64: daddiu [[SP:\$sp]], $sp, -64 264 265; Save variable argument portion on the stack 266; O32-DAG: sw $7, 20([[SP]]) 267; O32-DAG: sw $6, 16([[SP]]) 268; O32-DAG: sw $5, 12([[SP]]) 269 270; NEW-DAG: sd $11, 56([[SP]]) 271; NEW-DAG: sd $10, 48([[SP]]) 272; NEW-DAG: sd $9, 40([[SP]]) 273; NEW-DAG: sd $8, 32([[SP]]) 274; NEW-DAG: sd $7, 24([[SP]]) 275; NEW-DAG: sd $6, 16([[SP]]) 276; NEW-DAG: sd $5, 8([[SP]]) 277 278; Initialize variable argument pointer. 279; For O32, the offset is 12 due to the 4 bytes used to store local variables, 280; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first 281; fixed argument. 282; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 283; space. 284; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 285; O32-DAG: sw [[VA]], 0([[SP]]) 286 287; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 288; N32-DAG: sw [[VA]], 0([[SP]]) 289 290; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 291; N64-DAG: sd [[VA]], 0([[SP]]) 292 293; ALL: teqi $zero, 1 294 295; Increment [[VA]] (and realign pointer for O32) 296; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) 297; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 298; O32-DAG: addiu [[VA_TMP1:\$[0-9]+]], $zero, -8 299; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] 300; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 301; O32-DAG: sw [[VA2]], 0([[SP]]) 302 303; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 304; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 305; N32-DAG: sw [[VA2]], 0([[SP]]) 306 307; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 308; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 309; N64-DAG: sd [[VA2]], 0([[SP]]) 310 311; Load the first argument from the variable portion and copy it to the global. 312; This has used the stack pointer directly rather than the [[VA]] we just set 313; up. 314; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 315; order. 316; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 317; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA_TMP2]]) 318; O32-DAG: sw [[ARG1]], 8([[GV]]) 319; O32-DAG: addiu [[VA3:\$[0-9]+]], [[VA_TMP2]], 8 320; O32-DAG: sw [[VA3]], 0([[SP]]) 321; O32-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA_TMP2]]) 322; O32-DAG: sw [[ARG1]], 12([[GV]]) 323 324; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 325; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 326; NEW-DAG: ld [[ARG1:\$[0-9]+]], 0([[VA]]) 327; NEW-DAG: sd [[ARG1]], 8([[GV]]) 328 329; ALL: teqi $zero, 2 330 331; Increment [[VA]] again. 332; FIXME: We're still aligned from the last one but CodeGen doesn't spot that. 333; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) 334; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 335; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] 336; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 337; O32-DAG: sw [[VA2]], 0([[SP]]) 338 339; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 340; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 341; N32-DAG: sw [[VA3]], 0([[SP]]) 342 343; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 344; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 345; N64-DAG: sd [[VA3]], 0([[SP]]) 346 347; Load the second argument from the variable portion and copy it to the global. 348; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 349; O32-DAG: sw [[ARG2]], 16([[GV]]) 350; O32-DAG: addiu [[VA3:\$[0-9]+]], [[VA_TMP2]], 8 351; O32-DAG: sw [[VA3]], 0([[SP]]) 352; O32-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA_TMP2]]) 353; O32-DAG: sw [[ARG2]], 20([[GV]]) 354 355; NEW-DAG: ld [[ARG2:\$[0-9]+]], 0([[VA2]]) 356; NEW-DAG: sd [[ARG2]], 16([[GV]]) 357 358 %ap = alloca i8*, align 8 359 %ap2 = bitcast i8** %ap to i8* 360 call void @llvm.va_start(i8* %ap2) 361 362 call void asm sideeffect "teqi $$zero, 1", ""() 363 %arg1 = va_arg i8** %ap, i64 364 %e1 = getelementptr [3 x i64], [3 x i64]* @dwords, i32 0, i32 1 365 store volatile i64 %arg1, i64* %e1, align 8 366 367 call void asm sideeffect "teqi $$zero, 2", ""() 368 %arg2 = va_arg i8** %ap, i64 369 %e2 = getelementptr [3 x i64], [3 x i64]* @dwords, i32 0, i32 2 370 store volatile i64 %arg2, i64* %e2, align 8 371 372 call void @llvm.va_end(i8* %ap2) 373 374 ret void 375} 376 377define void @fn_i32_dotdotdot_i16(i32 %a, ...) { 378entry: 379; ALL-LABEL: fn_i32_dotdotdot_i16: 380 381; Set up the stack with an 8-byte local area. N32/N64 must also make room for 382; the argument save area (56 bytes). 383; O32: addiu [[SP:\$sp]], $sp, -8 384; N32: addiu [[SP:\$sp]], $sp, -64 385; N64: daddiu [[SP:\$sp]], $sp, -64 386 387; Save variable argument portion on the stack 388; O32-DAG: sw $7, 20([[SP]]) 389; O32-DAG: sw $6, 16([[SP]]) 390; O32-DAG: sw $5, 12([[SP]]) 391 392; NEW-DAG: sd $11, 56([[SP]]) 393; NEW-DAG: sd $10, 48([[SP]]) 394; NEW-DAG: sd $9, 40([[SP]]) 395; NEW-DAG: sd $8, 32([[SP]]) 396; NEW-DAG: sd $7, 24([[SP]]) 397; NEW-DAG: sd $6, 16([[SP]]) 398; NEW-DAG: sd $5, 8([[SP]]) 399 400; Initialize variable argument pointer. 401; For O32, the offset is 12 due to the 4 bytes used to store local variables, 402; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first 403; fixed argument. 404; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 405; space. 406; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 407; O32-DAG: sw [[VA]], 0([[SP]]) 408 409; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 410; N32-DAG: sw [[VA]], 0([[SP]]) 411 412; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 413; N64-DAG: sd [[VA]], 0([[SP]]) 414 415; ALL: teqi $zero, 1 416 417; Increment [[VA]] 418; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 419; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 420; O32-DAG: sw [[VA2]], 0([[SP]]) 421 422; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 423; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 424; N32-DAG: sw [[VA2]], 0([[SP]]) 425 426; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 427; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 428; N64-DAG: sd [[VA2]], 0([[SP]]) 429 430; Load the first argument from the variable portion. 431; This has used the stack pointer directly rather than the [[VA]] we just set 432; up. 433; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 434; order. 435; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 436 437; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 438; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) 439 440; Copy the arg to the global 441; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 442 443; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 444 445; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 446 447; ALL-DAG: sh [[ARG1]], 2([[GV]]) 448 449; ALL: teqi $zero, 2 450 451; Increment [[VA]] again. 452; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 453; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 454; O32-DAG: sw [[VA2]], 0([[SP]]) 455 456; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 457; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 458; N32-DAG: sw [[VA3]], 0([[SP]]) 459 460; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 461; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 462; N64-DAG: sd [[VA3]], 0([[SP]]) 463 464; Load the second argument from the variable portion. 465; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 466 467; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) 468; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) 469 470; Copy the arg to the global 471; ALL-DAG: sh [[ARG2]], 4([[GV]]) 472 473 %ap = alloca i8*, align 8 474 %ap2 = bitcast i8** %ap to i8* 475 call void @llvm.va_start(i8* %ap2) 476 477 call void asm sideeffect "teqi $$zero, 1", ""() 478 %arg1 = va_arg i8** %ap, i16 479 %e1 = getelementptr [3 x i16], [3 x i16]* @hwords, i32 0, i32 1 480 store volatile i16 %arg1, i16* %e1, align 2 481 482 call void asm sideeffect "teqi $$zero, 2", ""() 483 %arg2 = va_arg i8** %ap, i16 484 %e2 = getelementptr [3 x i16], [3 x i16]* @hwords, i32 0, i32 2 485 store volatile i16 %arg2, i16* %e2, align 2 486 487 call void @llvm.va_end(i8* %ap2) 488 489 ret void 490} 491 492define void @fn_i32_dotdotdot_i32(i32 %a, ...) { 493entry: 494; ALL-LABEL: fn_i32_dotdotdot_i32: 495 496; Set up the stack with an 8-byte local area. N32/N64 must also make room for 497; the argument save area (56 bytes). 498; O32: addiu [[SP:\$sp]], $sp, -8 499; N32: addiu [[SP:\$sp]], $sp, -64 500; N64: daddiu [[SP:\$sp]], $sp, -64 501 502; Save variable argument portion on the stack 503; O32-DAG: sw $7, 20([[SP]]) 504; O32-DAG: sw $6, 16([[SP]]) 505; O32-DAG: sw $5, 12([[SP]]) 506 507; NEW-DAG: sd $11, 56([[SP]]) 508; NEW-DAG: sd $10, 48([[SP]]) 509; NEW-DAG: sd $9, 40([[SP]]) 510; NEW-DAG: sd $8, 32([[SP]]) 511; NEW-DAG: sd $7, 24([[SP]]) 512; NEW-DAG: sd $6, 16([[SP]]) 513; NEW-DAG: sd $5, 8([[SP]]) 514 515; Initialize variable argument pointer. 516; For O32, the offset is 12 due to the 4 bytes used to store local variables, 517; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first 518; fixed argument. 519; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 520; space. 521; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 522; O32-DAG: sw [[VA]], 0([[SP]]) 523 524; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 525; N32-DAG: sw [[VA]], 0([[SP]]) 526 527; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 528; N64-DAG: sd [[VA]], 0([[SP]]) 529 530; ALL: teqi $zero, 1 531 532; Increment [[VA]] 533; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 534; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 535; O32-DAG: sw [[VA2]], 0([[SP]]) 536 537; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 538; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 539; N32-DAG: sw [[VA2]], 0([[SP]]) 540 541; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 542; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 543; N64-DAG: sd [[VA2]], 0([[SP]]) 544 545; Load the first argument from the variable portion. 546; This has used the stack pointer directly rather than the [[VA]] we just set 547; up. 548; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 549; order. 550; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 551 552; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 553; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) 554 555; Copy the arg to the global 556; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 557 558; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 559 560; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 561 562; ALL-DAG: sw [[ARG1]], 4([[GV]]) 563 564; ALL: teqi $zero, 2 565 566; Increment [[VA]] again. 567; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 568; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 569; O32-DAG: sw [[VA2]], 0([[SP]]) 570 571; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 572; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 573; N32-DAG: sw [[VA3]], 0([[SP]]) 574 575; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 576; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 577; N64-DAG: sd [[VA3]], 0([[SP]]) 578 579; Load the second argument from the variable portion. 580; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 581 582; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) 583; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) 584 585; Copy the arg to the global 586; ALL-DAG: sw [[ARG2]], 8([[GV]]) 587 588 %ap = alloca i8*, align 8 589 %ap2 = bitcast i8** %ap to i8* 590 call void @llvm.va_start(i8* %ap2) 591 592 call void asm sideeffect "teqi $$zero, 1", ""() 593 %arg1 = va_arg i8** %ap, i32 594 %e1 = getelementptr [3 x i32], [3 x i32]* @words, i32 0, i32 1 595 store volatile i32 %arg1, i32* %e1, align 4 596 597 call void asm sideeffect "teqi $$zero, 2", ""() 598 %arg2 = va_arg i8** %ap, i32 599 %e2 = getelementptr [3 x i32], [3 x i32]* @words, i32 0, i32 2 600 store volatile i32 %arg2, i32* %e2, align 4 601 602 call void @llvm.va_end(i8* %ap2) 603 604 ret void 605} 606 607define void @fn_i32_dotdotdot_i64(i32 %a, ...) { 608entry: 609; ALL-LABEL: fn_i32_dotdotdot_i64: 610 611; Set up the stack with an 8-byte local area. N32/N64 must also make room for 612; the argument save area (56 bytes). 613; O32: addiu [[SP:\$sp]], $sp, -8 614; N32: addiu [[SP:\$sp]], $sp, -64 615; N64: daddiu [[SP:\$sp]], $sp, -64 616 617; Save variable argument portion on the stack 618; O32-DAG: sw $7, 20([[SP]]) 619; O32-DAG: sw $6, 16([[SP]]) 620; O32-DAG: sw $5, 12([[SP]]) 621 622; NEW-DAG: sd $11, 56([[SP]]) 623; NEW-DAG: sd $10, 48([[SP]]) 624; NEW-DAG: sd $9, 40([[SP]]) 625; NEW-DAG: sd $8, 32([[SP]]) 626; NEW-DAG: sd $7, 24([[SP]]) 627; NEW-DAG: sd $6, 16([[SP]]) 628; NEW-DAG: sd $5, 8([[SP]]) 629 630; Initialize variable argument pointer. 631; For O32, the offset is 12 due to the 4 bytes used to store local variables, 632; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first 633; fixed argument. 634; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 635; space. 636; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 637; O32-DAG: sw [[VA]], 0([[SP]]) 638 639; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 640; N32-DAG: sw [[VA]], 0([[SP]]) 641 642; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 643; N64-DAG: sd [[VA]], 0([[SP]]) 644 645; ALL: teqi $zero, 1 646 647; Increment [[VA]] (and realign pointer for O32) 648; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) 649; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 650; O32-DAG: addiu [[VA_TMP1:\$[0-9]+]], $zero, -8 651; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] 652; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 653; O32-DAG: sw [[VA2]], 0([[SP]]) 654 655; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 656; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 657; N32-DAG: sw [[VA2]], 0([[SP]]) 658 659; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 660; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 661; N64-DAG: sd [[VA2]], 0([[SP]]) 662 663; Load the first argument from the variable portion and copy it to the global. 664; This has used the stack pointer directly rather than the [[VA]] we just set 665; up. 666; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 667; order. 668; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 669; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA_TMP2]]) 670; O32-DAG: sw [[ARG1]], 8([[GV]]) 671; O32-DAG: addiu [[VA3:\$[0-9]+]], [[VA_TMP2]], 8 672; O32-DAG: sw [[VA3]], 0([[SP]]) 673; O32-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA_TMP2]]) 674; O32-DAG: sw [[ARG1]], 12([[GV]]) 675 676; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 677; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 678; NEW-DAG: ld [[ARG1:\$[0-9]+]], 0([[VA]]) 679; NEW-DAG: sd [[ARG1]], 8([[GV]]) 680 681; ALL: teqi $zero, 2 682 683; Increment [[VA]] again. 684; FIXME: We're still aligned from the last one but CodeGen doesn't spot that. 685; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) 686; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 687; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] 688; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 689; O32-DAG: sw [[VA2]], 0([[SP]]) 690 691; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 692; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 693; N32-DAG: sw [[VA3]], 0([[SP]]) 694 695; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 696; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 697; N64-DAG: sd [[VA3]], 0([[SP]]) 698 699; Load the second argument from the variable portion and copy it to the global. 700; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 701; O32-DAG: sw [[ARG2]], 16([[GV]]) 702; O32-DAG: addiu [[VA3:\$[0-9]+]], [[VA_TMP2]], 8 703; O32-DAG: sw [[VA3]], 0([[SP]]) 704; O32-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA_TMP2]]) 705; O32-DAG: sw [[ARG2]], 20([[GV]]) 706 707; NEW-DAG: ld [[ARG2:\$[0-9]+]], 0([[VA2]]) 708; NEW-DAG: sd [[ARG2]], 16([[GV]]) 709 710 %ap = alloca i8*, align 8 711 %ap2 = bitcast i8** %ap to i8* 712 call void @llvm.va_start(i8* %ap2) 713 714 call void asm sideeffect "teqi $$zero, 1", ""() 715 %arg1 = va_arg i8** %ap, i64 716 %e1 = getelementptr [3 x i64], [3 x i64]* @dwords, i32 0, i32 1 717 store volatile i64 %arg1, i64* %e1, align 8 718 719 call void asm sideeffect "teqi $$zero, 2", ""() 720 %arg2 = va_arg i8** %ap, i64 721 %e2 = getelementptr [3 x i64], [3 x i64]* @dwords, i32 0, i32 2 722 store volatile i64 %arg2, i64* %e2, align 8 723 724 call void @llvm.va_end(i8* %ap2) 725 726 ret void 727} 728 729define void @fn_i64_dotdotdot_i16(i64 %a, ...) { 730entry: 731; ALL-LABEL: fn_i64_dotdotdot_i16: 732 733; Set up the stack with an 8-byte local area. N32/N64 must also make room for 734; the argument save area (56 bytes). 735; O32: addiu [[SP:\$sp]], $sp, -8 736; N32: addiu [[SP:\$sp]], $sp, -64 737; N64: daddiu [[SP:\$sp]], $sp, -64 738 739; Save variable argument portion on the stack 740; O32-DAG: sw $7, 20([[SP]]) 741; O32-DAG: sw $6, 16([[SP]]) 742 743; NEW-DAG: sd $11, 56([[SP]]) 744; NEW-DAG: sd $10, 48([[SP]]) 745; NEW-DAG: sd $9, 40([[SP]]) 746; NEW-DAG: sd $8, 32([[SP]]) 747; NEW-DAG: sd $7, 24([[SP]]) 748; NEW-DAG: sd $6, 16([[SP]]) 749; NEW-DAG: sd $5, 8([[SP]]) 750 751; Initialize variable argument pointer. 752; For O32, the offset is 16 due to the 4 bytes used to store local variables, 753; 4 bytes padding to maintain stack alignment, and the two 4 byte slots for the 754; first fixed argument. 755; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 756; space. 757; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 16 758; O32-DAG: sw [[VA]], 0([[SP]]) 759 760; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 761; N32-DAG: sw [[VA]], 0([[SP]]) 762 763; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 764; N64-DAG: sd [[VA]], 0([[SP]]) 765 766; ALL: teqi $zero, 1 767 768; Increment [[VA]] 769; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 770; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 771; O32-DAG: sw [[VA2]], 0([[SP]]) 772 773; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 774; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 775; N32-DAG: sw [[VA2]], 0([[SP]]) 776 777; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 778; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 779; N64-DAG: sd [[VA2]], 0([[SP]]) 780 781; Load the first argument from the variable portion. 782; This has used the stack pointer directly rather than the [[VA]] we just set 783; up. 784; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 785; order. 786; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 787 788; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 789; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) 790 791; Copy the arg to the global 792; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 793 794; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 795 796; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 797 798; ALL-DAG: sh [[ARG1]], 2([[GV]]) 799 800; ALL: teqi $zero, 2 801 802; Increment [[VA]] again. 803; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 804; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 805; O32-DAG: sw [[VA2]], 0([[SP]]) 806 807; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 808; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 809; N32-DAG: sw [[VA3]], 0([[SP]]) 810 811; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 812; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 813; N64-DAG: sd [[VA3]], 0([[SP]]) 814 815; Load the second argument from the variable portion. 816; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 817 818; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) 819; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) 820 821; Copy the arg to the global 822; ALL-DAG: sh [[ARG2]], 4([[GV]]) 823 824 %ap = alloca i8*, align 8 825 %ap2 = bitcast i8** %ap to i8* 826 call void @llvm.va_start(i8* %ap2) 827 828 call void asm sideeffect "teqi $$zero, 1", ""() 829 %arg1 = va_arg i8** %ap, i16 830 %e1 = getelementptr [3 x i16], [3 x i16]* @hwords, i32 0, i32 1 831 store volatile i16 %arg1, i16* %e1, align 2 832 833 call void asm sideeffect "teqi $$zero, 2", ""() 834 %arg2 = va_arg i8** %ap, i16 835 %e2 = getelementptr [3 x i16], [3 x i16]* @hwords, i32 0, i32 2 836 store volatile i16 %arg2, i16* %e2, align 2 837 838 call void @llvm.va_end(i8* %ap2) 839 840 ret void 841} 842 843define void @fn_i64_dotdotdot_i32(i64 %a, ...) { 844entry: 845; ALL-LABEL: fn_i64_dotdotdot_i32: 846 847; Set up the stack with an 8-byte local area. N32/N64 must also make room for 848; the argument save area (56 bytes). 849; O32: addiu [[SP:\$sp]], $sp, -8 850; N32: addiu [[SP:\$sp]], $sp, -64 851; N64: daddiu [[SP:\$sp]], $sp, -64 852 853; Save variable argument portion on the stack 854; O32-DAG: sw $7, 20([[SP]]) 855; O32-DAG: sw $6, 16([[SP]]) 856 857; NEW-DAG: sd $11, 56([[SP]]) 858; NEW-DAG: sd $10, 48([[SP]]) 859; NEW-DAG: sd $9, 40([[SP]]) 860; NEW-DAG: sd $8, 32([[SP]]) 861; NEW-DAG: sd $7, 24([[SP]]) 862; NEW-DAG: sd $6, 16([[SP]]) 863; NEW-DAG: sd $5, 8([[SP]]) 864 865; Initialize variable argument pointer. 866; For O32, the offset is 16 due to the 4 bytes used to store local variables, 867; 4 bytes padding to maintain stack alignment, and the two 4 byte slots for the 868; first fixed argument. 869; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 870; space. 871; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 16 872; O32-DAG: sw [[VA]], 0([[SP]]) 873 874; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 875; N32-DAG: sw [[VA]], 0([[SP]]) 876 877; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 878; N64-DAG: sd [[VA]], 0([[SP]]) 879 880; ALL: teqi $zero, 1 881 882; Increment [[VA]] 883; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 884; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 885; O32-DAG: sw [[VA2]], 0([[SP]]) 886 887; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 888; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 889; N32-DAG: sw [[VA2]], 0([[SP]]) 890 891; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 892; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 893; N64-DAG: sd [[VA2]], 0([[SP]]) 894 895; Load the first argument from the variable portion. 896; This has used the stack pointer directly rather than the [[VA]] we just set 897; up. 898; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 899; order. 900; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 901 902; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 903; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) 904 905; Copy the arg to the global 906; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 907 908; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 909 910; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 911 912; ALL-DAG: sw [[ARG1]], 4([[GV]]) 913 914; ALL: teqi $zero, 2 915 916; Increment [[VA]] again. 917; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 918; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 919; O32-DAG: sw [[VA2]], 0([[SP]]) 920 921; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 922; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 923; N32-DAG: sw [[VA3]], 0([[SP]]) 924 925; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 926; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 927; N64-DAG: sd [[VA3]], 0([[SP]]) 928 929; Load the second argument from the variable portion. 930; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 931 932; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) 933; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) 934 935; Copy the arg to the global 936; ALL-DAG: sw [[ARG2]], 8([[GV]]) 937 938 %ap = alloca i8*, align 8 939 %ap2 = bitcast i8** %ap to i8* 940 call void @llvm.va_start(i8* %ap2) 941 942 call void asm sideeffect "teqi $$zero, 1", ""() 943 %arg1 = va_arg i8** %ap, i32 944 %e1 = getelementptr [3 x i32], [3 x i32]* @words, i32 0, i32 1 945 store volatile i32 %arg1, i32* %e1, align 4 946 947 call void asm sideeffect "teqi $$zero, 2", ""() 948 %arg2 = va_arg i8** %ap, i32 949 %e2 = getelementptr [3 x i32], [3 x i32]* @words, i32 0, i32 2 950 store volatile i32 %arg2, i32* %e2, align 4 951 952 call void @llvm.va_end(i8* %ap2) 953 954 ret void 955} 956 957define void @fn_i64_dotdotdot_i64(i64 %a, ...) { 958entry: 959; ALL-LABEL: fn_i64_dotdotdot_i64: 960 961; Set up the stack with an 8-byte local area. N32/N64 must also make room for 962; the argument save area (56 bytes). 963; O32: addiu [[SP:\$sp]], $sp, -8 964; N32: addiu [[SP:\$sp]], $sp, -64 965; N64: daddiu [[SP:\$sp]], $sp, -64 966 967; Save variable argument portion on the stack 968; O32-DAG: sw $7, 20([[SP]]) 969; O32-DAG: sw $6, 16([[SP]]) 970 971; NEW-DAG: sd $11, 56([[SP]]) 972; NEW-DAG: sd $10, 48([[SP]]) 973; NEW-DAG: sd $9, 40([[SP]]) 974; NEW-DAG: sd $8, 32([[SP]]) 975; NEW-DAG: sd $7, 24([[SP]]) 976; NEW-DAG: sd $6, 16([[SP]]) 977; NEW-DAG: sd $5, 8([[SP]]) 978 979; Initialize variable argument pointer. 980; For O32, the offset is 16 due to the 4 bytes used to store local variables, 981; 4 bytes padding to maintain stack alignment, and the two 4 byte slots for the 982; first fixed argument. 983; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 984; space. 985; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 16 986; O32-DAG: sw [[VA]], 0([[SP]]) 987 988; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 989; N32-DAG: sw [[VA]], 0([[SP]]) 990 991; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 992; N64-DAG: sd [[VA]], 0([[SP]]) 993 994; ALL: teqi $zero, 1 995 996; Increment [[VA]] (and realign pointer for O32) 997; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) 998; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 999; O32-DAG: addiu [[VA_TMP1:\$[0-9]+]], $zero, -8 1000; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] 1001; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 1002; O32-DAG: sw [[VA2]], 0([[SP]]) 1003 1004; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 1005; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 1006; N32-DAG: sw [[VA2]], 0([[SP]]) 1007 1008; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 1009; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 1010; N64-DAG: sd [[VA2]], 0([[SP]]) 1011 1012; Load the first argument from the variable portion and copy it to the global. 1013; This has used the stack pointer directly rather than the [[VA]] we just set 1014; up. 1015; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 1016; order. 1017; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 1018; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 1019; O32-DAG: sw [[ARG1]], 8([[GV]]) 1020; O32-DAG: addiu [[VA3:\$[0-9]+]], [[VA_TMP2]], 8 1021; O32-DAG: sw [[VA3]], 0([[SP]]) 1022; O32-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA_TMP2]]) 1023; O32-DAG: sw [[ARG1]], 12([[GV]]) 1024 1025; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 1026; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 1027; NEW-DAG: ld [[ARG1:\$[0-9]+]], 0([[VA]]) 1028; NEW-DAG: sd [[ARG1]], 8([[GV]]) 1029 1030; ALL: teqi $zero, 2 1031 1032; Increment [[VA]] again. 1033; FIXME: We're still aligned from the last one but CodeGen doesn't spot that. 1034; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) 1035; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 1036; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] 1037; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 1038; O32-DAG: sw [[VA2]], 0([[SP]]) 1039 1040; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 1041; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 1042; N32-DAG: sw [[VA3]], 0([[SP]]) 1043 1044; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 1045; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 1046; N64-DAG: sd [[VA3]], 0([[SP]]) 1047 1048; Load the second argument from the variable portion and copy it to the global. 1049; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 1050; O32-DAG: addiu [[VA3:\$[0-9]+]], [[VA_TMP2]], 8 1051; O32-DAG: sw [[VA3]], 0([[SP]]) 1052; O32-DAG: lw [[ARG3:\$[0-9]+]], 4([[VA_TMP2]]) 1053; O32-DAG: sw [[ARG3]], 20([[GV]]) 1054; O32-DAG: sw [[ARG2]], 16([[GV]]) 1055 1056; NEW-DAG: ld [[ARG2:\$[0-9]+]], 0([[VA2]]) 1057; NEW-DAG: sd [[ARG2]], 16([[GV]]) 1058 1059 %ap = alloca i8*, align 8 1060 %ap2 = bitcast i8** %ap to i8* 1061 call void @llvm.va_start(i8* %ap2) 1062 1063 call void asm sideeffect "teqi $$zero, 1", ""() 1064 %arg1 = va_arg i8** %ap, i64 1065 %e1 = getelementptr [3 x i64], [3 x i64]* @dwords, i32 0, i32 1 1066 store volatile i64 %arg1, i64* %e1, align 8 1067 1068 call void asm sideeffect "teqi $$zero, 2", ""() 1069 %arg2 = va_arg i8** %ap, i64 1070 %e2 = getelementptr [3 x i64], [3 x i64]* @dwords, i32 0, i32 2 1071 store volatile i64 %arg2, i64* %e2, align 8 1072 1073 call void @llvm.va_end(i8* %ap2) 1074 1075 ret void 1076} 1077 1078declare void @llvm.va_start(i8*) 1079declare void @llvm.va_end(i8*) 1080