Go back to asking CodeGenTypes whether a type is zero-initializable.

Make CGT defer to the ABI on all member pointer types.
This requires giving CGT a handle to the ABI.
It's way easier to make that work if we avoid lazily creating the ABI.
Make it so.

llvm-svn: 111786
This commit is contained in:
John McCall 2010-08-22 21:01:12 +00:00
parent 0b84914da0
commit 614dbdcd55
13 changed files with 96 additions and 118 deletions

View File

@ -393,10 +393,7 @@ llvm::Constant *CGCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) {
MD->getParent()->getTypeForDecl())); MD->getParent()->getTypeForDecl()));
} }
bool CGCXXABI::RequiresNonZeroInitializer(QualType T) { bool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
return false; // Fake answer.
} return true;
bool CGCXXABI::RequiresNonZeroInitializer(const CXXRecordDecl *D) {
return RequiresNonZeroInitializer(QualType(D->getTypeForDecl(), 0));
} }

View File

@ -59,10 +59,10 @@ public:
// Manipulations on constant expressions. // Manipulations on constant expressions.
/// \brief Returns true if zero-initializing the given type requires /// \brief Returns true if the given member pointer can be
/// a constant other than the LLVM null value. /// zero-initialized (in the C++ sense) with an LLVM
virtual bool RequiresNonZeroInitializer(QualType T); /// zeroinitialized.
virtual bool RequiresNonZeroInitializer(const CXXRecordDecl *D); virtual bool isZeroInitializable(const MemberPointerType *MPT);
virtual llvm::Constant * virtual llvm::Constant *
EmitMemberFunctionPointerConversion(llvm::Constant *C, EmitMemberFunctionPointerConversion(llvm::Constant *C,

View File

@ -547,8 +547,7 @@ static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E,
if (!E->hasInitializer() || Ctor->getParent()->isEmpty()) if (!E->hasInitializer() || Ctor->getParent()->isEmpty())
return; return;
if (!CGF.CGM.getCXXABI().RequiresNonZeroInitializer( if (CGF.CGM.getTypes().isZeroInitializable(E->getAllocatedType())) {
E->getAllocatedType())) {
// Optimization: since zero initialization will just set the memory // Optimization: since zero initialization will just set the memory
// to all zeroes, generate a single memset to do it in one shot. // to all zeroes, generate a single memset to do it in one shot.
EmitZeroMemSet(CGF, E->getAllocatedType(), NewPtr, EmitZeroMemSet(CGF, E->getAllocatedType(), NewPtr,

View File

@ -958,8 +958,7 @@ FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T,
uint64_t StartOffset) { uint64_t StartOffset) {
assert(StartOffset % 8 == 0 && "StartOffset not byte aligned!"); assert(StartOffset % 8 == 0 && "StartOffset not byte aligned!");
if (!CGM.getLangOptions().CPlusPlus || if (CGM.getTypes().isZeroInitializable(T))
!CGM.getCXXABI().RequiresNonZeroInitializer(T))
return; return;
if (const ConstantArrayType *CAT = if (const ConstantArrayType *CAT =
@ -992,7 +991,7 @@ FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T,
continue; continue;
// Ignore bases that don't have any pointer to data members. // Ignore bases that don't have any pointer to data members.
if (!CGM.getCXXABI().RequiresNonZeroInitializer(BaseDecl)) if (CGM.getTypes().isZeroInitializable(BaseDecl))
continue; continue;
uint64_t BaseOffset = Layout.getBaseClassOffset(BaseDecl); uint64_t BaseOffset = Layout.getBaseClassOffset(BaseDecl);
@ -1006,7 +1005,7 @@ FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T,
E = RD->field_end(); I != E; ++I, ++FieldNo) { E = RD->field_end(); I != E; ++I, ++FieldNo) {
QualType FieldType = I->getType(); QualType FieldType = I->getType();
if (!CGM.getCXXABI().RequiresNonZeroInitializer(FieldType)) if (CGM.getTypes().isZeroInitializable(FieldType))
continue; continue;
uint64_t FieldOffset = StartOffset + Layout.getFieldOffset(FieldNo); uint64_t FieldOffset = StartOffset + Layout.getFieldOffset(FieldNo);
@ -1031,8 +1030,7 @@ FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T,
} }
llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) { llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) {
if (!getLangOptions().CPlusPlus || if (getTypes().isZeroInitializable(T))
!getCXXABI().RequiresNonZeroInitializer(T))
return llvm::Constant::getNullValue(getTypes().ConvertTypeForMem(T)); return llvm::Constant::getNullValue(getTypes().ConvertTypeForMem(T));
if (const ConstantArrayType *CAT = Context.getAsConstantArrayType(T)) { if (const ConstantArrayType *CAT = Context.getAsConstantArrayType(T)) {
@ -1076,7 +1074,7 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) {
continue; continue;
// Ignore bases that don't have any pointer to data members. // Ignore bases that don't have any pointer to data members.
if (!getCXXABI().RequiresNonZeroInitializer(BaseDecl)) if (getTypes().isZeroInitializable(BaseDecl))
continue; continue;
// Currently, all bases are arrays of i8. Figure out how many elements // Currently, all bases are arrays of i8. Figure out how many elements

View File

@ -174,20 +174,21 @@ private:
/// Whether one of the fields in this record layout is a pointer to data /// Whether one of the fields in this record layout is a pointer to data
/// member, or a struct that contains pointer to data member. /// member, or a struct that contains pointer to data member.
bool ContainsPointerToDataMember : 1; bool IsZeroInitializable : 1;
public: public:
CGRecordLayout(const llvm::Type *T, bool ContainsPointerToDataMember) CGRecordLayout(const llvm::Type *T, bool IsZeroInitializable)
: LLVMType(T), ContainsPointerToDataMember(ContainsPointerToDataMember) {} : LLVMType(T), IsZeroInitializable(IsZeroInitializable) {}
/// \brief Return the LLVM type associated with this record. /// \brief Return the LLVM type associated with this record.
const llvm::Type *getLLVMType() const { const llvm::Type *getLLVMType() const {
return LLVMType; return LLVMType;
} }
/// \brief Check whether this struct contains pointers to data members. /// \brief Check whether this struct can be C++ zero-initialized
bool containsPointerToDataMember() const { /// with a zeroinitializer.
return ContainsPointerToDataMember; bool isZeroInitializable() const {
return IsZeroInitializable;
} }
/// \brief Return llvm::StructType element number that corresponds to the /// \brief Return llvm::StructType element number that corresponds to the

View File

@ -18,6 +18,7 @@
#include "clang/AST/Expr.h" #include "clang/AST/Expr.h"
#include "clang/AST/RecordLayout.h" #include "clang/AST/RecordLayout.h"
#include "CodeGenTypes.h" #include "CodeGenTypes.h"
#include "CGCXXABI.h"
#include "llvm/DerivedTypes.h" #include "llvm/DerivedTypes.h"
#include "llvm/Type.h" #include "llvm/Type.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
@ -45,10 +46,9 @@ public:
typedef std::pair<const CXXRecordDecl *, unsigned> LLVMBaseInfo; typedef std::pair<const CXXRecordDecl *, unsigned> LLVMBaseInfo;
llvm::SmallVector<LLVMBaseInfo, 16> LLVMNonVirtualBases; llvm::SmallVector<LLVMBaseInfo, 16> LLVMNonVirtualBases;
/// ContainsPointerToDataMember - Whether one of the fields in this record /// IsZeroInitializable - Whether this struct can be C++
/// layout is a pointer to data member, or a struct that contains pointer to /// zero-initialized with an LLVM zeroinitializer.
/// data member. bool IsZeroInitializable;
bool ContainsPointerToDataMember;
/// Packed - Whether the resulting LLVM struct will be packed or not. /// Packed - Whether the resulting LLVM struct will be packed or not.
bool Packed; bool Packed;
@ -115,14 +115,14 @@ private:
unsigned getTypeAlignment(const llvm::Type *Ty) const; unsigned getTypeAlignment(const llvm::Type *Ty) const;
/// CheckForPointerToDataMember - Check if the given type contains a pointer /// CheckZeroInitializable - Check if the given type contains a pointer
/// to data member. /// to data member.
void CheckForPointerToDataMember(QualType T); void CheckZeroInitializable(QualType T);
void CheckForPointerToDataMember(const CXXRecordDecl *RD); void CheckZeroInitializable(const CXXRecordDecl *RD);
public: public:
CGRecordLayoutBuilder(CodeGenTypes &Types) CGRecordLayoutBuilder(CodeGenTypes &Types)
: ContainsPointerToDataMember(false), Packed(false), Types(Types), : IsZeroInitializable(true), Packed(false), Types(Types),
Alignment(0), AlignmentAsLLVMStruct(1), Alignment(0), AlignmentAsLLVMStruct(1),
BitsAvailableInLastField(0), NextFieldOffsetInBytes(0) { } BitsAvailableInLastField(0), NextFieldOffsetInBytes(0) { }
@ -311,8 +311,7 @@ bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D,
return true; return true;
} }
// Check if we have a pointer to data member in this field. CheckZeroInitializable(D->getType());
CheckForPointerToDataMember(D->getType());
assert(FieldOffset % 8 == 0 && "FieldOffset is not on a byte boundary!"); assert(FieldOffset % 8 == 0 && "FieldOffset is not on a byte boundary!");
uint64_t FieldOffsetInBytes = FieldOffset / 8; uint64_t FieldOffsetInBytes = FieldOffset / 8;
@ -458,7 +457,7 @@ void CGRecordLayoutBuilder::LayoutNonVirtualBase(const CXXRecordDecl *BaseDecl,
return; return;
} }
CheckForPointerToDataMember(BaseDecl); CheckZeroInitializable(BaseDecl);
// FIXME: Actually use a better type than [sizeof(BaseDecl) x i8] when we can. // FIXME: Actually use a better type than [sizeof(BaseDecl) x i8] when we can.
AppendPadding(BaseOffset / 8, 1); AppendPadding(BaseOffset / 8, 1);
@ -603,9 +602,9 @@ unsigned CGRecordLayoutBuilder::getTypeAlignment(const llvm::Type *Ty) const {
return Types.getTargetData().getABITypeAlignment(Ty); return Types.getTargetData().getABITypeAlignment(Ty);
} }
void CGRecordLayoutBuilder::CheckForPointerToDataMember(QualType T) { void CGRecordLayoutBuilder::CheckZeroInitializable(QualType T) {
// This record already contains a member pointer. // This record already contains a member pointer.
if (ContainsPointerToDataMember) if (!IsZeroInitializable)
return; return;
// Can only have member pointers if we're compiling C++. // Can only have member pointers if we're compiling C++.
@ -615,21 +614,17 @@ void CGRecordLayoutBuilder::CheckForPointerToDataMember(QualType T) {
T = Types.getContext().getBaseElementType(T); T = Types.getContext().getBaseElementType(T);
if (const MemberPointerType *MPT = T->getAs<MemberPointerType>()) { if (const MemberPointerType *MPT = T->getAs<MemberPointerType>()) {
if (!MPT->getPointeeType()->isFunctionType()) { if (!Types.getCXXABI().isZeroInitializable(MPT))
// We have a pointer to data member. IsZeroInitializable = false;
ContainsPointerToDataMember = true;
}
} else if (const RecordType *RT = T->getAs<RecordType>()) { } else if (const RecordType *RT = T->getAs<RecordType>()) {
const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
CheckZeroInitializable(RD);
return CheckForPointerToDataMember(RD);
} }
} }
void void CGRecordLayoutBuilder::CheckZeroInitializable(const CXXRecordDecl *RD) {
CGRecordLayoutBuilder::CheckForPointerToDataMember(const CXXRecordDecl *RD) {
// This record already contains a member pointer. // This record already contains a member pointer.
if (ContainsPointerToDataMember) if (!IsZeroInitializable)
return; return;
// FIXME: It would be better if there was a way to explicitly compute the // FIXME: It would be better if there was a way to explicitly compute the
@ -638,8 +633,8 @@ CGRecordLayoutBuilder::CheckForPointerToDataMember(const CXXRecordDecl *RD) {
const CGRecordLayout &Layout = Types.getCGRecordLayout(RD); const CGRecordLayout &Layout = Types.getCGRecordLayout(RD);
if (Layout.containsPointerToDataMember()) if (!Layout.isZeroInitializable())
ContainsPointerToDataMember = true; IsZeroInitializable = false;
} }
CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) { CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) {
@ -652,7 +647,7 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) {
Builder.Packed); Builder.Packed);
CGRecordLayout *RL = CGRecordLayout *RL =
new CGRecordLayout(Ty, Builder.ContainsPointerToDataMember); new CGRecordLayout(Ty, Builder.IsZeroInitializable);
// Add all the non-virtual base field numbers. // Add all the non-virtual base field numbers.
RL->NonVirtualBaseFields.insert(Builder.LLVMNonVirtualBases.begin(), RL->NonVirtualBaseFields.insert(Builder.LLVMNonVirtualBases.begin(),
@ -723,7 +718,7 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) {
void CGRecordLayout::print(llvm::raw_ostream &OS) const { void CGRecordLayout::print(llvm::raw_ostream &OS) const {
OS << "<CGRecordLayout\n"; OS << "<CGRecordLayout\n";
OS << " LLVMType:" << *LLVMType << "\n"; OS << " LLVMType:" << *LLVMType << "\n";
OS << " ContainsPointerToDataMember:" << ContainsPointerToDataMember << "\n"; OS << " IsZeroInitializable:" << IsZeroInitializable << "\n";
OS << " BitFields:[\n"; OS << " BitFields:[\n";
// Print bit-field infos in declaration order. // Print bit-field infos in declaration order.

View File

@ -579,8 +579,7 @@ CodeGenFunction::EmitNullInitialization(llvm::Value *DestPtr, QualType Ty) {
// If the type contains a pointer to data member we can't memset it to zero. // If the type contains a pointer to data member we can't memset it to zero.
// Instead, create a null constant and copy it to the destination. // Instead, create a null constant and copy it to the destination.
if (CGM.getLangOptions().CPlusPlus && if (!CGM.getTypes().isZeroInitializable(Ty)) {
CGM.getCXXABI().RequiresNonZeroInitializer(Ty)) {
llvm::Constant *NullConstant = CGM.EmitNullConstant(Ty); llvm::Constant *NullConstant = CGM.EmitNullConstant(Ty);
llvm::GlobalVariable *NullVariable = llvm::GlobalVariable *NullVariable =

View File

@ -41,6 +41,17 @@
using namespace clang; using namespace clang;
using namespace CodeGen; using namespace CodeGen;
static CGCXXABI &createCXXABI(CodeGenModule &CGM) {
switch (CGM.getContext().Target.getCXXABI()) {
case CXXABI_ARM: return *CreateARMCXXABI(CGM);
case CXXABI_Itanium: return *CreateItaniumCXXABI(CGM);
case CXXABI_Microsoft: return *CreateMicrosoftCXXABI(CGM);
}
llvm_unreachable("invalid C++ ABI kind");
return *CreateItaniumCXXABI(CGM);
}
CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO, CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
llvm::Module &M, const llvm::TargetData &TD, llvm::Module &M, const llvm::TargetData &TD,
@ -48,8 +59,9 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
: BlockModule(C, M, TD, Types, *this), Context(C), : BlockModule(C, M, TD, Types, *this), Context(C),
Features(C.getLangOptions()), CodeGenOpts(CGO), TheModule(M), Features(C.getLangOptions()), CodeGenOpts(CGO), TheModule(M),
TheTargetData(TD), TheTargetCodeGenInfo(0), Diags(diags), TheTargetData(TD), TheTargetCodeGenInfo(0), Diags(diags),
Types(C, M, TD, getTargetCodeGenInfo().getABIInfo()), ABI(createCXXABI(*this)),
VTables(*this), Runtime(0), ABI(0), Types(C, M, TD, getTargetCodeGenInfo().getABIInfo(), ABI),
VTables(*this), Runtime(0),
CFConstantStringClassRef(0), NSConstantStringClassRef(0), CFConstantStringClassRef(0), NSConstantStringClassRef(0),
VMContext(M.getContext()), VMContext(M.getContext()),
NSConcreteGlobalBlockDecl(0), NSConcreteStackBlockDecl(0), NSConcreteGlobalBlockDecl(0), NSConcreteStackBlockDecl(0),
@ -66,17 +78,13 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
else else
Runtime = CreateMacObjCRuntime(*this); Runtime = CreateMacObjCRuntime(*this);
if (!Features.CPlusPlus)
ABI = 0;
else createCXXABI();
// If debug info generation is enabled, create the CGDebugInfo object. // If debug info generation is enabled, create the CGDebugInfo object.
DebugInfo = CodeGenOpts.DebugInfo ? new CGDebugInfo(*this) : 0; DebugInfo = CodeGenOpts.DebugInfo ? new CGDebugInfo(*this) : 0;
} }
CodeGenModule::~CodeGenModule() { CodeGenModule::~CodeGenModule() {
delete Runtime; delete Runtime;
delete ABI; delete &ABI;
delete DebugInfo; delete DebugInfo;
} }
@ -89,20 +97,6 @@ void CodeGenModule::createObjCRuntime() {
Runtime = CreateMacObjCRuntime(*this); Runtime = CreateMacObjCRuntime(*this);
} }
void CodeGenModule::createCXXABI() {
switch (Context.Target.getCXXABI()) {
case CXXABI_ARM:
ABI = CreateARMCXXABI(*this);
break;
case CXXABI_Itanium:
ABI = CreateItaniumCXXABI(*this);
break;
case CXXABI_Microsoft:
ABI = CreateMicrosoftCXXABI(*this);
break;
}
}
void CodeGenModule::Release() { void CodeGenModule::Release() {
EmitDeferred(); EmitDeferred();
EmitCXXGlobalInitFunc(); EmitCXXGlobalInitFunc();

View File

@ -109,6 +109,7 @@ class CodeGenModule : public BlockModule {
const llvm::TargetData &TheTargetData; const llvm::TargetData &TheTargetData;
mutable const TargetCodeGenInfo *TheTargetCodeGenInfo; mutable const TargetCodeGenInfo *TheTargetCodeGenInfo;
Diagnostic &Diags; Diagnostic &Diags;
CGCXXABI &ABI;
CodeGenTypes Types; CodeGenTypes Types;
/// VTables - Holds information about C++ vtables. /// VTables - Holds information about C++ vtables.
@ -116,7 +117,6 @@ class CodeGenModule : public BlockModule {
friend class CodeGenVTables; friend class CodeGenVTables;
CGObjCRuntime* Runtime; CGObjCRuntime* Runtime;
CGCXXABI* ABI;
CGDebugInfo* DebugInfo; CGDebugInfo* DebugInfo;
// WeakRefReferences - A set of references that have only been seen via // WeakRefReferences - A set of references that have only been seen via
@ -189,8 +189,6 @@ class CodeGenModule : public BlockModule {
/// Lazily create the Objective-C runtime /// Lazily create the Objective-C runtime
void createObjCRuntime(); void createObjCRuntime();
/// Lazily create the C++ ABI
void createCXXABI();
llvm::LLVMContext &VMContext; llvm::LLVMContext &VMContext;
@ -228,15 +226,8 @@ public:
/// been configured. /// been configured.
bool hasObjCRuntime() { return !!Runtime; } bool hasObjCRuntime() { return !!Runtime; }
/// getCXXABI() - Return a reference to the configured /// getCXXABI() - Return a reference to the configured C++ ABI.
/// C++ ABI. CGCXXABI &getCXXABI() { return ABI; }
CGCXXABI &getCXXABI() {
if (!ABI) createCXXABI();
return *ABI;
}
/// hasCXXABI() - Return true iff a C++ ABI has been configured.
bool hasCXXABI() { return !!ABI; }
llvm::Value *getStaticLocalDeclAddress(const VarDecl *VD) { llvm::Value *getStaticLocalDeclAddress(const VarDecl *VD) {
return StaticLocalDeclMap[VD]; return StaticLocalDeclMap[VD];
@ -253,8 +244,7 @@ public:
llvm::Module &getModule() const { return TheModule; } llvm::Module &getModule() const { return TheModule; }
CodeGenTypes &getTypes() { return Types; } CodeGenTypes &getTypes() { return Types; }
MangleContext &getMangleContext() { MangleContext &getMangleContext() {
if (!ABI) createCXXABI(); return ABI.getMangleContext();
return ABI->getMangleContext();
} }
CodeGenVTables &getVTables() { return VTables; } CodeGenVTables &getVTables() { return VTables; }
Diagnostic &getDiags() const { return Diags; } Diagnostic &getDiags() const { return Diags; }

View File

@ -13,6 +13,7 @@
#include "CodeGenTypes.h" #include "CodeGenTypes.h"
#include "CGCall.h" #include "CGCall.h"
#include "CGCXXABI.h"
#include "CGRecordLayout.h" #include "CGRecordLayout.h"
#include "clang/AST/ASTContext.h" #include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h" #include "clang/AST/DeclObjC.h"
@ -26,9 +27,10 @@ using namespace clang;
using namespace CodeGen; using namespace CodeGen;
CodeGenTypes::CodeGenTypes(ASTContext &Ctx, llvm::Module& M, CodeGenTypes::CodeGenTypes(ASTContext &Ctx, llvm::Module& M,
const llvm::TargetData &TD, const ABIInfo &Info) const llvm::TargetData &TD, const ABIInfo &Info,
CGCXXABI &CXXABI)
: Context(Ctx), Target(Ctx.Target), TheModule(M), TheTargetData(TD), : Context(Ctx), Target(Ctx.Target), TheModule(M), TheTargetData(TD),
TheABIInfo(Info) { TheABIInfo(Info), TheCXXABI(CXXABI) {
} }
CodeGenTypes::~CodeGenTypes() { CodeGenTypes::~CodeGenTypes() {
@ -491,31 +493,34 @@ CodeGenTypes::getCGRecordLayout(const RecordDecl *TD) const {
return *Layout; return *Layout;
} }
bool CodeGenTypes::ContainsPointerToDataMember(QualType T) { bool CodeGenTypes::isZeroInitializable(QualType T) {
// No need to check for member pointers when not compiling C++. // No need to check for member pointers when not compiling C++.
if (!Context.getLangOptions().CPlusPlus) if (!Context.getLangOptions().CPlusPlus)
return false; return true;
T = Context.getBaseElementType(T); T = Context.getBaseElementType(T);
// Records are non-zero-initializable if they contain any
// non-zero-initializable subobjects.
if (const RecordType *RT = T->getAs<RecordType>()) { if (const RecordType *RT = T->getAs<RecordType>()) {
const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
return isZeroInitializable(RD);
return ContainsPointerToDataMember(RD);
} }
// We have to ask the ABI about member pointers.
if (const MemberPointerType *MPT = T->getAs<MemberPointerType>()) if (const MemberPointerType *MPT = T->getAs<MemberPointerType>())
return !MPT->getPointeeType()->isFunctionType(); return getCXXABI().isZeroInitializable(MPT);
return false; // Everything else is okay.
return true;
} }
bool CodeGenTypes::ContainsPointerToDataMember(const CXXRecordDecl *RD) { bool CodeGenTypes::isZeroInitializable(const CXXRecordDecl *RD) {
// FIXME: It would be better if there was a way to explicitly compute the // FIXME: It would be better if there was a way to explicitly compute the
// record layout instead of converting to a type. // record layout instead of converting to a type.
ConvertTagDeclType(RD); ConvertTagDeclType(RD);
const CGRecordLayout &Layout = getCGRecordLayout(RD); const CGRecordLayout &Layout = getCGRecordLayout(RD);
return Layout.containsPointerToDataMember(); return Layout.isZeroInitializable();
} }

View File

@ -50,6 +50,7 @@ namespace clang {
typedef CanQual<Type> CanQualType; typedef CanQual<Type> CanQualType;
namespace CodeGen { namespace CodeGen {
class CGCXXABI;
class CGRecordLayout; class CGRecordLayout;
/// CodeGenTypes - This class organizes the cross-module state that is used /// CodeGenTypes - This class organizes the cross-module state that is used
@ -60,6 +61,7 @@ class CodeGenTypes {
llvm::Module& TheModule; llvm::Module& TheModule;
const llvm::TargetData& TheTargetData; const llvm::TargetData& TheTargetData;
const ABIInfo& TheABIInfo; const ABIInfo& TheABIInfo;
CGCXXABI &TheCXXABI;
llvm::SmallVector<std::pair<QualType, llvm::SmallVector<std::pair<QualType,
llvm::OpaqueType *>, 8> PointersToResolve; llvm::OpaqueType *>, 8> PointersToResolve;
@ -101,13 +103,14 @@ private:
public: public:
CodeGenTypes(ASTContext &Ctx, llvm::Module &M, const llvm::TargetData &TD, CodeGenTypes(ASTContext &Ctx, llvm::Module &M, const llvm::TargetData &TD,
const ABIInfo &Info); const ABIInfo &Info, CGCXXABI &CXXABI);
~CodeGenTypes(); ~CodeGenTypes();
const llvm::TargetData &getTargetData() const { return TheTargetData; } const llvm::TargetData &getTargetData() const { return TheTargetData; }
const TargetInfo &getTarget() const { return Target; } const TargetInfo &getTarget() const { return Target; }
ASTContext &getContext() const { return Context; } ASTContext &getContext() const { return Context; }
const ABIInfo &getABIInfo() const { return TheABIInfo; } const ABIInfo &getABIInfo() const { return TheABIInfo; }
CGCXXABI &getCXXABI() const { return TheCXXABI; }
llvm::LLVMContext &getLLVMContext() { return TheModule.getContext(); } llvm::LLVMContext &getLLVMContext() { return TheModule.getContext(); }
/// ConvertType - Convert type T into a llvm::Type. /// ConvertType - Convert type T into a llvm::Type.
@ -204,13 +207,13 @@ public: // These are internal details of CGT that shouldn't be used externally.
void GetExpandedTypes(QualType Ty, std::vector<const llvm::Type*> &ArgTys, void GetExpandedTypes(QualType Ty, std::vector<const llvm::Type*> &ArgTys,
bool IsRecursive); bool IsRecursive);
/// ContainsPointerToDataMember - Return whether the given type contains a /// IsZeroInitializable - Return whether a type can be
/// pointer to a data member. /// zero-initialized (in the C++ sense) with an LLVM zeroinitializer.
bool ContainsPointerToDataMember(QualType T); bool isZeroInitializable(QualType T);
/// ContainsPointerToDataMember - Return whether the record decl contains a /// IsZeroInitializable - Return whether a record type can be
/// pointer to a data member. /// zero-initialized (in the C++ sense) with an LLVM zeroinitializer.
bool ContainsPointerToDataMember(const CXXRecordDecl *RD); bool isZeroInitializable(const CXXRecordDecl *RD);
}; };
} // end namespace CodeGen } // end namespace CodeGen

View File

@ -41,8 +41,7 @@ public:
return MangleCtx; return MangleCtx;
} }
bool RequiresNonZeroInitializer(QualType T); bool isZeroInitializable(const MemberPointerType *MPT);
bool RequiresNonZeroInitializer(const CXXRecordDecl *D);
llvm::Value *EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, llvm::Value *EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
llvm::Value *&This, llvm::Value *&This,
@ -460,10 +459,8 @@ ItaniumCXXABI::EmitMemberFunctionPointerIsNotNull(CodeGenFunction &CGF,
return Result; return Result;
} }
bool ItaniumCXXABI::RequiresNonZeroInitializer(QualType T) { /// The Itanium ABI requires non-zero initialization only for data
return CGM.getTypes().ContainsPointerToDataMember(T); /// member pointers, for which '0' is a valid offset.
} bool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
return MPT->getPointeeType()->isFunctionType();
bool ItaniumCXXABI::RequiresNonZeroInitializer(const CXXRecordDecl *D) {
return CGM.getTypes().ContainsPointerToDataMember(D);
} }

View File

@ -12,7 +12,7 @@
// CHECK-RECORD: Record: struct s0 // CHECK-RECORD: Record: struct s0
// CHECK-RECORD: Layout: <CGRecordLayout // CHECK-RECORD: Layout: <CGRecordLayout
// CHECK-RECORD: LLVMType:<{ [3 x i8] }> // CHECK-RECORD: LLVMType:<{ [3 x i8] }>
// CHECK-RECORD: ContainsPointerToDataMember:0 // CHECK-RECORD: IsZeroInitializable:1
// CHECK-RECORD: BitFields:[ // CHECK-RECORD: BitFields:[
// CHECK-RECORD: <CGBitFieldInfo Size:24 IsSigned:1 // CHECK-RECORD: <CGBitFieldInfo Size:24 IsSigned:1
// CHECK-RECORD: NumComponents:2 Components: [ // CHECK-RECORD: NumComponents:2 Components: [
@ -57,7 +57,7 @@ unsigned long long test_0() {
// CHECK-RECORD: Record: struct s1 // CHECK-RECORD: Record: struct s1
// CHECK-RECORD: Layout: <CGRecordLayout // CHECK-RECORD: Layout: <CGRecordLayout
// CHECK-RECORD: LLVMType:<{ [2 x i8], i8 }> // CHECK-RECORD: LLVMType:<{ [2 x i8], i8 }>
// CHECK-RECORD: ContainsPointerToDataMember:0 // CHECK-RECORD: IsZeroInitializable:1
// CHECK-RECORD: BitFields:[ // CHECK-RECORD: BitFields:[
// CHECK-RECORD: <CGBitFieldInfo Size:10 IsSigned:1 // CHECK-RECORD: <CGBitFieldInfo Size:10 IsSigned:1
// CHECK-RECORD: NumComponents:1 Components: [ // CHECK-RECORD: NumComponents:1 Components: [
@ -114,7 +114,7 @@ unsigned long long test_1() {
// CHECK-RECORD: Record: union u2 // CHECK-RECORD: Record: union u2
// CHECK-RECORD: Layout: <CGRecordLayout // CHECK-RECORD: Layout: <CGRecordLayout
// CHECK-RECORD: LLVMType:<{ i8 }> // CHECK-RECORD: LLVMType:<{ i8 }>
// CHECK-RECORD: ContainsPointerToDataMember:0 // CHECK-RECORD: IsZeroInitializable:1
// CHECK-RECORD: BitFields:[ // CHECK-RECORD: BitFields:[
// CHECK-RECORD: <CGBitFieldInfo Size:3 IsSigned:0 // CHECK-RECORD: <CGBitFieldInfo Size:3 IsSigned:0
// CHECK-RECORD: NumComponents:1 Components: [ // CHECK-RECORD: NumComponents:1 Components: [
@ -289,7 +289,7 @@ _Bool test_6() {
// CHECK-RECORD: Record: struct s7 // CHECK-RECORD: Record: struct s7
// CHECK-RECORD: Layout: <CGRecordLayout // CHECK-RECORD: Layout: <CGRecordLayout
// CHECK-RECORD: LLVMType:{ i32, i32, i32, i8, [3 x i8], [4 x i8], [12 x i8] } // CHECK-RECORD: LLVMType:{ i32, i32, i32, i8, [3 x i8], [4 x i8], [12 x i8] }
// CHECK-RECORD: ContainsPointerToDataMember:0 // CHECK-RECORD: IsZeroInitializable:1
// CHECK-RECORD: BitFields:[ // CHECK-RECORD: BitFields:[
// CHECK-RECORD: <CGBitFieldInfo Size:5 IsSigned:1 // CHECK-RECORD: <CGBitFieldInfo Size:5 IsSigned:1
// CHECK-RECORD: NumComponents:1 Components: [ // CHECK-RECORD: NumComponents:1 Components: [