From c325036358cdb3a9cd522f3a1cf74d30ec3e654c Mon Sep 17 00:00:00 2001 From: Dmitry Mikulin Date: Mon, 5 Jun 2017 16:24:25 +0000 Subject: [PATCH] Symbols re-defined with -wrap and -defsym need to be excluded from inter- procedural optimizations to prevent dropping symbols and allow the linker to process re-directs. PR33145: --wrap doesn't work with lto. Differential Revision: https://reviews.llvm.org/D33621 llvm-svn: 304719 --- include/llvm/LTO/LTO.h | 9 +++++++-- lib/LTO/LTO.cpp | 17 +++++++++++++---- test/LTO/Resolution/X86/linker-redef.ll | 16 ++++++++++++++++ tools/llvm-lto2/llvm-lto2.cpp | 2 ++ 4 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 test/LTO/Resolution/X86/linker-redef.ll diff --git a/include/llvm/LTO/LTO.h b/include/llvm/LTO/LTO.h index 3772592757b..774e144b3ef 100644 --- a/include/llvm/LTO/LTO.h +++ b/include/llvm/LTO/LTO.h @@ -366,8 +366,9 @@ private: /// each global symbol based on its internal resolution of that symbol. struct SymbolResolution { SymbolResolution() - : Prevailing(0), FinalDefinitionInLinkageUnit(0), VisibleToRegularObj(0) { - } + : Prevailing(0), FinalDefinitionInLinkageUnit(0), VisibleToRegularObj(0), + LinkerRedefined(0) {} + /// The linker has chosen this definition of the symbol. unsigned Prevailing : 1; @@ -377,6 +378,10 @@ struct SymbolResolution { /// The definition of this symbol is visible outside of the LTO unit. unsigned VisibleToRegularObj : 1; + + /// Linker redefined version of the symbol which appeared in -wrap or -defsym + /// linker option. + unsigned LinkerRedefined : 1; }; } // namespace lto diff --git a/lib/LTO/LTO.cpp b/lib/LTO/LTO.cpp index 92145aaf667..6d322b26684 100644 --- a/lib/LTO/LTO.cpp +++ b/lib/LTO/LTO.cpp @@ -405,10 +405,11 @@ void LTO::addSymbolToGlobalRes(const InputFile::Symbol &Sym, if (Res.Prevailing) GlobalRes.IRName = Sym.getIRName(); - // Set the partition to external if we know it is used elsewhere, e.g. - // it is visible to a regular object, is referenced from llvm.compiler_used, - // or was already recorded as being referenced from a different partition. - if (Res.VisibleToRegularObj || Sym.isUsed() || + // Set the partition to external if we know it is re-defined by the linker + // with -defsym or -wrap options, used elsewhere, e.g. it is visible to a + // regular object, is referenced from llvm.compiler_used, or was already + // recorded as being referenced from a different partition. + if (Res.LinkerRedefined || Res.VisibleToRegularObj || Sym.isUsed() || (GlobalRes.Partition != GlobalResolution::Unknown && GlobalRes.Partition != Partition)) { GlobalRes.Partition = GlobalResolution::External; @@ -439,6 +440,8 @@ static void writeToResolutionFile(raw_ostream &OS, InputFile *Input, OS << 'l'; if (Res.VisibleToRegularObj) OS << 'x'; + if (Res.LinkerRedefined) + OS << 'r'; OS << '\n'; } OS.flush(); @@ -543,6 +546,12 @@ Error LTO::addRegularLTO(BitcodeModule BM, if (Sym.isUndefined()) continue; Keep.push_back(GV); + // For symbols re-defined with linker -wrap and -defsym options, + // set the linkage to weak to inhibit IPO. The linkage will be + // restored by the linker. + if (Res.LinkerRedefined) + GV->setLinkage(GlobalValue::WeakAnyLinkage); + GlobalValue::LinkageTypes OriginalLinkage = GV->getLinkage(); if (GlobalValue::isLinkOnceLinkage(OriginalLinkage)) GV->setLinkage(GlobalValue::getWeakLinkage( diff --git a/test/LTO/Resolution/X86/linker-redef.ll b/test/LTO/Resolution/X86/linker-redef.ll new file mode 100644 index 00000000000..802a54db93c --- /dev/null +++ b/test/LTO/Resolution/X86/linker-redef.ll @@ -0,0 +1,16 @@ +; RUN: llvm-as %s -o %t.o +; RUN: llvm-lto2 run -o %t1.o %t.o -r %t.o,bar,pr +; RUN: llvm-readobj -t %t1.o.0 | FileCheck %s + +; CHECK: Name: bar +; CHECK-NEXT: Value: +; CHECK-NEXT: Size: +; CHECK-NEXT: Binding: Weak +; CHECK-NEXT: Type: Function + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @bar() { + ret void +} diff --git a/tools/llvm-lto2/llvm-lto2.cpp b/tools/llvm-lto2/llvm-lto2.cpp index 89f85157e1d..bbfece517c8 100644 --- a/tools/llvm-lto2/llvm-lto2.cpp +++ b/tools/llvm-lto2/llvm-lto2.cpp @@ -162,6 +162,8 @@ static int run(int argc, char **argv) { Res.FinalDefinitionInLinkageUnit = true; else if (C == 'x') Res.VisibleToRegularObj = true; + else if (C == 'r') + Res.LinkerRedefined = true; else { llvm::errs() << "invalid character " << C << " in resolution: " << R << '\n';