[cfe-commits] r95066 - in /cfe/trunk: lib/CodeGen/CGExprConstant.cpp lib/CodeGen/CGRecordLayoutBuilder.cpp lib/CodeGen/CGRecordLayoutBuilder.h lib/CodeGen/CodeGenTypes.h test/CodeGenCXX/pointers-to-data-members.cpp

Anders Carlsson andersca at mac.com
Mon Feb 1 21:17:39 PST 2010


Author: andersca
Date: Mon Feb  1 23:17:25 2010
New Revision: 95066

URL: http://llvm.org/viewvc/llvm-project?rev=95066&view=rev
Log:
Improve handling of emitting 'null' pointers to data members.

Modified:
    cfe/trunk/lib/CodeGen/CGExprConstant.cpp
    cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp
    cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.h
    cfe/trunk/lib/CodeGen/CodeGenTypes.h
    cfe/trunk/test/CodeGenCXX/pointers-to-data-members.cpp

Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=95066&r1=95065&r2=95066&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Mon Feb  1 23:17:25 2010
@@ -911,7 +911,24 @@
   return C;
 }
 
-static inline bool isDataMemberPointerType(QualType T) {
+static bool containsPointerToDataMember(CodeGenTypes &Types, QualType T) {
+  // No need to check for member pointers when not compiling C++.
+  if (!Types.getContext().getLangOptions().CPlusPlus)
+    return false;
+  
+  T = Types.getContext().getBaseElementType(T);
+  
+  if (const RecordType *RT = T->getAs<RecordType>()) {
+    const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+    
+    // FIXME: It would be better if there was a way to explicitly compute the
+    // record layout instead of converting to a type.
+    Types.ConvertTagDeclType(RD);
+    
+    const CGRecordLayout &Layout = Types.getCGRecordLayout(RD);
+    return Layout.containsPointerToDataMember();
+  }
+    
   if (const MemberPointerType *MPT = T->getAs<MemberPointerType>())
     return !MPT->getPointeeType()->isFunctionType();
   
@@ -919,45 +936,58 @@
 }
 
 llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) {
-  // No need to check for member pointers when not compiling C++.
-  if (!getContext().getLangOptions().CPlusPlus)
+  if (!containsPointerToDataMember(getTypes(), T))
     return llvm::Constant::getNullValue(getTypes().ConvertTypeForMem(T));
-
+    
   if (const ConstantArrayType *CAT = Context.getAsConstantArrayType(T)) {
 
     QualType ElementTy = CAT->getElementType();
 
-    // FIXME: Handle arrays of structs that contain member pointers.
-    if (isDataMemberPointerType(Context.getBaseElementType(ElementTy))) {
-      llvm::Constant *Element = EmitNullConstant(ElementTy);
-      uint64_t NumElements = CAT->getSize().getZExtValue();
-      std::vector<llvm::Constant *> Array(NumElements);
-      for (uint64_t i = 0; i != NumElements; ++i)
-        Array[i] = Element;
-
-      const llvm::ArrayType *ATy =
-        cast<llvm::ArrayType>(getTypes().ConvertTypeForMem(T));
-      return llvm::ConstantArray::get(ATy, Array);
-    }
+    llvm::Constant *Element = EmitNullConstant(ElementTy);
+    unsigned NumElements = CAT->getSize().getZExtValue();
+    std::vector<llvm::Constant *> Array(NumElements);
+    for (unsigned i = 0; i != NumElements; ++i)
+      Array[i] = Element;
+
+    const llvm::ArrayType *ATy =
+      cast<llvm::ArrayType>(getTypes().ConvertTypeForMem(T));
+    return llvm::ConstantArray::get(ATy, Array);
   }
 
   if (const RecordType *RT = T->getAs<RecordType>()) {
-    const RecordDecl *RD = RT->getDecl();
-    // FIXME: It would be better if there was a way to explicitly compute the
-    // record layout instead of converting to a type.
-    Types.ConvertTagDeclType(RD);
-
-    const CGRecordLayout &Layout = Types.getCGRecordLayout(RD);
-    if (Layout.containsMemberPointer()) {
-      assert(0 && "FIXME: No support for structs with member pointers yet!");
+    const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+    assert(!RD->getNumBases() && 
+           "FIXME: Handle zero-initializing structs with bases and "
+           "pointers to data members.");
+    const llvm::StructType *STy =
+      cast<llvm::StructType>(getTypes().ConvertTypeForMem(T));
+    unsigned NumElements = STy->getNumElements();
+    std::vector<llvm::Constant *> Elements(NumElements);
+
+    for (RecordDecl::field_iterator I = RD->field_begin(),
+         E = RD->field_end(); I != E; ++I) {
+      const FieldDecl *FD = *I;
+      
+      unsigned FieldNo = getTypes().getLLVMFieldNo(FD);
+      Elements[FieldNo] = EmitNullConstant(FD->getType());
+    }
+    
+    // Now go through all other fields and zero them out.
+    for (unsigned i = 0; i != NumElements; ++i) {
+      if (!Elements[i])
+        Elements[i] = llvm::Constant::getNullValue(STy->getElementType(i));
     }
+    
+    return llvm::ConstantStruct::get(STy, Elements);
   }
 
-  // FIXME: Handle structs that contain member pointers.
-  if (isDataMemberPointerType(T))
-    return llvm::Constant::getAllOnesValue(getTypes().ConvertTypeForMem(T));
-
-  return llvm::Constant::getNullValue(getTypes().ConvertTypeForMem(T));
+  assert(!T->getAs<MemberPointerType>()->getPointeeType()->isFunctionType() &&
+         "Should only see pointers to data members here!");
+  
+  // Itanium C++ ABI 2.3:
+  //   A NULL pointer is represented as -1.
+  return llvm::ConstantInt::get(getTypes().ConvertTypeForMem(T), -1, 
+                                /*isSigned=*/true);
 }
 
 llvm::Constant *

Modified: cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp?rev=95066&r1=95065&r2=95066&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp Mon Feb  1 23:17:25 2010
@@ -108,6 +108,9 @@
     return true;
   }
 
+  // Check if we have a pointer to data member in this field.
+  CheckForPointerToDataMember(D->getType());
+  
   assert(FieldOffset % 8 == 0 && "FieldOffset is not on a byte boundary!");
   uint64_t FieldOffsetInBytes = FieldOffset / 8;
 
@@ -338,23 +341,34 @@
   return Types.getTargetData().getTypeAllocSize(Ty);
 }
 
-void CGRecordLayoutBuilder::CheckForMemberPointer(const FieldDecl *FD) {
+void CGRecordLayoutBuilder::CheckForPointerToDataMember(QualType T) {
   // This record already contains a member pointer.
-  if (ContainsMemberPointer)
+  if (ContainsPointerToDataMember)
     return;
 
   // Can only have member pointers if we're compiling C++.
   if (!Types.getContext().getLangOptions().CPlusPlus)
     return;
 
-  QualType Ty = FD->getType();
-
-  if (Ty->isMemberPointerType()) {
-    // We have a member pointer!
-    ContainsMemberPointer = true;
-    return;
-  }
+  T = Types.getContext().getBaseElementType(T);
 
+  if (const MemberPointerType *MPT = T->getAs<MemberPointerType>()) {
+    if (!MPT->getPointeeType()->isFunctionType()) {
+      // We have a pointer to data member.
+      ContainsPointerToDataMember = true;
+    }
+  } else if (const RecordType *RT = T->getAs<RecordType>()) {
+    const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+    
+    // FIXME: It would be better if there was a way to explicitly compute the
+    // record layout instead of converting to a type.
+    Types.ConvertTagDeclType(RD);
+    
+    const CGRecordLayout &Layout = Types.getCGRecordLayout(RD);
+    
+    if (Layout.containsPointerToDataMember())
+      ContainsPointerToDataMember = true;
+  }    
 }
 
 CGRecordLayout *
@@ -386,5 +400,5 @@
     Types.addBitFieldInfo(Info.FD, Info.FieldNo, Info.Start, Info.Size);
   }
 
-  return new CGRecordLayout(Ty, Builder.ContainsMemberPointer);
+  return new CGRecordLayout(Ty, Builder.ContainsPointerToDataMember);
 }

Modified: cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.h?rev=95066&r1=95065&r2=95066&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.h (original)
+++ cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.h Mon Feb  1 23:17:25 2010
@@ -27,6 +27,7 @@
   class CXXRecordDecl;
   class FieldDecl;
   class RecordDecl;
+  class QualType;
 
 namespace CodeGen {
   class CGRecordLayout;
@@ -38,9 +39,10 @@
   /// Packed - Whether the resulting LLVM struct will be packed or not.
   bool Packed;
 
-  /// ContainsMemberPointer - Whether one of the fields is a member pointer
-  /// or is a struct that contains a member pointer.
-  bool ContainsMemberPointer;
+  /// ContainsPointerToDataMember - Whether one of the fields in this record 
+  /// layout is a pointer to data member, or a struct that contains pointer to
+  /// data member.
+  bool ContainsPointerToDataMember;
 
   /// Alignment - Contains the alignment of the RecordDecl.
   unsigned Alignment;
@@ -78,7 +80,7 @@
   llvm::SmallVector<LLVMBitFieldInfo, 16> LLVMBitFields;
 
   CGRecordLayoutBuilder(CodeGenTypes &Types)
-    : Types(Types), Packed(false), ContainsMemberPointer(false)
+    : Types(Types), Packed(false), ContainsPointerToDataMember(false)
     , Alignment(0), AlignmentAsLLVMStruct(1)
     , BitsAvailableInLastField(0), NextFieldOffsetInBytes(0) { }
 
@@ -123,8 +125,9 @@
   unsigned getTypeAlignment(const llvm::Type *Ty) const;
   uint64_t getTypeSizeInBytes(const llvm::Type *Ty) const;
 
-  /// CheckForMemberPointer - Check if the field contains a member pointer.
-  void CheckForMemberPointer(const FieldDecl *FD);
+  /// CheckForPointerToDataMember - Check if the given type contains a pointer 
+  /// to data member.
+  void CheckForPointerToDataMember(QualType T);
 
 public:
   /// ComputeLayout - Return the right record layout for a given record decl.

Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.h?rev=95066&r1=95065&r2=95066&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenTypes.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenTypes.h Mon Feb  1 23:17:25 2010
@@ -60,21 +60,24 @@
     /// LLVMType - The LLVMType corresponding to this record layout.
     const llvm::Type *LLVMType;
 
-    /// ContainsMemberPointer - Whether one of the fields in this record layout
-    /// is a member pointer, or a struct that contains a member pointer.
-    bool ContainsMemberPointer;
+    /// ContainsPointerToDataMember - Whether one of the fields in this record 
+    /// layout is a pointer to data member, or a struct that contains pointer to
+    /// data member.
+    bool ContainsPointerToDataMember;
 
   public:
-    CGRecordLayout(const llvm::Type *T, bool ContainsMemberPointer)
-      : LLVMType(T), ContainsMemberPointer(ContainsMemberPointer) { }
+    CGRecordLayout(const llvm::Type *T, bool ContainsPointerToDataMember)
+      : LLVMType(T), ContainsPointerToDataMember(ContainsPointerToDataMember) { }
 
     /// getLLVMType - Return llvm type associated with this record.
     const llvm::Type *getLLVMType() const {
       return LLVMType;
     }
 
-    bool containsMemberPointer() const {
-      return ContainsMemberPointer;
+    /// containsPointerToDataMember - Whether this struct contains pointers to
+    /// data members.
+    bool containsPointerToDataMember() const {
+      return ContainsPointerToDataMember;
     }
   };
 

Modified: cfe/trunk/test/CodeGenCXX/pointers-to-data-members.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/pointers-to-data-members.cpp?rev=95066&r1=95065&r2=95066&view=diff

==============================================================================
--- cfe/trunk/test/CodeGenCXX/pointers-to-data-members.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/pointers-to-data-members.cpp Mon Feb  1 23:17:25 2010
@@ -17,6 +17,23 @@
   
   // CHECK: @_ZN8ZeroInit1bE = global i64 -1,
   int A::* b = 0;
+
+  // CHECK: @_ZN8ZeroInit2saE = global %struct.anon { i64 -1 }
+  struct {
+    int A::*a;
+  } sa;
+  
+  // CHECK: @_ZN8ZeroInit3ssaE = global [2 x %0] [%0 { [2 x i64] [i64 -1, i64 -1] }
+  struct {
+    int A::*aa[2];
+  } ssa[2];
+  
+  // CHECK: @_ZN8ZeroInit2ssE = global %1 { %struct.anon { i64 -1 } }
+  struct {
+    struct {
+      int A::*pa;
+    } s;
+  } ss;
 }
 
 // PR5674





More information about the cfe-commits mailing list