[LLVMdev] Passing and returning aggregates (who is responsible for the ABI?)

Chris Lattner sabre at nondot.org
Mon Nov 5 21:17:24 PST 2007

> I'm trying to port the XL compiler (http://xlr.sf.net) to use the
> LLVM back-end. So far, little trouble doing so. But there is one
> aspect of the semantics of the LLVM IR that surprises me. Why are the
> call, declare and define "halfway through" ABI conventions?


> I think it's the right thing to have a single high level node for
> each call, as opposed to separate instructions for pushing individual
> argument, for example. But that implies that the call semantics
> include a good dose of ABI and calling conventions. This is explicit
> in the fact that you tell what the calling conventions are (e.g ccc,
> fastcc).


> But then, why refuse aggregates as input or output of a call? What is
> the rationale?

Because LLVM has no notion of aggregates as "values" that can be  
passed around as atomic units.  This is a very important design point,  
and has many useful values.

> On x86, I think it does not make any difference. But
> for Itanium, it's clearly broken (e.g. Itanium can return a struct of
> up to 4 ints in registers, and packs input parameters in a "funny"
> way). Languages such as Ada or XL have output parameters, and they
> are similarly difficult to generate code for (you have to make it
> look like C).
> I don't think adding aggregate support would break any current IR
> producer, and assuming the aggregates are expanded early on, it
> probably has very localized impact in the code. Are there other good
> reasons not to add this capability, or would a patch adding it stand
> a good chance to be accepted?

Unfortunately, this wouldn't solve the problem that you think it  
does.  For example, lets assume that LLVM allowed you to pass and  
return structs by value.  Even with this, LLVM would not be able to  
directly implement all ABIs "naturally".  For example, some ABIs  
specify that a _Complex double should be returned in two FP registers,  
but that a struct with two doubles in it should be returned in memory.

By the time you lower to LLVM, all you have is {double,double}.  In  
fact, there is no way, in general, to retain all the high level  
information in LLVM without flavoring the LLVM IR with target info.


More information about the llvm-dev mailing list