Abstract more member-pointerness out.

llvm-svn: 111771
This commit is contained in:
John McCall
2010-08-22 04:16:24 +00:00
parent a8bbb82c55
commit 84fa510aa9
7 changed files with 173 additions and 70 deletions

View File

@@ -385,10 +385,36 @@ llvm::Value *CGCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
return llvm::Constant::getNullValue(FTy->getPointerTo());
}
void CGCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
const CastExpr *E,
llvm::Value *Src,
llvm::Value *Dest,
bool VolatileDest) {
ErrorUnsupportedABI(CGF, "member pointer conversions");
void CGCXXABI::EmitMemberFunctionPointerConversion(CodeGenFunction &CGF,
const CastExpr *E,
llvm::Value *Src,
llvm::Value *Dest,
bool VolatileDest) {
ErrorUnsupportedABI(CGF, "member function pointer conversions");
}
void CGCXXABI::EmitNullMemberFunctionPointer(CodeGenFunction &CGF,
const MemberPointerType *MPT,
llvm::Value *Dest,
bool VolatileDest) {
ErrorUnsupportedABI(CGF, "null member function pointers");
}
llvm::Constant *
CGCXXABI::EmitMemberFunctionPointerConversion(llvm::Constant *C,
const CastExpr *E) {
return 0;
}
llvm::Constant *
CGCXXABI::EmitNullMemberFunctionPointer(const MemberPointerType *MPT) {
return 0;
}
bool CGCXXABI::RequiresNonZeroInitializer(QualType T) {
return false;
}
bool CGCXXABI::RequiresNonZeroInitializer(const CXXRecordDecl *D) {
return RequiresNonZeroInitializer(QualType(D->getTypeForDecl(), 0));
}

View File

@@ -16,12 +16,15 @@
#define CLANG_CODEGEN_CXXABI_H
namespace llvm {
class Constant;
class Value;
}
namespace clang {
class CastExpr;
class CXXRecordDecl;
class MemberPointerType;
class QualType;
namespace CodeGen {
class CodeGenFunction;
@@ -42,11 +45,31 @@ public:
llvm::Value *MemPtr,
const MemberPointerType *MPT);
virtual void EmitMemberPointerConversion(CodeGenFunction &CGF,
const CastExpr *E,
llvm::Value *Src,
llvm::Value *Dest,
bool VolatileDest);
virtual void
EmitMemberFunctionPointerConversion(CodeGenFunction &CGF,
const CastExpr *E,
llvm::Value *Src,
llvm::Value *Dest,
bool VolatileDest);
virtual void EmitNullMemberFunctionPointer(CodeGenFunction &CGF,
const MemberPointerType *MPT,
llvm::Value *Dest,
bool VolatileDest);
// Manipulations on constant expressions.
/// \brief Returns true if zero-initializing the given type requires
/// a constant other than the LLVM null value.
virtual bool RequiresNonZeroInitializer(QualType T);
virtual bool RequiresNonZeroInitializer(const CXXRecordDecl *D);
virtual llvm::Constant *
EmitMemberFunctionPointerConversion(llvm::Constant *C,
const CastExpr *E);
virtual llvm::Constant *
EmitNullMemberFunctionPointer(const MemberPointerType *MPT);
};
/// Creates an instance of a C++ ABI class.

View File

@@ -293,15 +293,9 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
if (E->getSubExpr()->getType()->isNullPtrType())
Visit(E->getSubExpr());
const llvm::Type *PtrDiffTy =
CGF.ConvertType(CGF.getContext().getPointerDiffType());
llvm::Value *NullValue = llvm::Constant::getNullValue(PtrDiffTy);
llvm::Value *Ptr = Builder.CreateStructGEP(DestPtr, 0, "ptr");
Builder.CreateStore(NullValue, Ptr, VolatileDest);
llvm::Value *Adj = Builder.CreateStructGEP(DestPtr, 1, "adj");
Builder.CreateStore(NullValue, Adj, VolatileDest);
CGF.CGM.getCXXABI().EmitNullMemberFunctionPointer(CGF,
E->getType()->getAs<MemberPointerType>(),
DestPtr, VolatileDest);
break;
}
@@ -329,8 +323,8 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
// ABIs where an actual null check is thus required; fortunately,
// the Itanium and ARM ABIs ignore the adjustment value when
// considering null-ness.
CGF.CGM.getCXXABI().EmitMemberPointerConversion(CGF, E, Src,
DestPtr, VolatileDest);
CGF.CGM.getCXXABI().EmitMemberFunctionPointerConversion(CGF, E, Src,
DestPtr, VolatileDest);
break;
}
}

View File

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

View File

@@ -549,42 +549,17 @@ public:
return llvm::ConstantStruct::get(STy, Elts);
}
case CastExpr::CK_NullToMemberPointer:
return CGM.EmitNullConstant(E->getType());
return CGM.getCXXABI().EmitNullMemberFunctionPointer(
E->getType()->getAs<MemberPointerType>());
case CastExpr::CK_BaseToDerivedMemberPointer: {
Expr *SubExpr = E->getSubExpr();
const MemberPointerType *SrcTy =
SubExpr->getType()->getAs<MemberPointerType>();
const MemberPointerType *DestTy =
E->getType()->getAs<MemberPointerType>();
const CXXRecordDecl *DerivedClass =
cast<CXXRecordDecl>(cast<RecordType>(DestTy->getClass())->getDecl());
llvm::Constant *C =
CGM.EmitConstantExpr(SubExpr, SubExpr->getType(), CGF);
if (!C) return 0;
if (SrcTy->getPointeeType()->isFunctionProtoType()) {
llvm::Constant *C =
CGM.EmitConstantExpr(SubExpr, SubExpr->getType(), CGF);
if (!C)
return 0;
llvm::ConstantStruct *CS = cast<llvm::ConstantStruct>(C);
// Check if we need to update the adjustment.
if (llvm::Constant *Offset =
CGM.GetNonVirtualBaseClassOffset(DerivedClass,
E->path_begin(),
E->path_end())) {
llvm::Constant *Values[2];
Values[0] = CS->getOperand(0);
Values[1] = llvm::ConstantExpr::getAdd(CS->getOperand(1), Offset);
return llvm::ConstantStruct::get(CGM.getLLVMContext(), Values, 2,
/*Packed=*/false);
}
return CS;
}
return CGM.getCXXABI().EmitMemberFunctionPointerConversion(C, E);
}
case CastExpr::CK_BitCast:
@@ -990,7 +965,8 @@ FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T,
uint64_t StartOffset) {
assert(StartOffset % 8 == 0 && "StartOffset not byte aligned!");
if (!CGM.getTypes().ContainsPointerToDataMember(T))
if (!CGM.getLangOptions().CPlusPlus ||
!CGM.getCXXABI().RequiresNonZeroInitializer(T))
return;
if (const ConstantArrayType *CAT =
@@ -1023,7 +999,7 @@ FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T,
continue;
// Ignore bases that don't have any pointer to data members.
if (!CGM.getTypes().ContainsPointerToDataMember(BaseDecl))
if (!CGM.getCXXABI().RequiresNonZeroInitializer(BaseDecl))
continue;
uint64_t BaseOffset = Layout.getBaseClassOffset(BaseDecl);
@@ -1037,7 +1013,7 @@ FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T,
E = RD->field_end(); I != E; ++I, ++FieldNo) {
QualType FieldType = I->getType();
if (!CGM.getTypes().ContainsPointerToDataMember(FieldType))
if (!CGM.getCXXABI().RequiresNonZeroInitializer(FieldType))
continue;
uint64_t FieldOffset = StartOffset + Layout.getFieldOffset(FieldNo);
@@ -1062,7 +1038,8 @@ FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T,
}
llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) {
if (!getTypes().ContainsPointerToDataMember(T))
if (!getLangOptions().CPlusPlus ||
!getCXXABI().RequiresNonZeroInitializer(T))
return llvm::Constant::getNullValue(getTypes().ConvertTypeForMem(T));
if (const ConstantArrayType *CAT = Context.getAsConstantArrayType(T)) {
@@ -1106,7 +1083,7 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) {
continue;
// Ignore bases that don't have any pointer to data members.
if (!getTypes().ContainsPointerToDataMember(BaseDecl))
if (!getCXXABI().RequiresNonZeroInitializer(BaseDecl))
continue;
// Currently, all bases are arrays of i8. Figure out how many elements

View File

@@ -579,7 +579,8 @@ CodeGenFunction::EmitNullInitialization(llvm::Value *DestPtr, QualType Ty) {
// 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.
if (CGM.getTypes().ContainsPointerToDataMember(Ty)) {
if (CGM.getLangOptions().CPlusPlus &&
CGM.getCXXABI().RequiresNonZeroInitializer(Ty)) {
llvm::Constant *NullConstant = CGM.EmitNullConstant(Ty);
llvm::GlobalVariable *NullVariable =

View File

@@ -42,16 +42,30 @@ public:
return MangleCtx;
}
bool RequiresNonZeroInitializer(QualType T);
bool RequiresNonZeroInitializer(const CXXRecordDecl *D);
llvm::Value *EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
llvm::Value *&This,
llvm::Value *MemFnPtr,
const MemberPointerType *MPT);
void EmitMemberPointerConversion(CodeGenFunction &CGF,
const CastExpr *E,
llvm::Value *Src,
llvm::Value *Dest,
bool VolatileDest);
void EmitMemberFunctionPointerConversion(CodeGenFunction &CGF,
const CastExpr *E,
llvm::Value *Src,
llvm::Value *Dest,
bool VolatileDest);
llvm::Constant *EmitMemberFunctionPointerConversion(llvm::Constant *C,
const CastExpr *E);
void EmitNullMemberFunctionPointer(CodeGenFunction &CGF,
const MemberPointerType *MPT,
llvm::Value *Dest,
bool VolatileDest);
llvm::Constant *EmitNullMemberFunctionPointer(const MemberPointerType *MPT);
};
class ARMCXXABI : public ItaniumCXXABI {
@@ -176,11 +190,11 @@ ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
}
/// Perform a derived-to-base or base-to-derived member pointer conversion.
void ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
const CastExpr *E,
llvm::Value *Src,
llvm::Value *Dest,
bool VolatileDest) {
void ItaniumCXXABI::EmitMemberFunctionPointerConversion(CodeGenFunction &CGF,
const CastExpr *E,
llvm::Value *Src,
llvm::Value *Dest,
bool VolatileDest) {
assert(E->getCastKind() == CastExpr::CK_DerivedToBaseMemberPointer ||
E->getCastKind() == CastExpr::CK_BaseToDerivedMemberPointer);
@@ -225,3 +239,71 @@ void ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
Builder.CreateStore(SrcAdj, DstAdj, VolatileDest);
}
llvm::Constant *
ItaniumCXXABI::EmitMemberFunctionPointerConversion(llvm::Constant *C,
const CastExpr *E) {
const MemberPointerType *SrcTy =
E->getSubExpr()->getType()->getAs<MemberPointerType>();
const MemberPointerType *DestTy =
E->getType()->getAs<MemberPointerType>();
bool DerivedToBase =
E->getCastKind() == CastExpr::CK_DerivedToBaseMemberPointer;
const CXXRecordDecl *DerivedDecl;
if (DerivedToBase)
DerivedDecl = SrcTy->getClass()->getAsCXXRecordDecl();
else
DerivedDecl = DestTy->getClass()->getAsCXXRecordDecl();
// Calculate the offset to the base class.
llvm::Constant *Offset =
CGM.GetNonVirtualBaseClassOffset(DerivedDecl,
E->path_begin(),
E->path_end());
// If there's no offset, we're done.
if (!Offset) return C;
llvm::ConstantStruct *CS = cast<llvm::ConstantStruct>(C);
llvm::Constant *Values[2] = {
CS->getOperand(0),
llvm::ConstantExpr::getAdd(CS->getOperand(1), Offset)
};
return llvm::ConstantStruct::get(CGM.getLLVMContext(), Values, 2,
/*Packed=*/false);
}
void ItaniumCXXABI::EmitNullMemberFunctionPointer(CodeGenFunction &CGF,
const MemberPointerType *MPT,
llvm::Value *Dest,
bool VolatileDest) {
// Should this be "unabstracted" and implemented in terms of the
// Constant version?
CGBuilderTy &Builder = CGF.Builder;
const llvm::IntegerType *PtrDiffTy = CGF.IntPtrTy;
llvm::Value *Zero = llvm::ConstantInt::get(PtrDiffTy, 0);
llvm::Value *Ptr = Builder.CreateStructGEP(Dest, 0, "ptr");
Builder.CreateStore(Zero, Ptr, VolatileDest);
llvm::Value *Adj = Builder.CreateStructGEP(Dest, 1, "adj");
Builder.CreateStore(Zero, Adj, VolatileDest);
}
llvm::Constant *
ItaniumCXXABI::EmitNullMemberFunctionPointer(const MemberPointerType *MPT) {
return CGM.EmitNullConstant(QualType(MPT, 0));
}
bool ItaniumCXXABI::RequiresNonZeroInitializer(QualType T) {
return CGM.getTypes().ContainsPointerToDataMember(T);
}
bool ItaniumCXXABI::RequiresNonZeroInitializer(const CXXRecordDecl *D) {
return CGM.getTypes().ContainsPointerToDataMember(D);
}