From: Rui Ueyama Date: Tue, 6 Jan 2015 23:06:49 +0000 (+0000) Subject: Convert CoreInputGraph. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a5f2816b1cded58718b033fa92b39a7e10c6dd99;p=platform%2Fupstream%2Fllvm.git Convert CoreInputGraph. 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>. 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 --- diff --git a/lld/include/lld/Core/File.h b/lld/include/lld/Core/File.h index 1edf943..e6d1ec6 100644 --- a/lld/include/lld/Core/File.h +++ b/lld/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 @@ 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 &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 diff --git a/lld/include/lld/Core/InputGraph.h b/lld/include/lld/Core/InputGraph.h index 81fb42a..56d8d51 100644 --- a/lld/include/lld/Core/InputGraph.h +++ b/lld/include/lld/Core/InputGraph.h @@ -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 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 index ade6f49..0000000 --- a/lld/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 diff --git a/lld/include/lld/Driver/Driver.h b/lld/include/lld/Driver/Driver.h index 6ea7ca6..b65a7c8 100644 --- a/lld/include/lld/Driver/Driver.h +++ b/lld/include/lld/Driver/Driver.h @@ -32,6 +32,12 @@ class MachOLinkingContext; 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: diff --git a/lld/include/lld/Driver/WrapperInputGraph.h b/lld/include/lld/Driver/WrapperInputGraph.h new file mode 100644 index 0000000..778823b --- /dev/null +++ b/lld/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 diff --git a/lld/lib/Core/InputGraph.cpp b/lld/lib/Core/InputGraph.cpp index 8dabe16..c7158b5 100644 --- a/lld/lib/Core/InputGraph.cpp +++ b/lld/lib/Core/InputGraph.cpp @@ -101,3 +101,10 @@ bool FileNode::getReplacements(InputGraph::InputElementVectorT &result) { 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(); +} diff --git a/lld/lib/Driver/CoreDriver.cpp b/lld/lib/Driver/CoreDriver.cpp index 07af587..1db3342 100644 --- a/lld/lib/Driver/CoreDriver.cpp +++ b/lld/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 @@ 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( - 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; diff --git a/lld/lib/Driver/Driver.cpp b/lld/lib/Driver/Driver.cpp index b26ab25..d55bc4a 100644 --- a/lld/lib/Driver/Driver.cpp +++ b/lld/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)) + 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 index a78a3bf..0000000 --- a/lld/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: ...