<div dir="ltr">When I run that through cl.exe with my test harness I get the following layouts:<div><br></div><div><div>A : 4 : 4</div><div> 0 : 00FC8144 vfp</div><div><br></div><div>B : 4 : 4</div><div> 0 : 00FC814C vfp</div>
<div><br></div><div>C : 8 : 4</div><div> 0 : 00FC815C A's vfp</div><div> 4 : 00FC8154 B's vfp</div><div><br></div><div>D : 20 : 4</div><div> 0 : 00FC8174  vfp</div><div> 4 : 00FC8178  vpb</div><div> 8 : 00000000  C's vtordisp (A and B don't have vtordisps)</div>
<div> c : 00FC816C C's (& A's) vfp</div><div>10 : 00FC8164 B's vfp</div></div><div><br></div><div>By my understanding, the offset for C is -4, A and B don't have them.</div><div><br></div><div>-Warren</div>
<div><br></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Thu, Oct 10, 2013 at 10:38 AM, Timur Iskhodzhanov <span dir="ltr"><<a href="mailto:timurrrr@google.com" target="_blank">timurrrr@google.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This one requires -8.<br>
We probably need to add something like getVtorDispOffset() to ASTRecordLayout...<br>
------------------<br>
struct A {<br>
  virtual void x();<br>
};<br>
<br>
struct B {<br>
  virtual void f();<br>
};<br>
<br>
struct C : A, B {};<br>
<br>
struct D : virtual C {<br>
  virtual void f();<br>
  virtual ~D();<br>
};<br>
<br>
D d;<br>
------------------<br>
<br>
2013/10/10 Warren Hunt <<a href="mailto:whunt@google.com">whunt@google.com</a>>:<br>
<div class="HOEnZb"><div class="h5">> In all of the tests I have run the vtorDisp is at -4.  RecordlayoutBuilder<br>
> puts it there (there are weird padding rules when vtordisps are present, but<br>
> the location of a vtordisp with respect to its virtual base has always been<br>
> constant to my testing).  If you have any counterexamples I would love to<br>
> see them!<br>
><br>
> -Warren<br>
><br>
><br>
> On Thu, Oct 10, 2013 at 7:52 AM, Timur Iskhodzhanov <<a href="mailto:timurrrr@google.com">timurrrr@google.com</a>><br>
> wrote:<br>
>><br>
>> 2013/10/9 Timur Iskhodzhanov <<a href="mailto:timurrrr@google.com">timurrrr@google.com</a>>:<br>
>> > Author: timurrrr<br>
>> > Date: Wed Oct  9 13:16:58 2013<br>
>> > New Revision: 192312<br>
>> ><br>
>> > URL: <a href="http://llvm.org/viewvc/llvm-project?rev=192312&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=192312&view=rev</a><br>
>> > Log:<br>
>> > Initialize vtorDisp in class constructors and destructors<br>
>> ><br>
>> > Reviewed at <a href="http://llvm-reviews.chandlerc.com/D1867" target="_blank">http://llvm-reviews.chandlerc.com/D1867</a><br>
>> ><br>
>> > ...<br>
>> > Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp<br>
>> > URL:<br>
>> > <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=192312&r1=192311&r2=192312&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=192312&r1=192311&r2=192312&view=diff</a><br>

>> ><br>
>> > ==============================================================================<br>
>> > --- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)<br>
>> > +++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Wed Oct  9 13:16:58 2013<br>
>> > @@ -456,6 +459,61 @@ MicrosoftCXXABI::EmitCtorCompleteObjectH<br>
>> >    return SkipVbaseCtorsBB;<br>
>> >  }<br>
>> ><br>
>> > +void MicrosoftCXXABI::initializeHiddenVirtualInheritanceMembers(<br>
>> > +    CodeGenFunction &CGF, const CXXRecordDecl *RD) {<br>
>> > +  // In most cases, an override for a vbase virtual method can adjust<br>
>> > +  // the "this" parameter by applying a constant offset.<br>
>> > +  // However, this is not enough while a constructor or a destructor of<br>
>> > some<br>
>> > +  // class X is being executed if all the following conditions are met:<br>
>> > +  //  - X has virtual bases, (1)<br>
>> > +  //  - X overrides a virtual method M of a vbase Y, (2)<br>
>> > +  //  - X itself is a vbase of the most derived class.<br>
>> > +  //<br>
>> > +  // If (1) and (2) are true, the vtorDisp for vbase Y is a hidden<br>
>> > member of X<br>
>> > +  // which holds the extra amount of "this" adjustment we must do when<br>
>> > we use<br>
>> > +  // the X vftables (i.e. during X ctor or dtor).<br>
>> > +  // Outside the ctors and dtors, the values of vtorDisps are zero.<br>
>> > +<br>
>> > +  const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);<br>
>> > +  typedef ASTRecordLayout::VBaseOffsetsMapTy VBOffsets;<br>
>> > +  const VBOffsets &VBaseMap = Layout.getVBaseOffsetsMap();<br>
>> > +  CGBuilderTy &Builder = CGF.Builder;<br>
>> > +<br>
>> > +  unsigned AS =<br>
>> > +<br>
>> > cast<llvm::PointerType>(getThisValue(CGF)->getType())->getAddressSpace();<br>
>> > +  llvm::Value *Int8This = 0;  // Initialize lazily.<br>
>> > +<br>
>> > +  for (VBOffsets::const_iterator I = VBaseMap.begin(), E =<br>
>> > VBaseMap.end();<br>
>> > +        I != E; ++I) {<br>
>> > +    if (!I->second.hasVtorDisp())<br>
>> > +      continue;<br>
>> > +<br>
>> > +    llvm::Value *VBaseOffset =<br>
>> > CGM.getCXXABI().GetVirtualBaseClassOffset(<br>
>> > +        CGF, getThisValue(CGF), RD, I->first);<br>
>> > +    // FIXME: it doesn't look right that we SExt in<br>
>> > GetVirtualBaseClassOffset()<br>
>> > +    // just to Trunc back immediately.<br>
>> > +    VBaseOffset = Builder.CreateTruncOrBitCast(VBaseOffset,<br>
>> > CGF.Int32Ty);<br>
>> > +    uint64_t ConstantVBaseOffset =<br>
>> > +        Layout.getVBaseClassOffset(I->first).getQuantity();<br>
>> > +<br>
>> > +    // vtorDisp_for_vbase = vbptr[vbase_idx] - offsetof(RD, vbase).<br>
>> > +    llvm::Value *VtorDispValue = Builder.CreateSub(<br>
>> > +        VBaseOffset, llvm::ConstantInt::get(CGM.Int32Ty,<br>
>> > ConstantVBaseOffset),<br>
>> > +        "vtordisp.value");<br>
>> > +<br>
>> > +    if (!Int8This)<br>
>> > +      Int8This = Builder.CreateBitCast(getThisValue(CGF),<br>
>> > +                                       CGF.Int8Ty->getPointerTo(AS));<br>
>> > +    llvm::Value *VtorDispPtr = Builder.CreateInBoundsGEP(Int8This,<br>
>> > VBaseOffset);<br>
>> > +    // vtorDisp is always the 32-bits before the vbase in the class<br>
>> > layout.<br>
>> > +    VtorDispPtr = Builder.CreateConstGEP1_32(VtorDispPtr, -4);<br>
>><br>
>> After investigating some other tests, I'm pretty sure the "-4"<br>
>> vtordisp offset is not constant but rather might have a different<br>
>> value for more complex record layouts.<br>
>><br>
>> Warren, do you have any insight to share on the vtordisp location in a<br>
>> record layout?<br>
>><br>
>> > +    VtorDispPtr = Builder.CreateBitCast(<br>
>> > +        VtorDispPtr, CGF.Int32Ty->getPointerTo(AS), "vtordisp.ptr");<br>
>> > +<br>
>> > +    Builder.CreateStore(VtorDispValue, VtorDispPtr);<br>
>> > +  }<br>
>> > +}<br>
>> > +<br>
>> >  void MicrosoftCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D)<br>
>> > {<br>
>> >    // There's only one constructor type in this ABI.<br>
>> >    CGM.EmitGlobal(GlobalDecl(D, Ctor_Complete));<br>
>> ><br>
><br>
><br>
</div></div></blockquote></div><br></div>