diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2009-10-15 07:44:25 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2009-10-15 07:44:25 +0000 |
commit | 67e5495076feb6c1338273ace96b58da95cdaf61 (patch) | |
tree | badd8f913c2a7db8d5fbe7d83c862e35e403fd41 /lib/CodeGen | |
parent | 9092c3e0fa01f3139b016d05d267a89e3b07747a (diff) | |
download | FreeBSD-src-67e5495076feb6c1338273ace96b58da95cdaf61.zip FreeBSD-src-67e5495076feb6c1338273ace96b58da95cdaf61.tar.gz |
Update clang to 84175.
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 48 | ||||
-rw-r--r-- | lib/CodeGen/CGVtable.cpp | 96 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 47 |
3 files changed, 156 insertions, 35 deletions
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 2834dfe..01a057f 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -78,6 +78,26 @@ RValue CodeGenFunction::EmitAnyExprToTemp(const Expr *E, RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E, QualType DestType, bool IsInitializer) { + if (const CXXExprWithTemporaries *TE = dyn_cast<CXXExprWithTemporaries>(E)) { + // If we shouldn't destroy the temporaries, just emit the + // child expression. + if (!TE->shouldDestroyTemporaries()) + return EmitReferenceBindingToExpr(TE->getSubExpr(), DestType, + IsInitializer); + + // Keep track of the current cleanup stack depth. + unsigned OldNumLiveTemporaries = LiveTemporaries.size(); + + RValue RV = EmitReferenceBindingToExpr(TE->getSubExpr(), DestType, + IsInitializer); + + // Pop temporaries. + while (LiveTemporaries.size() > OldNumLiveTemporaries) + PopCXXTemporary(); + + return RV; + } + RValue Val; if (E->isLvalue(getContext()) == Expr::LV_Valid) { // Emit the expr as an lvalue. @@ -86,9 +106,21 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E, return RValue::get(LV.getAddress()); Val = EmitLoadOfLValue(LV, E->getType()); } else { - // FIXME: Initializers don't work with casts yet. For example - // const A& a = B(); - // if B inherits from A. + const CXXRecordDecl *BaseClassDecl = 0; + const CXXRecordDecl *DerivedClassDecl = 0; + + if (const CastExpr *CE = + dyn_cast<CastExpr>(E->IgnoreParenNoopCasts(getContext()))) { + if (CE->getCastKind() == CastExpr::CK_DerivedToBase) { + E = CE->getSubExpr(); + + BaseClassDecl = + cast<CXXRecordDecl>(CE->getType()->getAs<RecordType>()->getDecl()); + DerivedClassDecl = + cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl()); + } + } + Val = EmitAnyExprToTemp(E, /*IsAggLocVolatile=*/false, IsInitializer); @@ -106,6 +138,16 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E, } } } + + // Check if need to perform the derived-to-base cast. + if (BaseClassDecl) { + llvm::Value *Derived = Val.getAggregateAddr(); + + llvm::Value *Base = + GetAddressCXXOfBaseClass(Derived, DerivedClassDecl, BaseClassDecl, + /*NullCheckValue=*/false); + return RValue::get(Base); + } } if (Val.isAggregate()) { diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 41f7eef..6e73db3 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -56,6 +56,8 @@ private: const bool Extern; const uint32_t LLVMPointerWidth; Index_t extra; + int CurrentVBaseOffset; + typedef std::vector<std::pair<const CXXRecordDecl *, int64_t> > Path_t; public: VtableBuilder(std::vector<llvm::Constant *> &meth, const CXXRecordDecl *c, @@ -63,7 +65,8 @@ public: : methods(meth), Class(c), BLayout(cgm.getContext().getASTRecordLayout(c)), rtti(cgm.GenerateRtti(c)), VMContext(cgm.getModule().getContext()), CGM(cgm), Extern(true), - LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0)) { + LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0)), + CurrentVBaseOffset(0) { Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0); } @@ -187,7 +190,10 @@ public: VCall[MD] = idx; CallOffset ThisOffset; // FIXME: calculate non-virtual offset - ThisOffset = std::make_pair(0, -((idx+extra+2)*LLVMPointerWidth/8)); + ThisOffset = std::make_pair(0 /* -CurrentVBaseOffset/8 + Offset/8 */, + -((idx+extra+2)*LLVMPointerWidth/8)); + // FIXME: Do we always have to build a covariant thunk to save oret, + // which is the containing virtual base class? if (ReturnOffset.first || ReturnOffset.second) CovariantThunks[MD] = std::make_pair(std::make_pair(ThisOffset, ReturnOffset), @@ -199,6 +205,7 @@ public: // FIXME: finish off int64_t O = VCallOffset[OMD] - Offset/8; + // int64_t O = CurrentVBaseOffset/8 - Offset/8; if (O || ReturnOffset.first || ReturnOffset.second) { CallOffset ThisOffset = std::make_pair(O, 0); @@ -241,10 +248,8 @@ public: CovariantThunks.clear(); } - void OverrideMethods(std::vector<std::pair<const CXXRecordDecl *, - int64_t> > *Path, bool MorallyVirtual) { - for (std::vector<std::pair<const CXXRecordDecl *, - int64_t> >::reverse_iterator i =Path->rbegin(), + void OverrideMethods(Path_t *Path, bool MorallyVirtual) { + for (Path_t::reverse_iterator i = Path->rbegin(), e = Path->rend(); i != e; ++i) { const CXXRecordDecl *RD = i->first; int64_t Offset = i->second; @@ -314,7 +319,8 @@ public: void NonVirtualBases(const CXXRecordDecl *RD, const ASTRecordLayout &Layout, const CXXRecordDecl *PrimaryBase, bool PrimaryBaseWasVirtual, bool MorallyVirtual, - int64_t Offset) { + int64_t Offset, Path_t *Path) { + Path->push_back(std::make_pair(RD, Offset)); for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), e = RD->bases_end(); i != e; ++i) { if (i->isVirtual()) @@ -324,41 +330,65 @@ public: if (Base != PrimaryBase || PrimaryBaseWasVirtual) { uint64_t o = Offset + Layout.getBaseClassOffset(Base); StartNewTable(); - std::vector<std::pair<const CXXRecordDecl *, - int64_t> > S; - S.push_back(std::make_pair(RD, Offset)); - GenerateVtableForBase(Base, MorallyVirtual, o, false, &S); + CurrentVBaseOffset = Offset; + GenerateVtableForBase(Base, MorallyVirtual, o, false, Path); } } + Path->pop_back(); + } + +// #define D(X) do { X; } while (0) +#define D(X) + + void insertVCalls(int InsertionPoint) { + llvm::Constant *e = 0; + D(VCalls.insert(VCalls.begin(), 673)); + D(VCalls.push_back(672)); + methods.insert(methods.begin() + InsertionPoint, VCalls.size()/*+2*/, e); + // The vcalls come first... + for (std::vector<Index_t>::reverse_iterator i = VCalls.rbegin(), + e = VCalls.rend(); + i != e; ++i) + methods[InsertionPoint++] = wrap((0?600:0) + *i); + VCalls.clear(); } Index_t end(const CXXRecordDecl *RD, std::vector<llvm::Constant *> &offsets, const ASTRecordLayout &Layout, const CXXRecordDecl *PrimaryBase, bool PrimaryBaseWasVirtual, bool MorallyVirtual, - int64_t Offset, bool ForVirtualBase) { + int64_t Offset, bool ForVirtualBase, Path_t *Path) { + bool alloc = false; + if (Path == 0) { + alloc = true; + Path = new Path_t; + } + StartNewTable(); extra = 0; // FIXME: Cleanup. if (!ForVirtualBase) { + D(methods.push_back(wrap(666))); // then virtual base offsets... for (std::vector<llvm::Constant *>::reverse_iterator i = offsets.rbegin(), e = offsets.rend(); i != e; ++i) methods.push_back(*i); + D(methods.push_back(wrap(667))); } - // The vcalls come first... - for (std::vector<Index_t>::reverse_iterator i=VCalls.rbegin(), - e=VCalls.rend(); - i != e; ++i) - methods.push_back(wrap((0?600:0) + *i)); - VCalls.clear(); + bool DeferVCalls = MorallyVirtual || ForVirtualBase; + int VCallInsertionPoint = methods.size(); + if (!DeferVCalls) { + insertVCalls(VCallInsertionPoint); + } if (ForVirtualBase) { + D(methods.push_back(wrap(668))); // then virtual base offsets... for (std::vector<llvm::Constant *>::reverse_iterator i = offsets.rbegin(), e = offsets.rend(); i != e; ++i) methods.push_back(*i); + D(methods.push_back(wrap(669))); } methods.push_back(wrap(-(Offset/8))); @@ -371,7 +401,18 @@ public: // and then the non-virtual bases. NonVirtualBases(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual, - MorallyVirtual, Offset); + MorallyVirtual, Offset, Path); + + if (ForVirtualBase) { + D(methods.push_back(wrap(670))); + insertVCalls(VCallInsertionPoint); + AddressPoint += VCalls.size(); + D(methods.push_back(wrap(671))); + } + + if (alloc) { + delete Path; + } return AddressPoint; } @@ -397,8 +438,7 @@ public: int64_t GenerateVtableForBase(const CXXRecordDecl *RD, bool MorallyVirtual = false, int64_t Offset = 0, bool ForVirtualBase = false, - std::vector<std::pair<const CXXRecordDecl *, - int64_t> > *Path = 0) { + Path_t *Path = 0) { if (!RD->isDynamicClass()) return 0; @@ -426,18 +466,16 @@ public: OverrideMethods(Path, MorallyVirtual); return end(RD, offsets, Layout, PrimaryBase, PrimaryBaseWasVirtual, - MorallyVirtual, Offset, ForVirtualBase); + MorallyVirtual, Offset, ForVirtualBase, Path); } void GenerateVtableForVBases(const CXXRecordDecl *RD, int64_t Offset = 0, - std::vector<std::pair<const CXXRecordDecl *, - int64_t> > *Path = 0) { + Path_t *Path = 0) { bool alloc = false; if (Path == 0) { alloc = true; - Path = new std::vector<std::pair<const CXXRecordDecl *, - int64_t> >; + Path = new Path_t; } // FIXME: We also need to override using all paths to a virtual base, // right now, we just process the first path @@ -450,14 +488,18 @@ public: // Mark it so we don't output it twice. IndirectPrimary.insert(Base); StartNewTable(); + VCall.clear(); int64_t BaseOffset = BLayout.getVBaseClassOffset(Base); + CurrentVBaseOffset = BaseOffset; GenerateVtableForBase(Base, true, BaseOffset, true, Path); } int64_t BaseOffset = Offset; if (i->isVirtual()) BaseOffset = BLayout.getVBaseClassOffset(Base); - if (Base->getNumVBases()) + if (Base->getNumVBases()) { + CurrentVBaseOffset = BaseOffset; GenerateVtableForVBases(Base, BaseOffset, Path); + } } Path->pop_back(); if (alloc) diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 36ad7f5..4763b7f 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -541,7 +541,12 @@ bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) { } } - return VD->getStorageClass() == VarDecl::Static; + // Static data may be deferred, but out-of-line static data members + // cannot be. + // FIXME: What if the initializer has side effects? + return VD->isInAnonymousNamespace() || + (VD->getStorageClass() == VarDecl::Static && + !(VD->isStaticDataMember() && VD->isOutOfLine())); } void CodeGenModule::EmitGlobal(GlobalDecl GD) { @@ -928,6 +933,37 @@ void CodeGenModule::EmitTentativeDefinition(const VarDecl *D) { EmitGlobalVarDefinition(D); } +static CodeGenModule::GVALinkage +GetLinkageForVariable(ASTContext &Context, const VarDecl *VD) { + // Everything located semantically within an anonymous namespace is + // always internal. + if (VD->isInAnonymousNamespace()) + return CodeGenModule::GVA_Internal; + + // Handle linkage for static data members. + if (VD->isStaticDataMember()) { + switch (VD->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ExplicitSpecialization: + case TSK_ExplicitInstantiationDefinition: + return CodeGenModule::GVA_StrongExternal; + + case TSK_ExplicitInstantiationDeclaration: + assert(false && "Variable should not be instantiated"); + // Fall through to treat this like any other instantiation. + + case TSK_ImplicitInstantiation: + return CodeGenModule::GVA_TemplateInstantiation; + } + } + + // Static variables get internal linkage. + if (VD->getStorageClass() == VarDecl::Static) + return CodeGenModule::GVA_Internal; + + return CodeGenModule::GVA_StrongExternal; +} + void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { llvm::Constant *Init = 0; QualType ASTTy = D->getType(); @@ -1021,9 +1057,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { GV->setAlignment(getContext().getDeclAlignInBytes(D)); // Set the llvm linkage type as appropriate. - if (D->isInAnonymousNamespace()) - GV->setLinkage(llvm::Function::InternalLinkage); - else if (D->getStorageClass() == VarDecl::Static) + GVALinkage Linkage = GetLinkageForVariable(getContext(), D); + if (Linkage == GVA_Internal) GV->setLinkage(llvm::Function::InternalLinkage); else if (D->hasAttr<DLLImportAttr>()) GV->setLinkage(llvm::Function::DLLImportLinkage); @@ -1034,7 +1069,9 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { GV->setLinkage(llvm::GlobalVariable::WeakODRLinkage); else GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage); - } else if (!CompileOpts.NoCommon && + } else if (Linkage == GVA_TemplateInstantiation) + GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage); + else if (!CompileOpts.NoCommon && !D->hasExternalStorage() && !D->getInit() && !D->getAttr<SectionAttr>()) { GV->setLinkage(llvm::GlobalVariable::CommonLinkage); |