[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:
http://llvm.org/docs/LangRef.html#t_classifications
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.
-Chris
More information about the llvm-dev
mailing list