diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGCXX.cpp | 9 | ||||
-rw-r--r-- | lib/CodeGen/CGCXXABI.h | 6 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 17 | ||||
-rw-r--r-- | lib/CodeGen/ItaniumCXXABI.cpp | 30 |
4 files changed, 53 insertions, 9 deletions
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index fbea42065b..f8d81fa796 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -359,6 +359,15 @@ llvm::Value *CGCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, return llvm::Constant::getNullValue(FTy->getPointerTo()); } +llvm::Value *CGCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF, + llvm::Value *Base, + llvm::Value *MemPtr, + const MemberPointerType *MPT) { + ErrorUnsupportedABI(CGF, "loads of member pointers"); + const llvm::Type *Ty = CGF.ConvertType(MPT->getPointeeType())->getPointerTo(); + return llvm::Constant::getNullValue(Ty); +} + llvm::Value *CGCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, const CastExpr *E, llvm::Value *Src) { diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h index b87d6c0259..8d3e70f0b3 100644 --- a/lib/CodeGen/CGCXXABI.h +++ b/lib/CodeGen/CGCXXABI.h @@ -88,6 +88,12 @@ public: llvm::Value *MemPtr, const MemberPointerType *MPT); + /// Calculate an l-value from an object and a data member pointer. + virtual llvm::Value *EmitMemberDataPointerAddress(CodeGenFunction &CGF, + llvm::Value *Base, + llvm::Value *MemPtr, + const MemberPointerType *MPT); + /// Perform a derived-to-base or base-to-derived member pointer /// conversion. virtual llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF, diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index a676333f49..1af0d56b44 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -2090,16 +2090,15 @@ EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E) { BaseV = EmitScalarExpr(E->getLHS()); else BaseV = EmitLValue(E->getLHS()).getAddress(); - const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(getLLVMContext()); - BaseV = Builder.CreateBitCast(BaseV, i8Ty); + llvm::Value *OffsetV = EmitScalarExpr(E->getRHS()); - llvm::Value *AddV = Builder.CreateInBoundsGEP(BaseV, OffsetV, "add.ptr"); - QualType Ty = E->getRHS()->getType(); - Ty = Ty->getAs<MemberPointerType>()->getPointeeType(); - - const llvm::Type *PType = ConvertType(getContext().getPointerType(Ty)); - AddV = Builder.CreateBitCast(AddV, PType); - return MakeAddrLValue(AddV, Ty); + const MemberPointerType *MPT + = E->getRHS()->getType()->getAs<MemberPointerType>(); + + llvm::Value *AddV = + CGM.getCXXABI().EmitMemberDataPointerAddress(*this, BaseV, OffsetV, MPT); + + return MakeAddrLValue(AddV, MPT->getPointeeType()); } diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index 920b833b25..13768006f4 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -66,6 +66,11 @@ public: llvm::Value *MemFnPtr, const MemberPointerType *MPT); + llvm::Value *EmitMemberDataPointerAddress(CodeGenFunction &CGF, + llvm::Value *Base, + llvm::Value *MemPtr, + const MemberPointerType *MPT); + llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF, const CastExpr *E, llvm::Value *Src); @@ -261,6 +266,31 @@ ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, return Callee; } +/// Compute an l-value by applying the given pointer-to-member to a +/// base object. +llvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF, + llvm::Value *Base, + llvm::Value *MemPtr, + const MemberPointerType *MPT) { + assert(MemPtr->getType() == getPtrDiffTy()); + + CGBuilderTy &Builder = CGF.Builder; + + unsigned AS = cast<llvm::PointerType>(Base->getType())->getAddressSpace(); + + // Cast to char*. + Base = Builder.CreateBitCast(Base, Builder.getInt8Ty()->getPointerTo(AS)); + + // Apply the offset, which we assume is non-null. + llvm::Value *Addr = Builder.CreateInBoundsGEP(Base, MemPtr, "memptr.offset"); + + // Cast the address to the appropriate pointer type, adopting the + // address space of the base pointer. + const llvm::Type *PType + = CGF.ConvertType(MPT->getPointeeType())->getPointerTo(AS); + return Builder.CreateBitCast(Addr, PType); +} + /// Perform a derived-to-base or base-to-derived member pointer conversion. /// /// Obligatory offset/adjustment diagram: |