From: Mike Stump Date: Thu, 19 Nov 2009 01:08:19 +0000 (+0000) Subject: Improve instantiation control for rtti data and allow key functions to X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=58588943a8283baf17815d56275bdb381560970c;p=clang Improve instantiation control for rtti data and allow key functions to instantiate a class. WIP. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89289 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGRtti.cpp b/lib/CodeGen/CGRtti.cpp index e18843d5cf..79d866427f 100644 --- a/lib/CodeGen/CGRtti.cpp +++ b/lib/CodeGen/CGRtti.cpp @@ -47,21 +47,35 @@ public: return llvm::ConstantExpr::getBitCast(C, Int8PtrTy); } - llvm::Constant *BuildName(QualType Ty, bool Hidden) { + llvm::Constant *BuildName(QualType Ty, bool Hidden, bool Extern) { llvm::SmallString<256> OutName; llvm::raw_svector_ostream Out(OutName); mangleCXXRttiName(CGM.getMangleContext(), Ty, Out); + llvm::StringRef Name = Out.str(); llvm::GlobalVariable::LinkageTypes linktype; linktype = llvm::GlobalValue::LinkOnceODRLinkage; + if (!Extern) + linktype = llvm::GlobalValue::InternalLinkage; + + llvm::GlobalVariable *GV; + GV = CGM.getModule().getGlobalVariable(Name); + if (GV && !GV->isDeclaration()) + return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); llvm::Constant *C; - C = llvm::ConstantArray::get(VMContext, Out.str().substr(4)); + C = llvm::ConstantArray::get(VMContext, Name.substr(4)); - llvm::GlobalVariable * GV = new llvm::GlobalVariable(CGM.getModule(), - C->getType(), - true, linktype, C, - Out.str()); + llvm::GlobalVariable *OGV = GV; + GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, linktype, + C, Name); + if (OGV) { + GV->takeName(OGV); + llvm::Constant *NewPtr = llvm::ConstantExpr::getBitCast(GV, + OGV->getType()); + OGV->replaceAllUsesWith(NewPtr); + OGV->eraseFromParent(); + } if (Hidden) GV->setVisibility(llvm::GlobalVariable::HiddenVisibility); return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); @@ -87,8 +101,9 @@ public: llvm::SmallString<256> OutName; llvm::raw_svector_ostream Out(OutName); mangleCXXRtti(CGM.getMangleContext(), Ty, Out); + llvm::StringRef Name = Out.str(); - C = CGM.getModule().getGlobalVariable(Out.str()); + C = CGM.getModule().getGlobalVariable(Name); if (C) return llvm::ConstantExpr::getBitCast(C, Int8PtrTy); @@ -96,7 +111,7 @@ public: linktype = llvm::GlobalValue::ExternalLinkage;; C = new llvm::GlobalVariable(CGM.getModule(), Int8PtrTy, true, linktype, - 0, Out.str()); + 0, Name); return llvm::ConstantExpr::getBitCast(C, Int8PtrTy); } @@ -147,20 +162,19 @@ public: llvm::Constant *finish(std::vector &info, llvm::GlobalVariable *GV, - llvm::StringRef Name, bool Hidden) { + llvm::StringRef Name, bool Hidden, bool Extern) { llvm::GlobalVariable::LinkageTypes linktype; linktype = llvm::GlobalValue::LinkOnceODRLinkage; + if (!Extern) + linktype = llvm::GlobalValue::InternalLinkage; llvm::Constant *C; C = llvm::ConstantStruct::get(VMContext, &info[0], info.size(), false); - if (GV == 0) - GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, - linktype, C, Name); - else { - llvm::GlobalVariable *OGV = GV; - GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, - linktype, C, Name); + llvm::GlobalVariable *OGV = GV; + GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, linktype, + C, Name); + if (OGV) { GV->takeName(OGV); llvm::Constant *NewPtr = llvm::ConstantExpr::getBitCast(GV, OGV->getType()); @@ -183,15 +197,17 @@ public: llvm::raw_svector_ostream Out(OutName); mangleCXXRtti(CGM.getMangleContext(), CGM.getContext().getTagDeclType(RD), Out); + llvm::StringRef Name = Out.str(); llvm::GlobalVariable *GV; - GV = CGM.getModule().getGlobalVariable(Out.str()); + GV = CGM.getModule().getGlobalVariable(Name); if (GV && !GV->isDeclaration()) return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); std::vector info; bool Hidden = CGM.getDeclVisibilityMode(RD) == LangOptions::Hidden; + bool Extern = !RD->isInAnonymousNamespace(); bool simple = false; if (RD->getNumBases() == 0) @@ -202,7 +218,8 @@ public: } else C = BuildVtableRef("_ZTVN10__cxxabiv121__vmi_class_type_infoE"); info.push_back(C); - info.push_back(BuildName(CGM.getContext().getTagDeclType(RD), Hidden)); + info.push_back(BuildName(CGM.getContext().getTagDeclType(RD), Hidden, + Extern)); // If we have no bases, there are no more fields. if (RD->getNumBases()) { @@ -235,7 +252,7 @@ public: } } - return finish(info, GV, Out.str(), Hidden); + return finish(info, GV, Name, Hidden, Extern); } /// - BuildFlags - Build a __flags value for __pbase_type_info. @@ -250,23 +267,49 @@ public: return BuildType(Ty); } + bool DecideExtern(QualType Ty) { + // For this type, see if all components are never in an anonymous namespace. + if (const MemberPointerType *MPT = Ty->getAs()) + return (DecideExtern(MPT->getPointeeType()) + && DecideExtern(QualType(MPT->getClass(), 0))); + if (const PointerType *PT = Ty->getAs()) + return DecideExtern(PT->getPointeeType()); + if (const RecordType *RT = Ty->getAs()) + if (const CXXRecordDecl *RD = dyn_cast(RT->getDecl())) + return !RD->isInAnonymousNamespace(); + return true; + } + + bool DecideHidden(QualType Ty) { + // For this type, see if all components are never hidden. + if (const MemberPointerType *MPT = Ty->getAs()) + return (DecideHidden(MPT->getPointeeType()) + && DecideHidden(QualType(MPT->getClass(), 0))); + if (const PointerType *PT = Ty->getAs()) + return DecideHidden(PT->getPointeeType()); + if (const RecordType *RT = Ty->getAs()) + if (const CXXRecordDecl *RD = dyn_cast(RT->getDecl())) + return CGM.getDeclVisibilityMode(RD) == LangOptions::Hidden; + return false; + } + llvm::Constant *BuildPointerType(QualType Ty) { llvm::Constant *C; llvm::SmallString<256> OutName; llvm::raw_svector_ostream Out(OutName); mangleCXXRtti(CGM.getMangleContext(), Ty, Out); + llvm::StringRef Name = Out.str(); llvm::GlobalVariable *GV; - GV = CGM.getModule().getGlobalVariable(Out.str()); + GV = CGM.getModule().getGlobalVariable(Name); if (GV && !GV->isDeclaration()) return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); std::vector info; - // FIXME: pointer to hidden should be hidden, we should be able to - // grab a bit off the type for this. - bool Hidden = false; + bool Extern = DecideExtern(Ty); + bool Hidden = DecideHidden(Ty); QualType PTy = Ty->getPointeeType(); QualType BTy; @@ -282,7 +325,7 @@ public: else C = BuildVtableRef("_ZTVN10__cxxabiv119__pointer_type_infoE"); info.push_back(C); - info.push_back(BuildName(Ty, Hidden)); + info.push_back(BuildName(Ty, Hidden, Extern)); Qualifiers Q = PTy.getQualifiers(); PTy = CGM.getContext().getCanonicalType(PTy).getUnqualifiedType(); int flags = 0; @@ -300,7 +343,8 @@ public: if (PtrMem) info.push_back(BuildType2(BTy)); - return finish(info, GV, Out.str(), true); + // We always generate these as hidden, only the name isn't hidden. + return finish(info, GV, Name, true, Extern); } llvm::Constant *BuildSimpleType(QualType Ty, const char *vtbl) { @@ -309,23 +353,24 @@ public: llvm::SmallString<256> OutName; llvm::raw_svector_ostream Out(OutName); mangleCXXRtti(CGM.getMangleContext(), Ty, Out); + llvm::StringRef Name = Out.str(); llvm::GlobalVariable *GV; - GV = CGM.getModule().getGlobalVariable(Out.str()); + GV = CGM.getModule().getGlobalVariable(Name); if (GV && !GV->isDeclaration()) return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); std::vector info; - // FIXME: pointer to hidden should be hidden, we should be able to - // grab a bit off the type for this. - bool Hidden = false; + bool Extern = DecideExtern(Ty); + bool Hidden = DecideHidden(Ty); C = BuildVtableRef(vtbl); info.push_back(C); - info.push_back(BuildName(Ty, Hidden)); + info.push_back(BuildName(Ty, Hidden, Extern)); - return finish(info, GV, Out.str(), true); + // We always generate these as hidden, only the name isn't hidden. + return finish(info, GV, Name, true, Extern); } llvm::Constant *BuildType(QualType Ty) { diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index a726fec571..d107edcbd7 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -1021,6 +1021,12 @@ llvm::Constant *CodeGenModule::GenerateVTT(const CXXRecordDecl *RD) { return llvm::ConstantExpr::getBitCast(vtt, Ptr8Ty); } +void CGVtableInfo::GenerateClassData(const CXXRecordDecl *RD) { + Vtables[RD] = CGM.GenerateVtable(RD, RD); + CGM.GenerateRtti(RD); + CGM.GenerateVTT(RD); +} + llvm::Constant *CGVtableInfo::getVtable(const CXXRecordDecl *RD) { llvm::Constant *&vtbl = Vtables[RD]; if (vtbl) diff --git a/lib/CodeGen/CGVtable.h b/lib/CodeGen/CGVtable.h index f9ddf44284..78ae670cf3 100644 --- a/lib/CodeGen/CGVtable.h +++ b/lib/CodeGen/CGVtable.h @@ -61,6 +61,10 @@ public: llvm::Constant *getVtable(const CXXRecordDecl *RD); llvm::Constant *getCtorVtable(const CXXRecordDecl *RD, const CXXRecordDecl *Class, uint64_t Offset); + /// GenerateClassData - Generate all the class data requires to be generated + /// upon definition of a KeyFunction. This includes the vtable, the + /// rtti data structure and the VTT. + void GenerateClassData(const CXXRecordDecl *RD); }; } diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 0e6f4a63a4..195acc5bc1 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -616,6 +616,16 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) { Context.getSourceManager(), "Generating code for declaration"); + if (const CXXMethodDecl *MD = dyn_cast(D)) { + const CXXRecordDecl *RD = MD->getParent(); + // We have to convert it to have a record layout. + Types.ConvertTagDeclType(RD); + const CGRecordLayout &CGLayout = Types.getCGRecordLayout(RD); + // A definition of a KeyFunction, generates all the class data, such + // as vtable, rtti and the VTT. + if (CGLayout.getKeyFunction() == MD) + getVtableInfo().GenerateClassData(RD); + } if (const CXXConstructorDecl *CD = dyn_cast(D)) EmitCXXConstructor(CD, GD.getCtorType()); else if (const CXXDestructorDecl *DD = dyn_cast(D))