]> granicus.if.org Git - llvm/commitdiff
LTOCodeGenerator: add linkonce(_odr) to "llvm.compiler.used" when present in "MustPre...
authorMehdi Amini <mehdi.amini@apple.com>
Thu, 5 May 2016 05:14:24 +0000 (05:14 +0000)
committerMehdi Amini <mehdi.amini@apple.com>
Thu, 5 May 2016 05:14:24 +0000 (05:14 +0000)
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>

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@268607 91177308-0d34-0410-b5e6-96231b3b80d8

lib/LTO/LTOCodeGenerator.cpp
test/tools/lto/hide-linkonce-odr.ll

index 30cff72751330d4599c63e5556a41cdb1982f8a3..cad5d8eda51cf02af9277b17d8af91fba26656cb 100644 (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;
 }
index a1de96e8b3330e366a172072f417c6b6804db96c..6fbd75764ce808ea94eeb2b461e86fe1cdcd9b2b 100644 (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
 }