r201835 - MS ABI: Include the vfptr offset in memptrs to virtual methods

Reid Kleckner reid at kleckner.net
Thu Feb 20 18:27:32 PST 2014


Author: rnk
Date: Thu Feb 20 20:27:32 2014
New Revision: 201835

URL: http://llvm.org/viewvc/llvm-project?rev=201835&view=rev
Log:
MS ABI: Include the vfptr offset in memptrs to virtual methods

Virtual methods expect 'this' to point to the vfptr containing the
virtual method, and this extends to virtual member pointer thunks.  The
relevant vfptr is always at offset zero on entry to the thunk, and no
this adjustment is needed.

Previously we would not include the vfptr adjustment in the member
pointer, and we'd look at the vfptr offset when loading from the vftable
in the thunk.

Fixes PR18917.

Modified:
    cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
    cfe/trunk/test/CodeGenCXX/microsoft-abi-member-pointers.cpp

Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=201835&r1=201834&r2=201835&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Thu Feb 20 20:27:32 2014
@@ -328,8 +328,9 @@ private:
   const VBTableGlobals &enumerateVBTables(const CXXRecordDecl *RD);
 
   /// \brief Generate a thunk for calling a virtual member function MD.
-  llvm::Function *EmitVirtualMemPtrThunk(const CXXMethodDecl *MD,
-                                         StringRef ThunkName);
+  llvm::Function *EmitVirtualMemPtrThunk(
+      const CXXMethodDecl *MD,
+      const MicrosoftVTableContext::MethodVFTableLocation &ML);
 
 public:
   virtual llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT);
@@ -1015,9 +1016,15 @@ MicrosoftCXXABI::enumerateVBTables(const
   return VBGlobals;
 }
 
-llvm::Function *
-MicrosoftCXXABI::EmitVirtualMemPtrThunk(const CXXMethodDecl *MD,
-                                        StringRef ThunkName) {
+llvm::Function *MicrosoftCXXABI::EmitVirtualMemPtrThunk(
+    const CXXMethodDecl *MD,
+    const MicrosoftVTableContext::MethodVFTableLocation &ML) {
+  // Calculate the mangled name.
+  SmallString<256> ThunkName;
+  llvm::raw_svector_ostream Out(ThunkName);
+  getMangleContext().mangleVirtualMemPtrThunk(MD, Out);
+  Out.flush();
+
   // If the thunk has been generated previously, just return it.
   if (llvm::GlobalValue *GV = CGM.getModule().getNamedValue(ThunkName))
     return cast<llvm::Function>(GV);
@@ -1041,9 +1048,14 @@ MicrosoftCXXABI::EmitVirtualMemPtrThunk(
   CodeGenFunction CGF(CGM);
   CGF.StartThunk(ThunkFn, MD, FnInfo);
 
-  // Get to the Callee.
+  // Load the vfptr and then callee from the vftable.  The callee should have
+  // adjusted 'this' so that the vfptr is at offset zero.
   llvm::Value *This = CGF.LoadCXXThis();
-  llvm::Value *Callee = getVirtualFunctionPointer(CGF, MD, This, ThunkTy);
+  llvm::Value *VTable =
+      CGF.GetVTablePtr(This, ThunkTy->getPointerTo()->getPointerTo());
+  llvm::Value *VFuncPtr =
+      CGF.Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn");
+  llvm::Value *Callee = CGF.Builder.CreateLoad(VFuncPtr);
 
   // Make the call and return the result.
   CGF.EmitCallAndReturnForThunk(MD, Callee, 0);
@@ -1523,13 +1535,10 @@ MicrosoftCXXABI::BuildMemberPointer(cons
                                "member function in virtual base class");
       FirstField = llvm::Constant::getNullValue(CGM.VoidPtrTy);
     } else {
-      SmallString<256> ThunkName;
-      llvm::raw_svector_ostream Out(ThunkName);
-      getMangleContext().mangleVirtualMemPtrThunk(MD, Out);
-      Out.flush();
-
-      llvm::Function *Thunk = EmitVirtualMemPtrThunk(MD, ThunkName.str());
+      llvm::Function *Thunk = EmitVirtualMemPtrThunk(MD, ML);
       FirstField = llvm::ConstantExpr::getBitCast(Thunk, CGM.VoidPtrTy);
+      // Include the vfptr adjustment if the method is in a non-primary vftable.
+      NonVirtualBaseAdjustment += ML.VFPtrOffset;
     }
   }
 

Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-member-pointers.cpp?rev=201835&r1=201834&r2=201835&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/microsoft-abi-member-pointers.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/microsoft-abi-member-pointers.cpp Thu Feb 20 20:27:32 2014
@@ -560,6 +560,29 @@ int *load_data(A *a, int A::*mp) {
 }
 
 }
+
+namespace Test4 {
+
+struct A        { virtual void f(); };
+struct B        { virtual void g(); };
+struct C : A, B { virtual void g(); };
+
+void (C::*getmp())() {
+  return &C::g;
+}
+// CHECK-LABEL: define i64 @"\01?getmp at Test4@@YAP8C at 1@AEXXZXZ"()
+// CHECK: store { i8*, i32 } { i8* bitcast (void (i8*)* @"\01??_9C at Test4@@$BA at AE" to i8*), i32 4 }, { i8*, i32 }* %{{.*}}
+//
+
+// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C at Test4@@$BA at AE"(i8*)
+// CHECK-NOT:  getelementptr
+// CHECK:  load void (i8*)*** %{{.*}}
+// CHECK:  getelementptr inbounds void (i8*)** %{{.*}}, i64 0
+// CHECK-NOT:  getelementptr
+// CHECK:  call x86_thiscallcc void %
+
+}
+
 #else
 struct __virtual_inheritance A;
 #ifdef MEMFUN





More information about the cfe-commits mailing list