COFF: Load inputs immediately instead of adding them to a queue.
authorPeter Collingbourne <peter@pcc.me.uk>
Sun, 11 Dec 2016 22:15:25 +0000 (22:15 +0000)
committerPeter Collingbourne <peter@pcc.me.uk>
Sun, 11 Dec 2016 22:15:25 +0000 (22:15 +0000)
This patch replaces the symbol table's object and archive queues, as well as
the convergent loop in the linker driver, with a design more similar to the
ELF linker where symbol resolution directly causes input files to be added to
the link, including input files arising from linker directives. Effectively
this removes the last vestiges of the old parallel input file loader.

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

llvm-svn: 289409

lld/COFF/Driver.cpp
lld/COFF/SymbolTable.cpp
lld/COFF/SymbolTable.h
lld/test/COFF/order.test

index 9d3e9d7..abbd015 100644 (file)
@@ -575,27 +575,12 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
     MBs.erase(It, MBs.end());
   }
 
-  // Read all input files given via the command line. Note that step()
-  // doesn't read files that are specified by directive sections.
+  // Read all input files given via the command line.
   for (MemoryBufferRef MB : MBs)
     Symtab.addFile(createFile(MB));
-  Symtab.step();
-
-  // Determine machine type and check if all object files are
-  // for the same CPU type. Note that this needs to be done before
-  // any call to mangle().
-  for (InputFile *File : Symtab.getFiles()) {
-    MachineTypes MT = File->getMachineType();
-    if (MT == IMAGE_FILE_MACHINE_UNKNOWN)
-      continue;
-    if (Config->Machine == IMAGE_FILE_MACHINE_UNKNOWN) {
-      Config->Machine = MT;
-      continue;
-    }
-    if (Config->Machine != MT)
-      fatal(toString(File) + ": machine type " + machineToStr(MT) +
-            " conflicts with " + machineToStr(Config->Machine));
-  }
+
+  // We should have inferred a machine type by now from the input files, but if
+  // not we assume x64.
   if (Config->Machine == IMAGE_FILE_MACHINE_UNKNOWN) {
     errs() << "warning: /machine is not specified. x64 is assumed.\n";
     Config->Machine = AMD64;
@@ -686,50 +671,37 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
   Symtab.addAbsolute(mangle("__guard_fids_count"), 0);
   Symtab.addAbsolute(mangle("__guard_flags"), 0x100);
 
-  // Read as much files as we can from directives sections.
-  Symtab.run();
-
-  // Resolve auxiliary symbols until we get a convergence.
-  // (Trying to resolve a symbol may trigger a Lazy symbol to load a new file.
-  // A new file may contain a directive section to add new command line options.
-  // That's why we have to repeat until converge.)
-  for (;;) {
-    // Windows specific -- if entry point is not found,
-    // search for its mangled names.
-    if (Config->Entry)
-      Symtab.mangleMaybe(Config->Entry);
-
-    // Windows specific -- Make sure we resolve all dllexported symbols.
-    for (Export &E : Config->Exports) {
-      if (!E.ForwardTo.empty())
-        continue;
-      E.Sym = addUndefined(E.Name);
-      if (!E.Directives)
-        Symtab.mangleMaybe(E.Sym);
-    }
+  // Windows specific -- if entry point is not found,
+  // search for its mangled names.
+  if (Config->Entry)
+    Symtab.mangleMaybe(Config->Entry);
 
-    // Add weak aliases. Weak aliases is a mechanism to give remaining
-    // undefined symbols final chance to be resolved successfully.
-    for (auto Pair : Config->AlternateNames) {
-      StringRef From = Pair.first;
-      StringRef To = Pair.second;
-      Symbol *Sym = Symtab.find(From);
-      if (!Sym)
-        continue;
-      if (auto *U = dyn_cast<Undefined>(Sym->body()))
-        if (!U->WeakAlias)
-          U->WeakAlias = Symtab.addUndefined(To);
-    }
-
-    // Windows specific -- if __load_config_used can be resolved, resolve it.
-    if (Symtab.findUnderscore("_load_config_used"))
-      addUndefined(mangle("_load_config_used"));
+  // Windows specific -- Make sure we resolve all dllexported symbols.
+  for (Export &E : Config->Exports) {
+    if (!E.ForwardTo.empty())
+      continue;
+    E.Sym = addUndefined(E.Name);
+    if (!E.Directives)
+      Symtab.mangleMaybe(E.Sym);
+  }
 
-    if (Symtab.queueEmpty())
-      break;
-    Symtab.run();
+  // Add weak aliases. Weak aliases is a mechanism to give remaining
+  // undefined symbols final chance to be resolved successfully.
+  for (auto Pair : Config->AlternateNames) {
+    StringRef From = Pair.first;
+    StringRef To = Pair.second;
+    Symbol *Sym = Symtab.find(From);
+    if (!Sym)
+      continue;
+    if (auto *U = dyn_cast<Undefined>(Sym->body()))
+      if (!U->WeakAlias)
+        U->WeakAlias = Symtab.addUndefined(To);
   }
 
+  // Windows specific -- if __load_config_used can be resolved, resolve it.
+  if (Symtab.findUnderscore("_load_config_used"))
+    addUndefined(mangle("_load_config_used"));
+
   // Do LTO by compiling bitcode input files to a set of native COFF files then
   // link those files.
   Symtab.addCombinedLTOObjects();
index 2f7add2..e9737fa 100644 (file)
@@ -27,76 +27,33 @@ namespace coff {
 SymbolTable *Symtab;
 
 void SymbolTable::addFile(InputFile *File) {
-  Files.push_back(File);
-  if (auto *F = dyn_cast<ArchiveFile>(File)) {
-    ArchiveQueue.push_back(F);
-    return;
+  if (Config->Verbose)
+    outs() << "Reading " << toString(File) << "\n";
+  File->parse();
+
+  MachineTypes MT = File->getMachineType();
+  if (Config->Machine == IMAGE_FILE_MACHINE_UNKNOWN) {
+    Config->Machine = MT;
+  } else if (MT != IMAGE_FILE_MACHINE_UNKNOWN && Config->Machine != MT) {
+    fatal(toString(File) + ": machine type " + machineToStr(MT) +
+          " conflicts with " + machineToStr(Config->Machine));
   }
-  ObjectQueue.push_back(File);
+
   if (auto *F = dyn_cast<ObjectFile>(File)) {
     ObjectFiles.push_back(F);
   } else if (auto *F = dyn_cast<BitcodeFile>(File)) {
     BitcodeFiles.push_back(F);
-  } else {
-    ImportFiles.push_back(cast<ImportFile>(File));
+  } else if (auto *F = dyn_cast<ImportFile>(File)) {
+    ImportFiles.push_back(F);
   }
-}
-
-void SymbolTable::step() {
-  if (queueEmpty())
-    return;
-  readObjects();
-  readArchive();
-}
-
-void SymbolTable::run() {
-  while (!queueEmpty())
-    step();
-}
 
-void SymbolTable::readArchive() {
-  if (ArchiveQueue.empty())
+  StringRef S = File->getDirectives();
+  if (S.empty())
     return;
 
-  // Add lazy symbols to the symbol table. Lazy symbols that conflict
-  // with existing undefined symbols are accumulated in LazySyms.
-  ArchiveFile *File = ArchiveQueue.front();
-  ArchiveQueue.pop_front();
   if (Config->Verbose)
-    outs() << "Reading " << toString(File) << "\n";
-  File->parse();
-}
-
-void SymbolTable::readObjects() {
-  if (ObjectQueue.empty())
-    return;
-
-  // 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];
-    if (Config->Verbose)
-      outs() << "Reading " << toString(File) << "\n";
-    File->parse();
-    // Adding symbols may add more files to ObjectQueue
-    // (but not to ArchiveQueue).
-    StringRef S = File->getDirectives();
-    if (!S.empty()) {
-      Directives.push_back(S);
-      if (Config->Verbose)
-        outs() << "Directives: " << toString(File) << ": " << S << "\n";
-    }
-  }
-  ObjectQueue.clear();
-
-  // Parse directive sections. This may add files to
-  // ArchiveQueue and ObjectQueue.
-  for (StringRef S : Directives)
-    Driver->parseDirectives(S);
-}
-
-bool SymbolTable::queueEmpty() {
-  return ArchiveQueue.empty() && ObjectQueue.empty();
+    outs() << "Directives: " << toString(File) << ": " << S << "\n";
+  Driver->parseDirectives(S);
 }
 
 void SymbolTable::reportRemainingUndefines() {
@@ -419,7 +376,6 @@ void SymbolTable::addCombinedLTOObjects() {
   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");
 }
@@ -465,7 +421,6 @@ std::vector<ObjectFile *> SymbolTable::createLTOObjects(LTOCodeGenerator *CG) {
   std::vector<ObjectFile *> ObjFiles;
   for (SmallString<0> &Obj : Objs) {
     auto *ObjFile = new ObjectFile(MemoryBufferRef(Obj, "<LTO object>"));
-    Files.emplace_back(ObjFile);
     ObjectFiles.push_back(ObjFile);
     ObjFiles.push_back(ObjFile);
   }
index a7f27af..52636a3 100644 (file)
@@ -21,9 +21,6 @@
 #include <eh.h>
 #endif
 
-#include <future>
-#include <list>
-
 namespace llvm {
 struct LTOCodeGenerator;
 }
@@ -56,10 +53,6 @@ struct Symbol;
 class SymbolTable {
 public:
   void addFile(InputFile *File);
-  std::vector<InputFile *> &getFiles() { return Files; }
-  void step();
-  void run();
-  bool queueEmpty();
 
   // Try to resolve any undefined symbols and update the symbol table
   // accordingly, then print an error message for any remaining undefined
@@ -129,10 +122,6 @@ private:
 
   llvm::DenseMap<StringRef, Symbol *> Symtab;
 
-  std::vector<InputFile *> Files;
-  std::list<ArchiveFile *> ArchiveQueue;
-  std::vector<InputFile *> ObjectQueue;
-
   std::vector<BitcodeFile *> BitcodeFiles;
   std::vector<SmallString<0>> Objs;
 };
index 0ce638a..6e00a36 100644 (file)
@@ -9,7 +9,7 @@
 # RUN: FileCheck %s < %t.log
 
 CHECK: order.test.tmp1.obj
-CHECK: order.test.tmp3.obj
 CHECK: order.test.tmp2.lib
 CHECK: order.test.tmp2.lib(order.test.tmp2.obj) for foo
+CHECK: order.test.tmp3.obj
 CHECK: order.test.tmp3.lib