summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/InputFiles.cpp8
-rw-r--r--lld/ELF/Symbols.cpp8
-rw-r--r--lld/ELF/Symbols.h6
-rw-r--r--lld/test/ELF/lto/Inputs/internalize-exportdyn.ll6
-rw-r--r--lld/test/ELF/lto/internalize-exportdyn.ll22
5 files changed, 45 insertions, 5 deletions
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 71d7a585583..bccbddf5058 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -12,6 +12,7 @@
#include "InputSection.h"
#include "Symbols.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/CodeGen/Analysis.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Object/IRObjectFile.h"
@@ -498,8 +499,11 @@ BitcodeFile::createSymbolBody(const DenseSet<const Comdat *> &KeptComdats,
Body = new (Alloc) DefinedBitcode(NameRef, IsWeak, Visibility);
}
// FIXME: Expose a thread-local flag for module asm symbols.
- if (GV && GV->isThreadLocal())
- Body->Type = STT_TLS;
+ if (GV) {
+ if (GV->isThreadLocal())
+ Body->Type = STT_TLS;
+ Body->CanOmitFromDynSym = canBeOmittedFromSymbolTable(GV);
+ }
return Body;
}
diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp
index 747161efe8b..e6f8842b80d 100644
--- a/lld/ELF/Symbols.cpp
+++ b/lld/ELF/Symbols.cpp
@@ -109,6 +109,7 @@ void SymbolBody::init() {
K == DefinedSyntheticKind || K == UndefinedElfKind;
CanKeepUndefined = false;
MustBeInDynSym = false;
+ CanOmitFromDynSym = false;
NeedsCopyOrPltAddr = false;
}
@@ -241,6 +242,9 @@ int SymbolBody::compare(SymbolBody *Other) {
if (IsUsedInRegularObj || Other->IsUsedInRegularObj)
IsUsedInRegularObj = Other->IsUsedInRegularObj = true;
+ if (!CanOmitFromDynSym || !Other->CanOmitFromDynSym)
+ CanOmitFromDynSym = Other->CanOmitFromDynSym = false;
+
if (L != R)
return -1;
if (!isDefined() || isShared() || isWeak())
@@ -360,7 +364,9 @@ bool SymbolBody::includeInDynsym() const {
uint8_t V = getVisibility();
if (V != STV_DEFAULT && V != STV_PROTECTED)
return false;
- return Config->ExportDynamic || Config->Shared;
+ if (!Config->ExportDynamic && !Config->Shared)
+ return false;
+ return !CanOmitFromDynSym;
}
template uint32_t SymbolBody::template getVA<ELF32LE>(uint32_t) const;
diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h
index 11fcdcb5a45..da2ab59a72c 100644
--- a/lld/ELF/Symbols.h
+++ b/lld/ELF/Symbols.h
@@ -147,6 +147,12 @@ protected:
unsigned IsUsedInRegularObj : 1;
public:
+ // True if this symbol can be omitted from the symbol table if nothing else
+ // requires it to be there. Right now this is only used for linkonce_odr in
+ // LTO, but we could add the feature to ELF. It would be similar to
+ // MachO's .weak_def_can_be_hidden.
+ unsigned CanOmitFromDynSym : 1;
+
// If true, the symbol is added to .dynsym symbol table.
unsigned MustBeInDynSym : 1;
diff --git a/lld/test/ELF/lto/Inputs/internalize-exportdyn.ll b/lld/test/ELF/lto/Inputs/internalize-exportdyn.ll
new file mode 100644
index 00000000000..21ac3580762
--- /dev/null
+++ b/lld/test/ELF/lto/Inputs/internalize-exportdyn.ll
@@ -0,0 +1,6 @@
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define weak_odr void @bah() {
+ ret void
+}
diff --git a/lld/test/ELF/lto/internalize-exportdyn.ll b/lld/test/ELF/lto/internalize-exportdyn.ll
index fd70812fef7..4a71289c68f 100644
--- a/lld/test/ELF/lto/internalize-exportdyn.ll
+++ b/lld/test/ELF/lto/internalize-exportdyn.ll
@@ -1,6 +1,7 @@
; REQUIRES: x86
; RUN: llvm-as %s -o %t.o
-; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 --export-dynamic -save-temps
+; RUN: llvm-as %p/Inputs/internalize-exportdyn.ll -o %t2.o
+; RUN: ld.lld -m elf_x86_64 %t.o %t2.o -o %t2 --export-dynamic -save-temps
; RUN: llvm-dis < %t2.lto.bc | FileCheck %s
target triple = "x86_64-unknown-linux-gnu"
@@ -18,7 +19,24 @@ define hidden void @bar() {
ret void
}
-; Check that _start and foo are not internalized, but bar is.
+define linkonce_odr void @zed() unnamed_addr {
+ ret void
+}
+
+define linkonce_odr void @bah() {
+ ret void
+}
+
+define linkonce_odr void @baz() {
+ ret void
+}
+
+@use_baz = global void ()* @baz
+
+; Check what gets internalized.
; CHECK: define void @_start()
; CHECK: define void @foo()
; CHECK: define internal void @bar()
+; CHECK: define internal void @zed()
+; CHECK: define weak_odr void @bah()
+; CHECK: define weak_odr void @baz()
OpenPOWER on IntegriCloud