Extend the visibility-hidden optimization to linkonce_odr thunks for

functions with in-line definitions, since such thunks will be emitted at any
use of the function.

Completes the feature work for rdar://problem/7523229.

llvm-svn: 110285
This commit is contained in:
John McCall 2010-08-04 23:46:35 +00:00
parent 6b67ee425d
commit c8bd9c277b
2 changed files with 65 additions and 2 deletions

View File

@ -2460,6 +2460,56 @@ static llvm::Value *PerformTypeAdjustment(CodeGenFunction &CGF,
return CGF.Builder.CreateBitCast(V, Ptr->getType());
}
static void setThunkVisibility(CodeGenModule &CGM, const CXXMethodDecl *MD,
const ThunkInfo &Thunk, llvm::Function *Fn) {
CGM.setGlobalVisibility(Fn, MD);
// If the thunk has weak/linkonce linkage, but the function must be
// emitted in every translation unit that references it, then we can
// emit its thunks with hidden visibility, since its thunks must be
// emitted when the function is.
// This mostly follows CodeGenModule::setTypeVisibility.
if ((Fn->getLinkage() != llvm::GlobalVariable::LinkOnceODRLinkage &&
Fn->getLinkage() != llvm::GlobalVariable::WeakODRLinkage) ||
Fn->getVisibility() != llvm::GlobalVariable::DefaultVisibility)
return;
// Don't override an explicit visibility attribute.
if (MD->hasAttr<VisibilityAttr>())
return;
switch (MD->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 an explicit definition, and that definition is
// out-of-line, then we can't assume that all users will have a
// definition to emit.
const FunctionDecl *Def = 0;
if (MD->hasBody(Def) && Def->isOutOfLine())
return;
Fn->setVisibility(llvm::GlobalValue::HiddenVisibility);
}
void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD,
const ThunkInfo &Thunk) {
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
@ -2582,7 +2632,7 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD,
CGM.setFunctionLinkage(MD, Fn);
// Set the right visibility.
CGM.setGlobalVisibility(Fn, MD);
setThunkVisibility(CGM, MD, Thunk, Fn);
}
void CodeGenVTables::EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk)

View File

@ -246,8 +246,21 @@ namespace Test9 {
}
}
namespace Test10 {
struct A { virtual void foo(); };
struct B { virtual void foo(); };
struct C : A, B { void foo() {} };
// CHECK: define linkonce_odr void @_ZN6Test101C3fooEv
// CHECK: define linkonce_odr hidden void @_ZThn8_N6Test101C3fooEv
void test() {
C c;
}
}
/**** The following has to go at the end of the file ****/
// This is from Test5:
// CHECK: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
// CHECK: define linkonce_odr hidden void @_ZTv0_n24_N5Test51B1fEv
// CHECK: define internal void @_ZThn8_N12_GLOBAL__N_11C1fEv(