[lld] r334552 - Fix /WholeArchive bug.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 12 14:47:31 PDT 2018


Author: ruiu
Date: Tue Jun 12 14:47:31 2018
New Revision: 334552

URL: http://llvm.org/viewvc/llvm-project?rev=334552&view=rev
Log:
Fix /WholeArchive bug.

`lld-link foo.lib /wholearchive:foo.lib` should work the same way as
`lld-link /wholearchive:foo.lib foo.lib`. Previously, /wholearchive in
the former case was ignored.

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

Modified:
    lld/trunk/COFF/Driver.cpp
    lld/trunk/COFF/Driver.h
    lld/trunk/test/COFF/wholearchive.s

Modified: lld/trunk/COFF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=334552&r1=334551&r2=334552&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.cpp (original)
+++ lld/trunk/COFF/Driver.cpp Tue Jun 12 14:47:31 2018
@@ -332,13 +332,24 @@ StringRef LinkerDriver::doFindFile(Strin
   return Filename;
 }
 
+static Optional<sys::fs::UniqueID> getUniqueID(StringRef Path) {
+  sys::fs::UniqueID Ret;
+  if (sys::fs::getUniqueID(Path, Ret))
+    return None;
+  return Ret;
+}
+
 // Resolves a file path. This never returns the same path
 // (in that case, it returns None).
 Optional<StringRef> LinkerDriver::findFile(StringRef Filename) {
   StringRef Path = doFindFile(Filename);
-  bool Seen = !VisitedFiles.insert(Path.lower()).second;
-  if (Seen)
-    return None;
+
+  if (Optional<sys::fs::UniqueID> ID = getUniqueID(Path)) {
+    bool Seen = !VisitedFiles.insert(*ID).second;
+    if (Seen)
+      return None;
+  }
+
   if (Path.endswith_lower(".lib"))
     VisitedLibs.insert(sys::path::filename(Path));
   return Path;
@@ -361,11 +372,14 @@ Optional<StringRef> LinkerDriver::findLi
     return None;
   if (!VisitedLibs.insert(Filename.lower()).second)
     return None;
+
   StringRef Path = doFindLib(Filename);
   if (Config->NoDefaultLibs.count(Path))
     return None;
-  if (!VisitedFiles.insert(Path.lower()).second)
-    return None;
+
+  if (Optional<sys::fs::UniqueID> ID = getUniqueID(Path))
+    if (!VisitedFiles.insert(*ID).second)
+      return None;
   return Path;
 }
 
@@ -1231,22 +1245,29 @@ void LinkerDriver::link(ArrayRef<const c
   if (errorCount())
     return;
 
-  bool WholeArchiveFlag = Args.hasArg(OPT_wholearchive_flag);
+  std::set<sys::fs::UniqueID> WholeArchives;
+  for (auto *Arg : Args.filtered(OPT_wholearchive_file))
+    if (Optional<sys::fs::UniqueID> ID = getUniqueID(Arg->getValue()))
+      WholeArchives.insert(*ID);
+
+  // A predicate returning true if a given path is an argument for
+  // /wholearchive:, or /wholearchive is enabled globally.
+  // This function is a bit tricky because "foo.obj /wholearchive:././foo.obj"
+  // needs to be handled as "/wholearchive:foo.obj foo.obj".
+  auto IsWholeArchive = [&](StringRef Path) -> bool {
+    if (Args.hasArg(OPT_wholearchive_flag))
+      return true;
+    if (Optional<sys::fs::UniqueID> ID = getUniqueID(Path))
+      return WholeArchives.count(*ID);
+    return false;
+  };
+
   // Create a list of input files. Files can be given as arguments
   // for /defaultlib option.
-  std::vector<MemoryBufferRef> MBs;
-  for (auto *Arg : Args.filtered(OPT_INPUT, OPT_wholearchive_file)) {
-    switch (Arg->getOption().getID()) {
-    case OPT_INPUT:
-      if (Optional<StringRef> Path = findFile(Arg->getValue()))
-        enqueuePath(*Path, WholeArchiveFlag);
-      break;
-    case OPT_wholearchive_file:
-      if (Optional<StringRef> Path = findFile(Arg->getValue()))
-        enqueuePath(*Path, true);
-      break;
-    }
-  }
+  for (auto *Arg : Args.filtered(OPT_INPUT, OPT_wholearchive_file))
+    if (Optional<StringRef> Path = findFile(Arg->getValue()))
+      enqueuePath(*Path, IsWholeArchive(Arg->getValue()));
+
   for (auto *Arg : Args.filtered(OPT_defaultlib))
     if (Optional<StringRef> Path = findLib(Arg->getValue()))
       enqueuePath(*Path, false);

Modified: lld/trunk/COFF/Driver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.h?rev=334552&r1=334551&r2=334552&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.h (original)
+++ lld/trunk/COFF/Driver.h Tue Jun 12 14:47:31 2018
@@ -21,6 +21,7 @@
 #include "llvm/Object/COFF.h"
 #include "llvm/Option/Arg.h"
 #include "llvm/Option/ArgList.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/TarWriter.h"
 #include <memory>
 #include <set>
@@ -94,7 +95,11 @@ private:
 
   // Library search path. The first element is always "" (current directory).
   std::vector<StringRef> SearchPaths;
-  std::set<std::string> VisitedFiles;
+
+  // We don't want to add the same file more than once.
+  // Files are uniquified by their filesystem and file number.
+  std::set<llvm::sys::fs::UniqueID> VisitedFiles;
+
   std::set<std::string> VisitedLibs;
 
   Symbol *addUndefined(StringRef Sym);

Modified: lld/trunk/test/COFF/wholearchive.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/wholearchive.s?rev=334552&r1=334551&r2=334552&view=diff
==============================================================================
--- lld/trunk/test/COFF/wholearchive.s (original)
+++ lld/trunk/test/COFF/wholearchive.s Tue Jun 12 14:47:31 2018
@@ -10,6 +10,14 @@
 # RUN: lld-link -dll -out:%t.dll -entry:main %t.main.obj -wholearchive %t.archive.lib -implib:%t.lib
 # RUN: llvm-readobj %t.lib | FileCheck %s -check-prefix CHECK-IMPLIB
 
+# RUN: lld-link -dll -out:%t.dll -entry:main %t.main.obj %t.archive.lib -wholearchive:%t.archive.lib -implib:%t.lib
+# RUN: llvm-readobj %t.lib | FileCheck %s -check-prefix CHECK-IMPLIB
+
+# RUN: mkdir -p %t.dir
+# RUN: cp %t.archive.lib %t.dir/foo.lib
+# RUN: lld-link -dll -out:%t.dll -entry:main %t.main.obj %t.dir/./foo.lib -wholearchive:%t.dir/foo.lib -implib:%t.lib
+# RUN: llvm-readobj %t.lib | FileCheck %s -check-prefix CHECK-IMPLIB
+
 # CHECK-IMPLIB: Symbol: __imp_exportfn3
 # CHECK-IMPLIB: Symbol: exportfn3
 




More information about the llvm-commits mailing list