[lld] r360975 - Move symbol resolution code out of SymbolTable class.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Thu May 16 18:55:20 PDT 2019


Author: ruiu
Date: Thu May 16 18:55:20 2019
New Revision: 360975

URL: http://llvm.org/viewvc/llvm-project?rev=360975&view=rev
Log:
Move symbol resolution code out of SymbolTable class.

This is the last patch of the series of patches to make it possible to
resolve symbols without asking SymbolTable to do so.

The main point of this patch is the introduction of
`elf::resolveSymbol(Symbol *Old, Symbol *New)`. That function resolves
or merges given symbols by examining symbol types and call
replaceSymbol (which memcpy's New to Old) if necessary.

With the new function, we have now separated symbol resolution from
symbol lookup. If you already have a Symbol pointer, you can directly
resolve the symbol without asking SymbolTable to do that.

Now that the nice abstraction become available, I can start working on
performance improvement of the linker. As a starter, I'm thinking of
making --{start,end}-lib faster.

--{start,end}-lib is currently unnecessarily slow because it looks up
the symbol table twice for each symbol.

 - The first hash table lookup/insertion occurs when we instantiate a
   LazyObject file to insert LazyObject symbols.

 - The second hash table lookup/insertion occurs when we create an
   ObjFile from LazyObject file. That overwrites LazyObject symbols
   with Defined symbols.

I think it is not too hard to see how we can now eliminate the second
hash table lookup. We can keep LazyObject symbols in Step 1, and then
call elf::resolveSymbol() to do Step 2.

Differential Revision: https://reviews.llvm.org/D61898

Modified:
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/InputFiles.cpp
    lld/trunk/ELF/LTO.cpp
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/Relocations.cpp
    lld/trunk/ELF/SymbolTable.cpp
    lld/trunk/ELF/SymbolTable.h
    lld/trunk/ELF/Symbols.h
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=360975&r1=360974&r2=360975&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Thu May 16 18:55:20 2019
@@ -1337,10 +1337,9 @@ static void replaceCommonSymbols() {
     Bss->File = S->File;
     Bss->Live = !Config->GcSections;
     InputSections.push_back(Bss);
-
-    Defined New(S->File, S->getName(), S->Binding, S->StOther, S->Type,
-                /*Value=*/0, S->Size, Bss);
-    replaceSymbol(S, &New);
+    replaceSymbol(S, Defined{S->File, S->getName(), S->Binding, S->StOther,
+                             S->Type,
+                             /*Value=*/0, S->Size, Bss});
   }
 }
 
@@ -1355,8 +1354,8 @@ static void demoteSharedSymbols() {
       continue;
 
     bool Used = S->Used;
-    Undefined New(nullptr, S->getName(), STB_WEAK, S->StOther, S->Type);
-    replaceSymbol(S, &New);
+    replaceSymbol(
+        S, Undefined{nullptr, S->getName(), STB_WEAK, S->StOther, S->Type});
     S->Used = Used;
   }
 }
@@ -1426,7 +1425,7 @@ static void findKeepUniqueSections(opt::
 }
 
 template <class ELFT> static Symbol *addUndefined(StringRef Name) {
-  return Symtab->addUndefined(
+  return Symtab->addSymbol(
       Undefined{nullptr, Name, STB_GLOBAL, STV_DEFAULT, 0});
 }
 

Modified: lld/trunk/ELF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=360975&r1=360974&r2=360975&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.cpp (original)
+++ lld/trunk/ELF/InputFiles.cpp Thu May 16 18:55:20 2019
@@ -911,12 +911,12 @@ template <class ELFT> Symbol *ObjFile<EL
 
   switch (Sym->st_shndx) {
   case SHN_UNDEF:
-    return Symtab->addUndefined(Undefined{this, Name, Binding, StOther, Type});
+    return Symtab->addSymbol(Undefined{this, Name, Binding, StOther, Type});
   case SHN_COMMON:
     if (Value == 0 || Value >= UINT32_MAX)
       fatal(toString(this) + ": common symbol '" + Name +
             "' has invalid alignment: " + Twine(Value));
-    return Symtab->addCommon(
+    return Symtab->addSymbol(
         CommonSymbol{this, Name, Binding, StOther, Type, Value, Size});
   }
 
@@ -927,9 +927,8 @@ template <class ELFT> Symbol *ObjFile<EL
   case STB_WEAK:
   case STB_GNU_UNIQUE:
     if (Sec == &InputSection::Discarded)
-      return Symtab->addUndefined(
-          Undefined{this, Name, Binding, StOther, Type});
-    return Symtab->addDefined(
+      return Symtab->addSymbol(Undefined{this, Name, Binding, StOther, Type});
+    return Symtab->addSymbol(
         Defined{this, Name, Binding, StOther, Type, Value, Size, Sec});
   }
 }
@@ -940,7 +939,7 @@ ArchiveFile::ArchiveFile(std::unique_ptr
 
 void ArchiveFile::parse() {
   for (const Archive::Symbol &Sym : File->symbols())
-    Symtab->addLazyArchive(LazyArchive{*this, Sym});
+    Symtab->addSymbol(LazyArchive{*this, Sym});
 }
 
 // Returns a buffer pointing to a member file containing a given symbol.
@@ -1141,7 +1140,7 @@ template <class ELFT> void SharedFile::p
     }
 
     if (Sym.isUndefined()) {
-      Symbol *S = Symtab->addUndefined(
+      Symbol *S = Symtab->addSymbol(
           Undefined{this, Name, Sym.getBinding(), Sym.st_other, Sym.getType()});
       S->ExportDynamic = true;
       continue;
@@ -1157,7 +1156,7 @@ template <class ELFT> void SharedFile::p
 
     uint32_t Alignment = getAlignment<ELFT>(Sections, Sym);
     if (!(Versyms[I] & VERSYM_HIDDEN)) {
-      Symtab->addShared(SharedSymbol{*this, Name, Sym.getBinding(),
+      Symtab->addSymbol(SharedSymbol{*this, Name, Sym.getBinding(),
                                      Sym.st_other, Sym.getType(), Sym.st_value,
                                      Sym.st_size, Alignment, Idx});
     }
@@ -1179,7 +1178,7 @@ template <class ELFT> void SharedFile::p
         reinterpret_cast<const Elf_Verdef *>(Verdefs[Idx])->getAux()->vda_name;
     VersionedNameBuffer.clear();
     Name = (Name + "@" + VerName).toStringRef(VersionedNameBuffer);
-    Symtab->addShared(SharedSymbol{*this, Saver.save(Name), Sym.getBinding(),
+    Symtab->addSymbol(SharedSymbol{*this, Saver.save(Name), Sym.getBinding(),
                                    Sym.st_other, Sym.getType(), Sym.st_value,
                                    Sym.st_size, Alignment, Idx});
   }
@@ -1281,18 +1280,18 @@ static Symbol *createBitcodeSymbol(const
     Undefined New(&F, Name, Binding, Visibility, Type);
     if (CanOmitFromDynSym)
       New.ExportDynamic = false;
-    return Symtab->addUndefined(New);
+    return Symtab->addSymbol(New);
   }
 
   if (ObjSym.isCommon())
-    return Symtab->addCommon(
+    return Symtab->addSymbol(
         CommonSymbol{&F, Name, Binding, Visibility, STT_OBJECT,
                      ObjSym.getCommonAlignment(), ObjSym.getCommonSize()});
 
   Defined New(&F, Name, Binding, Visibility, Type, 0, 0, nullptr);
   if (CanOmitFromDynSym)
     New.ExportDynamic = false;
-  return Symtab->addDefined(New);
+  return Symtab->addSymbol(New);
 }
 
 template <class ELFT>
@@ -1350,12 +1349,12 @@ void BinaryFile::parse() {
     if (!isAlnum(S[I]))
       S[I] = '_';
 
-  Symtab->addDefined(Defined{nullptr, Saver.save(S + "_start"), STB_GLOBAL,
-                             STV_DEFAULT, STT_OBJECT, 0, 0, Section});
-  Symtab->addDefined(Defined{nullptr, Saver.save(S + "_end"), STB_GLOBAL,
-                             STV_DEFAULT, STT_OBJECT, Data.size(), 0, Section});
-  Symtab->addDefined(Defined{nullptr, Saver.save(S + "_size"), STB_GLOBAL,
-                             STV_DEFAULT, STT_OBJECT, Data.size(), 0, nullptr});
+  Symtab->addSymbol(Defined{nullptr, Saver.save(S + "_start"), STB_GLOBAL,
+                            STV_DEFAULT, STT_OBJECT, 0, 0, Section});
+  Symtab->addSymbol(Defined{nullptr, Saver.save(S + "_end"), STB_GLOBAL,
+                            STV_DEFAULT, STT_OBJECT, Data.size(), 0, Section});
+  Symtab->addSymbol(Defined{nullptr, Saver.save(S + "_size"), STB_GLOBAL,
+                            STV_DEFAULT, STT_OBJECT, Data.size(), 0, nullptr});
 }
 
 InputFile *elf::createObjectFile(MemoryBufferRef MB, StringRef ArchiveName,
@@ -1423,7 +1422,7 @@ template <class ELFT> void LazyObjFile::
     for (const lto::InputFile::Symbol &Sym : Obj->symbols()) {
       if (Sym.isUndefined())
         continue;
-      Symtab->addLazyObject(LazyObject{*this, Saver.save(Sym.getName())});
+      Symtab->addSymbol(LazyObject{*this, Saver.save(Sym.getName())});
     }
     return;
   }
@@ -1448,7 +1447,7 @@ template <class ELFT> void LazyObjFile::
     for (const typename ELFT::Sym &Sym : Syms.slice(FirstGlobal)) {
       if (Sym.st_shndx == SHN_UNDEF)
         continue;
-      Symtab->addLazyObject(
+      Symtab->addSymbol(
           LazyObject{*this, CHECK(Sym.getName(StringTable), this)});
     }
     return;

Modified: lld/trunk/ELF/LTO.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LTO.cpp?rev=360975&r1=360974&r2=360975&view=diff
==============================================================================
--- lld/trunk/ELF/LTO.cpp (original)
+++ lld/trunk/ELF/LTO.cpp Thu May 16 18:55:20 2019
@@ -152,11 +152,6 @@ BitcodeCompiler::BitcodeCompiler() {
 
 BitcodeCompiler::~BitcodeCompiler() = default;
 
-static void undefine(Symbol *S) {
-  Undefined New(nullptr, S->getName(), STB_GLOBAL, STV_DEFAULT, S->Type);
-  replaceSymbol(S, &New);
-}
-
 void BitcodeCompiler::add(BitcodeFile &F) {
   lto::InputFile &Obj = *F.Obj;
   bool IsExec = !Config->Shared && !Config->Relocatable;
@@ -201,7 +196,8 @@ void BitcodeCompiler::add(BitcodeFile &F
         !(DR->Section == nullptr && (!Sym->File || Sym->File->isElf()));
 
     if (R.Prevailing)
-      undefine(Sym);
+      replaceSymbol(Sym, Undefined{nullptr, Sym->getName(), STB_GLOBAL,
+                                   STV_DEFAULT, Sym->Type});
 
     // We tell LTO to not apply interprocedural optimization for wrapped
     // (with --wrap) symbols because otherwise LTO would inline them while

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=360975&r1=360974&r2=360975&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Thu May 16 18:55:20 2019
@@ -186,9 +186,9 @@ void LinkerScript::addSymbol(SymbolAssig
   Defined New(nullptr, Cmd->Name, STB_GLOBAL, Visibility, STT_NOTYPE, SymValue,
               0, Sec);
 
-  Symbol *Sym = Symtab->insert(New);
-  Symtab->mergeProperties(Sym, New);
-  replaceSymbol(Sym, &New);
+  Symbol *Sym = Symtab->insert(Cmd->Name);
+  mergeSymbolProperties(Sym, New);
+  replaceSymbol(Sym, New);
   Cmd->Sym = cast<Defined>(Sym);
 }
 
@@ -203,9 +203,9 @@ static void declareSymbol(SymbolAssignme
               nullptr);
 
   // We can't calculate final value right now.
-  Symbol *Sym = Symtab->insert(New);
-  Symtab->mergeProperties(Sym, New);
-  replaceSymbol(Sym, &New);
+  Symbol *Sym = Symtab->insert(Cmd->Name);
+  mergeSymbolProperties(Sym, New);
+  replaceSymbol(Sym, New);
 
   Cmd->Sym = cast<Defined>(Sym);
   Cmd->Provide = false;

Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=360975&r1=360974&r2=360975&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Thu May 16 18:55:20 2019
@@ -530,9 +530,8 @@ static void replaceWithDefined(Symbol &S
                                uint64_t Size) {
   Symbol Old = Sym;
 
-  Defined New(Sym.File, Sym.getName(), Sym.Binding, Sym.StOther, Sym.Type,
-              Value, Size, Sec);
-  replaceSymbol(&Sym, &New);
+  replaceSymbol(&Sym, Defined{Sym.File, Sym.getName(), Sym.Binding, Sym.StOther,
+                              Sym.Type, Value, Size, Sec});
 
   Sym.PltIndex = Old.PltIndex;
   Sym.GotIndex = Old.GotIndex;

Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=360975&r1=360974&r2=360975&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Thu May 16 18:55:20 2019
@@ -86,15 +86,14 @@ static uint8_t getMinVisibility(uint8_t
   return std::min(VA, VB);
 }
 
-// Find an existing symbol or create and insert a new one.
-Symbol *SymbolTable::insert(const Symbol &New) {
+// Find an existing symbol or create a new one.
+Symbol *SymbolTable::insert(StringRef Name) {
   // <name>@@<version> means the symbol is the default version. In that
   // case <name>@@<version> will be used to resolve references to <name>.
   //
   // Since this is a hot path, the following string search code is
   // optimized for speed. StringRef::find(char) is much faster than
   // StringRef::find(StringRef).
-  StringRef Name = New.getName();
   size_t Pos = Name.find('@');
   if (Pos != StringRef::npos && Pos + 1 < Name.size() && Name[Pos + 1] == '@')
     Name = Name.take_front(Pos);
@@ -110,55 +109,35 @@ Symbol *SymbolTable::insert(const Symbol
     Traced = true;
   }
 
-  Symbol *Old;
-  if (IsNew) {
-    Old = reinterpret_cast<Symbol *>(make<SymbolUnion>());
-    SymVector.push_back(Old);
-
-    Old->SymbolKind = Symbol::PlaceholderKind;
-    Old->VersionId = Config->DefaultSymbolVersion;
-    Old->Visibility = STV_DEFAULT;
-    Old->IsUsedInRegularObj = false;
-    Old->ExportDynamic = false;
-    Old->CanInline = true;
-    Old->Traced = Traced;
-    Old->ScriptDefined = false;
-  } else {
-    Old = SymVector[SymIndex];
-  }
-
-  return Old;
-}
+  if (!IsNew)
+    return SymVector[SymIndex];
 
-// Merge symbol properties.
-//
-// When we have many symbols of the same name, we choose one of them,
-// and that's the result of symbol resolution. However, symbols that
-// were not chosen still affect some symbol properteis.
-void SymbolTable::mergeProperties(Symbol *Old, const Symbol &New) {
-  // Merge symbol properties.
-  Old->ExportDynamic = Old->ExportDynamic || New.ExportDynamic;
-  Old->IsUsedInRegularObj = Old->IsUsedInRegularObj || New.IsUsedInRegularObj;
+  Symbol *Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
+  SymVector.push_back(Sym);
 
-  // DSO symbols do not affect visibility in the output.
-  if (!isa<SharedSymbol>(New))
-    Old->Visibility = getMinVisibility(Old->Visibility, New.Visibility);
+  Sym->SymbolKind = Symbol::PlaceholderKind;
+  Sym->VersionId = Config->DefaultSymbolVersion;
+  Sym->Visibility = STV_DEFAULT;
+  Sym->IsUsedInRegularObj = false;
+  Sym->ExportDynamic = false;
+  Sym->CanInline = true;
+  Sym->Traced = Traced;
+  Sym->ScriptDefined = false;
+  return Sym;
+}
+
+Symbol *SymbolTable::addSymbol(const Symbol &New) {
+  Symbol *Old = Symtab->insert(New.getName());
+  resolveSymbol(Old, New);
+  return Old;
 }
 
-Symbol *SymbolTable::addUndefined(const Undefined &New) {
-  Symbol *Old = insert(New);
-  mergeProperties(Old, New);
-
-  if (Old->isPlaceholder()) {
-    replaceSymbol(Old, &New);
-    return Old;
-  }
-
+static void addUndefined(Symbol *Old, const Undefined &New) {
   // An undefined symbol with non default visibility must be satisfied
   // in the same DSO.
   if (Old->isShared() && New.Visibility != STV_DEFAULT) {
-    replaceSymbol(Old, &New);
-    return Old;
+    replaceSymbol(Old, New);
+    return;
   }
 
   if (Old->isShared() || Old->isLazy() ||
@@ -170,7 +149,7 @@ Symbol *SymbolTable::addUndefined(const
     // Symbols.h for the details.
     if (New.Binding == STB_WEAK) {
       Old->Type = New.Type;
-      return Old;
+      return;
     }
 
     // Do extra check for --warn-backrefs.
@@ -225,7 +204,7 @@ Symbol *SymbolTable::addUndefined(const
     // group assignment rule simulates the traditional linker's semantics.
     bool Backref = Config->WarnBackrefs && New.File &&
                    Old->File->GroupId < New.File->GroupId;
-    fetchLazy(Old);
+    Symtab->fetchLazy(Old);
 
     // We don't report backward references to weak symbols as they can be
     // overridden later.
@@ -233,7 +212,6 @@ Symbol *SymbolTable::addUndefined(const
       warn("backward reference detected: " + New.getName() + " in " +
            toString(New.File) + " refers to " + toString(Old->File));
   }
-  return Old;
 }
 
 // Using .symver foo,foo@@VER unfortunately creates two symbols: foo and
@@ -300,22 +278,14 @@ static int compare(const Symbol *Old, co
   return 0;
 }
 
-Symbol *SymbolTable::addCommon(const CommonSymbol &New) {
-  Symbol *Old = insert(New);
-  mergeProperties(Old, New);
-
-  if (Old->isPlaceholder()) {
-    replaceSymbol(Old, &New);
-    return Old;
-  }
-
+static void addCommon(Symbol *Old, const CommonSymbol &New) {
   int Cmp = compare(Old, &New);
   if (Cmp < 0)
-    return Old;
+    return;
 
   if (Cmp > 0) {
-    replaceSymbol(Old, &New);
-    return Old;
+    replaceSymbol(Old, New);
+    return;
   }
 
   CommonSymbol *OldSym = cast<CommonSymbol>(Old);
@@ -325,7 +295,6 @@ Symbol *SymbolTable::addCommon(const Com
     OldSym->File = New.File;
     OldSym->Size = New.Size;
   }
-  return OldSym;
 }
 
 static void reportDuplicate(Symbol *Sym, InputFile *NewFile,
@@ -363,45 +332,23 @@ static void reportDuplicate(Symbol *Sym,
   error(Msg);
 }
 
-Symbol *SymbolTable::addDefined(const Defined &New) {
-  Symbol *Old = insert(New);
-  mergeProperties(Old, New);
-
-  if (Old->isPlaceholder()) {
-    replaceSymbol(Old, &New);
-    return Old;
-  }
-
+static void addDefined(Symbol *Old, const Defined &New) {
   int Cmp = compare(Old, &New);
   if (Cmp > 0)
-    replaceSymbol(Old, &New);
+    replaceSymbol(Old, New);
   else if (Cmp == 0)
     reportDuplicate(Old, New.File,
                     dyn_cast_or_null<InputSectionBase>(New.Section), New.Value);
-  return Old;
 }
 
-Symbol *SymbolTable::addShared(const SharedSymbol &New) {
-  Symbol *Old = insert(New);
-  mergeProperties(Old, New);
-
-  // Make sure we preempt DSO symbols with default visibility.
-  if (New.Visibility == STV_DEFAULT)
-    Old->ExportDynamic = true;
-
-  if (Old->isPlaceholder()) {
-    replaceSymbol(Old, &New);
-    return Old;
-  }
-
+static void addShared(Symbol *Old, const SharedSymbol &New) {
   if (Old->Visibility == STV_DEFAULT && (Old->isUndefined() || Old->isLazy())) {
     // An undefined symbol with non default visibility must be satisfied
     // in the same DSO.
     uint8_t Binding = Old->Binding;
-    replaceSymbol(Old, &New);
+    replaceSymbol(Old, New);
     Old->Binding = Binding;
   }
-  return Old;
 }
 
 Symbol *SymbolTable::find(StringRef Name) {
@@ -413,39 +360,30 @@ Symbol *SymbolTable::find(StringRef Name
   return SymVector[It->second];
 }
 
-template <class LazyT> Symbol *SymbolTable::addLazy(const LazyT &New) {
-  Symbol *Old = insert(New);
-  mergeProperties(Old, New);
-
-  if (Old->isPlaceholder()) {
-    replaceSymbol(Old, &New);
-    return Old;
-  }
-
+template <class LazyT> static void addLazy(Symbol *Old, const LazyT &New) {
   if (!Old->isUndefined())
-    return Old;
+    return;
 
   // An undefined weak will not fetch archive members. See comment on Lazy in
   // Symbols.h for the details.
   if (Old->isWeak()) {
     uint8_t Type = Old->Type;
-    replaceSymbol(Old, &New);
+    replaceSymbol(Old, New);
     Old->Type = Type;
     Old->Binding = STB_WEAK;
-    return Old;
+    return;
   }
 
   if (InputFile *F = New.fetch())
     parseFile(F);
-  return Old;
 }
 
-Symbol *SymbolTable::addLazyArchive(const LazyArchive &New) {
-  return addLazy(New);
+static void addLazyArchive(Symbol *Old, const LazyArchive &New) {
+  addLazy(Old, New);
 }
 
-Symbol *SymbolTable::addLazyObject(const LazyObject &New) {
-  return addLazy(New);
+static void addLazyObject(Symbol *Old, const LazyObject &New) {
+  addLazy(Old, New);
 }
 
 void SymbolTable::fetchLazy(Symbol *Sym) {
@@ -621,6 +559,53 @@ void SymbolTable::scanVersionScript() {
     Sym->parseSymbolVersion();
 }
 
+// Merge symbol properties.
+//
+// When we have many symbols of the same name, we choose one of them,
+// and that's the result of symbol resolution. However, symbols that
+// were not chosen still affect some symbol properties.
+void elf::mergeSymbolProperties(Symbol *Old, const Symbol &New) {
+  // Merge symbol properties.
+  Old->ExportDynamic = Old->ExportDynamic || New.ExportDynamic;
+  Old->IsUsedInRegularObj = Old->IsUsedInRegularObj || New.IsUsedInRegularObj;
+
+  // DSO symbols do not affect visibility in the output.
+  if (!New.isShared())
+    Old->Visibility = getMinVisibility(Old->Visibility, New.Visibility);
+}
+
+void elf::resolveSymbol(Symbol *Old, const Symbol &New) {
+  mergeSymbolProperties(Old, New);
+
+  if (Old->isPlaceholder()) {
+    replaceSymbol(Old, New);
+    return;
+  }
+
+  switch (New.kind()) {
+  case Symbol::UndefinedKind:
+    addUndefined(Old, cast<Undefined>(New));
+    break;
+  case Symbol::CommonKind:
+    addCommon(Old, cast<CommonSymbol>(New));
+    break;
+  case Symbol::DefinedKind:
+    addDefined(Old, cast<Defined>(New));
+    break;
+  case Symbol::LazyArchiveKind:
+    addLazyArchive(Old, cast<LazyArchive>(New));
+    break;
+  case Symbol::LazyObjectKind:
+    addLazyObject(Old, cast<LazyObject>(New));
+    break;
+  case Symbol::SharedKind:
+    addShared(Old, cast<SharedSymbol>(New));
+    break;
+  case Symbol::PlaceholderKind:
+    llvm_unreachable("bad symbol kind");
+  }
+}
+
 template void SymbolTable::addCombinedLTOObject<ELF32LE>();
 template void SymbolTable::addCombinedLTOObject<ELF32BE>();
 template void SymbolTable::addCombinedLTOObject<ELF64LE>();

Modified: lld/trunk/ELF/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.h?rev=360975&r1=360974&r2=360975&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.h (original)
+++ lld/trunk/ELF/SymbolTable.h Thu May 16 18:55:20 2019
@@ -45,15 +45,9 @@ public:
 
   ArrayRef<Symbol *> getSymbols() const { return SymVector; }
 
-  Symbol *addUndefined(const Undefined &New);
-  Symbol *addDefined(const Defined &New);
-  Symbol *addShared(const SharedSymbol &New);
-  Symbol *addLazyArchive(const LazyArchive &New);
-  Symbol *addLazyObject(const LazyObject &New);
-  Symbol *addCommon(const CommonSymbol &New);
+  Symbol *insert(StringRef Name);
 
-  Symbol *insert(const Symbol &New);
-  void mergeProperties(Symbol *Old, const Symbol &New);
+  Symbol *addSymbol(const Symbol &New);
 
   void fetchLazy(Symbol *Sym);
 
@@ -69,8 +63,6 @@ public:
   llvm::DenseMap<StringRef, SharedFile *> SoNames;
 
 private:
-  template <class LazyT> Symbol *addLazy(const LazyT &New);
-
   std::vector<Symbol *> findByVersion(SymbolVersion Ver);
   std::vector<Symbol *> findAllByVersion(SymbolVersion Ver);
 
@@ -106,6 +98,10 @@ private:
 };
 
 extern SymbolTable *Symtab;
+
+void mergeSymbolProperties(Symbol *Old, const Symbol &New);
+void resolveSymbol(Symbol *Old, const Symbol &New);
+
 } // namespace elf
 } // namespace lld
 

Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=360975&r1=360974&r2=360975&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Thu May 16 18:55:20 2019
@@ -172,17 +172,23 @@ public:
   uint64_t getSize() const;
   OutputSection *getOutputSection() const;
 
+private:
+  static bool isExportDynamic(Kind K, uint8_t Visibility) {
+    if (K == SharedKind)
+      return Visibility == llvm::ELF::STV_DEFAULT;
+    return Config->Shared || Config->ExportDynamic;
+  }
+
 protected:
   Symbol(Kind K, InputFile *File, StringRefZ Name, uint8_t Binding,
          uint8_t StOther, uint8_t Type)
       : File(File), NameData(Name.Data), NameSize(Name.Size), Binding(Binding),
         Type(Type), StOther(StOther), SymbolKind(K), Visibility(StOther & 3),
         IsUsedInRegularObj(!File || File->kind() == InputFile::ObjKind),
-        ExportDynamic(K != SharedKind &&
-                      (Config->Shared || Config->ExportDynamic)),
-        CanInline(false), Traced(false), NeedsPltAddr(false), IsInIplt(false),
-        GotInIgot(false), IsPreemptible(false), Used(!Config->GcSections),
-        NeedsTocRestore(false), ScriptDefined(false) {}
+        ExportDynamic(isExportDynamic(K, Visibility)), CanInline(false),
+        Traced(false), NeedsPltAddr(false), IsInIplt(false), GotInIgot(false),
+        IsPreemptible(false), Used(!Config->GcSections), NeedsTocRestore(false),
+        ScriptDefined(false) {}
 
 public:
   // True the symbol should point to its PLT entry.
@@ -395,24 +401,53 @@ struct ElfSym {
 // using the placement new.
 union SymbolUnion {
   alignas(Defined) char A[sizeof(Defined)];
+  alignas(CommonSymbol) char B[sizeof(CommonSymbol)];
   alignas(Undefined) char C[sizeof(Undefined)];
   alignas(SharedSymbol) char D[sizeof(SharedSymbol)];
   alignas(LazyArchive) char E[sizeof(LazyArchive)];
   alignas(LazyObject) char F[sizeof(LazyObject)];
 };
 
-void printTraceSymbol(Symbol *Sym);
-
-template <typename T> void replaceSymbol(Symbol *Sym, const T *New) {
-  using llvm::ELF::STT_TLS;
-
+template <typename T> struct AssertSymbol {
   static_assert(std::is_trivially_destructible<T>(),
                 "Symbol types must be trivially destructible");
   static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
   static_assert(alignof(T) <= alignof(SymbolUnion),
                 "SymbolUnion not aligned enough");
-  assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
-         "Not a Symbol");
+};
+
+static inline void assertSymbols() {
+  AssertSymbol<Defined>();
+  AssertSymbol<CommonSymbol>();
+  AssertSymbol<Undefined>();
+  AssertSymbol<SharedSymbol>();
+  AssertSymbol<LazyArchive>();
+  AssertSymbol<LazyObject>();
+}
+
+void printTraceSymbol(Symbol *Sym);
+
+static size_t getSymbolSize(const Symbol &Sym) {
+  switch (Sym.kind()) {
+  case Symbol::CommonKind:
+    return sizeof(CommonSymbol);
+  case Symbol::DefinedKind:
+    return sizeof(Defined);
+  case Symbol::LazyArchiveKind:
+    return sizeof(LazyArchive);
+  case Symbol::LazyObjectKind:
+    return sizeof(LazyObject);
+  case Symbol::SharedKind:
+    return sizeof(SharedSymbol);
+  case Symbol::UndefinedKind:
+    return sizeof(Undefined);
+  case Symbol::PlaceholderKind:
+    return sizeof(Symbol);
+  }
+}
+
+inline void replaceSymbol(Symbol *Sym, const Symbol &New) {
+  using llvm::ELF::STT_TLS;
 
   // Symbols representing thread-local variables must be referenced by
   // TLS-aware relocations, and non-TLS symbols must be reference by
@@ -420,16 +455,16 @@ template <typename T> void replaceSymbol
   // and non-TLS symbols. It is an error if the same symbol is defined
   // as a TLS symbol in one file and as a non-TLS symbol in other file.
   if (Sym->SymbolKind != Symbol::PlaceholderKind && !Sym->isLazy() &&
-      !New->isLazy()) {
-    bool TlsMismatch = (Sym->Type == STT_TLS && New->Type != STT_TLS) ||
-                       (Sym->Type != STT_TLS && New->Type == STT_TLS);
+      !New.isLazy()) {
+    bool TlsMismatch = (Sym->Type == STT_TLS && New.Type != STT_TLS) ||
+                       (Sym->Type != STT_TLS && New.Type == STT_TLS);
     if (TlsMismatch)
       error("TLS attribute mismatch: " + toString(*Sym) + "\n>>> defined in " +
-            toString(New->File) + "\n>>> defined in " + toString(Sym->File));
+            toString(New.File) + "\n>>> defined in " + toString(Sym->File));
   }
 
   Symbol Old = *Sym;
-  memcpy(Sym, New, sizeof(T));
+  memcpy(Sym, &New, getSymbolSize(New));
 
   Sym->VersionId = Old.VersionId;
   Sym->Visibility = Old.Visibility;

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=360975&r1=360974&r2=360975&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Thu May 16 18:55:20 2019
@@ -180,14 +180,14 @@ static Defined *addOptionalRegular(Strin
   if (!S || S->isDefined())
     return nullptr;
 
-  return cast<Defined>(Symtab->addDefined(
+  return cast<Defined>(Symtab->addSymbol(
       Defined{/*File=*/nullptr, Name, Binding, StOther, STT_NOTYPE, Val,
               /*Size=*/0, Sec}));
 }
 
 static Defined *addAbsolute(StringRef Name) {
-  Defined New(nullptr, Name, STB_GLOBAL, STV_HIDDEN, STT_NOTYPE, 0, 0, nullptr);
-  Symbol *Sym = Symtab->addDefined(New);
+  Symbol *Sym = Symtab->addSymbol(Defined{nullptr, Name, STB_GLOBAL, STV_HIDDEN,
+                                          STT_NOTYPE, 0, 0, nullptr});
   if (!Sym->isDefined())
     error("duplicate symbol: " + toString(*Sym));
   return cast<Defined>(Sym);
@@ -239,9 +239,9 @@ void elf::addReservedSymbols() {
     if (Config->EMachine == EM_PPC || Config->EMachine == EM_PPC64)
       GotOff = 0x8000;
 
-    Symtab->addDefined(Defined{/*File=*/nullptr, GotSymName, STB_GLOBAL,
-                               STV_HIDDEN, STT_NOTYPE, GotOff, /*Size=*/0,
-                               Out::ElfHeader});
+    Symtab->addSymbol(Defined{/*File=*/nullptr, GotSymName, STB_GLOBAL,
+                              STV_HIDDEN, STT_NOTYPE, GotOff, /*Size=*/0,
+                              Out::ElfHeader});
     ElfSym::GlobalOffsetTable = cast<Defined>(S);
   }
 
@@ -1592,9 +1592,9 @@ template <class ELFT> void Writer<ELFT>:
   // Even the author of gold doesn't remember why gold behaves that way.
   // https://sourceware.org/ml/binutils/2002-03/msg00360.html
   if (In.Dynamic->Parent)
-    Symtab->addDefined(Defined{/*File=*/nullptr, "_DYNAMIC", STB_WEAK,
-                               STV_HIDDEN, STT_NOTYPE,
-                               /*Value=*/0, /*Size=*/0, In.Dynamic});
+    Symtab->addSymbol(Defined{/*File=*/nullptr, "_DYNAMIC", STB_WEAK,
+                              STV_HIDDEN, STT_NOTYPE,
+                              /*Value=*/0, /*Size=*/0, In.Dynamic});
 
   // Define __rel[a]_iplt_{start,end} symbols if needed.
   addRelIpltSymbols();




More information about the llvm-commits mailing list