[LLVMdev] First-class aggregate semantics
baldrick at free.fr
Thu Jan 7 22:24:53 PST 2010
> I think I'm missing something basic about the semantics of returning an
> aggregate type (in my case, a structure) from a function. Returning a
> structure containing only compile-time constants is simple enough. But
> I don't quite get how this works with a struct composed at run-time. If
> I constructed it on the stack with alloca, would I be letting a stack
> variable escape to to a context where it doesn't exist if I return it?
first class aggregates are basically implemented by sticking the value of each
struct field in a register. For example, returning a struct with two i32
fields amounts to placing each of the fields in a machine register (eg: EAX,
ECX) then returning from the function. The caller gets hold of the values
by reading EAX and ECX. Note that it doesn't return a pointer to the struct,
it returns the value of the struct. Suppose you have stored the struct in
an alloca. Then to get it as a first class aggregate, you first need to do
a load of the alloca (this results in an LLVM register of aggregate type,
equivalent to two machine registers of type i32), then return the loaded value.
At the machine code level, this corresponds to loading the first field from
the stack into EAX, loading the second field from the stack into EDX then
> Or does the return semantics guarantee it will be copied (or space
> allocated in the caller) appropriately? Otherwise I should abandon the
> idea of returning such a struct and simply pass in a pointer to space
> allocated in the caller.
If the struct is so big that there aren't enough machine registers available
to return it, then the code generator will automagically allocate some stack
space in the caller, pass a pointer to it into the called function, and have
the callee return the struct by copying it into the passed stack space [*].
[*] This functionality was implemented after LLVM 2.6 was released. In LLVM
2.6 the code generator will crash if it runs out of registers. In this case
you should pass in a pointer by hand.
More information about the llvm-dev