Convert CoreInputGraph.
authorRui Ueyama <ruiu@google.com>
Tue, 6 Jan 2015 23:06:49 +0000 (23:06 +0000)
committerRui Ueyama <ruiu@google.com>
Tue, 6 Jan 2015 23:06:49 +0000 (23:06 +0000)
This is a part of InputGraph cleanup to represent input files as a flat
list of Files (and some meta-nodes for group etc.)

We cannot achieve that goal in one gigantic patch, so I split the task
into small steps as shown below.

(Recap the progress so far: Currently InputGraph contains a list of
InputElements. Each InputElement contain one File (that used to have
multiple Files, but I eliminated that use case in r223867). Files are
currently instantiated in Driver::link(), but I already made a change
to separate file parsing from object instantiation (r224102), so we
can safely instantiate Files when we need them, instead of wrapping
a file with the wrapper class (FileNode class). InputGraph used to
act like a generator class by interpreting groups by itself, but it's
now just a container of a list of InputElements (r223867).)

1. Instantiate Files in the driver and wrap them with WrapperNode.
WrapperNode is a temporary class that allows us to instantiate Files
in the driver while keep using the current InputGraph data structure.

This patch demonstrates how this step 1 looks like, using Core driver
as an example.

2. Do the same thing for the other drivers.

When step 2 is done, an InputGraph consists of GroupEnd objects or
WrapperNodes each of which contains one File. Other types of
FileNode subclasses are removed.

3. Replace InputGraph with std::vector<std::unique_ptr<InputElement>>.
InputGraph is already just a container of list of InputElements,
so this step removes that needless class.

4. Remove WrapperNode.

We need some code cleanup between each step, because many classes
do a bit odd things (e.g. InputGraph::getGroupSize()). I'll straight
things up as I need to.

llvm-svn: 225313

lld/include/lld/Core/File.h
lld/include/lld/Core/InputGraph.h
lld/include/lld/Driver/CoreInputGraph.h [deleted file]
lld/include/lld/Driver/Driver.h
lld/include/lld/Driver/WrapperInputGraph.h [new file with mode: 0644]
lld/lib/Core/InputGraph.cpp
lld/lib/Driver/CoreDriver.cpp
lld/lib/Driver/Driver.cpp
lld/test/core/empty.objtxt [deleted file]

index 1edf943..e6d1ec6 100644 (file)
@@ -16,6 +16,7 @@
 #include "lld/Core/UndefinedAtom.h"
 #include "lld/Core/range.h"
 #include "llvm/ADT/Optional.h"
+#include "llvm/ADT/Twine.h"
 #include "llvm/Support/ErrorHandling.h"
 #include <functional>
 #include <memory>
@@ -265,6 +266,35 @@ protected:
   /// \brief only subclasses of MutableFile can be instantiated
   MutableFile(StringRef p) : File(p, kindObject) {}
 };
+
+/// An ErrorFile represents a file that doesn't exist.
+/// If you try to parse a file which doesn't exist, an instance of this
+/// class will be returned. That's parse method always returns an error.
+/// This is useful to delay erroring on non-existent files, so that we
+/// can do unit testing a driver using non-existing file paths.
+class ErrorFile : public File {
+public:
+  ErrorFile(StringRef p, std::error_code ec) : File(p, kindObject), _ec(ec) {}
+
+  std::error_code doParse() override { return _ec; }
+
+  const atom_collection<DefinedAtom> &defined() const override {
+    llvm_unreachable("internal error");
+  }
+  const atom_collection<UndefinedAtom> &undefined() const override {
+    llvm_unreachable("internal error");
+  }
+  const atom_collection<SharedLibraryAtom> &sharedLibrary() const override {
+    llvm_unreachable("internal error");
+  }
+  const atom_collection<AbsoluteAtom> &absolute() const override {
+    llvm_unreachable("internal error");
+  }
+
+private:
+  std::error_code _ec;
+};
+
 } // end namespace lld
 
 #endif
index 81fb42a..56d8d51 100644 (file)
@@ -208,6 +208,8 @@ public:
     return _files[_nextFileIndex++].get();
   }
 
+  std::error_code parse(const LinkingContext &, raw_ostream &) override;
+
 protected:
   StringRef _path;                       // The path of the Input file
   InputGraph::FileVectorT _files;        // A vector of lld File objects
@@ -231,12 +233,8 @@ public:
   virtual void appendInputFile(std::unique_ptr<File> f) {
     _files.push_back(std::move(f));
   }
-
-  /// \brief parse the input element
-  std::error_code parse(const LinkingContext &, raw_ostream &) override {
-    return std::error_code();
-  }
 };
+
 } // namespace lld
 
 #endif // LLD_CORE_INPUT_GRAPH_H
diff --git a/lld/include/lld/Driver/CoreInputGraph.h b/lld/include/lld/Driver/CoreInputGraph.h
deleted file mode 100644 (file)
index ade6f49..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-//===- lld/Driver/CoreInputGraph.h - Input Graph Node for Core linker -----===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-///
-/// Handles Options for CORE linking and provides InputElements
-/// for the CORE linker
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_DRIVER_CORE_INPUT_GRAPH_H
-#define LLD_DRIVER_CORE_INPUT_GRAPH_H
-
-#include "lld/Core/InputGraph.h"
-#include "lld/ReaderWriter/CoreLinkingContext.h"
-#include "lld/ReaderWriter/Reader.h"
-#include "llvm/Support/Errc.h"
-#include <map>
-#include <memory>
-
-namespace lld {
-
-/// \brief Represents a Core File
-class CoreFileNode : public FileNode {
-public:
-  CoreFileNode(CoreLinkingContext &, StringRef path) : FileNode(path) {}
-
-  /// \brief Parse the input file to lld::File.
-  std::error_code parse(const LinkingContext &ctx,
-                        raw_ostream &diagnostics) override {
-    ErrorOr<StringRef> filePath = getPath(ctx);
-    if (filePath.getError() == llvm::errc::no_such_file_or_directory)
-      return make_error_code(llvm::errc::no_such_file_or_directory);
-
-    // Create a memory buffer
-    ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
-        MemoryBuffer::getFileOrSTDIN(*filePath);
-    if (std::error_code ec = mb.getError())
-      return ec;
-
-    return ctx.registry().parseFile(std::move(mb.get()), _files);
-  }
-};
-
-} // namespace lld
-
-#endif
index 6ea7ca6..b65a7c8 100644 (file)
@@ -32,6 +32,12 @@ class MachOLinkingContext;
 class PECOFFLinkingContext;
 class ELFLinkingContext;
 
+typedef std::vector<std::unique_ptr<File>> FileVector;
+
+FileVector makeErrorFile(StringRef path, std::error_code ec);
+FileVector parseMemberFiles(FileVector &files);
+FileVector parseFile(LinkingContext &ctx, StringRef path, bool wholeArchive);
+
 /// Base class for all Drivers.
 class Driver {
 protected:
diff --git a/lld/include/lld/Driver/WrapperInputGraph.h b/lld/include/lld/Driver/WrapperInputGraph.h
new file mode 100644 (file)
index 0000000..778823b
--- /dev/null
@@ -0,0 +1,31 @@
+//===- lld/Driver/WrapperInputGraph.h - dummy InputGraph node -------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_DRIVER_WRAPPER_INPUT_GRAPH_H
+#define LLD_DRIVER_WRAPPER_INPUT_GRAPH_H
+
+#include "lld/Core/InputGraph.h"
+#include "lld/ReaderWriter/CoreLinkingContext.h"
+#include "lld/ReaderWriter/Reader.h"
+#include "llvm/Support/Errc.h"
+#include <map>
+#include <memory>
+
+namespace lld {
+
+class WrapperNode : public FileNode {
+public:
+  WrapperNode(std::unique_ptr<File> file) : FileNode(file->path()) {
+    _files.push_back(std::move(file));
+  }
+};
+
+}
+
+#endif
index 8dabe16..c7158b5 100644 (file)
@@ -101,3 +101,10 @@ bool FileNode::getReplacements(InputGraph::InputElementVectorT &result) {
     result.push_back(llvm::make_unique<SimpleFileNode>(_path, std::move(file)));
   return true;
 }
+
+std::error_code FileNode::parse(const LinkingContext &, raw_ostream &) {
+  for (std::unique_ptr<File> &file : _files)
+    if (std::error_code ec = file->parse())
+      return ec;
+  return std::error_code();
+}
index 07af587..1db3342 100644 (file)
@@ -8,7 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "lld/Driver/Driver.h"
-#include "lld/Driver/CoreInputGraph.h"
+#include "lld/Driver/WrapperInputGraph.h"
 #include "lld/ReaderWriter/CoreLinkingContext.h"
 #include "lld/ReaderWriter/Reader.h"
 #include "llvm/ADT/ArrayRef.h"
@@ -76,16 +76,15 @@ static const Registry::KindStrings coreKindStrings[] = {
 
 bool CoreDriver::link(int argc, const char *argv[], raw_ostream &diagnostics) {
   CoreLinkingContext ctx;
-  if (!parse(argc, argv, ctx))
-    return false;
 
   // Register possible input file parsers.
   ctx.registry().addSupportNativeObjects();
   ctx.registry().addSupportYamlFiles();
-
   ctx.registry().addKindTable(Reference::KindNamespace::testing,
                               Reference::KindArch::all, coreKindStrings);
 
+  if (!parse(argc, argv, ctx))
+    return false;
   return Driver::link(ctx);
 }
 
@@ -151,10 +150,15 @@ bool CoreDriver::parse(int argc, const char *argv[], CoreLinkingContext &ctx,
       ctx.addPassNamed(inputArg->getValue());
       break;
 
-    case OPT_INPUT:
-      inputGraph->addInputElement(std::unique_ptr<InputElement>(
-          new CoreFileNode(ctx, inputArg->getValue())));
+    case OPT_INPUT: {
+      std::vector<std::unique_ptr<File>> files
+        = parseFile(ctx, inputArg->getValue(), false);
+      for (std::unique_ptr<File> &file : files) {
+        inputGraph->addInputElement(std::unique_ptr<InputElement>(
+            new WrapperNode(std::move(file))));
+      }
       break;
+    }
 
     default:
       break;
index b26ab25..d55bc4a 100644 (file)
@@ -8,6 +8,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "lld/Driver/Driver.h"
+#include "lld/Core/ArchiveLibraryFile.h"
+#include "lld/Core/File.h"
 #include "lld/Core/Instrumentation.h"
 #include "lld/Core/LLVM.h"
 #include "lld/Core/Parallel.h"
 
 namespace lld {
 
+FileVector makeErrorFile(StringRef path, std::error_code ec) {
+  std::vector<std::unique_ptr<File>> result;
+  result.push_back(llvm::make_unique<ErrorFile>(path, ec));
+  return result;
+}
+
+FileVector parseMemberFiles(FileVector &files) {
+  std::vector<std::unique_ptr<File>> members;
+  for (std::unique_ptr<File> &file : files) {
+    if (auto *archive = dyn_cast<ArchiveLibraryFile>(file.get())) {
+      if (std::error_code ec = archive->parseAllMembers(members))
+        return makeErrorFile(file->path(), ec);
+    } else {
+      members.push_back(std::move(file));
+    }
+  }
+  return members;
+}
+
+FileVector parseFile(LinkingContext &ctx, StringRef path, bool wholeArchive) {
+  ErrorOr<std::unique_ptr<MemoryBuffer>> mb
+      = MemoryBuffer::getFileOrSTDIN(path);
+  if (std::error_code ec = mb.getError())
+    return makeErrorFile(path, ec);
+  std::vector<std::unique_ptr<File>> files;
+  if (std::error_code ec = ctx.registry().parseFile(std::move(mb.get()), files))
+    return makeErrorFile(path, ec);
+  if (wholeArchive)
+    return parseMemberFiles(files);
+  return files;
+}
+
 /// This is where the link is actually performed.
 bool Driver::link(LinkingContext &context, raw_ostream &diagnostics) {
   // Honor -mllvm
diff --git a/lld/test/core/empty.objtxt b/lld/test/core/empty.objtxt
deleted file mode 100644 (file)
index a78a3bf..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-# RUN: lld -core %s | FileCheck %s
-
-#
-# Test that an empty file is handled properly
-#
-
----
-...
-
-# CHECK:       ---
-# CHECK:       ...