Index: include/lld/Core/File.h =================================================================== --- include/lld/Core/File.h +++ include/lld/Core/File.h @@ -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 #include @@ -265,6 +266,35 @@ /// \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 &defined() const override { + llvm_unreachable("internal error"); + } + const atom_collection &undefined() const override { + llvm_unreachable("internal error"); + } + const atom_collection &sharedLibrary() const override { + llvm_unreachable("internal error"); + } + const atom_collection &absolute() const override { + llvm_unreachable("internal error"); + } + +private: + std::error_code _ec; +}; + } // end namespace lld #endif Index: include/lld/Core/InputGraph.h =================================================================== --- include/lld/Core/InputGraph.h +++ include/lld/Core/InputGraph.h @@ -208,6 +208,8 @@ 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 @@ virtual void appendInputFile(std::unique_ptr 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 Index: include/lld/Driver/CoreInputGraph.h =================================================================== --- include/lld/Driver/CoreInputGraph.h +++ /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 -#include - -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 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> 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: include/lld/Driver/Driver.h =================================================================== --- include/lld/Driver/Driver.h +++ include/lld/Driver/Driver.h @@ -32,6 +32,12 @@ class PECOFFLinkingContext; class ELFLinkingContext; +typedef std::vector> 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: Index: include/lld/Driver/WrapperInputGraph.h =================================================================== --- /dev/null +++ include/lld/Driver/WrapperInputGraph.h @@ -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 +#include + +namespace lld { + +class WrapperNode : public FileNode { +public: + WrapperNode(std::unique_ptr file) : FileNode(file->path()) { + _files.push_back(std::move(file)); + } +}; + +} + +#endif Index: lib/Core/InputGraph.cpp =================================================================== --- lib/Core/InputGraph.cpp +++ lib/Core/InputGraph.cpp @@ -101,3 +101,10 @@ result.push_back(llvm::make_unique(_path, std::move(file))); return true; } + +std::error_code FileNode::parse(const LinkingContext &, raw_ostream &) { + for (std::unique_ptr &file : _files) + if (std::error_code ec = file->parse()) + return ec; + return std::error_code(); +} Index: lib/Driver/CoreDriver.cpp =================================================================== --- lib/Driver/CoreDriver.cpp +++ lib/Driver/CoreDriver.cpp @@ -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 @@ 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 @@ ctx.addPassNamed(inputArg->getValue()); break; - case OPT_INPUT: - inputGraph->addInputElement(std::unique_ptr( - new CoreFileNode(ctx, inputArg->getValue()))); + case OPT_INPUT: { + std::vector> files + = parseFile(ctx, inputArg->getValue(), false); + for (std::unique_ptr &file : files) { + inputGraph->addInputElement(std::unique_ptr( + new WrapperNode(std::move(file)))); + } break; + } default: break; Index: lib/Driver/Driver.cpp =================================================================== --- lib/Driver/Driver.cpp +++ lib/Driver/Driver.cpp @@ -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" @@ -28,6 +30,38 @@ namespace lld { +FileVector makeErrorFile(StringRef path, std::error_code ec) { + std::vector> result; + result.push_back(llvm::make_unique(path, ec)); + return result; +} + +FileVector parseMemberFiles(FileVector &files) { + std::vector> members; + for (std::unique_ptr &file : files) { + if (auto *archive = dyn_cast(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> mb + = MemoryBuffer::getFileOrSTDIN(path); + if (std::error_code ec = mb.getError()) + return makeErrorFile(path, ec); + std::vector> files; + if (std::error_code ec = ctx.registry().parseFile(std::move(mb.get()), files, false)) + 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 Index: test/core/empty.objtxt =================================================================== --- test/core/empty.objtxt +++ /dev/null @@ -1,11 +0,0 @@ -# RUN: lld -core %s | FileCheck %s - -# -# Test that an empty file is handled properly -# - ---- -... - -# CHECK: --- -# CHECK: ...