#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>
/// \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
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
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
+++ /dev/null
-//===- 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
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:
--- /dev/null
+//===- 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
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();
+}
//===----------------------------------------------------------------------===//
#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"
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);
}
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;
//===----------------------------------------------------------------------===//
#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
+++ /dev/null
-# RUN: lld -core %s | FileCheck %s
-
-#
-# Test that an empty file is handled properly
-#
-
----
-...
-
-# CHECK: ---
-# CHECK: ...