forked from OSchip/llvm-project
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:
parent
0b84914da0
commit
614dbdcd55
|
@ -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));
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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 =
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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: [
|
||||||
|
|
Loading…
Reference in New Issue