[LLVMdev] First-class aggregate semantics

Jon Harrop jon at ffconsultancy.com
Thu Jan 7 18:52:00 PST 2010


On Thursday 07 January 2010 21:56:11 Dustin Laurence wrote:
> 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?

No. The idea is that you pass the structs around as values and not that you 
alloca them and pass by reference/pointer.

> What bothers me about that is the explicit specification with alloca
> that the space is reserved in the callee's frame.

Yes. Don't do that.

> 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?

No. LLVM is trusting you not to return pointers to locals.

> 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 have had great success with my HLVM project by passing around large numbers 
of large structs by hand. LLVM has not only survived but actually generated 
decent code that beats most languages according to my benchmarks. In 
particular, HLVM uses "fat" quadword references (where word = sizeof(void*)) 
that are passed everywhere by value except when a struct is returned and HLVM 
gets the caller to alloca and passes that space by pointer to the callee for 
it to fill in.

> > ...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?

Good question. There was a very interesting discussion about this here a while 
ago and everyone coming to LLVM says the same thing: why doesn't LLVM just 
handle this for me automatically? The answer is that LLVM cannot make that 
decision because it depends upon the ABI. C99 apparently returns user-defined 
structs of two doubles by reference but complex numbers in registers. So the 
ABI requires knowledge of the front-end and, therefore, LLVM cannot fully 
automate this.

Something LLVM could do is spill safely when it knows you don't care about the 
foreign ABI (e.g. with fastcc) and that work is underway.

-- 
Dr Jon Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/?e



More information about the llvm-dev mailing list