[llvm] r197645 - Begin adding docs and IR-level support for the inalloca attribute

Reid Kleckner rnk at google.com
Wed Jan 15 16:44:59 PST 2014


On Tue, Jan 14, 2014 at 10:41 PM, Chris Lattner <clattner at apple.com> wrote:

> On Dec 18, 2013, at 6:14 PM, Reid Kleckner <reid at kleckner.net> wrote:
> > The inalloca attribute is designed to support passing C++ objects by
> > value in the Microsoft C++ ABI.  It behaves the same as byval, except
> > that it always implies that the argument is in memory and that the bytes
> > are never copied.  This attribute allows the caller to take the address
> > of an outgoing argument's memory and execute arbitrary code to store
> > into it.
>
> I'm glad you're working on this, I'm a big fan of your project to get MSVC
> ABI compatibility.


Thanks!


> >
> > +The :ref:`attr_inalloca` attribute is designed to allow taking the
> > +address of an aggregate argument that is being passed by value through
> > +memory.  Primarily, this feature is required for compatibility with the
> > +Microsoft C++ ABI.  Under that ABI, class instances that are passed by
> > +value are constructed directly into argument stack memory.  Prior to the
> > +addition of inalloca, calls in LLVM were indivisible instructions.
> > +There was no way to perform intermediate work, such as object
> > +construction, between the first stack adjustment and the final control
> > +transfer.  With inalloca, each argument is modelled as an alloca, which
> > +can be stored to independently of the call.  Unfortunately, this
> > +complicated feature comes with a large set of restrictions designed to
> > +bound the lifetime of the argument memory around the call, which are
> > +explained in this document.
> > +
>
> I'm deeply concerned about this design, since this effectively breaks
> value semantic guarantees for LLVM IR by requiring that the immediate
> argument be an alloca.
>
> It is a deeply held truth that  values are in SSA registers, and that any
> operation that doesn't affect the value can be done to the register.  Noop
> bitcasts can be inserted, stores and reloads to memory (e.g. the reg to
> stack pass), passing values as arguments to functions and returning them
> (for example, the code extraction pass), inserting PHI nodes when commoning
> code, are all examples of this.
>
> I don't think that this is a good tradeoff in terms of compiler complexity
> to throw all of these guarantees out of the window for this.
>

OK.  I think there are a couple ways we can get this back.

The simplest is to go back to the bag of bytes approach.  This has the
downside that frontends have to deeply understand the memory layout of the
outgoing call frame, but we already have that problem.

The "bag of bytes" approach can be implemented with the same inalloca
attribute, except that each call is only allowed to have one inalloca
argument and it has to be the last one.  The alloca is typically a packed
struct representing the entire call frame containing all the arguments as
fields at appropriate offsets.  We might have to mark the alloca somehow to
prevent it from being considered static.

A much more complicated approach would still try to let the backend sort
out the memory layout of the arguments.  We'd have some callseq_start
instruction or intrinsic that takes a function prototype, and returns
multiple pointers that point to various outgoing arguments.

With this, we should be able to tail merge the call to foo in "if (a)
foo(b()); else foo(c());" where foo's argument is non-trivially passed by
value.

----

Even with this, we would still have a rule against reordering allocas,
which is pretty ugly.  Fortunately, there aren't many places that we move
allocas other than the inliner.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140115/1fe5d935/attachment.html>


More information about the llvm-commits mailing list