From 4ff3a09576aed5a942ef78ff4922150a1f9085ed Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Tue, 23 Jun 2015 07:31:07 +0000 Subject: [PATCH] [MS ABI] Refactor member pointer generation The MS ABI has very complicated member pointers. Don't attempt to synthesize the final member pointer ab ovo usque ad mala in one go. Instead, start with a member pointer which points to the declaration in question as-if it's decl context was the target class. Then, utilize our conversion logical to convert it to the target type. This allows us to simplify how we think about member pointers because we don't need to consider non-zero nv adjustments before we even generate the member pointer. Furthermore, it gives our adjustment logic more exposure by utilizing it in a common path. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@240383 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MicrosoftCXXABI.cpp | 103 +++++++++++++++++++++++--------- 1 file changed, 75 insertions(+), 28 deletions(-) diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp index 07d88422c1..3c0aecaa16 100644 --- a/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/lib/CodeGen/MicrosoftCXXABI.cpp @@ -502,10 +502,6 @@ private: CharUnits NonVirtualBaseAdjustment, unsigned VBTableIndex); - llvm::Constant *BuildMemberPointer(const CXXRecordDecl *RD, - const CXXMethodDecl *MD, - CharUnits NonVirtualBaseAdjustment); - bool MemberPointerConstantIsNull(const MemberPointerType *MPT, llvm::Constant *MP); @@ -570,6 +566,11 @@ public: llvm::Constant *EmitMemberPointerConversion(const CastExpr *E, llvm::Constant *Src) override; + llvm::Constant *EmitMemberPointerConversion( + const MemberPointerType *SrcTy, const MemberPointerType *DstTy, + CastKind CK, CastExpr::path_const_iterator PathBegin, + CastExpr::path_const_iterator PathEnd, llvm::Constant *Src); + llvm::Value * EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, const Expr *E, llvm::Value *&This, llvm::Value *MemPtr, @@ -2479,38 +2480,67 @@ MicrosoftCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, CharUnits::Zero(), /*VBTableIndex=*/0); } -llvm::Constant * -MicrosoftCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) { - return BuildMemberPointer(MD->getParent(), MD, CharUnits::Zero()); -} - llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(const APValue &MP, QualType MPType) { - const MemberPointerType *MPT = MPType->castAs(); + const MemberPointerType *DstTy = MPType->castAs(); const ValueDecl *MPD = MP.getMemberPointerDecl(); if (!MPD) - return EmitNullMemberPointer(MPT); - - CharUnits ThisAdjustment = getMemberPointerPathAdjustment(MP); + return EmitNullMemberPointer(DstTy); - // FIXME PR15713: Support virtual inheritance paths. + ASTContext &Ctx = getContext(); + ArrayRef MemberPointerPath = MP.getMemberPointerPath(); - if (const CXXMethodDecl *MD = dyn_cast(MPD)) - return BuildMemberPointer(MPT->getMostRecentCXXRecordDecl(), MD, - ThisAdjustment); + llvm::Constant *C; + if (const CXXMethodDecl *MD = dyn_cast(MPD)) { + C = EmitMemberFunctionPointer(MD); + } else { + CharUnits FieldOffset = Ctx.toCharUnitsFromBits(Ctx.getFieldOffset(MPD)); + C = EmitMemberDataPointer(DstTy, FieldOffset); + } + + if (!MemberPointerPath.empty()) { + const CXXRecordDecl *SrcRD = cast(MPD->getDeclContext()); + const Type *SrcRecTy = Ctx.getTypeDeclType(SrcRD).getTypePtr(); + const MemberPointerType *SrcTy = + Ctx.getMemberPointerType(DstTy->getPointeeType(), SrcRecTy) + ->castAs(); + + bool DerivedMember = MP.isMemberPointerToDerivedMember(); + SmallVector DerivedToBasePath; + const CXXRecordDecl *PrevRD = SrcRD; + for (const CXXRecordDecl *PathElem : MemberPointerPath) { + const CXXRecordDecl *Base = nullptr; + const CXXRecordDecl *Derived = nullptr; + if (DerivedMember) { + Base = PathElem; + Derived = PrevRD; + } else { + Base = PrevRD; + Derived = PathElem; + } + for (const CXXBaseSpecifier &BS : Derived->bases()) + if (BS.getType()->getAsCXXRecordDecl()->getCanonicalDecl() == + Base->getCanonicalDecl()) + DerivedToBasePath.push_back(&BS); + PrevRD = PathElem; + } + assert(DerivedToBasePath.size() == MemberPointerPath.size()); - CharUnits FieldOffset = - getContext().toCharUnitsFromBits(getContext().getFieldOffset(MPD)); - return EmitMemberDataPointer(MPT, ThisAdjustment + FieldOffset); + CastKind CK = DerivedMember ? CK_DerivedToBaseMemberPointer + : CK_BaseToDerivedMemberPointer; + C = EmitMemberPointerConversion(SrcTy, DstTy, CK, DerivedToBasePath.begin(), + DerivedToBasePath.end(), C); + } + return C; } llvm::Constant * -MicrosoftCXXABI::BuildMemberPointer(const CXXRecordDecl *RD, - const CXXMethodDecl *MD, - CharUnits NonVirtualBaseAdjustment) { +MicrosoftCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) { assert(MD->isInstance() && "Member function must not be static!"); + MD = MD->getCanonicalDecl(); - RD = RD->getMostRecentDecl(); + CharUnits NonVirtualBaseAdjustment = CharUnits::Zero(); + const CXXRecordDecl *RD = MD->getParent()->getMostRecentDecl(); CodeGenTypes &Types = CGM.getTypes(); unsigned VBTableIndex = 0; @@ -2923,9 +2953,22 @@ llvm::Constant * MicrosoftCXXABI::EmitMemberPointerConversion(const CastExpr *E, llvm::Constant *Src) { const MemberPointerType *SrcTy = - E->getSubExpr()->getType()->castAs(); + E->getSubExpr()->getType()->castAs(); const MemberPointerType *DstTy = E->getType()->castAs(); + CastKind CK = E->getCastKind(); + + return EmitMemberPointerConversion(SrcTy, DstTy, CK, E->path_begin(), + E->path_end(), Src); +} + +llvm::Constant *MicrosoftCXXABI::EmitMemberPointerConversion( + const MemberPointerType *SrcTy, const MemberPointerType *DstTy, CastKind CK, + CastExpr::path_const_iterator PathBegin, + CastExpr::path_const_iterator PathEnd, llvm::Constant *Src) { + assert(CK == CK_DerivedToBaseMemberPointer || + CK == CK_BaseToDerivedMemberPointer || + CK == CK_ReinterpretMemberPointer); // If src is null, emit a new null for dst. We can't return src because dst // might have a new representation. if (MemberPointerConstantIsNull(SrcTy, Src)) @@ -2934,7 +2977,7 @@ MicrosoftCXXABI::EmitMemberPointerConversion(const CastExpr *E, // We don't need to do anything for reinterpret_casts of non-null member // pointers. We should only get here when the two type representations have // the same size. - if (E->getCastKind() == CK_ReinterpretMemberPointer) + if (CK == CK_ReinterpretMemberPointer) return Src; MSInheritanceAttr::Spelling SrcInheritance = getInheritanceFromMemptr(SrcTy); @@ -2960,12 +3003,16 @@ MicrosoftCXXABI::EmitMemberPointerConversion(const CastExpr *E, // For data pointers, we adjust the field offset directly. For functions, we // have a separate field. - llvm::Constant *Adj = getMemberPointerAdjustment(E); + const MemberPointerType *DerivedTy = + CK == CK_DerivedToBaseMemberPointer ? SrcTy : DstTy; + const CXXRecordDecl *DerivedClass = DerivedTy->getMostRecentCXXRecordDecl(); + llvm::Constant *Adj = + CGM.GetNonVirtualBaseClassOffset(DerivedClass, PathBegin, PathEnd); if (Adj) { Adj = llvm::ConstantExpr::getTruncOrBitCast(Adj, CGM.IntTy); llvm::Constant *&NVAdjustField = IsFunc ? NonVirtualBaseAdjustment : FirstField; - bool IsDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer); + bool IsDerivedToBase = (CK == CK_DerivedToBaseMemberPointer); if (!NVAdjustField) // If this field didn't exist in src, it's zero. NVAdjustField = getZeroInt(); if (IsDerivedToBase) -- 2.40.0