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