1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

LTOCodeGenerator: add linkonce(_odr) to "llvm.compiler.used" when present in "MustPreserve" set

If the linker requested to preserve a linkonce function, we should
honor this even if we drop all uses.
We explicitely avoid turning them into weak_odr (unlike the first
version of this patch in r267644), because the codegen can be
different on Darwin: because of `llvm::canBeOmittedFromSymbolTable()`
we may emit the symbol as weak_def_can_be_hidden instead of
weak_definition.

From: Mehdi Amini <mehdi.amini@apple.com>
llvm-svn: 268607
This commit is contained in:
Mehdi Amini 2016-05-05 05:14:24 +00:00
parent e7edfc94c8
commit 5e5633cf8a
2 changed files with 78 additions and 21 deletions

View File

@ -348,8 +348,73 @@ 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 add it to the
// "llvm.compiler.used" global.
static void preserveDiscardableGVs(
Module &TheModule,
llvm::function_ref<bool(const GlobalValue &)> mustPreserveGV) {
SetVector<Constant *> UsedValuesSet;
if (GlobalVariable *LLVMUsed =
TheModule.getGlobalVariable("llvm.compiler.used")) {
ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer());
for (auto &V : Inits->operands())
UsedValuesSet.insert(cast<Constant>(&V));
LLVMUsed->eraseFromParent();
}
llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(TheModule.getContext());
auto mayPreserveGlobal = [&](GlobalValue &GV) {
if (!GV.isDiscardableIfUnused() || GV.isDeclaration())
return;
if (!mustPreserveGV(GV))
return;
assert(!GV.hasAvailableExternallyLinkage() && !GV.hasInternalLinkage());
UsedValuesSet.insert(ConstantExpr::getBitCast(&GV, i8PTy));
};
for (auto &GV : TheModule)
mayPreserveGlobal(GV);
for (auto &GV : TheModule.globals())
mayPreserveGlobal(GV);
for (auto &GV : TheModule.aliases())
mayPreserveGlobal(GV);
if (UsedValuesSet.empty())
return;
llvm::ArrayType *ATy = llvm::ArrayType::get(i8PTy, UsedValuesSet.size());
auto *LLVMUsed = new llvm::GlobalVariable(
TheModule, ATy, false, llvm::GlobalValue::AppendingLinkage,
llvm::ConstantArray::get(ATy, UsedValuesSet.getArrayRef()),
"llvm.compiler.used");
LLVMUsed->setSection("llvm.metadata");
}
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 {
// Unnamed globals can't be mangled, but they can't be preserved either.
if (!GV.hasName())
return false;
// 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) {
@ -373,22 +438,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,21 +1,28 @@
; 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 -exported_symbol _GlobLinkonce
; 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 appended in llvm.used
; IR: @llvm.compiler.used = appending global [2 x i8*] [i8* bitcast ([1 x i8*]* @GlobLinkonce to i8*), i8* bitcast (void ()* @b to i8*)], section "llvm.metadata"
; RUN: llvm-nm %t.dylib | FileCheck --check-prefix=NM %s
; check that the linker can hide @a but not @b
; check that the linker can hide @a but not @b, nor @GlobLinkonce
; NM: 0000000000000f48 S _GlobLinkonce
; NM: 0000000000000f10 t _a
; NM: 0000000000000f20 T _b
; NM: 0000000000000f00 T _c
target triple = "x86_64-apple-macosx10.10.0"
declare void @external()
@GlobLinkonce = linkonce_odr unnamed_addr constant [1 x i8*] [i8* null], align 8
define linkonce_odr void @a() noinline {
%use_of_GlobLinkonce = load [1 x i8*], [1 x i8*] *@GlobLinkonce
call void @external()
ret void
}