r177753 - [ms-cxxabi] Implement member data pointers for non-dynamic classes

Reid Kleckner reid at kleckner.net
Fri Mar 22 12:02:54 PDT 2013


Author: rnk
Date: Fri Mar 22 14:02:54 2013
New Revision: 177753

URL: http://llvm.org/viewvc/llvm-project?rev=177753&view=rev
Log:
[ms-cxxabi] Implement member data pointers for non-dynamic classes

Summary:
For non-dynamic classes (no virtual bases), member data pointers are
simple offsets from the base of the record.  Dynamic classes use an
aggregate for member data pointers and are therefore currently
unsupported.

Unlike Itanium, the ms ABI uses 0 to represent null for polymorphic
classes.  Non-polymorphic classes use -1 like Itanium, since 0 is a
valid field offset.

Reviewers: rjmccall

CC: timurrrr, cfe-commits

Differential Revision: http://llvm-reviews.chandlerc.com/D558

Added:
    cfe/trunk/test/CodeGenCXX/microsoft-abi-member-pointers.cpp   (with props)
Modified:
    cfe/trunk/lib/CodeGen/CGCXXABI.cpp
    cfe/trunk/lib/CodeGen/CGCXXABI.h
    cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp

Modified: cfe/trunk/lib/CodeGen/CGCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.cpp?rev=177753&r1=177752&r2=177753&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.cpp Fri Mar 22 14:02:54 2013
@@ -19,8 +19,7 @@ using namespace CodeGen;
 
 CGCXXABI::~CGCXXABI() { }
 
-static void ErrorUnsupportedABI(CodeGenFunction &CGF,
-                                StringRef S) {
+void CGCXXABI::ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S) {
   DiagnosticsEngine &Diags = CGF.CGM.getDiags();
   unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
                                           "cannot yet compile %0 in this ABI");
@@ -29,8 +28,7 @@ static void ErrorUnsupportedABI(CodeGenF
     << S;
 }
 
-static llvm::Constant *GetBogusMemberPointer(CodeGenModule &CGM,
-                                             QualType T) {
+llvm::Constant *CGCXXABI::GetBogusMemberPointer(QualType T) {
   return llvm::Constant::getNullValue(CGM.getTypes().ConvertType(T));
 }
 
@@ -67,12 +65,12 @@ llvm::Value *CGCXXABI::EmitMemberPointer
                                                    const CastExpr *E,
                                                    llvm::Value *Src) {
   ErrorUnsupportedABI(CGF, "member function pointer conversions");
-  return GetBogusMemberPointer(CGM, E->getType());
+  return GetBogusMemberPointer(E->getType());
 }
 
 llvm::Constant *CGCXXABI::EmitMemberPointerConversion(const CastExpr *E,
                                                       llvm::Constant *Src) {
-  return GetBogusMemberPointer(CGM, E->getType());
+  return GetBogusMemberPointer(E->getType());
 }
 
 llvm::Value *
@@ -95,22 +93,22 @@ CGCXXABI::EmitMemberPointerIsNotNull(Cod
 
 llvm::Constant *
 CGCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
-  return GetBogusMemberPointer(CGM, QualType(MPT, 0));
+  return GetBogusMemberPointer(QualType(MPT, 0));
 }
 
 llvm::Constant *CGCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
-  return GetBogusMemberPointer(CGM,
+  return GetBogusMemberPointer(
                          CGM.getContext().getMemberPointerType(MD->getType(),
                                          MD->getParent()->getTypeForDecl()));
 }
 
 llvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
                                                 CharUnits offset) {
-  return GetBogusMemberPointer(CGM, QualType(MPT, 0));
+  return GetBogusMemberPointer(QualType(MPT, 0));
 }
 
 llvm::Constant *CGCXXABI::EmitMemberPointer(const APValue &MP, QualType MPT) {
-  return GetBogusMemberPointer(CGM, MPT);
+  return GetBogusMemberPointer(MPT);
 }
 
 bool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) {

Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=177753&r1=177752&r2=177753&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.h Fri Mar 22 14:02:54 2013
@@ -54,6 +54,12 @@ protected:
     return CGF.CXXABIThisValue;
   }
 
+  /// Issue a diagnostic about unsupported features in the ABI.
+  void ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S);
+
+  /// Get a null value for unsupported member pointers.
+  llvm::Constant *GetBogusMemberPointer(QualType T);
+
   // FIXME: Every place that calls getVTT{Decl,Value} is something
   // that needs to be abstracted properly.
   ImplicitParamDecl *&getVTTDecl(CodeGenFunction &CGF) {

Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=177753&r1=177752&r2=177753&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Fri Mar 22 14:02:54 2013
@@ -109,6 +109,33 @@ public:
                                    llvm::Value *allocPtr,
                                    CharUnits cookieSize);
   static bool needThisReturn(GlobalDecl GD);
+
+private:
+  llvm::Constant *getSimpleNullMemberPointer(const MemberPointerType *MPT);
+
+  llvm::Constant *getZeroPtrDiff() {
+    return llvm::ConstantInt::get(CGM.PtrDiffTy, 0);
+  }
+
+  llvm::Constant *getAllOnesPtrDiff() {
+    return  llvm::Constant::getAllOnesValue(CGM.PtrDiffTy);
+  }
+
+public:
+  virtual llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT);
+
+  virtual llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
+                                                CharUnits offset);
+
+  virtual llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
+                                                  llvm::Value *MemPtr,
+                                                  const MemberPointerType *MPT);
+
+  virtual llvm::Value *EmitMemberDataPointerAddress(CodeGenFunction &CGF,
+                                                    llvm::Value *Base,
+                                                    llvm::Value *MemPtr,
+                                                  const MemberPointerType *MPT);
+
 };
 
 }
@@ -352,6 +379,95 @@ void MicrosoftCXXABI::EmitGuardedInit(Co
   CGF.EmitCXXGlobalVarDeclInit(D, DeclPtr, PerformInit);
 }
 
+// Returns true for member pointer types that we know how to represent with a
+// simple ptrdiff_t.  Currently we only know how to emit, test, and load member
+// data pointers for complete single inheritance classes.
+static bool isSimpleMemberPointer(const MemberPointerType *MPT) {
+  const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
+  return (MPT->isMemberDataPointer() &&
+          !MPT->getClass()->isIncompleteType() &&
+          RD->getNumVBases() == 0);
+}
+
+llvm::Constant *
+MicrosoftCXXABI::getSimpleNullMemberPointer(const MemberPointerType *MPT) {
+  if (isSimpleMemberPointer(MPT)) {
+    const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
+    // A null member data pointer is represented as -1 if the class is not
+    // polymorphic, and 0 otherwise.
+    if (RD->isPolymorphic())
+      return getZeroPtrDiff();
+    return getAllOnesPtrDiff();
+  }
+  return GetBogusMemberPointer(QualType(MPT, 0));
+}
+
+llvm::Constant *
+MicrosoftCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
+  if (isSimpleMemberPointer(MPT))
+    return getSimpleNullMemberPointer(MPT);
+  // FIXME: Implement function member pointers.
+  return GetBogusMemberPointer(QualType(MPT, 0));
+}
+
+llvm::Constant *
+MicrosoftCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
+                                       CharUnits offset) {
+  // Member data pointers are plain offsets when no virtual bases are involved.
+  if (isSimpleMemberPointer(MPT))
+    return llvm::ConstantInt::get(CGM.PtrDiffTy, offset.getQuantity());
+  // FIXME: Implement member pointers other inheritance models.
+  return GetBogusMemberPointer(QualType(MPT, 0));
+}
+
+llvm::Value *
+MicrosoftCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
+                                            llvm::Value *MemPtr,
+                                            const MemberPointerType *MPT) {
+  CGBuilderTy &Builder = CGF.Builder;
+
+  // For member data pointers, this is just a check against -1 or 0.
+  if (isSimpleMemberPointer(MPT)) {
+    llvm::Constant *Val = getSimpleNullMemberPointer(MPT);
+    return Builder.CreateICmpNE(MemPtr, Val, "memptr.tobool");
+  }
+
+  // FIXME: Implement member pointers other inheritance models.
+  ErrorUnsupportedABI(CGF, "function member pointer tests");
+  return GetBogusMemberPointer(QualType(MPT, 0));
+}
+
+llvm::Value *
+MicrosoftCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF,
+                                              llvm::Value *Base,
+                                              llvm::Value *MemPtr,
+                                              const MemberPointerType *MPT) {
+  unsigned AS = Base->getType()->getPointerAddressSpace();
+  llvm::Type *PType =
+      CGF.ConvertTypeForMem(MPT->getPointeeType())->getPointerTo(AS);
+  CGBuilderTy &Builder = CGF.Builder;
+
+  if (MPT->isMemberFunctionPointer()) {
+    ErrorUnsupportedABI(CGF, "function member pointer address");
+    return llvm::Constant::getNullValue(PType);
+  }
+
+  llvm::Value *Addr;
+  if (isSimpleMemberPointer(MPT)) {
+    // Add the offset with GEP and i8*.
+    assert(MemPtr->getType() == CGM.PtrDiffTy);
+    Base = Builder.CreateBitCast(Base, Builder.getInt8Ty()->getPointerTo(AS));
+    Addr = Builder.CreateInBoundsGEP(Base, MemPtr, "memptr.offset");
+  } else {
+    ErrorUnsupportedABI(CGF, "non-scalar member pointers");
+    return llvm::Constant::getNullValue(PType);
+  }
+
+  // Cast the address to the appropriate pointer type, adopting the address
+  // space of the base pointer.
+  return Builder.CreateBitCast(Addr, PType);
+}
+
 CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) {
   return new MicrosoftCXXABI(CGM);
 }

Added: 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=177753&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/microsoft-abi-member-pointers.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/microsoft-abi-member-pointers.cpp Fri Mar 22 14:02:54 2013
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+
+struct POD {
+  int a;
+  int b;
+};
+
+void podMemPtrs() {
+  int POD::*memptr;
+  memptr = &POD::a;
+  memptr = &POD::b;
+  if (memptr)
+    memptr = 0;
+// Check that member pointers use the right offsets and that null is -1.
+// CHECK:      define void @"\01?podMemPtrs@@YAXXZ"() #0 {
+// CHECK:        %[[memptr:.*]] = alloca i32, align 4
+// CHECK-NEXT:   store i32 0, i32* %[[memptr]], align 4
+// CHECK-NEXT:   store i32 4, i32* %[[memptr]], align 4
+// CHECK-NEXT:   %[[memptr_val:.*]] = load i32* %[[memptr]], align 4
+// CHECK-NEXT:   %{{.*}} = icmp ne i32 %[[memptr_val]], -1
+// CHECK-NEXT:   br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
+// CHECK:        store i32 -1, i32* %[[memptr]], align 4
+// CHECK:        ret void
+// CHECK:      }
+}
+
+struct Polymorphic {
+  virtual void myVirtual();
+  int a;
+  int b;
+};
+
+void polymorphicMemPtrs() {
+  int Polymorphic::*memptr;
+  memptr = &Polymorphic::a;
+  memptr = &Polymorphic::b;
+  if (memptr)
+    memptr = 0;
+// Member pointers for polymorphic classes include the vtable slot in their
+// offset and use 0 to represent null.
+// CHECK:      define void @"\01?polymorphicMemPtrs@@YAXXZ"() #0 {
+// CHECK:        %[[memptr:.*]] = alloca i32, align 4
+// CHECK-NEXT:   store i32 4, i32* %[[memptr]], align 4
+// CHECK-NEXT:   store i32 8, i32* %[[memptr]], align 4
+// CHECK-NEXT:   %[[memptr_val:.*]] = load i32* %[[memptr]], align 4
+// CHECK-NEXT:   %{{.*}} = icmp ne i32 %[[memptr_val]], 0
+// CHECK-NEXT:   br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
+// CHECK:        store i32 0, i32* %[[memptr]], align 4
+// CHECK:        ret void
+// CHECK:      }
+}

Propchange: cfe/trunk/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
------------------------------------------------------------------------------
    svn:executable = *





More information about the cfe-commits mailing list