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];
On Tue, 3 Apr 2007, Nicolas Geoffray wrote:> A VAARG call requires a lot of computation. Typically the C code for > va_arg(ap, int)If you use va_arg in C, are you seeing llvm.vaarg in the output .ll file? -Chris> 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]; > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >-Chris -- http://nondot.org/sabre/ http://llvm.org/
Hi Chris, Chris Lattner wrote:> On Tue, 3 Apr 2007, Nicolas Geoffray wrote: > >> A VAARG call requires a lot of computation. Typically the C code for >> va_arg(ap, int) >> > > If you use va_arg in C, are you seeing llvm.vaarg in the output .ll file? >I'm guessing that if you're asking, then no llvm.vaarg is generated. I can not test it on my box 'cause llvm-gcc does not compile on Linux/PPC, but the llvm.org online demo does not indeed generate a llvvm.vaarg instruction. But this is horribly not portable! The va_arg(ap, int) for Linux/PPC is really different from Darwin/PPC (see my previous message). And the .ll file generated by llvm-gcc can not be executed on Linux/PPC. Btw, I'm using the JIT of llvm, not llvm-gcc, I do not code in C to generate llvm code, but in "MyLanguage". And I want "MyLanguage" to have variadic functions and interoperate with C code. Cheers, Nicolas> -Chris > > >> 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]; >> _______________________________________________ >> LLVM Developers mailing list >> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >> >> > > -Chris > >
On 4/3/07, Nicolas Geoffray <nicolas.geoffray at lip6.fr> wrote:> 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; > } > }This isn't much more (any more?) complex than Alpha's vaargs. You can do it without introducing any new branches with some selects and generate DAG code directly. Andrew