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

Chris Lattner sabre at nondot.org
Mon Nov 5 23:33:30 PST 2007

>> This doesn't fit naturally with the way that LLVM does things:  In
>> LLVM, each instruction can produce at most one value.  This means  
>> that
>> a pointer to the instruction is as good as a pointer to the value,
>> which dramatically simplifies the IR and everything that consumes or
>> produces it.
> An additional constraint you did not mention is that all the values
> must be first-class. But what is "first class" actually depends on
> the hardware and ABI. An i64, for instance, is first class on 64-bit
> CPUs, but not on 32-bit CPUs. Is the following legal on a 32-bit  
> target?
> 	declare i64 @foo(i128, i256)

Yes it is, LLVM explicitly defines what it considers to be a first- 
class type:

The language definition is orthogonal from how the language is mapped  
onto any particular hardware.

>>  The "getaggregatevalue" is a localized hack to work
>> around this for the few cases that return multiple values.
> As a matter of fact, what annoys me the most with the
> getaggregatevalue proposal is precisely that it does not seem too
> localized to me. What about:
>    %Agg = call {int, float} %foo()
>    %intpart = getaggregatevalue {int, float} %Agg, uint 0
>    [insert 200 instructions here]
>    %floatpart = getaggregatevalue {int, float} %Agg, uint 1

It is localized in the sense that it adds one feature to the IR, which  
will require very minor changes to optimizers and other pieces of the  
compiler.  I don't mean localized in the code layout sense.

>> 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.
> Even today, that must be special cased, i.e. the IR needs to be
> distinct between the two cases. As I understand it, the following is
> already legal, since vectors are first class:
> 	declare <2 x double> @builtin_complex_add (<2 x double>, <2 x  
> double>)

Complex != vectors.

You are right though that the front-end has to be aware of this.  I  
think that darwin/ppc specifies that Complex float is returned in two  
integer GPRs (!!), where as a struct of two floats is returned by  
hidden reference.

llvm-gcc lowers the former to return an "i64" value, which it knows  
gets mapped onto two GPRs.  The latter is lowered to pass a pointer to  
the return value as the first argument.

My point about ABIs is that there is no way to prevent the front-end  
from having to know this kind of magic, without teaching llvm about  
the full C type system (and every other language that targets it)  
something we don't want to do.


More information about the llvm-dev mailing list