diff options
author | John McCall <rjmccall@apple.com> | 2010-08-22 03:04:22 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-08-22 03:04:22 +0000 |
commit | 3023def6bea3af6dbb51eea51f8cb8ea892d26cf (patch) | |
tree | 6b36fd5c4cd5344c45cd709f58d267a1d3b83093 /lib/CodeGen/ItaniumCXXABI.cpp | |
parent | a7e6845660f91ec611427e1db842780e1ec12bdb (diff) |
Abstract out member-pointer conversions.
Pretty much everything having to do with member pointers is ABI-specific.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111770 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/ItaniumCXXABI.cpp')
-rw-r--r-- | lib/CodeGen/ItaniumCXXABI.cpp | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index 9ab7591ca2..9fc6be179d 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -46,6 +46,12 @@ public: llvm::Value *&This, llvm::Value *MemFnPtr, const MemberPointerType *MPT); + + void EmitMemberPointerConversion(CodeGenFunction &CGF, + const CastExpr *E, + llvm::Value *Src, + llvm::Value *Dest, + bool VolatileDest); }; class ARMCXXABI : public ItaniumCXXABI { @@ -168,3 +174,54 @@ ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, Callee->addIncoming(NonVirtualFn, FnNonVirtual); return Callee; } + +/// 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) { + assert(E->getCastKind() == CastExpr::CK_DerivedToBaseMemberPointer || + E->getCastKind() == CastExpr::CK_BaseToDerivedMemberPointer); + + CGBuilderTy &Builder = CGF.Builder; + + const MemberPointerType *SrcTy = + E->getSubExpr()->getType()->getAs<MemberPointerType>(); + const MemberPointerType *DestTy = E->getType()->getAs<MemberPointerType>(); + + const CXXRecordDecl *SrcDecl = SrcTy->getClass()->getAsCXXRecordDecl(); + const CXXRecordDecl *DestDecl = DestTy->getClass()->getAsCXXRecordDecl(); + + llvm::Value *SrcPtr = Builder.CreateStructGEP(Src, 0, "src.ptr"); + SrcPtr = Builder.CreateLoad(SrcPtr); + + llvm::Value *SrcAdj = Builder.CreateStructGEP(Src, 1, "src.adj"); + SrcAdj = Builder.CreateLoad(SrcAdj); + + llvm::Value *DstPtr = Builder.CreateStructGEP(Dest, 0, "dst.ptr"); + Builder.CreateStore(SrcPtr, DstPtr, VolatileDest); + + llvm::Value *DstAdj = Builder.CreateStructGEP(Dest, 1, "dst.adj"); + + bool DerivedToBase = + E->getCastKind() == CastExpr::CK_DerivedToBaseMemberPointer; + + const CXXRecordDecl *BaseDecl, *DerivedDecl; + if (DerivedToBase) + DerivedDecl = SrcDecl, BaseDecl = DestDecl; + else + BaseDecl = SrcDecl, DerivedDecl = DestDecl; + + if (llvm::Constant *Adj = + CGF.CGM.GetNonVirtualBaseClassOffset(DerivedDecl, + E->path_begin(), + E->path_end())) { + if (DerivedToBase) + SrcAdj = Builder.CreateSub(SrcAdj, Adj, "adj"); + else + SrcAdj = Builder.CreateAdd(SrcAdj, Adj, "adj"); + } + + Builder.CreateStore(SrcAdj, DstAdj, VolatileDest); +} |