diff options
| -rw-r--r-- | llvm/lib/LTO/LTOCodeGenerator.cpp | 84 | ||||
| -rw-r--r-- | llvm/test/tools/lto/hide-linkonce-odr.ll | 15 | 
2 files changed, 78 insertions, 21 deletions
diff --git a/llvm/lib/LTO/LTOCodeGenerator.cpp b/llvm/lib/LTO/LTOCodeGenerator.cpp index 30cff727513..cad5d8eda51 100644 --- a/llvm/lib/LTO/LTOCodeGenerator.cpp +++ b/llvm/lib/LTO/LTOCodeGenerator.cpp @@ -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;  } diff --git a/llvm/test/tools/lto/hide-linkonce-odr.ll b/llvm/test/tools/lto/hide-linkonce-odr.ll index a1de96e8b33..6fbd75764ce 100644 --- a/llvm/test/tools/lto/hide-linkonce-odr.ll +++ b/llvm/test/tools/lto/hide-linkonce-odr.ll @@ -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  }  | 

