Files
clang-p2996/lld/lib/Core/InputGraph.cpp
Rui Ueyama a5f2816b1c 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<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
2015-01-06 23:06:49 +00:00

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();
}