diff options
-rw-r--r-- | lld/ELF/LTO.cpp | 14 | ||||
-rw-r--r-- | lld/test/ELF/lto/Inputs/linker-script-symbols-ipo.ll | 9 | ||||
-rw-r--r-- | lld/test/ELF/lto/linker-script-symbols-assign.ll | 50 | ||||
-rw-r--r-- | lld/test/ELF/lto/linker-script-symbols-ipo.ll | 32 |
4 files changed, 104 insertions, 1 deletions
diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp index 3dac26454bc..24a8ff65b91 100644 --- a/lld/ELF/LTO.cpp +++ b/lld/ELF/LTO.cpp @@ -10,6 +10,7 @@ #include "LTO.h" #include "Config.h" #include "Error.h" +#include "LinkerScript.h" #include "InputFiles.h" #include "SymbolTable.h" #include "Symbols.h" @@ -128,6 +129,11 @@ void BitcodeCompiler::add(BitcodeFile &F) { std::vector<SymbolBody *> Syms = F.getSymbols(); std::vector<lto::SymbolResolution> Resols(Syms.size()); + DenseSet<StringRef> ScriptSymbols; + for (BaseCommand *Base : Script->Opt.Commands) + if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) + ScriptSymbols.insert(Cmd->Name); + // Provide a resolution to the LTO API for each symbol. for (const lto::InputFile::Symbol &ObjSym : Obj.symbols()) { SymbolBody *B = Syms[SymNum]; @@ -153,7 +159,13 @@ void BitcodeCompiler::add(BitcodeFile &F) { UsedStartStop.count(ObjSym.getSectionName()); if (R.Prevailing) undefine(Sym); - R.LinkerRedefined = !Sym->CanInline; + + // We tell LTO to not apply interprocedural optimization for following + // symbols because otherwise LTO would inline them while their values are + // still not final: + // 1) Aliased (with --defsym) or wrapped (with --wrap) symbols. + // 2) Symbols redefined in linker script. + R.LinkerRedefined = !Sym->CanInline || ScriptSymbols.count(B->getName()); } checkError(LTOObj->add(std::move(F.Obj), Resols)); } diff --git a/lld/test/ELF/lto/Inputs/linker-script-symbols-ipo.ll b/lld/test/ELF/lto/Inputs/linker-script-symbols-ipo.ll new file mode 100644 index 00000000000..c872f9e1dd5 --- /dev/null +++ b/lld/test/ELF/lto/Inputs/linker-script-symbols-ipo.ll @@ -0,0 +1,9 @@ +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +declare i32 @bar() + +define i32 @_start() { + %1 = tail call i32 @bar() + ret i32 %1 +} diff --git a/lld/test/ELF/lto/linker-script-symbols-assign.ll b/lld/test/ELF/lto/linker-script-symbols-assign.ll new file mode 100644 index 00000000000..c69911d295a --- /dev/null +++ b/lld/test/ELF/lto/linker-script-symbols-assign.ll @@ -0,0 +1,50 @@ +; REQUIRES: x86 +; RUN: llvm-as %s -o %t.o + +; RUN: echo "foo = 1;" > %t.script +; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 --script %t.script -save-temps +; RUN: llvm-readobj -symbols %t2.lto.o | FileCheck %s + +; CHECK-NOT: bar +; CHECK: Symbol { +; CHECK: Name: foo +; CHECK-NEXT: Value: 0x0 +; CHECK-NEXT: Size: 4 +; FIXME: Binding should be Global here. Symbols redefined in script does not +; receive correct binding and visibility, this is a known bug. +; CHECK-NEXT: Binding: Weak +; CHECK-NEXT: Type: Object +; CHECK-NEXT: Other: 0 +; CHECK-NEXT: Section: .bss.foo +; CHECK-NEXT: } +; CHECK-NEXT:] + +; RUN: llvm-readobj -symbols %t2 | FileCheck %s --check-prefix=VAL +; VAL: Symbol { +; VAL: Name: foo +; VAL-NEXT: Value: 0x1 +; VAL-NEXT: Size: +; VAL-NEXT: Binding: Global +; VAL-NEXT: Type: None +; VAL-NEXT: Other: +; VAL-NEXT: Section: Absolute +; VAL-NEXT: } + +; RUN: echo "zed = 1;" > %t2.script +; RUN: ld.lld -m elf_x86_64 %t.o -o %t3 --script %t2.script +; RUN: llvm-readobj -symbols %t3 | FileCheck %s --check-prefix=ABS +; ABS: Symbol { +; ABS: Name: zed +; ABS-NEXT: Value: 0x1 +; ABS-NEXT: Size: 0 +; ABS-NEXT: Binding: Global +; ABS-NEXT: Type: None +; ABS-NEXT: Other: 0 +; ABS-NEXT: Section: Absolute +; ABS-NEXT: } + +target triple = "x86_64-unknown-linux-gnu" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +@foo = global i32 0 +@bar = global i32 0 diff --git a/lld/test/ELF/lto/linker-script-symbols-ipo.ll b/lld/test/ELF/lto/linker-script-symbols-ipo.ll new file mode 100644 index 00000000000..6ac1a83e1ec --- /dev/null +++ b/lld/test/ELF/lto/linker-script-symbols-ipo.ll @@ -0,0 +1,32 @@ +; REQUIRES: x86 +; RUN: llvm-as %s -o %t1.o +; RUN: llvm-as %S/Inputs/linker-script-symbols-ipo.ll -o %t2.o +; RUN: echo "bar = foo;" > %t.script + +;; Check that without linkerscript bar is inlined. +; RUN: ld.lld -m elf_x86_64 %t1.o %t2.o -o %t3 -save-temps +; RUN: llvm-objdump -d %t3 | FileCheck %s --check-prefix=IPO +; IPO: Disassembly of section .text: +; IPO: _start: +; IPO-NEXT: 201000: {{.*}} movl $1, %eax +; IPO-NEXT: 201005: {{.*}} retq + +;; Check that LTO does not do IPO for symbols assigned by script. +; RUN: ld.lld -m elf_x86_64 %t1.o %t2.o -o %t4 --script %t.script -save-temps +; RUN: llvm-objdump -d %t4 | FileCheck %s --check-prefix=NOIPO +; NOIPO: Disassembly of section .text: +; NOIPO: foo: +; NOIPO-NEXT: 201010: {{.*}} movl $2, %eax +; NOIPO: _start: +; NOIPO-NEXT: 201020: {{.*}} jmp -21 <foo> + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define i32 @bar() { + ret i32 1 +} + +define i32 @foo() { + ret i32 2 +} |