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? 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. I think my confusion stems from thinking in terms of high-level languages and not having done nearly enough assembly work to know what LLVM really wants to do, and I'd be grateful for a clue about the idiomatic way to do this. Dustin
On Thursday 07 January 2010 15:28, Dustin Laurence wrote:> 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? > 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. > > I think my confusion stems from thinking in terms of high-level > languages and not having done nearly enough assembly work to know what > LLVM really wants to do, and I'd be grateful for a clue about the > idiomatic way to do this.The way this works on many targets is that the caller allocates stack space in its frame for the returned struct and passes a pointer to it as a first "hidden" argument to the callee. The callee then copies that data into the space pointed to by the address. This is all specified by the ABI so it varies by processor and OS. The target-dependent lowering pieces of LLVM should take care of it. Long-term, first-class status means that returns of structs should "just work" and you don't need to worry about getting a pointer to invalid memory. I believe right now, however, only structs up to a certain size are supported, perhaps because under some ABIs, small structs can be returned in registers and one doesn't need to worry about generating the hidden argument. Someone working directly on this can answer with more authority. -Dave
On 01/07/2010 01:38 PM, David Greene wrote:> The way this works on many targets is that the caller allocates stack > space in its frame for the returned struct and passes a pointer to it > as a first "hidden" argument to the callee. The callee then copies > that data into the space pointed to by the address.<nod>> Long-term, first-class status means that returns of structs should > "just work" and you don't need to worry about getting a pointer to > invalid memory.OK, so my thought of constructing the object on the stack was correct? What I originally wanted to do was roughly %Token = type {%c_int, %i8*} define %Token @foo() { ... ret %Token {%c_int %token, %i8* %value} } but the compiler complains about the invalid usage of a local name. So I decided the problem was that I was thinking in terms of languages that would create a temporary implicitly, and in IR I need to do it explicitly. So it occurred to me to create the struct on the stack, as I mentioned. What bothers me about that is the explicit specification with alloca that the space is reserved in the callee's frame. Do I just trust the optimizer to eliminate that and turn the reference to alloca'd memory into a reference to the space reserved by the caller? Or is that going to create an unnecessary copy from the alloca'd memory to that reserved by the caller? From what you said my guess is the former (optimizer eliminates the pointless temporary), but us premature optimizers like to be reassured we haven't given up an all-important microsecond. :-)> ...I believe right now, however, only structs up to a > certain size are supported, perhaps because under some ABIs, small > structs can be returned in registers and one doesn't need to worry > about generating the hidden argument.In the case that prompted the question the struct isn't going to be bigger than two of whatever the architecture regards as a word, which surely should be fine, but in principle shouldn't LLVM and not the front-end programmer be making the decision about whether the struct is big enough to spill into memory? Dustin
On Thu, Jan 7, 2010 at 3:38 PM, David Greene <dag at cray.com> wrote:> On Thursday 07 January 2010 15:28, Dustin Laurence wrote: >> 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? >> 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. >> >> I think my confusion stems from thinking in terms of high-level >> languages and not having done nearly enough assembly work to know what >> LLVM really wants to do, and I'd be grateful for a clue about the >> idiomatic way to do this. > > The way this works on many targets is that the caller allocates stack > space in its frame for the returned struct and passes a pointer to it > as a first "hidden" argument to the callee. The callee then copies > that data into the space pointed to by the address. > > This is all specified by the ABI so it varies by processor and OS. > The target-dependent lowering pieces of LLVM should take care of it. > > Long-term, first-class status means that returns of structs should > "just work" and you don't need to worry about getting a pointer to > invalid memory. I believe right now, however, only structs up to a > certain size are supported, perhaps because under some ABIs, small > structs can be returned in registers and one doesn't need to worry > about generating the hidden argument. > > Someone working directly on this can answer with more authority.On x86, the hidden argument is generated automatically at codegen time if it's needed. As far as I know, other platforms don't yet have that support.
Hi Dustin,> 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 returning.> 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 [*]. Ciao, Duncan. [*] 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.
On Fri, Jan 8, 2010 at 12:24 AM, Duncan Sands <baldrick at free.fr> wrote:> Hi Dustin, > >> 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 > returning. > >> 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 [*].There are small target hooks that need to be implemented for each target to get this to work. As far as I know, the only hook implemented was for x86.