Implementing a complicated VAARG

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Implementing a complicated VAARG

varth
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];
_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: Implementing a complicated VAARG

Chris Lattner
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
> [hidden email]         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>

-Chris

--
http://nondot.org/sabre/
http://llvm.org/
_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: Implementing a complicated VAARG

varth
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
>> [hidden email]         http://llvm.cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>>
>>    
>
> -Chris
>
>  

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: Implementing a complicated VAARG

Andrew Lenharth
In reply to this post by varth
On 4/3/07, Nicolas Geoffray <[hidden email]> 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
_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: Implementing a complicated VAARG

Chris Lattner
In reply to this post by varth
On Tue, 3 Apr 2007, Nicolas Geoffray wrote:
> 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.

ok

> But this is horribly not portable! The va_arg(ap, int) for Linux/PPC is
> really different
> from Darwin/PPC (see my previous message).

I agree.

> And the .ll file generated by
> llvm-gcc
> can not be executed on Linux/PPC.

Right.

> 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.

Ok, if you have a non-C input, implementing llvm.vaarg is important. :)

-Chris

> 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
>>> [hidden email]         http://llvm.cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>>>
>>>
>>
>> -Chris
>>
>>
>
> _______________________________________________
> LLVM Developers mailing list
> [hidden email]         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>

-Chris

--
http://nondot.org/sabre/
http://llvm.org/
_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev