From: Rafael Espindola Date: Wed, 6 Apr 2016 13:22:41 +0000 (+0000) Subject: Change the type hierarchy for undefined symbols. X-Git-Tag: llvmorg-3.9.0-rc1~9873 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f47657301be6ca744402e783e830f23e83833ec9;p=platform%2Fupstream%2Fllvm.git Change the type hierarchy for undefined symbols. We have to differentiate undefined symbols from bitcode and undefined symbols from other sources. Undefined symbols from bitcode should not inhibit the symbol being internalized. Undefined symbols from other sources should. llvm-svn: 265536 --- diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 4d11f35..3d23fde 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -473,7 +473,7 @@ BitcodeFile::createSymbolBody(const DenseSet &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 6a2e493..18d1ed4 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -1501,7 +1501,7 @@ SymbolTableSection::getOutputSection(SymbolBody *Sym) { return Out::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 1cc9a30..ba91b10 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -122,7 +122,8 @@ template void SymbolTable::addCombinedLtoObject() { // Add an undefined symbol. template SymbolBody *SymbolTable::addUndefined(StringRef Name) { - auto *Sym = new (Alloc) Undefined(Name, false, STV_DEFAULT, false); + auto *Sym = new (Alloc) + UndefinedElf(Name, STB_GLOBAL, STV_DEFAULT, /*Type*/ 0, false); resolve(Sym); return Sym; } @@ -131,7 +132,8 @@ SymbolBody *SymbolTable::addUndefined(StringRef Name) { // doesn't have to be resolved, thus "opt" (optional). template SymbolBody *SymbolTable::addUndefinedOpt(StringRef Name) { - auto *Sym = new (Alloc) Undefined(Name, false, STV_HIDDEN, true); + auto *Sym = new (Alloc) + UndefinedElf(Name, STB_GLOBAL, STV_HIDDEN, /*Type*/ 0, true); resolve(Sym); return Sym; } @@ -222,8 +224,8 @@ template void SymbolTable::resolve(SymbolBody *New) { SymbolBody *Existing = Sym->Body; if (auto *L = dyn_cast(Existing)) { - if (auto *Undef = dyn_cast(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 SymbolBody *SymbolTable::find(StringRef Name) { template void SymbolTable::addLazy(Lazy *L) { Symbol *Sym = insert(L); - if (Sym->Body == L) + SymbolBody *Cur = Sym->Body; + if (Cur == L) return; - if (auto *Undef = dyn_cast(Sym->Body)) { + if (Cur->isUndefined()) { Sym->Body = L; - addMemberFile(Undef, L); + addMemberFile(Cur, L); } } template -void SymbolTable::addMemberFile(Undefined *Undef, Lazy *L) { +void SymbolTable::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 ea2ea94..b80e7df 100644 --- a/lld/ELF/SymbolTable.h +++ b/lld/ELF/SymbolTable.h @@ -19,7 +19,6 @@ namespace elf { class Lazy; template 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 78fabc8..add7546 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::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 UndefinedElf::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 +UndefinedElf::UndefinedElf(StringRef Name, uint8_t Binding, + uint8_t StOther, uint8_t Type, + bool CanKeepUndefined) + : SymbolBody(SymbolBody::UndefinedElfKind, Name, Binding, StOther, Type), + CanKeepUndefined(CanKeepUndefined) {} + +template UndefinedElf::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 72d7d81..afd8743 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 &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 UndefinedElf : public Undefined { +template 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 e3601f4..27a1e0f 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1069,9 +1069,11 @@ template void Writer::createSections() { std::vector CommonSymbols; for (auto &P : Symtab.getSymbols()) { SymbolBody *Body = P.second->Body; - if (auto *U = dyn_cast(Body)) - if (!U->isWeak() && !U->canKeepUndefined()) + if (Body->isUndefined() && !Body->isWeak()) { + auto *U = dyn_cast>(Body); + if (!U || !U->canKeepUndefined()) reportUndefined(Symtab, Body); + } if (auto *C = dyn_cast(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 0000000..71c1e4f --- /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 0000000..5d74c31 --- /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()