r192312 - Initialize vtorDisp in class constructors and destructors

Timur Iskhodzhanov timurrrr at google.com
Thu Oct 10 10:38:37 PDT 2013


This one requires -8.
We probably need to add something like getVtorDispOffset() to ASTRecordLayout...
------------------
struct A {
  virtual void x();
};

struct B {
  virtual void f();
};

struct C : A, B {};

struct D : virtual C {
  virtual void f();
  virtual ~D();
};

D d;
------------------

2013/10/10 Warren Hunt <whunt at google.com>:
> In all of the tests I have run the vtorDisp is at -4.  RecordlayoutBuilder
> puts it there (there are weird padding rules when vtordisps are present, but
> the location of a vtordisp with respect to its virtual base has always been
> constant to my testing).  If you have any counterexamples I would love to
> see them!
>
> -Warren
>
>
> On Thu, Oct 10, 2013 at 7:52 AM, Timur Iskhodzhanov <timurrrr at google.com>
> wrote:
>>
>> 2013/10/9 Timur Iskhodzhanov <timurrrr at google.com>:
>> > Author: timurrrr
>> > Date: Wed Oct  9 13:16:58 2013
>> > New Revision: 192312
>> >
>> > URL: http://llvm.org/viewvc/llvm-project?rev=192312&view=rev
>> > Log:
>> > Initialize vtorDisp in class constructors and destructors
>> >
>> > Reviewed at http://llvm-reviews.chandlerc.com/D1867
>> >
>> > ...
>> > Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
>> > URL:
>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=192312&r1=192311&r2=192312&view=diff
>> >
>> > ==============================================================================
>> > --- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
>> > +++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Wed Oct  9 13:16:58 2013
>> > @@ -456,6 +459,61 @@ MicrosoftCXXABI::EmitCtorCompleteObjectH
>> >    return SkipVbaseCtorsBB;
>> >  }
>> >
>> > +void MicrosoftCXXABI::initializeHiddenVirtualInheritanceMembers(
>> > +    CodeGenFunction &CGF, const CXXRecordDecl *RD) {
>> > +  // In most cases, an override for a vbase virtual method can adjust
>> > +  // the "this" parameter by applying a constant offset.
>> > +  // However, this is not enough while a constructor or a destructor of
>> > some
>> > +  // class X is being executed if all the following conditions are met:
>> > +  //  - X has virtual bases, (1)
>> > +  //  - X overrides a virtual method M of a vbase Y, (2)
>> > +  //  - X itself is a vbase of the most derived class.
>> > +  //
>> > +  // If (1) and (2) are true, the vtorDisp for vbase Y is a hidden
>> > member of X
>> > +  // which holds the extra amount of "this" adjustment we must do when
>> > we use
>> > +  // the X vftables (i.e. during X ctor or dtor).
>> > +  // Outside the ctors and dtors, the values of vtorDisps are zero.
>> > +
>> > +  const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
>> > +  typedef ASTRecordLayout::VBaseOffsetsMapTy VBOffsets;
>> > +  const VBOffsets &VBaseMap = Layout.getVBaseOffsetsMap();
>> > +  CGBuilderTy &Builder = CGF.Builder;
>> > +
>> > +  unsigned AS =
>> > +
>> > cast<llvm::PointerType>(getThisValue(CGF)->getType())->getAddressSpace();
>> > +  llvm::Value *Int8This = 0;  // Initialize lazily.
>> > +
>> > +  for (VBOffsets::const_iterator I = VBaseMap.begin(), E =
>> > VBaseMap.end();
>> > +        I != E; ++I) {
>> > +    if (!I->second.hasVtorDisp())
>> > +      continue;
>> > +
>> > +    llvm::Value *VBaseOffset =
>> > CGM.getCXXABI().GetVirtualBaseClassOffset(
>> > +        CGF, getThisValue(CGF), RD, I->first);
>> > +    // FIXME: it doesn't look right that we SExt in
>> > GetVirtualBaseClassOffset()
>> > +    // just to Trunc back immediately.
>> > +    VBaseOffset = Builder.CreateTruncOrBitCast(VBaseOffset,
>> > CGF.Int32Ty);
>> > +    uint64_t ConstantVBaseOffset =
>> > +        Layout.getVBaseClassOffset(I->first).getQuantity();
>> > +
>> > +    // vtorDisp_for_vbase = vbptr[vbase_idx] - offsetof(RD, vbase).
>> > +    llvm::Value *VtorDispValue = Builder.CreateSub(
>> > +        VBaseOffset, llvm::ConstantInt::get(CGM.Int32Ty,
>> > ConstantVBaseOffset),
>> > +        "vtordisp.value");
>> > +
>> > +    if (!Int8This)
>> > +      Int8This = Builder.CreateBitCast(getThisValue(CGF),
>> > +                                       CGF.Int8Ty->getPointerTo(AS));
>> > +    llvm::Value *VtorDispPtr = Builder.CreateInBoundsGEP(Int8This,
>> > VBaseOffset);
>> > +    // vtorDisp is always the 32-bits before the vbase in the class
>> > layout.
>> > +    VtorDispPtr = Builder.CreateConstGEP1_32(VtorDispPtr, -4);
>>
>> After investigating some other tests, I'm pretty sure the "-4"
>> vtordisp offset is not constant but rather might have a different
>> value for more complex record layouts.
>>
>> Warren, do you have any insight to share on the vtordisp location in a
>> record layout?
>>
>> > +    VtorDispPtr = Builder.CreateBitCast(
>> > +        VtorDispPtr, CGF.Int32Ty->getPointerTo(AS), "vtordisp.ptr");
>> > +
>> > +    Builder.CreateStore(VtorDispValue, VtorDispPtr);
>> > +  }
>> > +}
>> > +
>> >  void MicrosoftCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D)
>> > {
>> >    // There's only one constructor type in this ABI.
>> >    CGM.EmitGlobal(GlobalDecl(D, Ctor_Complete));
>> >
>
>



More information about the cfe-commits mailing list