r240453 - [MS ABI] Account for the virtual inheritance quirk when mangling

David Majnemer david.majnemer at gmail.com
Tue Jun 23 13:34:18 PDT 2015


Author: majnemer
Date: Tue Jun 23 15:34:18 2015
New Revision: 240453

URL: http://llvm.org/viewvc/llvm-project?rev=240453&view=rev
Log:
[MS ABI] Account for the virtual inheritance quirk when mangling

Virtual inheritance member pointers are always relative to the vbindex,
even when the member pointer doesn't point into a virtual base.  This is
corrected by adjusting the non-virtual offset backwards from the vbptr
back to the top of the most derived class.  While we performed this
adjustment when manifesting member pointers as constants or when
performing conversions, we didn't perform the adjustment when mangling
them.

Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/MicrosoftMangle.cpp
    cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
    cfe/trunk/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=240453&r1=240452&r2=240453&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Tue Jun 23 15:34:18 2015
@@ -1780,6 +1780,17 @@ public:
   /// \param method should be the declaration from the class definition
   void setNonKeyFunction(const CXXMethodDecl *method);
 
+  /// Loading virtual member pointers using the virtual inheritance model
+  /// always results in an adjustment using the vbtable even if the index is
+  /// zero.
+  ///
+  /// This is usually OK because the first slot in the vbtable points
+  /// backwards to the top of the MDC.  However, the MDC might be reusing a
+  /// vbptr from an nv-base.  In this case, the first slot in the vbtable
+  /// points to the start of the nv-base which introduced the vbptr and *not*
+  /// the MDC.  Modify the NonVirtualBaseAdjustment to account for this.
+  CharUnits getOffsetOfBaseWithVBPtr(const CXXRecordDecl *RD) const;
+
   /// Get the offset of a FieldDecl or IndirectFieldDecl, in bits.
   uint64_t getFieldOffset(const ValueDecl *FD) const;
 

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=240453&r1=240452&r2=240453&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Tue Jun 23 15:34:18 2015
@@ -1866,6 +1866,16 @@ CharUnits ASTContext::getAlignOfGlobalVa
   return toCharUnitsFromBits(getAlignOfGlobalVar(T));
 }
 
+CharUnits ASTContext::getOffsetOfBaseWithVBPtr(const CXXRecordDecl *RD) const {
+  CharUnits Offset = CharUnits::Zero();
+  const ASTRecordLayout *Layout = &getASTRecordLayout(RD);
+  while (const CXXRecordDecl *Base = Layout->getBaseSharingVBPtr()) {
+    Offset += Layout->getBaseClassOffset(Base);
+    Layout = &getASTRecordLayout(Base);
+  }
+  return Offset;
+}
+
 /// DeepCollectObjCIvars -
 /// This routine first collects all declared, but not synthesized, ivars in
 /// super class and then collects all ivars, including those synthesized for

Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=240453&r1=240452&r2=240453&view=diff
==============================================================================
--- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)
+++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Tue Jun 23 15:34:18 2015
@@ -502,6 +502,9 @@ void MicrosoftCXXNameMangler::mangleMemb
     FieldOffset /= getASTContext().getCharWidth();
 
     VBTableOffset = 0;
+
+    if (IM == MSInheritanceAttr::Keyword_virtual_inheritance)
+      FieldOffset -= getASTContext().getOffsetOfBaseWithVBPtr(RD).getQuantity();
   } else {
     FieldOffset = RD->nullFieldOffsetIsZero() ? 0 : -1;
 
@@ -570,6 +573,10 @@ MicrosoftCXXNameMangler::mangleMemberFun
       mangleName(MD);
       mangleFunctionEncoding(MD, /*ShouldMangle=*/true);
     }
+
+    if (VBTableOffset == 0 &&
+        IM == MSInheritanceAttr::Keyword_virtual_inheritance)
+      NVOffset -= getASTContext().getOffsetOfBaseWithVBPtr(RD).getQuantity();
   } else {
     // Null single inheritance member functions are encoded as a simple nullptr.
     if (IM == MSInheritanceAttr::Keyword_single_inheritance) {
@@ -582,7 +589,7 @@ MicrosoftCXXNameMangler::mangleMemberFun
   }
 
   if (MSInheritanceAttr::hasNVOffsetField(/*IsMemberFunction=*/true, IM))
-    mangleNumber(NVOffset);
+    mangleNumber(static_cast<uint32_t>(NVOffset));
   if (MSInheritanceAttr::hasVBPtrOffsetField(IM))
     mangleNumber(VBPtrOffset);
   if (MSInheritanceAttr::hasVBTableOffsetField(IM))

Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=240453&r1=240452&r2=240453&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Tue Jun 23 15:34:18 2015
@@ -2514,33 +2514,13 @@ MicrosoftCXXABI::EmitFullMemberPointer(l
   return llvm::ConstantStruct::getAnon(fields);
 }
 
-// Loading virtual member pointers using the virtual inheritance model
-// always results in an adjustment using the vbtable even if the index is
-// zero.
-//
-// This is usually OK because the first slot in the vbtable points
-// backwards to the top of the MDC.  However, the MDC might be reusing a
-// vbptr from an nv-base.  In this case, the first slot in the vbtable
-// points to the start of the nv-base which introduced the vbptr and *not*
-// the MDC.  Modify the NonVirtualBaseAdjustment to account for this.
-static CharUnits computeOffsetOfBaseWithVBPtr(const ASTContext &Ctx,
-                                              const CXXRecordDecl *RD) {
-  CharUnits Offset = CharUnits::Zero();
-  const ASTRecordLayout *Layout = &Ctx.getASTRecordLayout(RD);
-  while (const CXXRecordDecl *Base = Layout->getBaseSharingVBPtr()) {
-    Offset += Layout->getBaseClassOffset(Base);
-    Layout = &Ctx.getASTRecordLayout(Base);
-  }
-  return Offset;
-}
-
 llvm::Constant *
 MicrosoftCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
                                        CharUnits offset) {
   const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
   if (RD->getMSInheritanceModel() ==
       MSInheritanceAttr::Keyword_virtual_inheritance)
-    offset -= computeOffsetOfBaseWithVBPtr(getContext(), RD);
+    offset -= getContext().getOffsetOfBaseWithVBPtr(RD);
   llvm::Constant *FirstField =
     llvm::ConstantInt::get(CGM.IntTy, offset.getQuantity());
   return EmitFullMemberPointer(FirstField, /*IsMemberFunction=*/false, RD,
@@ -2639,7 +2619,7 @@ MicrosoftCXXABI::EmitMemberFunctionPoint
   if (VBTableIndex == 0 &&
       RD->getMSInheritanceModel() ==
           MSInheritanceAttr::Keyword_virtual_inheritance)
-    NonVirtualBaseAdjustment -= computeOffsetOfBaseWithVBPtr(getContext(), RD);
+    NonVirtualBaseAdjustment -= getContext().getOffsetOfBaseWithVBPtr(RD);
 
   // The rest of the fields are common with data member pointers.
   FirstField = llvm::ConstantExpr::getBitCast(FirstField, CGM.VoidPtrTy);
@@ -2987,7 +2967,7 @@ MicrosoftCXXABI::EmitMemberPointerConver
       Builder.CreateICmpEQ(VirtualBaseAdjustmentOffset, getZeroInt());
   if (SrcInheritance == MSInheritanceAttr::Keyword_virtual_inheritance) {
     if (int64_t SrcOffsetToFirstVBase =
-            computeOffsetOfBaseWithVBPtr(getContext(), SrcRD).getQuantity()) {
+            getContext().getOffsetOfBaseWithVBPtr(SrcRD).getQuantity()) {
       llvm::Value *UndoSrcAdjustment = Builder.CreateSelect(
           SrcVBIndexEqZero,
           llvm::ConstantInt::get(CGM.IntTy, SrcOffsetToFirstVBase),
@@ -3049,7 +3029,7 @@ MicrosoftCXXABI::EmitMemberPointerConver
   // virtual base and the top of the MDC.
   if (DstInheritance == MSInheritanceAttr::Keyword_virtual_inheritance) {
     if (int64_t DstOffsetToFirstVBase =
-            computeOffsetOfBaseWithVBPtr(getContext(), DstRD).getQuantity()) {
+            getContext().getOffsetOfBaseWithVBPtr(DstRD).getQuantity()) {
       llvm::Value *DoDstAdjustment = Builder.CreateSelect(
           DstVBIndexEqZero,
           llvm::ConstantInt::get(CGM.IntTy, DstOffsetToFirstVBase),
@@ -3155,8 +3135,7 @@ llvm::Constant *MicrosoftCXXABI::EmitMem
       llvm::ICmpInst::ICMP_EQ, VirtualBaseAdjustmentOffset, getZeroInt());
   if (SrcInheritance == MSInheritanceAttr::Keyword_virtual_inheritance) {
     llvm::Constant *SrcOffsetToFirstVBase = llvm::ConstantInt::get(
-        CGM.IntTy,
-        computeOffsetOfBaseWithVBPtr(getContext(), SrcRD).getQuantity());
+        CGM.IntTy, getContext().getOffsetOfBaseWithVBPtr(SrcRD).getQuantity());
     llvm::Constant *UndoSrcAdjustment = llvm::ConstantExpr::getSelect(
         SrcVBIndexEqZero, SrcOffsetToFirstVBase, getZeroInt());
     NVAdjustField =
@@ -3219,8 +3198,7 @@ llvm::Constant *MicrosoftCXXABI::EmitMem
   // virtual base and the top of the MDC.
   if (DstInheritance == MSInheritanceAttr::Keyword_virtual_inheritance) {
     llvm::Constant *DstOffsetToFirstVBase = llvm::ConstantInt::get(
-        CGM.IntTy,
-        computeOffsetOfBaseWithVBPtr(getContext(), DstRD).getQuantity());
+        CGM.IntTy, getContext().getOffsetOfBaseWithVBPtr(DstRD).getQuantity());
     llvm::Constant *DoDstAdjustment = llvm::ConstantExpr::getSelect(
         DstVBIndexEqZero, DstOffsetToFirstVBase, getZeroInt());
     NVAdjustField =

Modified: cfe/trunk/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp?rev=240453&r1=240452&r2=240453&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp Tue Jun 23 15:34:18 2015
@@ -141,3 +141,15 @@ void CallMethods() {
 // CHECK: call {{.*}} @"\01??$CallMethod at UM@@$0A@@@YAXAAUM@@@Z"
 // CHECK: call {{.*}} @"\01??$CallMethod at UV@@$0A@@@YAXAAUV@@@Z"
 // CHECK: call {{.*}} @"\01??$CallMethod at UU@@$0A@@@YAXAAUU@@@Z"
+
+namespace NegativeNVOffset {
+struct A {};
+struct B : virtual A {};
+struct C : B {
+  virtual void f();
+};
+}
+
+template void CallMethod<NegativeNVOffset::C, &NegativeNVOffset::C::f>(NegativeNVOffset::C &);
+
+// CHECK-LABEL: define {{.*}} @"\01??$CallMethod at UC@NegativeNVOffset@@$I??_912@$BA at AEPPPPPPPM@A@@@YAXAAUC at NegativeNVOffset@@@Z"





More information about the cfe-commits mailing list