diff options
-rw-r--r-- | lld/ELF/InputFiles.cpp | 2 | ||||
-rw-r--r-- | lld/ELF/OutputSections.cpp | 2 | ||||
-rw-r--r-- | lld/ELF/SymbolTable.cpp | 19 | ||||
-rw-r--r-- | lld/ELF/SymbolTable.h | 3 | ||||
-rw-r--r-- | lld/ELF/Symbols.cpp | 52 | ||||
-rw-r--r-- | lld/ELF/Symbols.h | 41 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 6 | ||||
-rw-r--r-- | lld/test/ELF/lto/Inputs/internalize-undef.ll | 6 | ||||
-rw-r--r-- | lld/test/ELF/lto/internalize-undef.ll | 16 |
9 files changed, 87 insertions, 60 deletions
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 4d11f359374..3d23fde0577 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -473,7 +473,7 @@ BitcodeFile::createSymbolBody(const DenseSet<const Comdat *> &KeptComdats, uint32_t Flags = Sym.getFlags(); bool IsWeak = Flags & BasicSymbolRef::SF_Weak; if (Flags & BasicSymbolRef::SF_Undefined) { - Body = new (Alloc) Undefined(NameRef, IsWeak, Visibility, false); + Body = new (Alloc) UndefinedBitcode(NameRef, IsWeak, Visibility); } else if (Flags & BasicSymbolRef::SF_Common) { const DataLayout &DL = M.getDataLayout(); uint64_t Size = DL.getTypeAllocSize(GV->getValueType()); diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 6a2e4933de2..18d1ed47350 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -1501,7 +1501,7 @@ SymbolTableSection<ELFT>::getOutputSection(SymbolBody *Sym) { return Out<ELFT>::Bss; break; case SymbolBody::UndefinedElfKind: - case SymbolBody::UndefinedKind: + case SymbolBody::UndefinedBitcodeKind: case SymbolBody::LazyKind: break; case SymbolBody::DefinedBitcodeKind: diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index 1cc9a30e460..ba91b10bcac 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -122,7 +122,8 @@ template <class ELFT> void SymbolTable<ELFT>::addCombinedLtoObject() { // Add an undefined symbol. template <class ELFT> SymbolBody *SymbolTable<ELFT>::addUndefined(StringRef Name) { - auto *Sym = new (Alloc) Undefined(Name, false, STV_DEFAULT, false); + auto *Sym = new (Alloc) + UndefinedElf<ELFT>(Name, STB_GLOBAL, STV_DEFAULT, /*Type*/ 0, false); resolve(Sym); return Sym; } @@ -131,7 +132,8 @@ SymbolBody *SymbolTable<ELFT>::addUndefined(StringRef Name) { // doesn't have to be resolved, thus "opt" (optional). template <class ELFT> SymbolBody *SymbolTable<ELFT>::addUndefinedOpt(StringRef Name) { - auto *Sym = new (Alloc) Undefined(Name, false, STV_HIDDEN, true); + auto *Sym = new (Alloc) + UndefinedElf<ELFT>(Name, STB_GLOBAL, STV_HIDDEN, /*Type*/ 0, true); resolve(Sym); return Sym; } @@ -222,8 +224,8 @@ template <class ELFT> void SymbolTable<ELFT>::resolve(SymbolBody *New) { SymbolBody *Existing = Sym->Body; if (auto *L = dyn_cast<Lazy>(Existing)) { - if (auto *Undef = dyn_cast<Undefined>(New)) { - addMemberFile(Undef, L); + if (New->isUndefined()) { + addMemberFile(New, L); return; } // Found a definition for something also in an archive. @@ -273,16 +275,17 @@ template <class ELFT> SymbolBody *SymbolTable<ELFT>::find(StringRef Name) { template <class ELFT> void SymbolTable<ELFT>::addLazy(Lazy *L) { Symbol *Sym = insert(L); - if (Sym->Body == L) + SymbolBody *Cur = Sym->Body; + if (Cur == L) return; - if (auto *Undef = dyn_cast<Undefined>(Sym->Body)) { + if (Cur->isUndefined()) { Sym->Body = L; - addMemberFile(Undef, L); + addMemberFile(Cur, L); } } template <class ELFT> -void SymbolTable<ELFT>::addMemberFile(Undefined *Undef, Lazy *L) { +void SymbolTable<ELFT>::addMemberFile(SymbolBody *Undef, Lazy *L) { if (Undef->isUsedInRegularObj()) L->setUsedInRegularObj(); // Weak undefined symbols should not fetch members from archives. diff --git a/lld/ELF/SymbolTable.h b/lld/ELF/SymbolTable.h index ea2ea94af8d..b80e7df18eb 100644 --- a/lld/ELF/SymbolTable.h +++ b/lld/ELF/SymbolTable.h @@ -19,7 +19,6 @@ namespace elf { class Lazy; template <class ELFT> class OutputSectionBase; struct Symbol; -class Undefined; // SymbolTable is a bucket of all known symbols, including defined, // undefined, or lazy symbols (the last one is symbols in archive @@ -68,7 +67,7 @@ public: private: Symbol *insert(SymbolBody *New); void addLazy(Lazy *New); - void addMemberFile(Undefined *Undef, Lazy *L); + void addMemberFile(SymbolBody *Undef, Lazy *L); void resolve(SymbolBody *Body); std::string conflictMsg(SymbolBody *Old, SymbolBody *New); diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index 78fabc8b9ec..add75461481 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -76,7 +76,7 @@ static typename ELFT::uint getSymVA(const SymbolBody &Body, return Out<ELFT>::Bss->getVA() + SS.OffsetInBss; } case SymbolBody::UndefinedElfKind: - case SymbolBody::UndefinedKind: + case SymbolBody::UndefinedBitcodeKind: return 0; case SymbolBody::LazyKind: assert(Body.isUsedInRegularObj() && "lazy symbol reached writer"); @@ -91,8 +91,22 @@ SymbolBody::SymbolBody(Kind K, uint32_t NameOffset, uint8_t StOther, uint8_t Type) : SymbolKind(K), MustBeInDynSym(false), NeedsCopyOrPltAddr(false), Type(Type), Binding(STB_LOCAL), StOther(StOther), NameOffset(NameOffset) { - IsUsedInRegularObj = - K != SharedKind && K != LazyKind && K != DefinedBitcodeKind; + init(); +} + +SymbolBody::SymbolBody(Kind K, StringRef Name, uint8_t Binding, uint8_t StOther, + uint8_t Type) + : SymbolKind(K), MustBeInDynSym(false), NeedsCopyOrPltAddr(false), + Type(Type), Binding(Binding), StOther(StOther), + Name({Name.data(), Name.size()}) { + assert(!isLocal()); + init(); +} + +void SymbolBody::init() { + Kind K = kind(); + IsUsedInRegularObj = K == DefinedRegularKind || K == DefinedCommonKind || + K == DefinedSyntheticKind || K == UndefinedElfKind; } // Returns true if a symbol can be replaced at load-time by a symbol @@ -239,31 +253,27 @@ bool DefinedBitcode::classof(const SymbolBody *S) { return S->kind() == DefinedBitcodeKind; } -Undefined::Undefined(SymbolBody::Kind K, StringRef N, uint8_t Binding, - uint8_t Other, uint8_t Type) - : SymbolBody(K, N, Binding, Other, Type), CanKeepUndefined(false) {} - -Undefined::Undefined(SymbolBody::Kind K, uint32_t NameOffset, - uint8_t StOther, uint8_t Type) - : SymbolBody(K, NameOffset, StOther, Type), CanKeepUndefined(false) {} - -Undefined::Undefined(StringRef N, bool IsWeak, uint8_t StOther, - bool CanKeepUndefined) - : Undefined(SymbolBody::UndefinedKind, N, IsWeak ? STB_WEAK : STB_GLOBAL, - StOther, 0 /* Type */) { - this->CanKeepUndefined = CanKeepUndefined; -} +UndefinedBitcode::UndefinedBitcode(StringRef N, bool IsWeak, uint8_t StOther) + : SymbolBody(SymbolBody::UndefinedBitcodeKind, N, + IsWeak ? STB_WEAK : STB_GLOBAL, StOther, 0 /* Type */) {} template <typename ELFT> UndefinedElf<ELFT>::UndefinedElf(StringRef N, const Elf_Sym &Sym) - : Undefined(SymbolBody::UndefinedElfKind, N, Sym.getBinding(), Sym.st_other, - Sym.getType()), + : SymbolBody(SymbolBody::UndefinedElfKind, N, Sym.getBinding(), + Sym.st_other, Sym.getType()), Size(Sym.st_size) {} template <typename ELFT> +UndefinedElf<ELFT>::UndefinedElf(StringRef Name, uint8_t Binding, + uint8_t StOther, uint8_t Type, + bool CanKeepUndefined) + : SymbolBody(SymbolBody::UndefinedElfKind, Name, Binding, StOther, Type), + CanKeepUndefined(CanKeepUndefined) {} + +template <typename ELFT> UndefinedElf<ELFT>::UndefinedElf(const Elf_Sym &Sym) - : Undefined(SymbolBody::UndefinedElfKind, Sym.st_name, Sym.st_other, - Sym.getType()), + : SymbolBody(SymbolBody::UndefinedElfKind, Sym.st_name, Sym.st_other, + Sym.getType()), Size(Sym.st_size) { assert(Sym.getBinding() == STB_LOCAL); } diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index 72d7d81425d..afd8743f6dd 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -46,6 +46,8 @@ struct Symbol { // The base class for real symbol classes. class SymbolBody { + void init(); + public: enum Kind { DefinedFirst, @@ -56,7 +58,7 @@ public: DefinedSyntheticKind, DefinedLast = DefinedSyntheticKind, UndefinedElfKind, - UndefinedKind, + UndefinedBitcodeKind, LazyKind }; @@ -64,7 +66,7 @@ public: bool isWeak() const { return Binding == llvm::ELF::STB_WEAK; } bool isUndefined() const { - return SymbolKind == UndefinedKind || SymbolKind == UndefinedElfKind; + return SymbolKind == UndefinedBitcodeKind || SymbolKind == UndefinedElfKind; } bool isDefined() const { return SymbolKind <= DefinedLast; } bool isCommon() const { return SymbolKind == DefinedCommonKind; } @@ -125,14 +127,7 @@ public: protected: SymbolBody(Kind K, StringRef Name, uint8_t Binding, uint8_t StOther, - uint8_t Type) - : SymbolKind(K), MustBeInDynSym(false), NeedsCopyOrPltAddr(false), - Type(Type), Binding(Binding), StOther(StOther), - Name({Name.data(), Name.size()}) { - assert(!isLocal()); - IsUsedInRegularObj = - K != SharedKind && K != LazyKind && K != DefinedBitcodeKind; - } + uint8_t Type); SymbolBody(Kind K, uint32_t NameOffset, uint8_t StOther, uint8_t Type); @@ -282,31 +277,27 @@ public: const OutputSectionBase<ELFT> &Section; }; -// Undefined symbol. -class Undefined : public SymbolBody { - typedef SymbolBody::Kind Kind; - bool CanKeepUndefined; - -protected: - Undefined(Kind K, StringRef N, uint8_t Binding, uint8_t StOther, - uint8_t Type); - Undefined(Kind K, uint32_t NameOffset, uint8_t StOther, uint8_t Type); - +class UndefinedBitcode : public SymbolBody { public: - Undefined(StringRef N, bool IsWeak, uint8_t StOther, bool CanKeepUndefined); + UndefinedBitcode(StringRef N, bool IsWeak, uint8_t StOther); - static bool classof(const SymbolBody *S) { return S->isUndefined(); } - - bool canKeepUndefined() const { return CanKeepUndefined; } + static bool classof(const SymbolBody *S) { + return S->kind() == UndefinedBitcodeKind; + } }; -template <class ELFT> class UndefinedElf : public Undefined { +template <class ELFT> class UndefinedElf : public SymbolBody { typedef typename ELFT::uint uintX_t; typedef typename ELFT::Sym Elf_Sym; + bool CanKeepUndefined = false; public: UndefinedElf(StringRef N, const Elf_Sym &Sym); UndefinedElf(const Elf_Sym &Sym); + UndefinedElf(StringRef Name, uint8_t Binding, uint8_t StOther, uint8_t Type, + bool CanKeepUndefined); + + bool canKeepUndefined() const { return CanKeepUndefined; } uintX_t Size; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index e3601f4e7cf..27a1e0f4f6b 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1069,9 +1069,11 @@ template <class ELFT> void Writer<ELFT>::createSections() { std::vector<DefinedCommon *> CommonSymbols; for (auto &P : Symtab.getSymbols()) { SymbolBody *Body = P.second->Body; - if (auto *U = dyn_cast<Undefined>(Body)) - if (!U->isWeak() && !U->canKeepUndefined()) + if (Body->isUndefined() && !Body->isWeak()) { + auto *U = dyn_cast<UndefinedElf<ELFT>>(Body); + if (!U || !U->canKeepUndefined()) reportUndefined<ELFT>(Symtab, Body); + } if (auto *C = dyn_cast<DefinedCommon>(Body)) CommonSymbols.push_back(C); diff --git a/lld/test/ELF/lto/Inputs/internalize-undef.ll b/lld/test/ELF/lto/Inputs/internalize-undef.ll new file mode 100644 index 00000000000..71c1e4f3560 --- /dev/null +++ b/lld/test/ELF/lto/Inputs/internalize-undef.ll @@ -0,0 +1,6 @@ +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @f() { + ret void +} diff --git a/lld/test/ELF/lto/internalize-undef.ll b/lld/test/ELF/lto/internalize-undef.ll new file mode 100644 index 00000000000..5d74c31eee8 --- /dev/null +++ b/lld/test/ELF/lto/internalize-undef.ll @@ -0,0 +1,16 @@ +; REQUIRES: x86 +; RUN: llvm-as %s -o %t.o +; RUN: llvm-as %p/Inputs/internalize-undef.ll -o %t2.o +; RUN: ld.lld -m elf_x86_64 %t.o %t2.o -o %t -save-temps +; RUN: llvm-dis < %t.lto.bc | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +declare void @f() +define void @_start() { + call void @f() + ret void +} + +; CHECK: define internal void @f() |