[lld] r289280 - COFF: New symbol table design.

Peter Collingbourne via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 12 10:53:23 PST 2016


Should be fixed by r289451.

Peter

On Mon, Dec 12, 2016 at 9:36 AM, Mike Aizatsky <aizatsky at google.com> wrote:

> Peter,
>
> I think this breaks asan bot:
>
> http://lab.llvm.org:8011/builders/sanitizer-x86_64-
> linux-bootstrap/builds/414/steps/check-lld%20asan/logs/stdio
>
> =================================================================
> ==6557==ERROR: LeakSanitizer: detected memory leaks
>
> Direct leak of 56 byte(s) in 1 object(s) allocated from:
>     #0 0x706540 in operator new(unsigned long) /mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/projects/compiler-rt/lib/asan/asan_new_delete.cc:82
>     #1 0x7a7b39 in lld::coff::DefinedImportThunk::DefinedImportThunk(llvm::StringRef, lld::coff::DefinedImportData*, unsigned short) /mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/tools/lld/COFF/Symbols.cpp:64:26
>     #2 0x79e014 in replaceBody<lld::coff::DefinedImportThunk, llvm::StringRef &, lld::coff::DefinedImportData *&, unsigned short &> /mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/tools/lld/COFF/Symbols.h:417:24
>     #3 0x79e014 in lld::coff::SymbolTable::addImportThunk(llvm::StringRef, lld::coff::DefinedImportData*, unsigned short) /mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/tools/lld/COFF/SymbolTable.cpp:276
>     #4 0x780413 in lld::coff::ImportFile::parse() /mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/tools/lld/COFF/InputFiles.cpp:349:15
>     #5 0x79719b in lld::coff::SymbolTable::addFile(lld::coff::InputFile*) /mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/tools/lld/COFF/SymbolTable.cpp:32:9
>     #6 0x79b35e in lld::coff::SymbolTable::addMemberFile(lld::coff::ArchiveFile*, llvm::object::Archive::Symbol) /mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/tools/lld/COFF/SymbolTable.cpp:292:3
>     #7 0x79b715 in lld::coff::SymbolTable::addLazy(lld::coff::ArchiveFile*, llvm::object::Archive::Symbol) /mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/tools/lld/COFF/SymbolTable.cpp:156:3
>     #8 0x775f2c in lld::coff::ArchiveFile::parse() /mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/tools/lld/COFF/InputFiles.cpp:60:13
>     #9 0x79719b in lld::coff::SymbolTable::addFile(lld::coff::InputFile*) /mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/tools/lld/COFF/SymbolTable.cpp:32:9
>     #10 0x735c7b in lld::coff::LinkerDriver::link(llvm::ArrayRef<char const*>) /mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/tools/lld/COFF/Driver.cpp:580:12
>     #11 0x72eaa6 in lld::coff::link(llvm::ArrayRef<char const*>) /mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/tools/lld/COFF/Driver.cpp:49:11
>     #12 0x70adfd in main /mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/tools/lld/tools/lld/lld.cpp:106:13
>     #13 0x7f899f22af44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21f44)
>
> SUMMARY: AddressSanitizer: 56 byte(s) leaked in 1 allocation(s).
>
>
>
> On Fri, Dec 9, 2016 at 2:05 PM Peter Collingbourne via llvm-commits <
> llvm-commits at lists.llvm.org> wrote:
>
>> Author: pcc
>> Date: Fri Dec  9 15:55:24 2016
>> New Revision: 289280
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=289280&view=rev
>> Log:
>> COFF: New symbol table design.
>>
>> This ports the ELF linker's symbol table design, introduced in r268178,
>> to the COFF linker.
>>
>> Differential Revision: http://reviews.llvm.org/D21166
>>
>> Modified:
>>     lld/trunk/COFF/Chunks.cpp
>>     lld/trunk/COFF/Chunks.h
>>     lld/trunk/COFF/Config.h
>>     lld/trunk/COFF/DLL.cpp
>>     lld/trunk/COFF/Driver.cpp
>>     lld/trunk/COFF/Driver.h
>>     lld/trunk/COFF/DriverUtils.cpp
>>     lld/trunk/COFF/ICF.cpp
>>     lld/trunk/COFF/InputFiles.cpp
>>     lld/trunk/COFF/InputFiles.h
>>     lld/trunk/COFF/MarkLive.cpp
>>     lld/trunk/COFF/SymbolTable.cpp
>>     lld/trunk/COFF/SymbolTable.h
>>     lld/trunk/COFF/Symbols.cpp
>>     lld/trunk/COFF/Symbols.h
>>     lld/trunk/COFF/Writer.cpp
>>     lld/trunk/test/COFF/include2.test
>>     lld/trunk/test/COFF/order.test
>>     lld/trunk/test/COFF/symtab.test
>>
>> Modified: lld/trunk/COFF/Chunks.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Chunks.
>> cpp?rev=289280&r1=289279&r2=289280&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/COFF/Chunks.cpp (original)
>> +++ lld/trunk/COFF/Chunks.cpp Fri Dec  9 15:55:24 2016
>> @@ -150,7 +150,7 @@ void SectionChunk::writeTo(uint8_t *Buf)
>>    // Apply relocations.
>>    for (const coff_relocation &Rel : Relocs) {
>>      uint8_t *Off = Buf + OutputSectionOff + Rel.VirtualAddress;
>> -    SymbolBody *Body = File->getSymbolBody(Rel.
>> SymbolTableIndex)->repl();
>> +    SymbolBody *Body = File->getSymbolBody(Rel.SymbolTableIndex);
>>      Defined *Sym = cast<Defined>(Body);
>>      uint64_t P = RVA + Rel.VirtualAddress;
>>      switch (Config->Machine) {
>> @@ -203,7 +203,7 @@ void SectionChunk::getBaserels(std::vect
>>      uint8_t Ty = getBaserelType(Rel);
>>      if (Ty == IMAGE_REL_BASED_ABSOLUTE)
>>        continue;
>> -    SymbolBody *Body = File->getSymbolBody(Rel.
>> SymbolTableIndex)->repl();
>> +    SymbolBody *Body = File->getSymbolBody(Rel.SymbolTableIndex);
>>      if (isa<DefinedAbsolute>(Body))
>>        continue;
>>      Res->emplace_back(RVA + Rel.VirtualAddress, Ty);
>>
>> Modified: lld/trunk/COFF/Chunks.h
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Chunks.
>> h?rev=289280&r1=289279&r2=289280&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/COFF/Chunks.h (original)
>> +++ lld/trunk/COFF/Chunks.h Fri Dec  9 15:55:24 2016
>> @@ -28,7 +28,6 @@ using llvm::object::COFFSymbolRef;
>>  using llvm::object::SectionRef;
>>  using llvm::object::coff_relocation;
>>  using llvm::object::coff_section;
>> -using llvm::sys::fs::file_magic;
>>
>>  class Baserel;
>>  class Defined;
>>
>> Modified: lld/trunk/COFF/Config.h
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Config.
>> h?rev=289280&r1=289279&r2=289280&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/COFF/Config.h (original)
>> +++ lld/trunk/COFF/Config.h Fri Dec  9 15:55:24 2016
>> @@ -26,7 +26,8 @@ using llvm::StringRef;
>>  class DefinedAbsolute;
>>  class DefinedRelative;
>>  class StringChunk;
>> -class Undefined;
>> +struct Symbol;
>> +class SymbolBody;
>>
>>  // Short aliases.
>>  static const auto AMD64 = llvm::COFF::IMAGE_FILE_MACHINE_AMD64;
>> @@ -37,7 +38,7 @@ static const auto I386 = llvm::COFF::IMA
>>  struct Export {
>>    StringRef Name;       // N in /export:N or /export:E=N
>>    StringRef ExtName;    // E in /export:E=N
>> -  Undefined *Sym = nullptr;
>> +  SymbolBody *Sym = nullptr;
>>    uint16_t Ordinal = 0;
>>    bool Noname = false;
>>    bool Data = false;
>> @@ -76,7 +77,7 @@ struct Configuration {
>>    llvm::COFF::MachineTypes Machine = IMAGE_FILE_MACHINE_UNKNOWN;
>>    bool Verbose = false;
>>    WindowsSubsystem Subsystem = llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN;
>> -  Undefined *Entry = nullptr;
>> +  SymbolBody *Entry = nullptr;
>>    bool NoEntry = false;
>>    std::string OutputFile;
>>    bool DoGC = true;
>> @@ -89,7 +90,7 @@ struct Configuration {
>>    StringRef PDBPath;
>>
>>    // Symbols in this set are considered as live by the garbage collector.
>> -  std::set<Undefined *> GCRoot;
>> +  std::set<SymbolBody *> GCRoot;
>>
>>    std::set<StringRef> NoDefaultLibs;
>>    bool NoDefaultLibAll = false;
>> @@ -100,11 +101,11 @@ struct Configuration {
>>    std::vector<Export> Exports;
>>    std::set<std::string> DelayLoads;
>>    std::map<std::string, int> DLLOrder;
>> -  Undefined *DelayLoadHelper = nullptr;
>> +  SymbolBody *DelayLoadHelper = nullptr;
>>
>>    // Used for SafeSEH.
>> -  DefinedRelative *SEHTable = nullptr;
>> -  DefinedAbsolute *SEHCount = nullptr;
>> +  Symbol *SEHTable = nullptr;
>> +  Symbol *SEHCount = nullptr;
>>
>>    // Used for /opt:lldlto=N
>>    unsigned LTOOptLevel = 2;
>>
>> Modified: lld/trunk/COFF/DLL.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DLL.
>> cpp?rev=289280&r1=289279&r2=289280&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/COFF/DLL.cpp (original)
>> +++ lld/trunk/COFF/DLL.cpp Fri Dec  9 15:55:24 2016
>> @@ -324,7 +324,7 @@ public:
>>        if (E.ForwardChunk) {
>>          write32le(P, E.ForwardChunk->getRVA());
>>        } else {
>> -        write32le(P, cast<Defined>(E.Sym->repl())->getRVA());
>> +        write32le(P, cast<Defined>(E.Sym)->getRVA());
>>        }
>>      }
>>    }
>>
>> Modified: lld/trunk/COFF/Driver.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.
>> cpp?rev=289280&r1=289279&r2=289280&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/COFF/Driver.cpp (original)
>> +++ lld/trunk/COFF/Driver.cpp Fri Dec  9 15:55:24 2016
>> @@ -207,10 +207,10 @@ void LinkerDriver::addLibSearchPaths() {
>>    }
>>  }
>>
>> -Undefined *LinkerDriver::addUndefined(StringRef Name) {
>> -  Undefined *U = Symtab.addUndefined(Name);
>> -  Config->GCRoot.insert(U);
>> -  return U;
>> +SymbolBody *LinkerDriver::addUndefined(StringRef Name) {
>> +  SymbolBody *B = Symtab.addUndefined(Name);
>> +  Config->GCRoot.insert(B);
>> +  return B;
>>  }
>>
>>  // Symbol names are mangled by appending "_" prefix on x86.
>> @@ -232,7 +232,7 @@ StringRef LinkerDriver::findDefaultEntry
>>    };
>>    for (auto E : Entries) {
>>      StringRef Entry = Symtab.findMangle(mangle(E[0]));
>> -    if (!Entry.empty() && !isa<Undefined>(Symtab.find(Entry)->Body))
>> +    if (!Entry.empty() && !isa<Undefined>(Symtab.find(Entry)->body()))
>>        return mangle(E[1]);
>>    }
>>    return "";
>> @@ -715,7 +715,7 @@ void LinkerDriver::link(ArrayRef<const c
>>        Symbol *Sym = Symtab.find(From);
>>        if (!Sym)
>>          continue;
>> -      if (auto *U = dyn_cast<Undefined>(Sym->Body))
>> +      if (auto *U = dyn_cast<Undefined>(Sym->body()))
>>          if (!U->WeakAlias)
>>            U->WeakAlias = Symtab.addUndefined(To);
>>      }
>> @@ -734,7 +734,7 @@ void LinkerDriver::link(ArrayRef<const c
>>    Symtab.addCombinedLTOObjects();
>>
>>    // Make sure we have resolved all symbols.
>> -  Symtab.reportRemainingUndefines(/*Resolve=*/true);
>> +  Symtab.reportRemainingUndefines();
>>
>>    // Windows specific -- if no /subsystem is given, we need to infer
>>    // that from entry point name.
>>
>> Modified: lld/trunk/COFF/Driver.h
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.
>> h?rev=289280&r1=289279&r2=289280&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/COFF/Driver.h (original)
>> +++ lld/trunk/COFF/Driver.h Fri Dec  9 15:55:24 2016
>> @@ -59,6 +59,7 @@ private:
>>
>>  class LinkerDriver {
>>  public:
>> +  LinkerDriver() { coff::Symtab = &Symtab; }
>>    void link(llvm::ArrayRef<const char *> Args);
>>
>>    // Used by the resolver to parse .drectve section contents.
>> @@ -86,7 +87,7 @@ private:
>>    std::vector<StringRef> SearchPaths;
>>    std::set<std::string> VisitedFiles;
>>
>> -  Undefined *addUndefined(StringRef Sym);
>> +  SymbolBody *addUndefined(StringRef Sym);
>>    StringRef mangle(StringRef Sym);
>>
>>    // Windows specific -- "main" is not the only main function in Windows.
>>
>> Modified: lld/trunk/COFF/DriverUtils.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/
>> DriverUtils.cpp?rev=289280&r1=289279&r2=289280&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/COFF/DriverUtils.cpp (original)
>> +++ lld/trunk/COFF/DriverUtils.cpp Fri Dec  9 15:55:24 2016
>> @@ -510,13 +510,13 @@ void fixupExports() {
>>    }
>>
>>    for (Export &E : Config->Exports) {
>> +    SymbolBody *Sym = E.Sym;
>>      if (!E.ForwardTo.empty()) {
>>        E.SymbolName = E.Name;
>> -    } else if (Undefined *U = cast_or_null<Undefined>(E.Sym->WeakAlias))
>> {
>> -      E.SymbolName = U->getName();
>> -    } else {
>> -      E.SymbolName = E.Sym->getName();
>> -    }
>> +    } else if (auto *U = dyn_cast<Undefined>(Sym))
>> +      if (U->WeakAlias)
>> +        Sym = U->WeakAlias;
>> +    E.SymbolName = Sym->getName();
>>    }
>>
>>    for (Export &E : Config->Exports) {
>>
>> Modified: lld/trunk/COFF/ICF.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/ICF.
>> cpp?rev=289280&r1=289279&r2=289280&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/COFF/ICF.cpp (original)
>> +++ lld/trunk/COFF/ICF.cpp Fri Dec  9 15:55:24 2016
>> @@ -115,8 +115,8 @@ bool ICF::equalsConstant(const SectionCh
>>          R1.VirtualAddress != R2.VirtualAddress) {
>>        return false;
>>      }
>> -    SymbolBody *B1 = A->File->getSymbolBody(R1.
>> SymbolTableIndex)->repl();
>> -    SymbolBody *B2 = B->File->getSymbolBody(R2.
>> SymbolTableIndex)->repl();
>> +    SymbolBody *B1 = A->File->getSymbolBody(R1.SymbolTableIndex);
>> +    SymbolBody *B2 = B->File->getSymbolBody(R2.SymbolTableIndex);
>>      if (B1 == B2)
>>        return true;
>>      if (auto *D1 = dyn_cast<DefinedRegular>(B1))
>> @@ -141,8 +141,8 @@ bool ICF::equalsConstant(const SectionCh
>>  bool ICF::equalsVariable(const SectionChunk *A, const SectionChunk *B) {
>>    // Compare relocations.
>>    auto Eq = [&](const coff_relocation &R1, const coff_relocation &R2) {
>> -    SymbolBody *B1 = A->File->getSymbolBody(R1.
>> SymbolTableIndex)->repl();
>> -    SymbolBody *B2 = B->File->getSymbolBody(R2.
>> SymbolTableIndex)->repl();
>> +    SymbolBody *B1 = A->File->getSymbolBody(R1.SymbolTableIndex);
>> +    SymbolBody *B2 = B->File->getSymbolBody(R2.SymbolTableIndex);
>>      if (B1 == B2)
>>        return true;
>>      if (auto *D1 = dyn_cast<DefinedRegular>(B1))
>>
>> Modified: lld/trunk/COFF/InputFiles.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/
>> InputFiles.cpp?rev=289280&r1=289279&r2=289280&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/COFF/InputFiles.cpp (original)
>> +++ lld/trunk/COFF/InputFiles.cpp Fri Dec  9 15:55:24 2016
>> @@ -12,7 +12,9 @@
>>  #include "Driver.h"
>>  #include "Error.h"
>>  #include "InputFiles.h"
>> +#include "SymbolTable.h"
>>  #include "Symbols.h"
>> +#include "lld/Support/Memory.h"
>>  #include "llvm/ADT/SmallVector.h"
>>  #include "llvm/ADT/Triple.h"
>>  #include "llvm/ADT/Twine.h"
>> @@ -39,13 +41,13 @@ using namespace llvm::support::endian;
>>
>>  using llvm::Triple;
>>  using llvm::support::ulittle32_t;
>> +using llvm::sys::fs::file_magic;
>> +using llvm::sys::fs::identify_magic;
>>
>>  namespace lld {
>>  namespace coff {
>>
>> -int InputFile::NextIndex = 0;
>>  LLVMContext BitcodeFile::Context;
>> -std::mutex BitcodeFile::Mu;
>>
>>  ArchiveFile::ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M)
>> {}
>>
>> @@ -53,14 +55,6 @@ void ArchiveFile::parse() {
>>    // Parse a MemoryBufferRef as an archive file.
>>    File = check(Archive::create(MB), toString(this));
>>
>> -  // Allocate a buffer for Lazy objects.
>> -  size_t NumSyms = File->getNumberOfSymbols();
>> -  LazySymbols.reserve(NumSyms);
>> -
>> -  // Read the symbol table to construct Lazy objects.
>> -  for (const Archive::Symbol &Sym : File->symbols())
>> -    LazySymbols.emplace_back(this, Sym);
>> -
>>    // Seen is a map from member files to boolean values. Initially
>>    // all members are mapped to false, which indicates all these files
>>    // are not read yet.
>> @@ -69,18 +63,22 @@ void ArchiveFile::parse() {
>>      Seen[Child.getChildOffset()].clear();
>>    if (Err)
>>      fatal(Err, toString(this));
>> +
>> +  // Read the symbol table to construct Lazy objects.
>> +  for (const Archive::Symbol &Sym : File->symbols())
>> +    Symtab->addLazy(this, Sym);
>>  }
>>
>>  // Returns a buffer pointing to a member file containing a given symbol.
>>  // This function is thread-safe.
>> -MemoryBufferRef ArchiveFile::getMember(const Archive::Symbol *Sym) {
>> +InputFile *ArchiveFile::getMember(const Archive::Symbol *Sym) {
>>    const Archive::Child &C =
>>        check(Sym->getMember(),
>>              "could not get the member for symbol " + Sym->getName());
>>
>>    // Return an empty buffer if we have already returned the same buffer.
>>    if (Seen[C.getChildOffset()].test_and_set())
>> -    return MemoryBufferRef();
>> +    return nullptr;
>>
>>    MemoryBufferRef MB =
>>        check(C.getMemoryBufferRef(),
>> @@ -90,10 +88,21 @@ MemoryBufferRef ArchiveFile::getMember(c
>>      Driver->Cpio->append(relativeToRoot(check(C.getFullName())),
>>                           MB.getBuffer());
>>
>> -  return MB;
>> -}
>> +  file_magic Magic = identify_magic(MB.getBuffer());
>> +  if (Magic == file_magic::coff_import_library)
>> +    return make<ImportFile>(MB);
>> +
>> +  InputFile *Obj;
>> +  if (Magic == file_magic::coff_object)
>> +    Obj = make<ObjectFile>(MB);
>> +  else if (Magic == file_magic::bitcode)
>> +    Obj = make<BitcodeFile>(MB);
>> +  else
>> +    fatal("unknown file type: " + MB.getBufferIdentifier());
>>
>> -MutableArrayRef<Lazy> ArchiveFile::getLazySymbols() { return
>> LazySymbols; }
>> +  Obj->ParentName = getName();
>> +  return Obj;
>> +}
>>
>>  void ObjectFile::parse() {
>>    // Parse a memory buffer as a COFF file.
>> @@ -167,7 +176,7 @@ void ObjectFile::initializeSymbols() {
>>    uint32_t NumSymbols = COFFObj->getNumberOfSymbols();
>>    SymbolBodies.reserve(NumSymbols);
>>    SparseSymbolBodies.resize(NumSymbols);
>> -  SmallVector<std::pair<Undefined *, uint32_t>, 8> WeakAliases;
>> +  SmallVector<std::pair<SymbolBody *, uint32_t>, 8> WeakAliases;
>>    int32_t LastSectionNumber = 0;
>>    for (uint32_t I = 0; I < NumSymbols; ++I) {
>>      // Get a COFFSymbolRef object.
>> @@ -188,7 +197,7 @@ void ObjectFile::initializeSymbols() {
>>        Body = createUndefined(Sym);
>>        uint32_t TagIndex =
>>            static_cast<const coff_aux_weak_external *>(AuxP)->TagIndex;
>> -      WeakAliases.emplace_back((Undefined *)Body, TagIndex);
>> +      WeakAliases.emplace_back(Body, TagIndex);
>>      } else {
>>        Body = createDefined(Sym, AuxP, IsFirst);
>>      }
>> @@ -199,23 +208,30 @@ void ObjectFile::initializeSymbols() {
>>      I += Sym.getNumberOfAuxSymbols();
>>      LastSectionNumber = Sym.getSectionNumber();
>>    }
>> -  for (auto WeakAlias : WeakAliases)
>> -    WeakAlias.first->WeakAlias = SparseSymbolBodies[WeakAlias.second];
>> +  for (auto WeakAlias : WeakAliases) {
>> +    auto *U = dyn_cast<Undefined>(WeakAlias.first);
>> +    if (!U)
>> +      continue;
>> +    // Report an error if two undefined symbols have different weak
>> aliases.
>> +    if (U->WeakAlias && U->WeakAlias != SparseSymbolBodies[WeakAlias.
>> second])
>> +      Symtab->reportDuplicate(U->symbol(), this);
>> +    U->WeakAlias = SparseSymbolBodies[WeakAlias.second];
>> +  }
>>  }
>>
>> -Undefined *ObjectFile::createUndefined(COFFSymbolRef Sym) {
>> +SymbolBody *ObjectFile::createUndefined(COFFSymbolRef Sym) {
>>    StringRef Name;
>>    COFFObj->getSymbolName(Sym, Name);
>> -  return new (Alloc) Undefined(Name);
>> +  return Symtab->addUndefined(Name, this, Sym.isWeakExternal())->body();
>>  }
>>
>> -Defined *ObjectFile::createDefined(COFFSymbolRef Sym, const void *AuxP,
>> -                                   bool IsFirst) {
>> +SymbolBody *ObjectFile::createDefined(COFFSymbolRef Sym, const void
>> *AuxP,
>> +                                      bool IsFirst) {
>>    StringRef Name;
>>    if (Sym.isCommon()) {
>>      auto *C = new (Alloc) CommonChunk(Sym);
>>      Chunks.push_back(C);
>> -    return new (Alloc) DefinedCommon(this, Sym, C);
>> +    return Symtab->addCommon(this, Sym, C)->body();
>>    }
>>    if (Sym.isAbsolute()) {
>>      COFFObj->getSymbolName(Sym, Name);
>> @@ -228,7 +244,10 @@ Defined *ObjectFile::createDefined(COFFS
>>          SEHCompat = true;
>>        return nullptr;
>>      }
>> -    return new (Alloc) DefinedAbsolute(Name, Sym);
>> +    if (Sym.isExternal())
>> +      return Symtab->addAbsolute(Name, Sym)->body();
>> +    else
>> +      return new (Alloc) DefinedAbsolute(Name, Sym);
>>    }
>>    int32_t SectionNumber = Sym.getSectionNumber();
>>    if (SectionNumber == llvm::COFF::IMAGE_SYM_DEBUG)
>> @@ -258,7 +277,11 @@ Defined *ObjectFile::createDefined(COFFS
>>      SC->Checksum = Aux->CheckSum;
>>    }
>>
>> -  auto *B = new (Alloc) DefinedRegular(this, Sym, SC);
>> +  DefinedRegular *B;
>> +  if (Sym.isExternal())
>> +    B = cast<DefinedRegular>(Symtab->addRegular(this, Sym, SC)->body());
>> +  else
>> +    B = new (Alloc) DefinedRegular(this, Sym, SC);
>>    if (SC->isCOMDAT() && Sym.getValue() == 0 && !AuxP)
>>      SC->setSymbol(B);
>>
>> @@ -320,22 +343,23 @@ void ImportFile::parse() {
>>      ExtName = ExtName.substr(0, ExtName.find('@'));
>>      break;
>>    }
>> -  ImpSym = new (Alloc) DefinedImportData(DLLName, ImpName, ExtName, Hdr);
>> -  SymbolBodies.push_back(ImpSym);
>> +
>> +  this->Hdr = Hdr;
>> +  ExternalName = ExtName;
>> +
>> +  ImpSym = cast<DefinedImportData>(
>> +      Symtab->addImportData(ImpName, this)->body());
>>
>>    // If type is function, we need to create a thunk which jump to an
>>    // address pointed by the __imp_ symbol. (This allows you to call
>>    // DLL functions just like regular non-DLL functions.)
>>    if (Hdr->getType() != llvm::COFF::IMPORT_CODE)
>>      return;
>> -  ThunkSym = new (Alloc) DefinedImportThunk(Name, ImpSym, Hdr->Machine);
>> -  SymbolBodies.push_back(ThunkSym);
>> +  ThunkSym = cast<DefinedImportThunk>(
>> +      Symtab->addImportThunk(Name, ImpSym, Hdr->Machine)->body());
>>  }
>>
>>  void BitcodeFile::parse() {
>> -  // Usually parse() is thread-safe, but bitcode file is an exception.
>> -  std::lock_guard<std::mutex> Lock(Mu);
>> -
>>    Context.enableDebugTypeODRUniquing();
>>    ErrorOr<std::unique_ptr<LTOModule>> ModOrErr =
>> LTOModule::createFromBuffer(
>>        Context, MB.getBufferStart(), MB.getBufferSize(),
>> llvm::TargetOptions());
>> @@ -350,15 +374,15 @@ void BitcodeFile::parse() {
>>      StringRef SymName = Saver.save(M->getSymbolName(I));
>>      int SymbolDef = Attrs & LTO_SYMBOL_DEFINITION_MASK;
>>      if (SymbolDef == LTO_SYMBOL_DEFINITION_UNDEFINED) {
>> -      SymbolBodies.push_back(new (Alloc) Undefined(SymName));
>> +      SymbolBodies.push_back(Symtab->addUndefined(SymName, this,
>> false)->body());
>>      } else {
>>        bool Replaceable =
>>            (SymbolDef == LTO_SYMBOL_DEFINITION_TENTATIVE || // common
>>             (Attrs & LTO_SYMBOL_COMDAT) ||                  // comdat
>>             (SymbolDef == LTO_SYMBOL_DEFINITION_WEAK &&     // weak
>> external
>>              (Attrs & LTO_SYMBOL_ALIAS)));
>> -      SymbolBodies.push_back(new (Alloc) DefinedBitcode(this, SymName,
>> -                                                        Replaceable));
>> +      SymbolBodies.push_back(
>> +          Symtab->addBitcode(this, SymName, Replaceable)->body());
>>      }
>>    }
>>
>>
>> Modified: lld/trunk/COFF/InputFiles.h
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/
>> InputFiles.h?rev=289280&r1=289279&r2=289280&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/COFF/InputFiles.h (original)
>> +++ lld/trunk/COFF/InputFiles.h Fri Dec  9 15:55:24 2016
>> @@ -31,6 +31,7 @@ using llvm::COFF::MachineTypes;
>>  using llvm::object::Archive;
>>  using llvm::object::COFFObjectFile;
>>  using llvm::object::COFFSymbolRef;
>> +using llvm::object::coff_import_header;
>>  using llvm::object::coff_section;
>>
>>  class Chunk;
>> @@ -39,6 +40,7 @@ class DefinedImportData;
>>  class DefinedImportThunk;
>>  class Lazy;
>>  class SectionChunk;
>> +struct Symbol;
>>  class SymbolBody;
>>  class Undefined;
>>
>> @@ -52,9 +54,6 @@ public:
>>    // Returns the filename.
>>    StringRef getName() { return MB.getBufferIdentifier(); }
>>
>> -  // Returns symbols defined by this file.
>> -  virtual std::vector<SymbolBody *> &getSymbols() = 0;
>> -
>>    // Reads a file (the constructor doesn't do that).
>>    virtual void parse() = 0;
>>
>> @@ -67,14 +66,8 @@ public:
>>    // Returns .drectve section contents if exist.
>>    StringRef getDirectives() { return StringRef(Directives).trim(); }
>>
>> -  // Each file has a unique index. The index number is used to
>> -  // resolve ties in symbol resolution.
>> -  int Index;
>> -  static int NextIndex;
>> -
>>  protected:
>> -  InputFile(Kind K, MemoryBufferRef M)
>> -      : Index(NextIndex++), MB(M), FileKind(K) {}
>> +  InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {}
>>
>>    MemoryBufferRef MB;
>>    std::string Directives;
>> @@ -90,22 +83,14 @@ public:
>>    static bool classof(const InputFile *F) { return F->kind() ==
>> ArchiveKind; }
>>    void parse() override;
>>
>> -  // Returns a memory buffer for a given symbol. An empty memory buffer
>> -  // is returned if we have already returned the same memory buffer.
>> -  // (So that we don't instantiate same members more than once.)
>> -  MemoryBufferRef getMember(const Archive::Symbol *Sym);
>> -
>> -  llvm::MutableArrayRef<Lazy> getLazySymbols();
>> -
>> -  // All symbols returned by ArchiveFiles are of Lazy type.
>> -  std::vector<SymbolBody *> &getSymbols() override {
>> -    llvm_unreachable("internal fatal");
>> -  }
>> +  // Returns an input file for a given symbol. A null pointer is
>> returned if we
>> +  // have already returned the same input file. (So that we don't
>> instantiate
>> +  // the same member more than once.)
>> +  InputFile *getMember(const Archive::Symbol *Sym);
>>
>>  private:
>>    std::unique_ptr<Archive> File;
>>    std::string Filename;
>> -  std::vector<Lazy> LazySymbols;
>>    std::map<uint64_t, std::atomic_flag> Seen;
>>  };
>>
>> @@ -118,7 +103,7 @@ public:
>>    MachineTypes getMachineType() override;
>>    std::vector<Chunk *> &getChunks() { return Chunks; }
>>    std::vector<SectionChunk *> &getDebugChunks() { return DebugChunks; }
>> -  std::vector<SymbolBody *> &getSymbols() override { return
>> SymbolBodies; }
>> +  std::vector<SymbolBody *> &getSymbols() { return SymbolBodies; }
>>
>>    // Returns a SymbolBody object for the SymbolIndex'th symbol in the
>>    // underlying object file.
>> @@ -142,8 +127,8 @@ private:
>>    void initializeSymbols();
>>    void initializeSEH();
>>
>> -  Defined *createDefined(COFFSymbolRef Sym, const void *Aux, bool
>> IsFirst);
>> -  Undefined *createUndefined(COFFSymbolRef Sym);
>> +  SymbolBody *createDefined(COFFSymbolRef Sym, const void *Aux, bool
>> IsFirst);
>> +  SymbolBody *createUndefined(COFFSymbolRef Sym);
>>
>>    std::unique_ptr<COFFObjectFile> COFFObj;
>>    llvm::BumpPtrAllocator Alloc;
>> @@ -181,7 +166,6 @@ public:
>>    explicit ImportFile(MemoryBufferRef M)
>>        : InputFile(ImportKind, M), StringAlloc(StringAllocAux) {}
>>    static bool classof(const InputFile *F) { return F->kind() ==
>> ImportKind; }
>> -  std::vector<SymbolBody *> &getSymbols() override { return
>> SymbolBodies; }
>>
>>    DefinedImportData *ImpSym = nullptr;
>>    DefinedImportThunk *ThunkSym = nullptr;
>> @@ -190,10 +174,14 @@ public:
>>  private:
>>    void parse() override;
>>
>> -  std::vector<SymbolBody *> SymbolBodies;
>>    llvm::BumpPtrAllocator Alloc;
>>    llvm::BumpPtrAllocator StringAllocAux;
>>    llvm::StringSaver StringAlloc;
>> +
>> +public:
>> +  StringRef ExternalName;
>> +  const coff_import_header *Hdr;
>> +  Chunk *Location = nullptr;
>>  };
>>
>>  // Used for LTO.
>> @@ -201,7 +189,7 @@ class BitcodeFile : public InputFile {
>>  public:
>>    explicit BitcodeFile(MemoryBufferRef M) : InputFile(BitcodeKind, M) {}
>>    static bool classof(const InputFile *F) { return F->kind() ==
>> BitcodeKind; }
>> -  std::vector<SymbolBody *> &getSymbols() override { return
>> SymbolBodies; }
>> +  std::vector<SymbolBody *> &getSymbols() { return SymbolBodies; }
>>    MachineTypes getMachineType() override;
>>    std::unique_ptr<LTOModule> takeModule() { return std::move(M); }
>>
>>
>> Modified: lld/trunk/COFF/MarkLive.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/
>> MarkLive.cpp?rev=289280&r1=289279&r2=289280&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/COFF/MarkLive.cpp (original)
>> +++ lld/trunk/COFF/MarkLive.cpp Fri Dec  9 15:55:24 2016
>> @@ -38,8 +38,8 @@ void markLive(const std::vector<Chunk *>
>>    };
>>
>>    // Add GC root chunks.
>> -  for (Undefined *U : Config->GCRoot)
>> -    if (auto *D = dyn_cast<DefinedRegular>(U->repl()))
>> +  for (SymbolBody *B : Config->GCRoot)
>> +    if (auto *D = dyn_cast<DefinedRegular>(B))
>>        Enqueue(D->getChunk());
>>
>>    while (!Worklist.empty()) {
>> @@ -48,7 +48,7 @@ void markLive(const std::vector<Chunk *>
>>
>>      // Mark all symbols listed in the relocation table for this section.
>>      for (SymbolBody *S : SC->symbols())
>> -      if (auto *D = dyn_cast<DefinedRegular>(S->repl()))
>> +      if (auto *D = dyn_cast<DefinedRegular>(S))
>>          Enqueue(D->getChunk());
>>
>>      // Mark associative sections if any.
>>
>> Modified: lld/trunk/COFF/SymbolTable.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/
>> SymbolTable.cpp?rev=289280&r1=289279&r2=289280&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/COFF/SymbolTable.cpp (original)
>> +++ lld/trunk/COFF/SymbolTable.cpp Fri Dec  9 15:55:24 2016
>> @@ -12,7 +12,6 @@
>>  #include "Driver.h"
>>  #include "Error.h"
>>  #include "Symbols.h"
>> -#include "lld/Core/Parallel.h"
>>  #include "lld/Support/Memory.h"
>>  #include "llvm/IR/LLVMContext.h"
>>  #include "llvm/LTO/legacy/LTOCodeGenerator.h"
>> @@ -25,21 +24,15 @@ using namespace llvm;
>>  namespace lld {
>>  namespace coff {
>>
>> -void SymbolTable::addFile(InputFile *File) {
>> -#if LLVM_ENABLE_THREADS
>> -  std::launch Policy = std::launch::async;
>> -#else
>> -  std::launch Policy = std::launch::deferred;
>> -#endif
>> +SymbolTable *Symtab;
>>
>> +void SymbolTable::addFile(InputFile *File) {
>>    Files.push_back(File);
>>    if (auto *F = dyn_cast<ArchiveFile>(File)) {
>> -    ArchiveQueue.push_back(
>> -        std::async(Policy, [=]() { F->parse(); return F; }));
>> +    ArchiveQueue.push_back(F);
>>      return;
>>    }
>> -  ObjectQueue.push_back(
>> -      std::async(Policy, [=]() { File->parse(); return File; }));
>> +  ObjectQueue.push_back(File);
>>    if (auto *F = dyn_cast<ObjectFile>(File)) {
>>      ObjectFiles.push_back(F);
>>    } else if (auto *F = dyn_cast<BitcodeFile>(File)) {
>> @@ -53,7 +46,7 @@ void SymbolTable::step() {
>>    if (queueEmpty())
>>      return;
>>    readObjects();
>> -  readArchives();
>> +  readArchive();
>>  }
>>
>>  void SymbolTable::run() {
>> @@ -61,26 +54,17 @@ void SymbolTable::run() {
>>      step();
>>  }
>>
>> -void SymbolTable::readArchives() {
>> +void SymbolTable::readArchive() {
>>    if (ArchiveQueue.empty())
>>      return;
>>
>>    // Add lazy symbols to the symbol table. Lazy symbols that conflict
>>    // with existing undefined symbols are accumulated in LazySyms.
>> -  std::vector<Symbol *> LazySyms;
>> -  for (std::future<ArchiveFile *> &Future : ArchiveQueue) {
>> -    ArchiveFile *File = Future.get();
>> -    if (Config->Verbose)
>> -      outs() << "Reading " << toString(File) << "\n";
>> -    for (Lazy &Sym : File->getLazySymbols())
>> -      addLazy(&Sym, &LazySyms);
>> -  }
>> -  ArchiveQueue.clear();
>> -
>> -  // Add archive member files to ObjectQueue that should resolve
>> -  // existing undefined symbols.
>> -  for (Symbol *Sym : LazySyms)
>> -    addMemberFile(cast<Lazy>(Sym->Body));
>> +  ArchiveFile *File = ArchiveQueue.front();
>> +  ArchiveQueue.pop_front();
>> +  if (Config->Verbose)
>> +    outs() << "Reading " << toString(File) << "\n";
>> +  File->parse();
>>  }
>>
>>  void SymbolTable::readObjects() {
>> @@ -90,14 +74,12 @@ void SymbolTable::readObjects() {
>>    // Add defined and undefined symbols to the symbol table.
>>    std::vector<StringRef> Directives;
>>    for (size_t I = 0; I < ObjectQueue.size(); ++I) {
>> -    InputFile *File = ObjectQueue[I].get();
>> +    InputFile *File = ObjectQueue[I];
>>      if (Config->Verbose)
>>        outs() << "Reading " << toString(File) << "\n";
>> +    File->parse();
>>      // Adding symbols may add more files to ObjectQueue
>>      // (but not to ArchiveQueue).
>> -    for (SymbolBody *Sym : File->getSymbols())
>> -      if (Sym->isExternal())
>> -        addSymbol(Sym);
>>      StringRef S = File->getDirectives();
>>      if (!S.empty()) {
>>        Directives.push_back(S);
>> @@ -117,127 +99,239 @@ bool SymbolTable::queueEmpty() {
>>    return ArchiveQueue.empty() && ObjectQueue.empty();
>>  }
>>
>> -void SymbolTable::reportRemainingUndefines(bool Resolve) {
>> +void SymbolTable::reportRemainingUndefines() {
>>    SmallPtrSet<SymbolBody *, 8> Undefs;
>>    for (auto &I : Symtab) {
>>      Symbol *Sym = I.second;
>> -    auto *Undef = dyn_cast<Undefined>(Sym->Body);
>> +    auto *Undef = dyn_cast<Undefined>(Sym->body());
>>      if (!Undef)
>>        continue;
>> +    if (!Sym->IsUsedInRegularObj)
>> +      continue;
>>      StringRef Name = Undef->getName();
>>      // A weak alias may have been resolved, so check for that.
>>      if (Defined *D = Undef->getWeakAlias()) {
>> -      if (Resolve)
>> -        Sym->Body = D;
>> +      // We resolve weak aliases by replacing the alias's SymbolBody
>> with the
>> +      // target's SymbolBody. This causes all SymbolBody pointers
>> referring to
>> +      // the old symbol to instead refer to the new symbol. However, we
>> can't
>> +      // just blindly copy sizeof(Symbol::Body) bytes from D to Sym->Body
>> +      // because D may be an internal symbol, and internal symbols are
>> stored as
>> +      // "unparented" SymbolBodies. For that reason we need to check
>> which type
>> +      // of symbol we are dealing with and copy the correct number of
>> bytes.
>> +      if (isa<DefinedRegular>(D))
>> +        memcpy(Sym->Body.buffer, D, sizeof(DefinedRegular));
>> +      else if (isa<DefinedAbsolute>(D))
>> +        memcpy(Sym->Body.buffer, D, sizeof(DefinedAbsolute));
>> +      else
>> +        // No other internal symbols are possible.
>> +        Sym->Body = D->symbol()->Body;
>>        continue;
>>      }
>>      // If we can resolve a symbol by removing __imp_ prefix, do that.
>>      // This odd rule is for compatibility with MSVC linker.
>>      if (Name.startswith("__imp_")) {
>>        Symbol *Imp = find(Name.substr(strlen("__imp_")));
>> -      if (Imp && isa<Defined>(Imp->Body)) {
>> -        if (!Resolve)
>> -          continue;
>> -        auto *D = cast<Defined>(Imp->Body);
>> -        auto *S = make<DefinedLocalImport>(Name, D);
>> -        LocalImportChunks.push_back(S->getChunk());
>> -        Sym->Body = S;
>> +      if (Imp && isa<Defined>(Imp->body())) {
>> +        auto *D = cast<Defined>(Imp->body());
>> +        replaceBody<DefinedLocalImport>(Sym, Name, D);
>> +        LocalImportChunks.push_back(
>> +            cast<DefinedLocalImport>(Sym->body())->getChunk());
>>          continue;
>>        }
>>      }
>>      // Remaining undefined symbols are not fatal if /force is specified.
>>      // They are replaced with dummy defined symbols.
>> -    if (Config->Force && Resolve)
>> -      Sym->Body = make<DefinedAbsolute>(Name, 0);
>> -    Undefs.insert(Sym->Body);
>> +    if (Config->Force)
>> +      replaceBody<DefinedAbsolute>(Sym, Name, 0);
>> +    Undefs.insert(Sym->body());
>>    }
>>    if (Undefs.empty())
>>      return;
>> -  for (Undefined *U : Config->GCRoot)
>> -    if (Undefs.count(U->repl()))
>> -      errs() << "<root>: undefined symbol: " << U->getName() << "\n";
>> -  for (InputFile *File : Files)
>> -    if (!isa<ArchiveFile>(File))
>> -      for (SymbolBody *Sym : File->getSymbols())
>> -        if (Undefs.count(Sym->repl()))
>> -          errs() << toString(File) << ": undefined symbol: " <<
>> Sym->getName()
>> -                 << "\n";
>> +  for (SymbolBody *B : Config->GCRoot)
>> +    if (Undefs.count(B))
>> +      errs() << "<root>: undefined symbol: " << B->getName() << "\n";
>> +  for (ObjectFile *File : ObjectFiles)
>> +    for (SymbolBody *Sym : File->getSymbols())
>> +      if (Undefs.count(Sym))
>> +        errs() << toString(File) << ": undefined symbol: " <<
>> Sym->getName()
>> +               << "\n";
>>    if (!Config->Force)
>>      fatal("link failed");
>>  }
>>
>> -void SymbolTable::addLazy(Lazy *New, std::vector<Symbol *> *Accum) {
>> -  Symbol *Sym = insert(New);
>> -  if (Sym->Body == New)
>> -    return;
>> -  SymbolBody *Existing = Sym->Body;
>> -  if (isa<Defined>(Existing))
>> -    return;
>> -  if (Lazy *L = dyn_cast<Lazy>(Existing))
>> -    if (L->getFileIndex() < New->getFileIndex())
>> -      return;
>> -  Sym->Body = New;
>> -  New->setBackref(Sym);
>> -  if (isa<Undefined>(Existing))
>> -    Accum->push_back(Sym);
>> -}
>> -
>> -void SymbolTable::addSymbol(SymbolBody *New) {
>> -  // Find an existing symbol or create and insert a new one.
>> -  assert(isa<Defined>(New) || isa<Undefined>(New));
>> -  Symbol *Sym = insert(New);
>> -  if (Sym->Body == New)
>> -    return;
>> -  SymbolBody *Existing = Sym->Body;
>> -
>> -  // If we have an undefined symbol and a lazy symbol,
>> -  // let the lazy symbol to read a member file.
>> -  if (auto *L = dyn_cast<Lazy>(Existing)) {
>> -    // Undefined symbols with weak aliases need not to be resolved,
>> -    // since they would be replaced with weak aliases if they remain
>> -    // undefined.
>> -    if (auto *U = dyn_cast<Undefined>(New)) {
>> -      if (!U->WeakAlias) {
>> -        addMemberFile(L);
>> -        return;
>> -      }
>> -    }
>> -    Sym->Body = New;
>> -    return;
>> +std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) {
>> +  Symbol *&Sym = Symtab[Name];
>> +  if (Sym)
>> +    return {Sym, false};
>> +  Sym = make<Symbol>();
>> +  Sym->IsUsedInRegularObj = false;
>> +  return {Sym, true};
>> +}
>> +
>> +Symbol *SymbolTable::addUndefined(StringRef Name, InputFile *F,
>> +                                  bool IsWeakAlias) {
>> +  Symbol *S;
>> +  bool WasInserted;
>> +  std::tie(S, WasInserted) = insert(Name);
>> +  if (!F || !isa<BitcodeFile>(F))
>> +    S->IsUsedInRegularObj = true;
>> +  if (WasInserted || (isa<Lazy>(S->body()) && IsWeakAlias)) {
>> +    replaceBody<Undefined>(S, Name);
>> +    return S;
>>    }
>> -
>> -  // compare() returns -1, 0, or 1 if the lhs symbol is less preferable,
>> -  // equivalent (conflicting), or more preferable, respectively.
>> -  int Comp = Existing->compare(New);
>> -  if (Comp == 0)
>> -    fatal("duplicate symbol: " + toString(*Existing) + " in " +
>> -          toString(Existing->getFile()) + " and in " +
>> -          toString(New->getFile()));
>> -  if (Comp < 0)
>> -    Sym->Body = New;
>> -}
>> -
>> -Symbol *SymbolTable::insert(SymbolBody *New) {
>> -  Symbol *&Sym = Symtab[New->getName()];
>> -  if (Sym) {
>> -    New->setBackref(Sym);
>> -    return Sym;
>> -  }
>> -  Sym = make<Symbol>(New);
>> -  New->setBackref(Sym);
>> -  return Sym;
>> +  if (auto *L = dyn_cast<Lazy>(S->body()))
>> +    addMemberFile(L->File, L->Sym);
>> +  return S;
>> +}
>> +
>> +void SymbolTable::addLazy(ArchiveFile *F, const Archive::Symbol Sym) {
>> +  StringRef Name = Sym.getName();
>> +  Symbol *S;
>> +  bool WasInserted;
>> +  std::tie(S, WasInserted) = insert(Name);
>> +  if (WasInserted) {
>> +    replaceBody<Lazy>(S, F, Sym);
>> +    return;
>> +  }
>> +  auto *U = dyn_cast<Undefined>(S->body());
>> +  if (!U || U->WeakAlias)
>> +    return;
>> +  addMemberFile(F, Sym);
>> +}
>> +
>> +void SymbolTable::reportDuplicate(Symbol *Existing, InputFile *NewFile)
>> {
>> +  fatal("duplicate symbol: " + toString(*Existing->body()) + " in " +
>> +        toString(Existing->body()->getFile()) + " and in " +
>> +        (NewFile ? toString(NewFile) : "(internal)"));
>> +}
>> +
>> +Symbol *SymbolTable::addAbsolute(StringRef N, COFFSymbolRef Sym) {
>> +  Symbol *S;
>> +  bool WasInserted;
>> +  std::tie(S, WasInserted) = insert(N);
>> +  S->IsUsedInRegularObj = true;
>> +  if (WasInserted || isa<Undefined>(S->body()) || isa<Lazy>(S->body()))
>> +    replaceBody<DefinedAbsolute>(S, N, Sym);
>> +  else if (!isa<DefinedCOFF>(S->body()))
>> +    reportDuplicate(S, nullptr);
>> +  return S;
>> +}
>> +
>> +Symbol *SymbolTable::addAbsolute(StringRef N, uint64_t VA) {
>> +  Symbol *S;
>> +  bool WasInserted;
>> +  std::tie(S, WasInserted) = insert(N);
>> +  S->IsUsedInRegularObj = true;
>> +  if (WasInserted || isa<Undefined>(S->body()) || isa<Lazy>(S->body()))
>> +    replaceBody<DefinedAbsolute>(S, N, VA);
>> +  else if (!isa<DefinedCOFF>(S->body()))
>> +    reportDuplicate(S, nullptr);
>> +  return S;
>> +}
>> +
>> +Symbol *SymbolTable::addRelative(StringRef N, uint64_t VA) {
>> +  Symbol *S;
>> +  bool WasInserted;
>> +  std::tie(S, WasInserted) = insert(N);
>> +  S->IsUsedInRegularObj = true;
>> +  if (WasInserted || isa<Undefined>(S->body()) || isa<Lazy>(S->body()))
>> +    replaceBody<DefinedRelative>(S, N, VA);
>> +  else if (!isa<DefinedCOFF>(S->body()))
>> +    reportDuplicate(S, nullptr);
>> +  return S;
>> +}
>> +
>> +Symbol *SymbolTable::addRegular(ObjectFile *F, COFFSymbolRef Sym,
>> +                                SectionChunk *C) {
>> +  StringRef Name;
>> +  F->getCOFFObj()->getSymbolName(Sym, Name);
>> +  Symbol *S;
>> +  bool WasInserted;
>> +  std::tie(S, WasInserted) = insert(Name);
>> +  S->IsUsedInRegularObj = true;
>> +  if (WasInserted || isa<Undefined>(S->body()) || isa<Lazy>(S->body()))
>> +    replaceBody<DefinedRegular>(S, F, Sym, C);
>> +  else if (auto *R = dyn_cast<DefinedRegular>(S->body())) {
>> +    if (!C->isCOMDAT() || !R->isCOMDAT())
>> +      reportDuplicate(S, F);
>> +  } else if (auto *B = dyn_cast<DefinedBitcode>(S->body())) {
>> +    if (B->IsReplaceable)
>> +      replaceBody<DefinedRegular>(S, F, Sym, C);
>> +    else if (!C->isCOMDAT())
>> +      reportDuplicate(S, F);
>> +  } else
>> +    replaceBody<DefinedRegular>(S, F, Sym, C);
>> +  return S;
>> +}
>> +
>> +Symbol *SymbolTable::addBitcode(BitcodeFile *F, StringRef N, bool
>> IsReplaceable) {
>> +  Symbol *S;
>> +  bool WasInserted;
>> +  std::tie(S, WasInserted) = insert(N);
>> +  if (WasInserted || isa<Undefined>(S->body()) || isa<Lazy>(S->body())) {
>> +    replaceBody<DefinedBitcode>(S, F, N, IsReplaceable);
>> +    return S;
>> +  }
>> +  if (isa<DefinedCommon>(S->body()))
>> +    return S;
>> +  if (IsReplaceable)
>> +    if (isa<DefinedRegular>(S->body()) || isa<DefinedBitcode>(S->body())
>> )
>> +      return S;
>> +  reportDuplicate(S, F);
>> +  return S;
>> +}
>> +
>> +Symbol *SymbolTable::addCommon(ObjectFile *F, COFFSymbolRef Sym,
>> +                               CommonChunk *C) {
>> +  StringRef Name;
>> +  F->getCOFFObj()->getSymbolName(Sym, Name);
>> +  Symbol *S;
>> +  bool WasInserted;
>> +  std::tie(S, WasInserted) = insert(Name);
>> +  S->IsUsedInRegularObj = true;
>> +  if (WasInserted || !isa<DefinedCOFF>(S->body()))
>> +    replaceBody<DefinedCommon>(S, F, Sym, C);
>> +  else if (auto *DC = dyn_cast<DefinedCommon>(S->body()))
>> +    if (Sym.getValue() > DC->getSize())
>> +      replaceBody<DefinedCommon>(S, F, Sym, C);
>> +  return S;
>> +}
>> +
>> +Symbol *SymbolTable::addImportData(StringRef N, ImportFile *F) {
>> +  Symbol *S;
>> +  bool WasInserted;
>> +  std::tie(S, WasInserted) = insert(N);
>> +  S->IsUsedInRegularObj = true;
>> +  if (WasInserted || isa<Undefined>(S->body()) || isa<Lazy>(S->body()))
>> +    replaceBody<DefinedImportData>(S, N, F);
>> +  else if (!isa<DefinedCOFF>(S->body()))
>> +    reportDuplicate(S, nullptr);
>> +  return S;
>> +}
>> +
>> +Symbol *SymbolTable::addImportThunk(StringRef Name, DefinedImportData
>> *ID,
>> +                                    uint16_t Machine) {
>> +  Symbol *S;
>> +  bool WasInserted;
>> +  std::tie(S, WasInserted) = insert(Name);
>> +  S->IsUsedInRegularObj = true;
>> +  if (WasInserted || isa<Undefined>(S->body()) || isa<Lazy>(S->body()))
>> +    replaceBody<DefinedImportThunk>(S, Name, ID, Machine);
>> +  else if (!isa<DefinedCOFF>(S->body()))
>> +    reportDuplicate(S, nullptr);
>> +  return S;
>>  }
>>
>>  // Reads an archive member file pointed by a given symbol.
>> -void SymbolTable::addMemberFile(Lazy *Body) {
>> -  InputFile *File = Body->getMember();
>> +void SymbolTable::addMemberFile(ArchiveFile *F, const Archive::Symbol
>> Sym) {
>> +  InputFile *File = F->getMember(&Sym);
>>
>>    // getMember returns an empty buffer if the member was already
>>    // read from the library.
>>    if (!File)
>>      return;
>>    if (Config->Verbose)
>> -    outs() << "Loaded " << toString(File) << " for " << Body->getName()
>> << "\n";
>> +    outs() << "Loaded " << toString(File) << " for " << Sym.getName() <<
>> "\n";
>>    addFile(File);
>>  }
>>
>> @@ -274,7 +368,7 @@ StringRef SymbolTable::findByPrefix(Stri
>>
>>  StringRef SymbolTable::findMangle(StringRef Name) {
>>    if (Symbol *Sym = find(Name))
>> -    if (!isa<Undefined>(Sym->Body))
>> +    if (!isa<Undefined>(Sym->body()))
>>        return Name;
>>    if (Config->Machine != I386)
>>      return findByPrefix(("?" + Name + "@@Y").str());
>> @@ -288,34 +382,17 @@ StringRef SymbolTable::findMangle(String
>>    return findByPrefix(("?" + Name.substr(1) + "@@Y").str());
>>  }
>>
>> -void SymbolTable::mangleMaybe(Undefined *U) {
>> -  if (U->WeakAlias)
>> -    return;
>> -  if (!isa<Undefined>(U->repl()))
>> +void SymbolTable::mangleMaybe(SymbolBody *B) {
>> +  auto *U = dyn_cast<Undefined>(B);
>> +  if (!U || U->WeakAlias)
>>      return;
>>    StringRef Alias = findMangle(U->getName());
>>    if (!Alias.empty())
>>      U->WeakAlias = addUndefined(Alias);
>>  }
>>
>> -Undefined *SymbolTable::addUndefined(StringRef Name) {
>> -  auto *New = make<Undefined>(Name);
>> -  addSymbol(New);
>> -  if (auto *U = dyn_cast<Undefined>(New->repl()))
>> -    return U;
>> -  return New;
>> -}
>> -
>> -DefinedRelative *SymbolTable::addRelative(StringRef Name, uint64_t VA) {
>> -  auto *New = make<DefinedRelative>(Name, VA);
>> -  addSymbol(New);
>> -  return New;
>> -}
>> -
>> -DefinedAbsolute *SymbolTable::addAbsolute(StringRef Name, uint64_t VA) {
>> -  auto *New = make<DefinedAbsolute>(Name, VA);
>> -  addSymbol(New);
>> -  return New;
>> +SymbolBody *SymbolTable::addUndefined(StringRef Name) {
>> +  return addUndefined(Name, nullptr, false)->body();
>>  }
>>
>>  void SymbolTable::printMap(llvm::raw_ostream &OS) {
>> @@ -329,59 +406,19 @@ void SymbolTable::printMap(llvm::raw_ost
>>    }
>>  }
>>
>> -void SymbolTable::addCombinedLTOObject(ObjectFile *Obj) {
>> -  for (SymbolBody *Body : Obj->getSymbols()) {
>> -    if (!Body->isExternal())
>> -      continue;
>> -    // We should not see any new undefined symbols at this point, but
>> we'll
>> -    // diagnose them later in reportRemainingUndefines().
>> -    StringRef Name = Body->getName();
>> -    Symbol *Sym = insert(Body);
>> -    SymbolBody *Existing = Sym->Body;
>> -
>> -    if (Existing == Body)
>> -      continue;
>> -
>> -    if (isa<DefinedBitcode>(Existing)) {
>> -      Sym->Body = Body;
>> -      continue;
>> -    }
>> -    if (isa<Undefined>(Body)) {
>> -      if (auto *L = dyn_cast<Lazy>(Existing)) {
>> -        // We may see new references to runtime library symbols such as
>> __chkstk
>> -        // here. These symbols must be wholly defined in non-bitcode
>> files.
>> -        addMemberFile(L);
>> -        continue;
>> -      }
>> -    }
>> -
>> -    int Comp = Existing->compare(Body);
>> -    if (Comp == 0)
>> -      fatal("LTO: unexpected duplicate symbol: " + Name);
>> -    if (Comp < 0)
>> -      Sym->Body = Body;
>> -  }
>> -}
>> -
>>  void SymbolTable::addCombinedLTOObjects() {
>>    if (BitcodeFiles.empty())
>>      return;
>>
>> -  // Diagnose any undefined symbols early, but do not resolve weak
>> externals,
>> -  // as resolution breaks the invariant that each Symbol points to a
>> unique
>> -  // SymbolBody, which we rely on to replace DefinedBitcode symbols
>> correctly.
>> -  reportRemainingUndefines(/*Resolve=*/false);
>> -
>>    // Create an object file and add it to the symbol table by replacing
>> any
>>    // DefinedBitcode symbols with the definitions in the object file.
>>    LTOCodeGenerator CG(BitcodeFile::Context);
>>    CG.setOptLevel(Config->LTOOptLevel);
>>    std::vector<ObjectFile *> Objs = createLTOObjects(&CG);
>>
>> -  for (ObjectFile *Obj : Objs)
>> -    addCombinedLTOObject(Obj);
>> -
>>    size_t NumBitcodeFiles = BitcodeFiles.size();
>> +  for (ObjectFile *Obj : Objs)
>> +    Obj->parse();
>>    run();
>>    if (BitcodeFiles.size() != NumBitcodeFiles)
>>      fatal("LTO: late loaded symbol created new bitcode reference");
>> @@ -390,25 +427,17 @@ void SymbolTable::addCombinedLTOObjects(
>>  // Combine and compile bitcode files and then return the result
>>  // as a vector of regular COFF object files.
>>  std::vector<ObjectFile *> SymbolTable::createLTOObjects(LTOCodeGenerator
>> *CG) {
>> -  // All symbols referenced by non-bitcode objects must be preserved.
>> -  for (ObjectFile *File : ObjectFiles)
>> -    for (SymbolBody *Body : File->getSymbols())
>> -      if (auto *S = dyn_cast<DefinedBitcode>(Body->repl()))
>> -        CG->addMustPreserveSymbol(S->getName());
>> -
>> -  // Likewise for bitcode symbols which we initially resolved to
>> non-bitcode.
>> +  // All symbols referenced by non-bitcode objects, including GC roots,
>> must be
>> +  // preserved. We must also replace bitcode symbols with undefined
>> symbols so
>> +  // that they may be replaced with real definitions without conflicting.
>>    for (BitcodeFile *File : BitcodeFiles)
>> -    for (SymbolBody *Body : File->getSymbols())
>> -      if (isa<DefinedBitcode>(Body) && !isa<DefinedBitcode>(Body->
>> repl()))
>> +    for (SymbolBody *Body : File->getSymbols()) {
>> +      if (!isa<DefinedBitcode>(Body))
>> +        continue;
>> +      if (Body->symbol()->IsUsedInRegularObj)
>>          CG->addMustPreserveSymbol(Body->getName());
>> -
>> -  // Likewise for other symbols that must be preserved.
>> -  for (Undefined *U : Config->GCRoot) {
>> -    if (auto *S = dyn_cast<DefinedBitcode>(U->repl()))
>> -      CG->addMustPreserveSymbol(S->getName());
>> -    else if (auto *S = dyn_cast_or_null<DefinedBitcode>(U->
>> getWeakAlias()))
>> -      CG->addMustPreserveSymbol(S->getName());
>> -  }
>> +      replaceBody<Undefined>(Body->symbol(), Body->getName());
>> +    }
>>
>>    CG->setModule(BitcodeFiles[0]->takeModule());
>>    for (unsigned I = 1, E = BitcodeFiles.size(); I != E; ++I)
>> @@ -438,7 +467,6 @@ std::vector<ObjectFile *> SymbolTable::c
>>      auto *ObjFile = new ObjectFile(MemoryBufferRef(Obj, "<LTO
>> object>"));
>>      Files.emplace_back(ObjFile);
>>      ObjectFiles.push_back(ObjFile);
>> -    ObjFile->parse();
>>      ObjFiles.push_back(ObjFile);
>>    }
>>
>>
>> Modified: lld/trunk/COFF/SymbolTable.h
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/
>> SymbolTable.h?rev=289280&r1=289279&r2=289280&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/COFF/SymbolTable.h (original)
>> +++ lld/trunk/COFF/SymbolTable.h Fri Dec  9 15:55:24 2016
>> @@ -22,6 +22,7 @@
>>  #endif
>>
>>  #include <future>
>> +#include <list>
>>
>>  namespace llvm {
>>  struct LTOCodeGenerator;
>> @@ -31,6 +32,7 @@ namespace lld {
>>  namespace coff {
>>
>>  class Chunk;
>> +class CommonChunk;
>>  class Defined;
>>  class DefinedAbsolute;
>>  class DefinedRelative;
>> @@ -48,7 +50,9 @@ struct Symbol;
>>  // conflicts. For example, obviously, a defined symbol is better than
>>  // an undefined symbol. Or, if there's a conflict between a lazy and a
>>  // undefined, it'll read an archive member to read a real definition
>> -// to replace the lazy symbol. The logic is implemented in resolve().
>> +// to replace the lazy symbol. The logic is implemented in the
>> +// add*() functions, which are called by input files as they are parsed.
>> +// There is one add* function per symbol type.
>>  class SymbolTable {
>>  public:
>>    void addFile(InputFile *File);
>> @@ -57,9 +61,10 @@ public:
>>    void run();
>>    bool queueEmpty();
>>
>> -  // Print an error message on undefined symbols. If Resolve is true,
>> try to
>> -  // resolve any undefined symbols and update the symbol table
>> accordingly.
>> -  void reportRemainingUndefines(bool Resolve);
>> +  // Try to resolve any undefined symbols and update the symbol table
>> +  // accordingly, then print an error message for any remaining undefined
>> +  // symbols.
>> +  void reportRemainingUndefines();
>>
>>    // Returns a list of chunks of selected symbols.
>>    std::vector<Chunk *> getChunks();
>> @@ -72,7 +77,7 @@ public:
>>    // mangled symbol. This function tries to find a mangled name
>>    // for U from the symbol table, and if found, set the symbol as
>>    // a weak alias for U.
>> -  void mangleMaybe(Undefined *U);
>> +  void mangleMaybe(SymbolBody *B);
>>    StringRef findMangle(StringRef Name);
>>
>>    // Print a layout map to OS.
>> @@ -91,36 +96,49 @@ public:
>>    std::vector<ObjectFile *> ObjectFiles;
>>
>>    // Creates an Undefined symbol for a given name.
>> -  Undefined *addUndefined(StringRef Name);
>> -  DefinedRelative *addRelative(StringRef Name, uint64_t VA);
>> -  DefinedAbsolute *addAbsolute(StringRef Name, uint64_t VA);
>> +  SymbolBody *addUndefined(StringRef Name);
>> +
>> +  Symbol *addRelative(StringRef N, uint64_t VA);
>> +  Symbol *addAbsolute(StringRef N, uint64_t VA);
>> +
>> +  Symbol *addUndefined(StringRef Name, InputFile *F, bool IsWeakAlias);
>> +  void addLazy(ArchiveFile *F, const Archive::Symbol Sym);
>> +  Symbol *addAbsolute(StringRef N, COFFSymbolRef S);
>> +  Symbol *addRegular(ObjectFile *F, COFFSymbolRef S, SectionChunk *C);
>> +  Symbol *addBitcode(BitcodeFile *F, StringRef N, bool IsReplaceable);
>> +  Symbol *addCommon(ObjectFile *F, COFFSymbolRef S, CommonChunk *C);
>> +  Symbol *addImportData(StringRef N, ImportFile *F);
>> +  Symbol *addImportThunk(StringRef Name, DefinedImportData *S,
>> +                         uint16_t Machine);
>> +
>> +  void reportDuplicate(Symbol *Existing, InputFile *NewFile);
>>
>>    // A list of chunks which to be added to .rdata.
>>    std::vector<Chunk *> LocalImportChunks;
>>
>>  private:
>> -  void readArchives();
>> +  void readArchive();
>>    void readObjects();
>>
>> -  void addSymbol(SymbolBody *New);
>> -  void addLazy(Lazy *New, std::vector<Symbol *> *Accum);
>> -  Symbol *insert(SymbolBody *New);
>> +  std::pair<Symbol *, bool> insert(StringRef Name);
>>    StringRef findByPrefix(StringRef Prefix);
>>
>> -  void addMemberFile(Lazy *Body);
>> +  void addMemberFile(ArchiveFile *F, const Archive::Symbol Sym);
>>    void addCombinedLTOObject(ObjectFile *Obj);
>>    std::vector<ObjectFile *> createLTOObjects(llvm::LTOCodeGenerator
>> *CG);
>>
>>    llvm::DenseMap<StringRef, Symbol *> Symtab;
>>
>>    std::vector<InputFile *> Files;
>> -  std::vector<std::future<ArchiveFile *>> ArchiveQueue;
>> -  std::vector<std::future<InputFile *>> ObjectQueue;
>> +  std::list<ArchiveFile *> ArchiveQueue;
>> +  std::vector<InputFile *> ObjectQueue;
>>
>>    std::vector<BitcodeFile *> BitcodeFiles;
>>    std::vector<SmallString<0>> Objs;
>>  };
>>
>> +extern SymbolTable *Symtab;
>> +
>>  } // namespace coff
>>  } // namespace lld
>>
>>
>> Modified: lld/trunk/COFF/Symbols.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/
>> Symbols.cpp?rev=289280&r1=289279&r2=289280&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/COFF/Symbols.cpp (original)
>> +++ lld/trunk/COFF/Symbols.cpp Fri Dec  9 15:55:24 2016
>> @@ -18,8 +18,6 @@
>>
>>  using namespace llvm;
>>  using namespace llvm::object;
>> -using llvm::sys::fs::identify_magic;
>> -using llvm::sys::fs::file_magic;
>>
>>  namespace lld {
>>  namespace coff {
>> @@ -49,120 +47,6 @@ InputFile *SymbolBody::getFile() {
>>    return nullptr;
>>  }
>>
>> -// Returns 1, 0 or -1 if this symbol should take precedence
>> -// over the Other, tie or lose, respectively.
>> -int SymbolBody::compare(SymbolBody *Other) {
>> -  Kind LK = kind(), RK = Other->kind();
>> -
>> -  // Normalize so that the smaller kind is on the left.
>> -  if (LK > RK)
>> -    return -Other->compare(this);
>> -
>> -  // First handle comparisons between two different kinds.
>> -  if (LK != RK) {
>> -    if (RK > LastDefinedKind) {
>> -      if (LK == LazyKind && cast<Undefined>(Other)->WeakAlias)
>> -        return -1;
>> -
>> -      // The LHS is either defined or lazy and so it wins.
>> -      assert((LK <= LastDefinedKind || LK == LazyKind) && "Bad kind!");
>> -      return 1;
>> -    }
>> -
>> -    // Bitcode has special complexities.
>> -    if (RK == DefinedBitcodeKind) {
>> -      auto *RHS = cast<DefinedBitcode>(Other);
>> -
>> -      switch (LK) {
>> -      case DefinedCommonKind:
>> -        return 1;
>> -
>> -      case DefinedRegularKind:
>> -        // As an approximation, regular symbols win over bitcode symbols,
>> -        // but we definitely have a conflict if the regular symbol is not
>> -        // replaceable and neither is the bitcode symbol. We do not
>> -        // replicate the rest of the symbol resolution logic here; symbol
>> -        // resolution will be done accurately after lowering bitcode
>> symbols
>> -        // to regular symbols in addCombinedLTOObject().
>> -        if (cast<DefinedRegular>(this)->isCOMDAT() ||
>> RHS->IsReplaceable)
>> -          return 1;
>> -
>> -        // Fallthrough to the default of a tie otherwise.
>> -      default:
>> -        return 0;
>> -      }
>> -    }
>> -
>> -    // Either of the object file kind will trump a higher kind.
>> -    if (LK <= LastDefinedCOFFKind)
>> -      return 1;
>> -
>> -    // The remaining kind pairs are ties amongst defined symbols.
>> -    return 0;
>> -  }
>> -
>> -  // Now handle the case where the kinds are the same.
>> -  switch (LK) {
>> -  case DefinedRegularKind: {
>> -    auto *LHS = cast<DefinedRegular>(this);
>> -    auto *RHS = cast<DefinedRegular>(Other);
>> -    if (LHS->isCOMDAT() && RHS->isCOMDAT())
>> -      return LHS->getFileIndex() < RHS->getFileIndex() ? 1 : -1;
>> -    return 0;
>> -  }
>> -
>> -  case DefinedCommonKind: {
>> -    auto *LHS = cast<DefinedCommon>(this);
>> -    auto *RHS = cast<DefinedCommon>(Other);
>> -    if (LHS->getSize() == RHS->getSize())
>> -      return LHS->getFileIndex() < RHS->getFileIndex() ? 1 : -1;
>> -    return LHS->getSize() > RHS->getSize() ? 1 : -1;
>> -  }
>> -
>> -  case DefinedBitcodeKind: {
>> -    auto *LHS = cast<DefinedBitcode>(this);
>> -    auto *RHS = cast<DefinedBitcode>(Other);
>> -    // If both are non-replaceable, we have a tie.
>> -    if (!LHS->IsReplaceable && !RHS->IsReplaceable)
>> -      return 0;
>> -
>> -    // Non-replaceable symbols win, but even two replaceable symboles
>> don't
>> -    // tie. If both symbols are replaceable, choice is arbitrary.
>> -    if (RHS->IsReplaceable && LHS->IsReplaceable)
>> -      return uintptr_t(LHS) < uintptr_t(RHS) ? 1 : -1;
>> -    return LHS->IsReplaceable ? -1 : 1;
>> -  }
>> -
>> -  case LazyKind: {
>> -    // Don't tie, pick the earliest.
>> -    auto *LHS = cast<Lazy>(this);
>> -    auto *RHS = cast<Lazy>(Other);
>> -    return LHS->getFileIndex() < RHS->getFileIndex() ? 1 : -1;
>> -  }
>> -
>> -  case UndefinedKind: {
>> -    auto *LHS = cast<Undefined>(this);
>> -    auto *RHS = cast<Undefined>(Other);
>> -    // Tie if both undefined symbols have different weak aliases.
>> -    if (LHS->WeakAlias && RHS->WeakAlias) {
>> -      if (LHS->WeakAlias->getName() != RHS->WeakAlias->getName())
>> -        return 0;
>> -      return uintptr_t(LHS) < uintptr_t(RHS) ? 1 : -1;
>> -    }
>> -    return LHS->WeakAlias ? 1 : -1;
>> -  }
>> -
>> -  case DefinedLocalImportKind:
>> -  case DefinedImportThunkKind:
>> -  case DefinedImportDataKind:
>> -  case DefinedAbsoluteKind:
>> -  case DefinedRelativeKind:
>> -    // These all simply tie.
>> -    return 0;
>> -  }
>> -  llvm_unreachable("unknown symbol kind");
>> -}
>> -
>>  COFFSymbolRef DefinedCOFF::getCOFFSymbol() {
>>    size_t SymSize = File->getCOFFObj()->getSymbolTableEntrySize();
>>    if (SymSize == sizeof(coff_symbol16))
>> @@ -182,34 +66,10 @@ DefinedImportThunk::DefinedImportThunk(S
>>    }
>>  }
>>
>> -InputFile *Lazy::getMember() {
>> -  MemoryBufferRef MBRef = File->getMember(&Sym);
>> -
>> -  // getMember returns an empty buffer if the member was already
>> -  // read from the library.
>> -  if (MBRef.getBuffer().empty())
>> -    return nullptr;
>> -
>> -  file_magic Magic = identify_magic(MBRef.getBuffer());
>> -  if (Magic == file_magic::coff_import_library)
>> -    return make<ImportFile>(MBRef);
>> -
>> -  InputFile *Obj;
>> -  if (Magic == file_magic::coff_object)
>> -    Obj = make<ObjectFile>(MBRef);
>> -  else if (Magic == file_magic::bitcode)
>> -    Obj = make<BitcodeFile>(MBRef);
>> -  else
>> -    fatal("unknown file type: " + File->getName());
>> -
>> -  Obj->ParentName = File->getName();
>> -  return Obj;
>> -}
>> -
>>  Defined *Undefined::getWeakAlias() {
>>    // A weak alias may be a weak alias to another symbol, so check
>> recursively.
>>    for (SymbolBody *A = WeakAlias; A; A = cast<Undefined>(A)->WeakAlias)
>> -    if (auto *D = dyn_cast<Defined>(A->repl()))
>> +    if (auto *D = dyn_cast<Defined>(A))
>>        return D;
>>    return nullptr;
>>  }
>>
>> Modified: lld/trunk/COFF/Symbols.h
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/
>> Symbols.h?rev=289280&r1=289279&r2=289280&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/COFF/Symbols.h (original)
>> +++ lld/trunk/COFF/Symbols.h Fri Dec  9 15:55:24 2016
>> @@ -32,15 +32,8 @@ class ArchiveFile;
>>  class BitcodeFile;
>>  class InputFile;
>>  class ObjectFile;
>> -class SymbolBody;
>> -
>> -// A real symbol object, SymbolBody, is usually accessed indirectly
>> -// through a Symbol. There's always one Symbol for each symbol name.
>> -// The resolver updates SymbolBody pointers as it resolves symbols.
>> -struct Symbol {
>> -  explicit Symbol(SymbolBody *P) : Body(P) {}
>> -  SymbolBody *Body;
>> -};
>> +struct Symbol;
>> +class SymbolTable;
>>
>>  // The base class for real symbol classes.
>>  class SymbolBody {
>> @@ -78,21 +71,13 @@ public:
>>    // Returns the file from which this symbol was created.
>>    InputFile *getFile();
>>
>> -  // A SymbolBody has a backreference to a Symbol. Originally they are
>> -  // doubly-linked. A backreference will never change. But the pointer
>> -  // in the Symbol may be mutated by the resolver. If you have a
>> -  // pointer P to a SymbolBody and are not sure whether the resolver
>> -  // has chosen the object among other objects having the same name,
>> -  // you can access P->Backref->Body to get the resolver's result.
>> -  void setBackref(Symbol *P) { Backref = P; }
>> -  SymbolBody *repl() { return Backref ? Backref->Body : this; }
>> -
>> -  // Decides which symbol should "win" in the symbol table, this or
>> -  // the Other. Returns 1 if this wins, -1 if the Other wins, or 0 if
>> -  // they are duplicate (conflicting) symbols.
>> -  int compare(SymbolBody *Other);
>> +  Symbol *symbol();
>> +  const Symbol *symbol() const {
>> +    return const_cast<SymbolBody *>(this)->symbol();
>> +  }
>>
>>  protected:
>> +  friend SymbolTable;
>>    explicit SymbolBody(Kind K, StringRef N = "")
>>        : SymbolKind(K), IsExternal(true), IsCOMDAT(false),
>>          IsReplaceable(false), Name(N) {}
>> @@ -107,7 +92,6 @@ protected:
>>    unsigned IsReplaceable : 1;
>>
>>    StringRef Name;
>> -  Symbol *Backref = nullptr;
>>  };
>>
>>  // The base class for any defined symbols, including absolute symbols,
>> @@ -149,7 +133,6 @@ public:
>>    }
>>
>>    ObjectFile *getFile() { return File; }
>> -  int getFileIndex() { return File->Index; }
>>
>>    COFFSymbolRef getCOFFSymbol();
>>
>> @@ -195,7 +178,7 @@ public:
>>    uint64_t getRVA() { return Data->getRVA(); }
>>
>>  private:
>> -  friend SymbolBody;
>> +  friend SymbolTable;
>>    uint64_t getSize() { return Sym->Value; }
>>    CommonChunk *Data;
>>  };
>> @@ -254,15 +237,12 @@ public:
>>
>>    static bool classof(const SymbolBody *S) { return S->kind() ==
>> LazyKind; }
>>
>> -  // Returns an object file for this symbol, or a nullptr if the file
>> -  // was already returned.
>> -  InputFile *getMember();
>> -
>> -  int getFileIndex() { return File->Index; }
>> -
>>    ArchiveFile *File;
>>
>>  private:
>> +  friend SymbolTable;
>> +
>> +private:
>>    const Archive::Symbol Sym;
>>  };
>>
>> @@ -295,26 +275,22 @@ public:
>>  // table in an output. The former has "__imp_" prefix.
>>  class DefinedImportData : public Defined {
>>  public:
>> -  DefinedImportData(StringRef D, StringRef N, StringRef E,
>> -                    const coff_import_header *H)
>> -      : Defined(DefinedImportDataKind, N), DLLName(D), ExternalName(E),
>> Hdr(H) {
>> +  DefinedImportData(StringRef N, ImportFile *F)
>> +      : Defined(DefinedImportDataKind, N), File(F) {
>>    }
>>
>>    static bool classof(const SymbolBody *S) {
>>      return S->kind() == DefinedImportDataKind;
>>    }
>>
>> -  uint64_t getRVA() { return Location->getRVA(); }
>> -  StringRef getDLLName() { return DLLName; }
>> -  StringRef getExternalName() { return ExternalName; }
>> -  void setLocation(Chunk *AddressTable) { Location = AddressTable; }
>> -  uint16_t getOrdinal() { return Hdr->OrdinalHint; }
>> +  uint64_t getRVA() { return File->Location->getRVA(); }
>> +  StringRef getDLLName() { return File->DLLName; }
>> +  StringRef getExternalName() { return File->ExternalName; }
>> +  void setLocation(Chunk *AddressTable) { File->Location = AddressTable;
>> }
>> +  uint16_t getOrdinal() { return File->Hdr->OrdinalHint; }
>>
>>  private:
>> -  StringRef DLLName;
>> -  StringRef ExternalName;
>> -  const coff_import_header *Hdr;
>> -  Chunk *Location = nullptr;
>> +  ImportFile *File;
>>  };
>>
>>  // This class represents a symbol for a jump table entry which jumps
>> @@ -345,17 +321,17 @@ private:
>>  class DefinedLocalImport : public Defined {
>>  public:
>>    DefinedLocalImport(StringRef N, Defined *S)
>> -      : Defined(DefinedLocalImportKind, N), Data(S) {}
>> +      : Defined(DefinedLocalImportKind, N), Data(new
>> LocalImportChunk(S)) {}
>>
>>    static bool classof(const SymbolBody *S) {
>>      return S->kind() == DefinedLocalImportKind;
>>    }
>>
>> -  uint64_t getRVA() { return Data.getRVA(); }
>> -  Chunk *getChunk() { return &Data; }
>> +  uint64_t getRVA() { return Data->getRVA(); }
>> +  Chunk *getChunk() { return Data.get(); }
>>
>>  private:
>> -  LocalImportChunk Data;
>> +  std::unique_ptr<LocalImportChunk> Data;
>>  };
>>
>>  class DefinedBitcode : public Defined {
>> @@ -363,6 +339,11 @@ class DefinedBitcode : public Defined {
>>  public:
>>    DefinedBitcode(BitcodeFile *F, StringRef N, bool IsReplaceable)
>>        : Defined(DefinedBitcodeKind, N), File(F) {
>> +    // IsReplaceable tracks whether the bitcode symbol may be replaced
>> with some
>> +    // other (defined, common or bitcode) symbol. This is the case for
>> common,
>> +    // comdat and weak external symbols. We try to replace bitcode
>> symbols with
>> +    // "real" symbols (see SymbolTable::add{Regular,Bitcode}), and
>> resolve the
>> +    // result against the real symbol from the combined LTO object.
>>      this->IsReplaceable = IsReplaceable;
>>    }
>>
>> @@ -398,6 +379,45 @@ inline uint64_t Defined::getRVA() {
>>    llvm_unreachable("unknown symbol kind");
>>  }
>>
>> +// A real symbol object, SymbolBody, is usually stored within a Symbol.
>> There's
>> +// always one Symbol for each symbol name. The resolver updates the
>> SymbolBody
>> +// stored in the Body field of this object as it resolves symbols.
>> Symbol also
>> +// holds computed properties of symbol names.
>> +struct Symbol {
>> +  // True if this symbol was referenced by a regular (non-bitcode)
>> object.
>> +  unsigned IsUsedInRegularObj : 1;
>> +
>> +  // This field is used to store the Symbol's SymbolBody. This
>> instantiation of
>> +  // AlignedCharArrayUnion gives us a struct with a char array field
>> that is
>> +  // large and aligned enough to store any derived class of SymbolBody.
>> +  llvm::AlignedCharArrayUnion<DefinedRegular, DefinedCommon,
>> DefinedAbsolute,
>> +                              DefinedRelative, Lazy, Undefined,
>> +                              DefinedImportData, DefinedImportThunk,
>> +                              DefinedLocalImport, DefinedBitcode>
>> +      Body;
>> +
>> +  SymbolBody *body() {
>> +    return reinterpret_cast<SymbolBody *>(Body.buffer);
>> +  }
>> +  const SymbolBody *body() const { return const_cast<Symbol
>> *>(this)->body(); }
>> +};
>> +
>> +template <typename T, typename... ArgT>
>> +void replaceBody(Symbol *S, ArgT &&... Arg) {
>> +  static_assert(sizeof(T) <= sizeof(S->Body), "Body too small");
>> +  static_assert(alignof(T) <= alignof(decltype(S->Body)),
>> +                "Body not aligned enough");
>> +  assert(static_cast<SymbolBody *>(static_cast<T *>(nullptr)) == nullptr
>> &&
>> +         "Not a SymbolBody");
>> +  new (S->Body.buffer) T(std::forward<ArgT>(Arg)...);
>> +}
>> +
>> +inline Symbol *SymbolBody::symbol() {
>> +  assert(isExternal());
>> +  return reinterpret_cast<Symbol *>(reinterpret_cast<char *>(this) -
>> +                                    offsetof(Symbol, Body));
>> +}
>> +
>>  std::string toString(SymbolBody &B);
>>
>>  } // namespace coff
>>
>> Modified: lld/trunk/COFF/Writer.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.
>> cpp?rev=289280&r1=289279&r2=289280&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/COFF/Writer.cpp (original)
>> +++ lld/trunk/COFF/Writer.cpp Fri Dec  9 15:55:24 2016
>> @@ -388,7 +388,7 @@ void Writer::createMiscChunks() {
>>      if (!File->SEHCompat)
>>        return;
>>      for (SymbolBody *B : File->SEHandlers)
>> -      Handlers.insert(cast<Defined>(B->repl()));
>> +      Handlers.insert(cast<Defined>(B));
>>    }
>>
>>    SEHTable.reset(new SEHTableChunk(Handlers));
>> @@ -428,7 +428,7 @@ void Writer::createImportTables() {
>>        Sec->addChunk(C);
>>    }
>>    if (!DelayIdata.empty()) {
>> -    Defined *Helper = cast<Defined>(Config->DelayLoadHelper->repl());
>> +    Defined *Helper = cast<Defined>(Config->DelayLoadHelper);
>>      DelayIdata.create(Helper);
>>      OutputSection *Sec = createSection(".didat");
>>      for (Chunk *C : DelayIdata.getChunks())
>> @@ -471,6 +471,10 @@ size_t Writer::addEntryToStringTable(Str
>>  }
>>
>>  Optional<coff_symbol16> Writer::createSymbol(Defined *Def) {
>> +  // Relative symbols are unrepresentable in a COFF symbol table.
>> +  if (isa<DefinedRelative>(Def))
>> +    return None;
>> +
>>    if (auto *D = dyn_cast<DefinedRegular>(Def))
>>      if (!D->getChunk()->isLive())
>>        return None;
>> @@ -497,7 +501,6 @@ Optional<coff_symbol16> Writer::createSy
>>
>>    switch (Def->kind()) {
>>    case SymbolBody::DefinedAbsoluteKind:
>> -  case SymbolBody::DefinedRelativeKind:
>>      Sym.Value = Def->getRVA();
>>      Sym.SectionNumber = IMAGE_SYM_ABSOLUTE;
>>      break;
>> @@ -530,16 +533,13 @@ void Writer::createSymbolAndStringTable(
>>      Sec->setStringTableOff(addEntryToStringTable(Name));
>>    }
>>
>> +  std::set<SymbolBody *> SeenSymbols;
>>    for (lld::coff::ObjectFile *File : Symtab->ObjectFiles)
>>      for (SymbolBody *B : File->getSymbols())
>>        if (auto *D = dyn_cast<Defined>(B))
>> -        if (Optional<coff_symbol16> Sym = createSymbol(D))
>> -          OutputSymtab.push_back(*Sym);
>> -
>> -  for (ImportFile *File : Symtab->ImportFiles)
>> -    for (SymbolBody *B : File->getSymbols())
>> -      if (Optional<coff_symbol16> Sym = createSymbol(cast<Defined>(B)))
>> -        OutputSymtab.push_back(*Sym);
>> +        if (SeenSymbols.insert(D).second)
>> +          if (Optional<coff_symbol16> Sym = createSymbol(D))
>> +            OutputSymtab.push_back(*Sym);
>>
>>    OutputSection *LastSection = OutputSections.back();
>>    // We position the symbol table to be adjacent to the end of the last
>> section.
>> @@ -630,7 +630,7 @@ template <typename PEHeaderTy> void Writ
>>    PE->SizeOfImage = SizeOfImage;
>>    PE->SizeOfHeaders = SizeOfHeaders;
>>    if (!Config->NoEntry) {
>> -    Defined *Entry = cast<Defined>(Config->Entry->repl());
>> +    Defined *Entry = cast<Defined>(Config->Entry);
>>      PE->AddressOfEntryPoint = Entry->getRVA();
>>      // Pointer to thumb code must have the LSB set, so adjust it.
>>      if (Config->Machine == ARMNT)
>> @@ -685,7 +685,7 @@ template <typename PEHeaderTy> void Writ
>>      Dir[BASE_RELOCATION_TABLE].Size = Sec->getVirtualSize();
>>    }
>>    if (Symbol *Sym = Symtab->findUnderscore("_tls_used")) {
>> -    if (Defined *B = dyn_cast<Defined>(Sym->Body)) {
>> +    if (Defined *B = dyn_cast<Defined>(Sym->body())) {
>>        Dir[TLS_TABLE].RelativeVirtualAddress = B->getRVA();
>>        Dir[TLS_TABLE].Size = Config->is64()
>>                                  ? sizeof(object::coff_tls_directory64)
>> @@ -697,7 +697,7 @@ template <typename PEHeaderTy> void Writ
>>      Dir[DEBUG_DIRECTORY].Size = DebugDirectory->getSize();
>>    }
>>    if (Symbol *Sym = Symtab->findUnderscore("_load_config_used")) {
>> -    if (auto *B = dyn_cast<DefinedRegular>(Sym->Body)) {
>> +    if (auto *B = dyn_cast<DefinedRegular>(Sym->body())) {
>>        SectionChunk *SC = B->getChunk();
>>        assert(B->getRVA() >= SC->getRVA());
>>        uint64_t OffsetInChunk = B->getRVA() - SC->getRVA();
>> @@ -754,8 +754,10 @@ void Writer::openFile(StringRef Path) {
>>  void Writer::fixSafeSEHSymbols() {
>>    if (!SEHTable)
>>      return;
>> -  Config->SEHTable->setRVA(SEHTable->getRVA());
>> -  Config->SEHCount->setVA(SEHTable->getSize() / 4);
>> +  if (auto *T = dyn_cast<DefinedRelative>(Config->SEHTable->body()))
>> +    T->setRVA(SEHTable->getRVA());
>> +  if (auto *C = dyn_cast<DefinedAbsolute>(Config->SEHCount->body()))
>> +    C->setVA(SEHTable->getSize() / 4);
>>  }
>>
>>  // Handles /section options to allow users to overwrite
>>
>> Modified: lld/trunk/test/COFF/include2.test
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/
>> include2.test?rev=289280&r1=289279&r2=289280&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/test/COFF/include2.test (original)
>> +++ lld/trunk/test/COFF/include2.test Fri Dec  9 15:55:24 2016
>> @@ -9,6 +9,6 @@
>>
>>  CHECK: include2.test.tmp1.obj
>>  CHECK: include2.test.tmp2.lib
>> -CHECK: include2.test.tmp3.lib
>>  CHECK: include2.test.tmp2.lib(include2.test.tmp2.obj) for foo
>> +CHECK: include2.test.tmp3.lib
>>  CHECK: include2.test.tmp3.lib(include2.test.tmp3.obj) for bar
>>
>> Modified: lld/trunk/test/COFF/order.test
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/
>> order.test?rev=289280&r1=289279&r2=289280&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/test/COFF/order.test (original)
>> +++ lld/trunk/test/COFF/order.test Fri Dec  9 15:55:24 2016
>> @@ -11,5 +11,5 @@
>>  CHECK: order.test.tmp1.obj
>>  CHECK: order.test.tmp3.obj
>>  CHECK: order.test.tmp2.lib
>> -CHECK: order.test.tmp3.lib
>>  CHECK: order.test.tmp2.lib(order.test.tmp2.obj) for foo
>> +CHECK: order.test.tmp3.lib
>>
>> Modified: lld/trunk/test/COFF/symtab.test
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/
>> symtab.test?rev=289280&r1=289279&r2=289280&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/test/COFF/symtab.test (original)
>> +++ lld/trunk/test/COFF/symtab.test Fri Dec  9 15:55:24 2016
>> @@ -36,17 +36,17 @@
>>  # CHECK-NEXT:     AuxSymbolCount: 0
>>  # CHECK-NEXT:
>
> --
> Mike
> Sent from phone
>



-- 
-- 
Peter
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20161212/95aab0e6/attachment-0001.html>


More information about the llvm-commits mailing list