diff options
-rw-r--r-- | lld/ELF/InputFiles.cpp | 8 | ||||
-rw-r--r-- | lld/ELF/Symbols.cpp | 8 | ||||
-rw-r--r-- | lld/ELF/Symbols.h | 6 | ||||
-rw-r--r-- | lld/test/ELF/lto/Inputs/internalize-exportdyn.ll | 6 | ||||
-rw-r--r-- | lld/test/ELF/lto/internalize-exportdyn.ll | 22 |
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() |