[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