mirror of
https://github.com/intel/llvm.git
synced 2026-01-28 09:37:03 +08:00
Abstract more member-pointerness out.
llvm-svn: 111771
This commit is contained in:
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user