diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/CodeGen/CGRTTI.cpp | 45 | ||||
-rw-r--r-- | lib/CodeGen/CGVTables.cpp | 34 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 51 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.h | 5 |
4 files changed, 90 insertions, 45 deletions
diff --git a/lib/CodeGen/CGRTTI.cpp b/lib/CodeGen/CGRTTI.cpp index 1cca97702d..0724fdfba3 100644 --- a/lib/CodeGen/CGRTTI.cpp +++ b/lib/CodeGen/CGRTTI.cpp @@ -244,11 +244,9 @@ static bool TypeInfoIsInStandardLibrary(const PointerType *PointerTy) { return TypeInfoIsInStandardLibrary(BuiltinTy); } -/// ShouldUseExternalRTTIDescriptor - Returns whether the type information for -/// the given type exists somewhere else, and that we should not emit the type -/// information in this translation unit. -static bool ShouldUseExternalRTTIDescriptor(ASTContext &Context, - QualType Ty) { +/// IsStandardLibraryRTTIDescriptor - Returns whether the type +/// information for the given type exists in the standard library. +static bool IsStandardLibraryRTTIDescriptor(QualType Ty) { // Type info for builtin types is defined in the standard library. if (const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(Ty)) return TypeInfoIsInStandardLibrary(BuiltinTy); @@ -258,6 +256,15 @@ static bool ShouldUseExternalRTTIDescriptor(ASTContext &Context, if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty)) return TypeInfoIsInStandardLibrary(PointerTy); + return false; +} + +/// ShouldUseExternalRTTIDescriptor - Returns whether the type information for +/// the given type exists somewhere else, and that we should not emit the type +/// information in this translation unit. Assumes that it is not a +/// standard-library type. +static bool ShouldUseExternalRTTIDescriptor(ASTContext &Context, + QualType Ty) { // If RTTI is disabled, don't consider key functions. if (!Context.getLangOptions().RTTI) return false; @@ -456,8 +463,7 @@ void RTTIBuilder::BuildVTablePointer(const Type *Ty) { Fields.push_back(VTable); } -llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, - bool Force) { +llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) { // We want to operate on the canonical type. Ty = CGM.getContext().getCanonicalType(Ty); @@ -469,19 +475,26 @@ llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name); if (OldGV && !OldGV->isDeclaration()) return llvm::ConstantExpr::getBitCast(OldGV, Int8PtrTy); - + // Check if there is already an external RTTI descriptor for this type. - if (!Force && ShouldUseExternalRTTIDescriptor(CGM.getContext(), Ty)) + bool IsStdLib = IsStandardLibraryRTTIDescriptor(Ty); + if (!Force && + (IsStdLib || ShouldUseExternalRTTIDescriptor(CGM.getContext(), Ty))) return GetAddrOfExternalRTTIDescriptor(Ty); - llvm::GlobalVariable::LinkageTypes Linkage = getTypeInfoLinkage(Ty); + // Emit the standard library with external linkage. + llvm::GlobalVariable::LinkageTypes Linkage; + if (IsStdLib) + Linkage = llvm::GlobalValue::ExternalLinkage; + else + Linkage = getTypeInfoLinkage(Ty); // Add the vtable pointer. BuildVTablePointer(cast<Type>(Ty)); // And the name. Fields.push_back(BuildName(Ty, DecideHidden(Ty), Linkage)); - + switch (Ty->getTypeClass()) { default: assert(false && "Unhandled type class!"); @@ -551,7 +564,15 @@ llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, OldGV->replaceAllUsesWith(NewPtr); OldGV->eraseFromParent(); } - + + // GCC only relies on the uniqueness of the type names, not the + // type_infos themselves, so we can emit these as hidden symbols. + if (const RecordType *RT = dyn_cast<RecordType>(Ty)) + CGM.setTypeVisibility(GV, cast<CXXRecordDecl>(RT->getDecl()), + /*ForRTTI*/ true); + else if (Linkage == llvm::GlobalValue::WeakODRLinkage) + GV->setVisibility(llvm::GlobalValue::HiddenVisibility); + return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); } diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp index 9cb64c6d5b..db405d3673 100644 --- a/lib/CodeGen/CGVTables.cpp +++ b/lib/CodeGen/CGVTables.cpp @@ -2925,39 +2925,7 @@ CodeGenVTables::EmitVTableDefinition(llvm::GlobalVariable *VTable, VTable->setLinkage(Linkage); // Set the right visibility. - CGM.setGlobalVisibility(VTable, RD); - - // It's okay to have multiple copies of a vtable, so don't make the - // dynamic linker unique them. Suppress this optimization if it's - // possible that there might be unresolved references elsewhere - // which can only be resolved by this emission. - if (Linkage == llvm::GlobalVariable::WeakODRLinkage && - VTable->getVisibility() == llvm::GlobalVariable::DefaultVisibility && - !RD->hasAttr<VisibilityAttr>()) { - switch (RD->getTemplateSpecializationKind()) { - - // Every use of a non-template or explicitly-specialized class's - // vtable has to emit it. - case TSK_ExplicitSpecialization: - case TSK_Undeclared: - // Implicit instantiations can ignore the possibility of an - // explicit instantiation declaration because there necessarily - // must be an EI definition somewhere with default visibility. - case TSK_ImplicitInstantiation: - // If there's a key function, there may be translation units - // that don't have the key function's definition. - if (!CGM.Context.getKeyFunction(RD)) - // Otherwise, drop the visibility to hidden. - VTable->setVisibility(llvm::GlobalValue::HiddenVisibility); - break; - - // We have to disable the optimization if this is an EI definition - // because there might be EI declarations in other shared objects. - case TSK_ExplicitInstantiationDefinition: - case TSK_ExplicitInstantiationDeclaration: - break; - } - } + CGM.setTypeVisibility(VTable, RD, /*ForRTTI*/ false); } llvm::GlobalVariable * diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 63d79132b1..d2be5af14a 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -216,6 +216,57 @@ void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV, } } +/// Set the symbol visibility of type information (vtable and RTTI) +/// associated with the given type. +void CodeGenModule::setTypeVisibility(llvm::GlobalValue *GV, + const CXXRecordDecl *RD, + bool IsForRTTI) const { + setGlobalVisibility(GV, RD); + + // We want to drop the visibility to hidden for weak type symbols. + // This isn't possible if there might be unresolved references + // elsewhere that rely on this symbol being visible. + + // Preconditions. + if (GV->getLinkage() != llvm::GlobalVariable::WeakODRLinkage || + GV->getVisibility() != llvm::GlobalVariable::DefaultVisibility) + return; + + // Don't override an explicit visibility attribute. + if (RD->hasAttr<VisibilityAttr>()) + return; + + switch (RD->getTemplateSpecializationKind()) { + // We have to disable the optimization if this is an EI definition + // because there might be EI declarations in other shared objects. + case TSK_ExplicitInstantiationDefinition: + case TSK_ExplicitInstantiationDeclaration: + return; + + // Every use of a non-template or explicitly-specialized class's + // type information has to emit it. + case TSK_ExplicitSpecialization: + case TSK_Undeclared: + break; + + // Implicit instantiations can ignore the possibility of an + // explicit instantiation declaration because there necessarily + // must be an EI definition somewhere with default visibility. + case TSK_ImplicitInstantiation: + break; + } + + // If there's a key function, there may be translation units + // that don't have the key function's definition. But ignore + // this if we're emitting RTTI under -fno-rtti. + if (!IsForRTTI || Features.RTTI) + if (Context.getKeyFunction(RD)) + return; + + // Otherwise, drop the visibility to hidden. + GV->setVisibility(llvm::GlobalValue::HiddenVisibility); +} + llvm::StringRef CodeGenModule::getMangledName(GlobalDecl GD) { const NamedDecl *ND = cast<NamedDecl>(GD.getDecl()); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 2cb345a8a2..a4d8368d4d 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -270,6 +270,11 @@ public: /// GlobalValue. void setGlobalVisibility(llvm::GlobalValue *GV, const Decl *D) const; + /// setTypeVisibility - Set the visibility for the given global + /// value which holds information about a type. + void setTypeVisibility(llvm::GlobalValue *GV, const CXXRecordDecl *D, + bool IsForRTTI) const; + llvm::Constant *GetAddrOfGlobal(GlobalDecl GD) { if (isa<CXXConstructorDecl>(GD.getDecl())) return GetAddrOfCXXConstructor(cast<CXXConstructorDecl>(GD.getDecl()), |