[PATCH] [ms-cxxabi] Implement codegen for dereferencing member pointers
Reid Kleckner
rnk at google.com
Thu Apr 11 09:35:02 PDT 2013
On Tue, Apr 9, 2013 at 7:50 PM, John McCall <rjmccall at apple.com> wrote:
> On Apr 9, 2013, at 3:02 PM, Reid Kleckner <rnk at google.com> wrote:
>> On Mon, Apr 8, 2013 at 7:58 PM, John McCall <rjmccall at apple.com> wrote:
>>>
>>> On Apr 2, 2013, at 11:00 AM, Reid Kleckner <rnk at google.com> wrote:
>>> +llvm::Value *
>>> +MicrosoftCXXABI::AdjustVirtualBase(CGBuilderTy &Builder,
>>> + const CXXRecordDecl *RD, llvm::Value *Base,
>>> + llvm::Value *VirtualBaseAdjustmentOffset,
>>> + llvm::Value *VBTableOffset) {
>>>
>>> This code is assuming that it *has* to adjust by a virtual base.
>>> That is not the case (unless MSVC does something interesting
>>> in its vb-table layouts, like leave a zero offset at a particular offset
>>> in the table...), and even then it's suspect in the MSIM_unspecified
>>> case where it's completely legitimate that the record type might not
>>> have a vb-table.
>>
>> Good catch: the first vbtable entry points back to the base of the
>> current subobject. That means it's safe to perform the adjustment so
>> long as we know there is a vbptr. MSVC does this so I followed suit.
>
> Seems reasonable.
>
> As an aside, I wonder what the right trade-off here actually is: an extra
> branch vs. an unnecessary memory dependence... Anyway, it's not
> important right now.
Yeah, hard to say.
> + // If the class has an explicit inheritance model attribute, we conservatively
> + // use -1. This requires different TUs to see the same attribute or they have
> + // an ODR problem.
> + if (RD->hasAttr<MSInheritanceAttr>())
> + return true;
>
> If this is really how MSVC handles this issue — and that seems reasonable
> enough to me — then arguably these cases need to be distinguished in the
> MSInheritanceModel enum. I think we'd have six cases:
> - has no bases at non-zero offsets, known not polymorphic or unknown polymorphism
> - has no bases at non-zero offsets, known polymorphic
> - has bases at static non-zero offsets, known not polymorphic or unknown polymorphism
> - has bases at static non-zero offsets, known polymorphic
> - has virtual bases
> - unspecified
>
> The inheritance model is fundamentally about member pointers. It makes
> sense for it to capture everything necessary in order to interpret a member
> pointer.
Sounds good, I added MSIM_MultiplePolymorphic and MSIM_SinglePolymorphic.
> That would also make it easier to diagnose the following invalid code (unless
> we already diagnose attempts to add inheritance keywords after the definition?).
> class A {
> virtual void foo();
> };
> class __single_inheritance A;
I'm not sure, I need to go back and do a pass for diagnostics.
> + // Since zero is a valid offset for classes without vtables, they use -1. For
> + // some reason, classes with vtables use 0 in this ABI. In this inheritance
> + // model, only polymorphic classes have vtables.
> + return !RD->isPolymorphic();
>
> The reason's pretty straightforward: it is generally better to use 0 instead of -1
> because it's usually easier to produce 0 than -1. That's true even on the
> smallest level — on x86 it's a smaller instruction to load 0 into a register
> than to load -1 — but more importantly, it means that the compiler can do things
> like put a zero-initialized global in a zero-fill section or zero-initialize an
> object with a simple memset.
>
> + // There is only one kind of class with data member pointers that can be zero
> + // initialized: single or multiple inheritance classes with a vfptr.
>
> I'd put it this way: MSVC uses 0 as the null offset if it can guarantee that
> that won't point at a data member. It can make that guarantee:
> - if the class is known to be polymorphic (because offset 0 will be the vf-table), or otherwise
> - if the class is known to have virtual bases (because offset 0 will be the vb-table)
> class is known to have virtual bases (because offset 0 will be the vb-table).
>
> The way that you've got this logic split between NullFieldOffsetIsAllOnes and
> isZeroInitializable is really confusing to me.
>
> + if (Inheritance >= MSIM_Virtual)
>
> Instead of doing checks like this, consider making little predicate functions:
> static bool hasVirtualBaseAdjustmentField(MSInheritanceModel);
> It would remove the need for quite so many little comments everywhere.
This made the code much better, thanks!
> +llvm::SmallVector<llvm::Constant *, 4>
> +MicrosoftCXXABI::GetNullMemberPointerFields(const MemberPointerType *MPT) {
>
> Please have this take a SmallVectorImpl<llvm::Constant*> by reference instead
> of returning one.
OK.
> + // http://llvm.org/PR15713 : Taking a pointer to a member of a virtual
> + // base is not standard C++. Clang will reject this in SemaCast, so we
> + // don't have to handle it here.
>
> As covered above, when emitting a member pointer constant, you'll always
> be making something in its declaring class. This is why you can just ask
> for the offset of a field instead of computing offsets all along the base path.
Yep, I'll document that.
> + // in which case we need to skip the virtual base lookup. If there were a
> + // vbtable, the first entry is a no-op entry that gives back the original
>
> Grammar: "If there is a vbtable..."
OK. I'm confused about subjunctive tense. =/
> + llvm::BasicBlock *OriginalBB;
> + llvm::BasicBlock *SkipAdjustBB;
>
> You'll need to zero-initialize these in order to pacify compiler warnings.
OK. There's been some debate on the list, and I wasn't sure which way to go.
> + // Add it to VBPtr.
> + llvm::Value *AdjustedBase = Builder.CreateInBoundsGEP(VBPtr, VBaseOffs);
>
> On Win64, you need to be sure to sign-extend this. (vb-offsets can be
> negative in very particular circumstances.)
GEP sign extends the i32 implicitly, apparently.
> + assert(MPT->isMemberFunctionPointer());
> + const FunctionProtoType *FPT =
> + MPT->getPointeeType()->getAs<FunctionProtoType>();
>
> This can be castAs<>.
OK.
> Otherwise, this is looking great, thanks!
Thanks for the helpful review!
Should I commit the patch attached?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: msvc-memptrs.diff
Type: application/octet-stream
Size: 31444 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130411/4ad57d1f/attachment.obj>
More information about the cfe-commits
mailing list