LTOCodeGenerator: turns linkonce(_odr) into weak_(odr) when present "MustPreserve" set

Summary:
If the linker requested to preserve a linkonce function, we should
honor this even if we drop all uses.

Reviewers: dexonsmith

Subscribers: llvm-commits, joker.eph

Differential Revision: http://reviews.llvm.org/D19527

From: Mehdi Amini <mehdi.amini@apple.com>

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@267644 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Mehdi Amini 2016-04-27 00:32:02 +00:00
parent 7f794cf472
commit e69ab0b5ff
2 changed files with 53 additions and 22 deletions

View File

@ -348,14 +348,58 @@ std::unique_ptr<TargetMachine> LTOCodeGenerator::createTargetMachine() {
RelocModel, CodeModel::Default, CGOptLevel));
}
// If a linkonce global is present in the MustPreserveSymbols, we need to make
// sure we honor this. To force the compiler to not drop it, we turn its linkage
// to the weak equivalent.
static void
preserveDiscardableGVs(Module &TheModule,
function_ref<bool(const GlobalValue &)> mustPreserveGV) {
auto mayPreserveGlobal = [&](GlobalValue &GV) {
if (!GV.isDiscardableIfUnused() || GV.isDeclaration())
return;
if (!mustPreserveGV(GV))
return;
if (GV.hasAvailableExternallyLinkage() || GV.hasLocalLinkage())
report_fatal_error("The linker asked LTO to preserve a symbol with an"
"unexpected linkage");
GV.setLinkage(GlobalValue::getWeakLinkage(GV.hasLinkOnceODRLinkage()));
};
for (auto &GV : TheModule)
mayPreserveGlobal(GV);
for (auto &GV : TheModule.globals())
mayPreserveGlobal(GV);
for (auto &GV : TheModule.aliases())
mayPreserveGlobal(GV);
}
void LTOCodeGenerator::applyScopeRestrictions() {
if (ScopeRestrictionsDone || !ShouldInternalize)
if (ScopeRestrictionsDone)
return;
// Declare a callback for the internalize pass that will ask for every
// candidate GlobalValue if it can be internalized or not.
SmallString<64> MangledName;
auto mustPreserveGV = [&](const GlobalValue &GV) -> bool {
// Need to mangle the GV as the "MustPreserveSymbols" StringSet is filled
// with the linker supplied name, which on Darwin includes a leading
// underscore.
MangledName.clear();
MangledName.reserve(GV.getName().size() + 1);
Mangler::getNameWithPrefix(MangledName, GV.getName(),
MergedModule->getDataLayout());
return MustPreserveSymbols.count(MangledName);
};
// Preserve linkonce value on linker request
preserveDiscardableGVs(*MergedModule, mustPreserveGV);
if (!ShouldInternalize)
return;
if (ShouldRestoreGlobalsLinkage) {
// Record the linkage type of non-local symbols so they can be restored
// prior
// to module splitting.
// prior to module splitting.
auto RecordLinkage = [&](const GlobalValue &GV) {
if (!GV.hasAvailableExternallyLinkage() && !GV.hasLocalLinkage() &&
GV.hasName())
@ -373,22 +417,7 @@ void LTOCodeGenerator::applyScopeRestrictions() {
// symbols referenced from asm
UpdateCompilerUsed(*MergedModule, *TargetMach, AsmUndefinedRefs);
// Declare a callback for the internalize pass that will ask for every
// candidate GlobalValue if it can be internalized or not.
Mangler Mangler;
SmallString<64> MangledName;
auto MustPreserveGV = [&](const GlobalValue &GV) -> bool {
// Need to mangle the GV as the "MustPreserveSymbols" StringSet is filled
// with the linker supplied name, which on Darwin includes a leading
// underscore.
MangledName.clear();
MangledName.reserve(GV.getName().size() + 1);
Mangler::getNameWithPrefix(MangledName, GV.getName(),
MergedModule->getDataLayout());
return MustPreserveSymbols.count(MangledName);
};
internalizeModule(*MergedModule, MustPreserveGV);
internalizeModule(*MergedModule, mustPreserveGV);
ScopeRestrictionsDone = true;
}

View File

@ -1,9 +1,11 @@
; RUN: llvm-as %s -o %t.o
; RUN: %ld64 -lto_library %llvmshlibdir/libLTO.dylib -dylib -arch x86_64 -macosx_version_min 10.10.0 -lSystem -o %t.dylib %t.o -save-temps -undefined dynamic_lookup
; RUN: %ld64 -lto_library %llvmshlibdir/libLTO.dylib -dylib -arch x86_64 -macosx_version_min 10.10.0 -lSystem -o %t.dylib %t.o -save-temps -undefined dynamic_lookup -exported_symbol _c -exported_symbol _b
; RUN: llvm-dis %t.dylib.lto.opt.bc -o - | FileCheck --check-prefix=IR %s
; check that @a is still a linkonce_odr definition
; IR: define linkonce_odr void @a()
; check that @a is no longer a linkonce_odr definition
; IR-NOT: define linkonce_odr void @a()
; check that @b is turned into weak because it is exported
; IR: define weak_odr void @b() #1 {
; RUN: llvm-nm %t.dylib | FileCheck --check-prefix=NM %s
; check that the linker can hide @a but not @b