diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGCXXABI.cpp | 7 | ||||
-rw-r--r-- | lib/CodeGen/CGCXXABI.h | 3 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 22 | ||||
-rw-r--r-- | lib/CodeGen/CGExprConstant.cpp | 51 | ||||
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 6 | ||||
-rw-r--r-- | lib/CodeGen/CGValue.h | 2 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.h | 2 | ||||
-rw-r--r-- | lib/CodeGen/ItaniumCXXABI.cpp | 41 |
8 files changed, 59 insertions, 75 deletions
diff --git a/lib/CodeGen/CGCXXABI.cpp b/lib/CodeGen/CGCXXABI.cpp index 7fb1ffde2d..8373b660b2 100644 --- a/lib/CodeGen/CGCXXABI.cpp +++ b/lib/CodeGen/CGCXXABI.cpp @@ -105,10 +105,9 @@ llvm::Constant *CGCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) { MD->getParent()->getTypeForDecl())); } -llvm::Constant *CGCXXABI::EmitMemberPointer(const FieldDecl *FD) { - return GetBogusMemberPointer(CGM, - CGM.getContext().getMemberPointerType(FD->getType(), - FD->getParent()->getTypeForDecl())); +llvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, + CharUnits offset) { + return GetBogusMemberPointer(CGM, QualType(MPT, 0)); } bool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) { diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h index 547f98ac21..de4df3dcbe 100644 --- a/lib/CodeGen/CGCXXABI.h +++ b/lib/CodeGen/CGCXXABI.h @@ -122,7 +122,8 @@ public: virtual llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD); /// Create a member pointer for the given field. - virtual llvm::Constant *EmitMemberPointer(const FieldDecl *FD); + virtual llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT, + CharUnits offset); /// Emit a comparison between two member pointers. Returns an i1. virtual llvm::Value * diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 8bac4c0b02..2108e21ed3 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1178,24 +1178,10 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { setObjCGCLValueClass(getContext(), E, LV); return LV; } - - // If we're emitting an instance method as an independent lvalue, - // we're actually emitting a member pointer. - if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND)) - if (MD->isInstance()) { - llvm::Value *V = CGM.getCXXABI().EmitMemberPointer(MD); - return MakeAddrLValue(V, MD->getType(), Alignment); - } - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) - return EmitFunctionDeclLValue(*this, E, FD); - - // If we're emitting a field as an independent lvalue, we're - // actually emitting a member pointer. - if (const FieldDecl *FD = dyn_cast<FieldDecl>(ND)) { - llvm::Value *V = CGM.getCXXABI().EmitMemberPointer(FD); - return MakeAddrLValue(V, FD->getType(), Alignment); - } - + + if (const FunctionDecl *fn = dyn_cast<FunctionDecl>(ND)) + return EmitFunctionDeclLValue(*this, E, fn); + assert(false && "Unhandled DeclRefExpr"); // an invalid LValue, but the assert will diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 51b1de37a9..4d8a60e1e8 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -450,17 +450,10 @@ public: llvm::Constant *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { return Visit(E->getInitializer()); } - + llvm::Constant *VisitUnaryAddrOf(UnaryOperator *E) { - if (const MemberPointerType *MPT = - E->getType()->getAs<MemberPointerType>()) { - DeclRefExpr *DRE = cast<DeclRefExpr>(E->getSubExpr()); - NamedDecl *ND = DRE->getDecl(); - if (MPT->isMemberFunctionPointer()) - return CGM.getCXXABI().EmitMemberPointer(cast<CXXMethodDecl>(ND)); - else - return CGM.getCXXABI().EmitMemberPointer(cast<FieldDecl>(ND)); - } + if (E->getType()->isMemberPointerType()) + return CGM.getMemberPointerConstant(E); return 0; } @@ -934,6 +927,38 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E, return C; } +static uint64_t getFieldOffset(ASTContext &C, const FieldDecl *field) { + const ASTRecordLayout &layout = C.getASTRecordLayout(field->getParent()); + return layout.getFieldOffset(field->getFieldIndex()); +} + +llvm::Constant * +CodeGenModule::getMemberPointerConstant(const UnaryOperator *uo) { + // Member pointer constants always have a very particular form. + const MemberPointerType *type = cast<MemberPointerType>(uo->getType()); + const ValueDecl *decl = cast<DeclRefExpr>(uo->getSubExpr())->getDecl(); + + // A member function pointer. + if (const CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(decl)) + return getCXXABI().EmitMemberPointer(method); + + // Otherwise, a member data pointer. + uint64_t fieldOffset; + if (const FieldDecl *field = dyn_cast<FieldDecl>(decl)) + fieldOffset = getFieldOffset(getContext(), field); + else { + const IndirectFieldDecl *ifield = cast<IndirectFieldDecl>(decl); + + fieldOffset = 0; + for (IndirectFieldDecl::chain_iterator ci = ifield->chain_begin(), + ce = ifield->chain_end(); ci != ce; ++ci) + fieldOffset += getFieldOffset(getContext(), cast<FieldDecl>(*ci)); + } + + CharUnits chars = getContext().toCharUnitsFromBits((int64_t) fieldOffset); + return getCXXABI().EmitMemberDataPointer(type, chars); +} + static void FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T, std::vector<llvm::Constant *> &Elements, @@ -1000,9 +1025,10 @@ FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T, uint64_t StartIndex = StartOffset / 8; uint64_t EndIndex = StartIndex + CGM.getContext().getTypeSize(T) / 8; + // FIXME: hardcodes Itanium member pointer representation! llvm::Constant *NegativeOne = llvm::ConstantInt::get(llvm::Type::getInt8Ty(CGM.getLLVMContext()), - -1ULL, /*isSigned=*/true); + -1ULL, /*isSigned*/true); // Fill in the null data member pointer. for (uint64_t I = StartIndex; I != EndIndex; ++I) @@ -1123,6 +1149,5 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) { // Itanium C++ ABI 2.3: // A NULL pointer is represented as -1. - return llvm::ConstantInt::get(getTypes().ConvertTypeForMem(T), -1ULL, - /*isSigned=*/true); + return getCXXABI().EmitNullMemberPointer(T->castAs<MemberPointerType>()); } diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 096430e5ce..57627be9e3 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -307,9 +307,9 @@ public: Value *VisitUnaryAddrOf(const UnaryOperator *E) { - // If the sub-expression is an instance member reference, - // EmitDeclRefLValue will magically emit it with the appropriate - // value as the "address". + if (isa<MemberPointerType>(E->getType())) // never sugared + return CGF.CGM.getMemberPointerConstant(E); + return EmitLValue(E->getSubExpr()).getAddress(); } Value *VisitUnaryDeref(const UnaryOperator *E) { diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h index 30c872a8d5..7f77d55203 100644 --- a/lib/CodeGen/CGValue.h +++ b/lib/CodeGen/CGValue.h @@ -254,7 +254,7 @@ public: static LValue MakeAddr(llvm::Value *V, QualType T, unsigned Alignment, ASTContext &Context, llvm::MDNode *TBAAInfo = 0) { - Qualifiers Quals = Context.getCanonicalType(T).getQualifiers(); + Qualifiers Quals = T.getQualifiers(); Quals.setObjCGCAttr(Context.getObjCGCAttrKind(T)); LValue R; diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 7652b88fdc..39117c2da7 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -438,6 +438,8 @@ public: Types.UpdateCompletedType(TD); } + llvm::Constant *getMemberPointerConstant(const UnaryOperator *e); + /// EmitConstantExpr - Try to emit the given expression as a /// constant; returns 0 if the expression cannot be emitted as a /// constant. diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index 8a7ac0a83a..2068c2925c 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -79,7 +79,8 @@ public: llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT); llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD); - llvm::Constant *EmitMemberPointer(const FieldDecl *FD); + llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT, + CharUnits offset); llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF, llvm::Value *L, @@ -493,43 +494,13 @@ ItaniumCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) { /*Packed=*/false); } -static uint64_t getFieldOffset(const FieldDecl *FD, CodeGenModule &CGM) { - const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(FD->getParent()); - const llvm::StructType *ClassLTy = RL.getLLVMType(); - - unsigned FieldNo = RL.getLLVMFieldNo(FD); - return - CGM.getTargetData().getStructLayout(ClassLTy)->getElementOffset(FieldNo); -} - -llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const FieldDecl *FD) { +llvm::Constant * +ItaniumCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, + CharUnits offset) { // Itanium C++ ABI 2.3: // A pointer to data member is an offset from the base address of // the class object containing it, represented as a ptrdiff_t - - const RecordDecl *parent = FD->getParent(); - if (!parent->isAnonymousStructOrUnion()) - return llvm::ConstantInt::get(getPtrDiffTy(), getFieldOffset(FD, CGM)); - - // Handle a field injected from an anonymous struct or union. - - assert(FD->getDeclName() && "Requested pointer to member with no name!"); - - // Find the record which the field was injected into. - while (parent->isAnonymousStructOrUnion()) - parent = cast<RecordDecl>(parent->getParent()); - - RecordDecl::lookup_const_result lookup = parent->lookup(FD->getDeclName()); - assert(lookup.first != lookup.second && "Didn't find the field!"); - const IndirectFieldDecl *indirectFD = cast<IndirectFieldDecl>(*lookup.first); - - uint64_t Offset = 0; - for (IndirectFieldDecl::chain_iterator - I= indirectFD->chain_begin(), E= indirectFD->chain_end(); I!=E; ++I) { - Offset += getFieldOffset(cast<FieldDecl>(*I), CGM); - } - - return llvm::ConstantInt::get(getPtrDiffTy(), Offset); + return llvm::ConstantInt::get(getPtrDiffTy(), offset.getQuantity()); } llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) { |