From cf2c85e76fdafe7e634810a292321a6c8322483d Mon Sep 17 00:00:00 2001 From: John McCall Date: Sun, 22 Aug 2010 04:16:24 +0000 Subject: [PATCH] Abstract more member-pointerness out. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111771 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGCXX.cpp | 38 ++++++++++-- lib/CodeGen/CGCXXABI.h | 33 +++++++++-- lib/CodeGen/CGExprAgg.cpp | 16 ++--- lib/CodeGen/CGExprCXX.cpp | 2 +- lib/CodeGen/CGExprConstant.cpp | 51 +++++----------- lib/CodeGen/CodeGenFunction.cpp | 3 +- lib/CodeGen/ItaniumCXXABI.cpp | 102 ++++++++++++++++++++++++++++---- 7 files changed, 174 insertions(+), 71 deletions(-) diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 62c3954ee6..f56ea42427 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -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)); } diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h index a28436b3e9..36f8230b0c 100644 --- a/lib/CodeGen/CGCXXABI.h +++ b/lib/CodeGen/CGCXXABI.h @@ -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. diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 7b198bcf62..1f8964d0b6 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -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(), + 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; } } diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 11b6f053b2..fb5414016a 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -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. diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 6acc02c5b9..e72e7fd1d1 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -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()); case CastExpr::CK_BaseToDerivedMemberPointer: { Expr *SubExpr = E->getSubExpr(); - const MemberPointerType *SrcTy = - SubExpr->getType()->getAs(); - const MemberPointerType *DestTy = - E->getType()->getAs(); - - const CXXRecordDecl *DerivedClass = - cast(cast(DestTy->getClass())->getDecl()); - - if (SrcTy->getPointeeType()->isFunctionProtoType()) { - llvm::Constant *C = - CGM.EmitConstantExpr(SubExpr, SubExpr->getType(), CGF); - if (!C) - return 0; - - llvm::ConstantStruct *CS = cast(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; - } + llvm::Constant *C = + CGM.EmitConstantExpr(SubExpr, SubExpr->getType(), CGF); + if (!C) return 0; + + 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 diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 5bee016d7e..ca4e698229 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -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 = diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index 9fc6be179d..b7211058c9 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -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(); + const MemberPointerType *DestTy = + E->getType()->getAs(); + + 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(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); +} -- 2.40.0