John McCall wrote:> On Oct 11, 2010, at 2:01 PM, Kenneth Uildriks wrote: >> A better way for a front-end to declare that vtbl-ptr-hacking is not >> expected and not supported is for it to emit llvm.invariant.start and >> llvm.invariant.end calls for it. > > Some of us were talking about this apropos your earlier post. > @llvm.invariant.start/end aren't appropriate, because the memory *isn't* > invariant; the user is totally allowed to destruct the object in-place and > create a new object there.Emit an invariant.end before the destructor and invariant.start before the constructor. Are there cases where you can't tell (in Clang) whether the callee is the destructor? For example, it is forbidden to take the address of a destructor in C++. Nick The only thing the standard tells us is that> old references and pointers are only considered to be automatically > "forwarded" to the new object (i.e. aren't just invalid) if the types match. > So we're allowed to assume that a pointer or reference validly formed > to an object of dynamic type T will always refer to an object of that > dynamic type. > > One possibility is to attach metadata to the object pointer somehow, > saying that it's to an object of a certain dynamic type; it would then > be simple for a language-specific optimization to fold vtable loads > from such pointers into the appropriate vtable pointer, which would > in turn be subject to additional folding. The chief obstacle here is > preventing other optimizations from merging two tagged pointers > in a way that leaves only one of the tags in place, which could break > semantics. To handle this, we could introduce an opaque readnone > no-op intrinsic (@llvm.bless?) after constructor calls (its return value > being the result of the new-expression) and before destructor calls > (its return value becoming the dtor's 'this' pointer). That, however, > has the disadvantage of interfering with memory optimizations > between the ctor, lifetime, and dtor; but maybe those optimizations > could be taught to look through blessings. > > (kudos to djg and sabre for the discussion earlier) > > John. > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >
On Oct 11, 2010, at 10:06 PM, Nick Lewycky wrote:> John McCall wrote: >> On Oct 11, 2010, at 2:01 PM, Kenneth Uildriks wrote: >>> A better way for a front-end to declare that vtbl-ptr-hacking is not >>> expected and not supported is for it to emit llvm.invariant.start and >>> llvm.invariant.end calls for it. >> >> Some of us were talking about this apropos your earlier post. >> @llvm.invariant.start/end aren't appropriate, because the memory *isn't* >> invariant; the user is totally allowed to destruct the object in-place and >> create a new object there. > > Emit an invariant.end before the destructor and invariant.start before the constructor. > Are there cases where you can't tell (in Clang) whether the callee is the destructor? > For example, it is forbidden to take the address of a destructor in C++.It's true that constructors and destructors can only be called directly. They can, however, be called directly by a different function, which I may or may not inline. I'm not certain how these intrinsics are supposed to pair up in that case, or what happens to correctness if they don't. John.
John McCall wrote:> > On Oct 11, 2010, at 10:06 PM, Nick Lewycky wrote: > >> John McCall wrote: >>> On Oct 11, 2010, at 2:01 PM, Kenneth Uildriks wrote: >>>> A better way for a front-end to declare that vtbl-ptr-hacking is not >>>> expected and not supported is for it to emit llvm.invariant.start and >>>> llvm.invariant.end calls for it. >>> >>> Some of us were talking about this apropos your earlier post. >>> @llvm.invariant.start/end aren't appropriate, because the memory *isn't* >>> invariant; the user is totally allowed to destruct the object in-place and >>> create a new object there. >> >> Emit an invariant.end before the destructor and invariant.start before the constructor. >> Are there cases where you can't tell (in Clang) whether the callee is the destructor? >> For example, it is forbidden to take the address of a destructor in C++. > > It's true that constructors and destructors can only be called directly. They can, > however, be called directly by a different function, which I may or may not inline. > I'm not certain how these intrinsics are supposed to pair up in that case, or what > happens to correctness if they don't.The design of invariant.start/end is slightly wrong in that the first parameter of the end is the start. As you point out, this forces invariants to be local. I think we could simply remove that argument from invariant.end and the return from invariant.start, and rely on alias analysis to determine whether the two must/may/couldn't refer to the same memory. In general, the memory use markers were added specifically to address difficulties with devirtualization in the middle end or at LTO time. Feel free to adjust their semantics as needed; their implementation at this point is pretty minimal and they should be easy to work with. Nick