Declaration of a va_list should be an intrinsic?

Hi everyone,

Currently, when declaring a va_list in llvm, one only needs to do:

%ap = alloca i8 * (Reference : llvm/docs/LangRef.html#int_varargs)

This is OK for x86 and PPC/Darwin ABI because a va_list in these architectures is
just a pointer to the stack. The va_start intrinsic just initializes where
the pointer points at in the stack. I do not know how the other backends operate,
but I suppose it's the same.

However, on the PPC/ELF ABI, a va_list is a struct (referring to http://refspecs.freestandards.org/elf/elfspec_ppc.pdf)
of 12 bytes allocated on stack. The struct *should* not be allocated by va_start because a va_copy would not know
if the struct is allocated or not.

Therefore, I think there should be a special intrinsic for declaring a va_list. This unfortunately requires changes to all
backends, but i do not see how this can be handled differently. If an other backend already handles this correctly, please
tell me which one.

For X86 and PPC/Darwin (and others), the intrinsic will do:
alloca i8*

And for PPC/ELF it does:
alloca [12 * i8]

Does this sound correct?

Best,
Nicolas

Hi everyone,

Currently, when declaring a va_list in llvm, one only needs to do:

%ap = alloca i8 * (Reference : llvm/docs/LangRef.html#int_varargs)

This example is x86 specific. alpha allocas an {sbyte*, int} (and
does so in llvm-gcc). What the type of the alloca to use is requires
the frontend to know the abi of the backend. Even with an intrinsic
for allocating a va_list, you have the problem of what type should be
returned.

Therefore, I think there should be a special intrinsic for declaring a va_list. This
unfortunately requires changes to all
backends, but i do not see how this can be handled differently. If an other backend already handles this correctly, please
tell me which one.

No, the problem is just updating all the frontends. Right now, vaarg
handling is not target independent at the llvm level. I agree that a
va_list alloc intrinsic would go a long way towards abstracting the
target ABI from a vaarg function.

Andrew

Hi Andrew,

Andrew Lenharth wrote:

  

Hi everyone,

Currently, when declaring a va_list in llvm, one only needs to do:

%ap = alloca i8 * (Reference : llvm/docs/LangRef.html#int_varargs)
    
This example is x86 specific. alpha allocas an {sbyte*, int} (and
does so in llvm-gcc). What the type of the alloca to use is requires
the frontend to know the abi of the backend. Even with an intrinsic
for allocating a va_list, you have the problem of what type should be
returned.
  
We can set the type of the va_list to be i8* or i8**. Even if internally
it's something else.

Right now, vaarg
handling is not target independent at the llvm level.

Isn't this an error at the conception level? llvm bytecode should be
target independent.

I agree that a
va_list alloc intrinsic would go a long way towards abstracting the
target ABI from a vaarg function.

So you agree that it's the correct way to implement this target-dependant
feature? Updating all backends shouldn't be too hard.

Cheers,
Nicolas

Hi Andrew,
We can set the type of the va_list to be i8* or i8**. Even if internally
it's something else.

Yes, in the backend it just lowers to a reserved stack object of the
correct size (the TargetLowering should just set the size for va_list
and the lowering should turn it into a stack object I think). This
should only require one more like of code to each target.

> Right now, vaarg
> handling is not target independent at the llvm level.
Isn't this an error at the conception level? llvm bytecode should be
target independent.

I think so. There is no way, currently to really optimize/generate
vaargs in a target independent manner. It would be nice if we could.

> I agree that a
> va_list alloc intrinsic would go a long way towards abstracting the
> target ABI from a vaarg function.
So you agree that it's the correct way to implement this target-dependant
feature? Updating all backends shouldn't be too hard.

I don't see a problem with it.

Andrew

Right now, vaarg
handling is not target independent at the llvm level.

Isn't this an error at the conception level? llvm bytecode should be
target independent.

Ideally yes. However, llvm-gcc does a number of non-portable things already. For example, I think it currently lowers vaarg to pointer arithmetic, instead of using the correct intrinsic. If you'd like to look into fixing this stuff, it would be great, but I think some of the problems will be harder to fix than others.

I agree that a
va_list alloc intrinsic would go a long way towards abstracting the
target ABI from a vaarg function.

So you agree that it's the correct way to implement this target-dependant
feature? Updating all backends shouldn't be too hard.

This sounds like a great way to go to me. Updating llvm and the backends won't be hard. It may be more difficult to coax this intrinsic out of the f.e.

-Chris