[LLVMdev] Implementing a complicated VAARG

Nicolas Geoffray
Tue, 03 Apr 2007 14:14:09 -0000

Hi everyone,

I'm implementing varags handling for PPC32 with the ELF ABI. It is
largely more
complicated than the Macho ABI or x86 because it manipulates a struct
instead of a direct pointer in the stack. You can find the layout of the
va_list struct
at the end of this mail.

A VAARG call requires a lot of computation. Typically the C code for
va_arg(ap, int)
is:

int va_arg_gpr(ap_list ap) {
    int idx = ap->gpr;
    if (idx < 8) {
        ap->gpr = idx + 1;
        return ap->reg_save_area[idx];
    }
    else {
      int res = ap->overflow_arg_area[0];
      ap->gpr = idx + 1;
      ap->overflow_arg_area += 4;
      return res;
    }
}

Actually, all VAARG implementations for other backends use DAGs, but
this may be
too complicated to do for ELF32.

What would you suggest to code the VAARG instruction efficiently?
Should I code va_arg_gpr with DAGs (many lines of code) or should I
create a DAG that will
call the C method va_arg_gpr (Btw, i do not know how to do this ;))?

Thanks for your help!

Best,
Nicolas


  // For ELF 32 ABI we follow the layout of the va_list struct.
  // We suppose the given va_list is already allocated.
  //
  // typedef struct {
  //  char gpr;     /* index into the array of 8 GPRs
  //                 * stored in the register save area
  //                 * gpr=0 corresponds to r3,
  //                 * gpr=1 to r4, etc.
  //                 */
  //  char fpr;     /* index into the array of 8 FPRs
  //                 * stored in the register save area
  //                 * fpr=0 corresponds to f1,
  //                 * fpr=1 to f2, etc.
  //                 */
  //  char *overflow_arg_area;
  //                /* location on stack that holds
  //                 * the next overflow argument
  //                 */
  //  char *reg_save_area;
  //               /* where r3:r10 and f1:f8 (if saved)
  //                * are stored
  //                */
  // } va_list[1];