Is va_arg correct on Mips backend?

I check the Mips backend for the following C code fragment compile result. It seems not correct. Is it my misunderstand or it's a bug.

//ch8_3.cpp
#include <stdarg.h>

int sum_i(int amount, ...)
{
  int i = 0;
  int val = 0;
  int sum = 0;
  
  va_list vl;
  va_start(vl, amount);
  for (i = 0; i < amount; i++)
  {
    val = va_arg(vl, int);
    sum += val;
  }
  va_end(vl);
  
  return sum;
}

int main()
{
  int a = sum_i(6, 1, 2, 3, 4, 5, 6);
  
  return a;
}

Which part of the generated code do you think is not correct? Could you be more specific?

I compiled this program with clang and ran it on a mips board. It returns the expected result (21).

I didn’t have Mips board. I compile as the commands and check the asm output as below.

  1. Question:
    The distance of caller arg[4] and arg[5] is 4 bytes. But the the callee get every
    arg[] by 8 bytes offset (arg_ptr1+8 or arg_ptr2+8). I assume the #BB#4 and #BB#5 are the arg_ptr which is the pointer to access the stack arguments.

  2. Question:
    Stack memory 28($sp) has no initial value. If this memory address is a relocation record which set value by linker/loader, then it maybe is correct.

clang -c ch8_3.cpp -emit-llvm -o ch8_3.bc
llc -march=mips -relocation-model=pic -filetype=asm ch8_3.bc -o ch8_3.mips.s

.section .mdebug.abi32
.previous
.file “ch8_3.bc”
.text
.globl _Z5sum_iiz
.align 2
.type _Z5sum_iiz,@function
.set nomips16 # @_Z5sum_iiz
.ent _Z5sum_iiz
_Z5sum_iiz:
.cfi_startproc
.frame $sp,64,$ra
.mask 0x80000000,-4
.fmask 0x00000000,0
.set noreorder
.set nomacro
.set noat

BB#0:

lui $2, %hi(_gp_disp)
addiu $2, $2, %lo(_gp_disp)
addiu $sp, $sp, -64
$tmp2:
.cfi_def_cfa_offset 64
sw $ra, 60($sp) # 4-byte Folded Spill
$tmp3:
.cfi_offset 31, -4
addu $gp, $2, $25
sw $7, 76($sp)
sw $6, 72($sp)
sw $5, 68($sp)
lw $3, %got(__stack_chk_guard)($gp)
lw $1, 0($3)
sw $1, 56($sp)
sw $4, 52($sp)
sw $zero, 48($sp) // i
sw $zero, 44($sp) // val
sw $zero, 40($sp) // sum
addiu $1, $sp, 68
sw $1, 16($sp) // arg_ptr1
sw $zero, 48($sp)
b $BB0_2
addiu $2, $zero, 40
$BB0_1: # in Loop: Header=BB0_2 Depth=1
lw $1, 0($4) // $1 = *arg_ptr
sw $1, 44($sp) // val
lw $4, 40($sp) // sum
addu $1, $4, $1
sw $1, 40($sp) // sum += val
lw $1, 48($sp)
addiu $1, $1, 1
sw $1, 48($sp)
$BB0_2: # =>This Inner Loop Header: Depth=1
lw $1, 52($sp)
lw $4, 48($sp)
slt $1, $4, $1
beq $1, $zero, $BB0_6
nop

BB#3: # in Loop: Header=BB0_2 Depth=1

lw $4, 16($sp) // arg_ptr1
sltu $1, $2, $4
bne $1, $zero, $BB0_5
nop

BB#4: # in Loop: Header=BB0_2 Depth=1

addiu $1, $4, 8 // arg_ptr2 + 8
lw $5, 28($sp) // arg_ptr2_offset has no initial value
sw $1, 16($sp)
b $BB0_1
addu $4, $5, $4
$BB0_5: # in Loop: Header=BB0_2 Depth=1
lw $4, 24($sp) // arg_ptr2
addiu $1, $4, 8 // arg_ptr2 + 8
sw $1, 24($sp)
b $BB0_1
nop
$BB0_6:
lw $1, 0($3)
lw $3, 56($sp)
bne $1, $3, $BB0_8
lw $2, 40($sp)

BB#7: # %SP_return

lw $ra, 60($sp) # 4-byte Folded Reload
jr $ra
addiu $sp, $sp, 64
$BB0_8: # %CallStackCheckFailBlk
lw $25, %call16(__stack_chk_fail)($gp)
jalr $25
nop
.set at
.set macro
.set reorder
.end _Z5sum_iiz
$tmp4:
.size _Z5sum_iiz, ($tmp4)-_Z5sum_iiz
.cfi_endproc

.globl main
.align 2
.type main,@function
.set nomips16 # @main
.ent main
main:
.cfi_startproc
.frame $sp,48,$ra
.mask 0x80000000,-4
.fmask 0x00000000,0
.set noreorder
.set nomacro
.set noat

BB#0:

lui $2, %hi(_gp_disp)
addiu $2, $2, %lo(_gp_disp)
addiu $sp, $sp, -48
$tmp7:
.cfi_def_cfa_offset 48
sw $ra, 44($sp) # 4-byte Folded Spill
$tmp8:
.cfi_offset 31, -4
addu $gp, $2, $25
sw $zero, 40($sp)
addiu $1, $zero, 5
sw $1, 20($sp) // arg[5]
addiu $1, $zero, 4
sw $1, 16($sp) // arg[4]
addiu $1, $zero, 6
sw $1, 24($sp)
lw $25, %call16(_Z5sum_iiz)($gp)
addiu $4, $zero, 6
addiu $5, $zero, 1
addiu $6, $zero, 2
jalr $25
addiu $7, $zero, 3
sw $2, 36($sp)
lw $ra, 44($sp) # 4-byte Folded Reload
jr $ra
addiu $sp, $sp, 48
.set at
.set macro
.set reorder
.end main
$tmp9:
.size main, ($tmp9)-main
.cfi_endproc

Does it make a difference if you give the “-target” option to clang?

$ clang -target mips-linux-gnu ch8_3.cpp -o ch8_3.bc -emit-llvm -c

The .s file generated this way looks quite different from the one in your email.

Thank you. It’s work on Linux by following your instructions.

clang -target mips-linux-gnu

Do you know how to set clang -target option for iMac? Can we get the -target options available by command,
clang --help

Jonathan

After try with this command, it work now in iMac too. thank your kind help.

clang -target llvm-config --host-target -c ch8_3.cpp -emit-llvm -o ch8_3.bc

Jonathan