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
111 lines
3.2 KiB
C++
111 lines
3.2 KiB
C++
//===- lib/Core/InputGraph.cpp --------------------------------------------===//
|
|
//
|
|
// The LLVM Linker
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "lld/Core/InputGraph.h"
|
|
#include "lld/Core/Resolver.h"
|
|
#include <memory>
|
|
|
|
using namespace lld;
|
|
|
|
InputGraph::~InputGraph() { }
|
|
|
|
File *InputGraph::getNextFile() {
|
|
// Try to get the next file of _currentInputElement. If the current input
|
|
// element points to an archive file, and there's a file left in the archive,
|
|
// it will succeed. If not, try to get the next file in the input graph.
|
|
for (;;) {
|
|
if (_currentInputElement) {
|
|
File *next = _currentInputElement->getNextFile();
|
|
if (next) {
|
|
for (const std::function<void(File *)> &observer : _observers)
|
|
observer(next);
|
|
return next;
|
|
}
|
|
}
|
|
|
|
InputElement *elt = getNextInputElement();
|
|
if (!elt)
|
|
return nullptr;
|
|
_currentInputElement = elt;
|
|
}
|
|
}
|
|
|
|
void InputGraph::registerObserver(std::function<void(File *)> fn) {
|
|
_observers.push_back(fn);
|
|
}
|
|
|
|
void InputGraph::addInputElement(std::unique_ptr<InputElement> ie) {
|
|
_inputArgs.push_back(std::move(ie));
|
|
}
|
|
|
|
void InputGraph::addInputElementFront(std::unique_ptr<InputElement> ie) {
|
|
_inputArgs.insert(_inputArgs.begin(), std::move(ie));
|
|
}
|
|
|
|
bool InputGraph::dump(raw_ostream &diagnostics) {
|
|
for (std::unique_ptr<InputElement> &ie : _inputArgs)
|
|
if (!ie->dump(diagnostics))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
/// \brief Helper functions for the resolver
|
|
InputElement *InputGraph::getNextInputElement() {
|
|
if (_nextElementIndex >= _inputArgs.size())
|
|
return nullptr;
|
|
InputElement *elem = _inputArgs[_nextElementIndex++].get();
|
|
if (isa<GroupEnd>(elem))
|
|
return getNextInputElement();
|
|
return elem;
|
|
}
|
|
|
|
void InputGraph::normalize() {
|
|
std::vector<std::unique_ptr<InputElement>> vec;
|
|
for (std::unique_ptr<InputElement> &elt : _inputArgs) {
|
|
if (elt->getReplacements(vec))
|
|
continue;
|
|
vec.push_back(std::move(elt));
|
|
}
|
|
_inputArgs = std::move(vec);
|
|
}
|
|
|
|
// If we are at the end of a group, return its size (which indicates
|
|
// how many files we need to go back in the command line).
|
|
// Returns 0 if we are not at the end of a group.
|
|
int InputGraph::getGroupSize() {
|
|
if (_nextElementIndex >= _inputArgs.size())
|
|
return 0;
|
|
InputElement *elem = _inputArgs[_nextElementIndex].get();
|
|
if (const GroupEnd *group = dyn_cast<GroupEnd>(elem))
|
|
return group->getSize();
|
|
return 0;
|
|
}
|
|
|
|
void InputGraph::skipGroup() {
|
|
if (_nextElementIndex >= _inputArgs.size())
|
|
return;
|
|
if (isa<GroupEnd>(_inputArgs[_nextElementIndex].get()))
|
|
_nextElementIndex++;
|
|
}
|
|
|
|
bool FileNode::getReplacements(InputGraph::InputElementVectorT &result) {
|
|
if (_files.size() < 2)
|
|
return false;
|
|
for (std::unique_ptr<File> &file : _files)
|
|
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();
|
|
}
|