Remove InputGraph::getNextFile().

getNextFile used to have a complex logic to determine which file
should be processed by the Resolver on next iteration.
Now, it is just a sequential accessor to the internal array and
provides no sensible feature.

This patch also removes InputGraph::getGroupSize and InputGraph::
skipGroup to simplify the code.

llvm-svn: 225832
This commit is contained in:
Rui Ueyama 2015-01-13 21:27:12 +00:00
parent 332e8b1cd4
commit b34838424a
6 changed files with 31 additions and 158 deletions

View File

@ -50,12 +50,6 @@ public:
/// \brief Initialize the inputgraph
InputGraph() : _index(0) {}
virtual ~InputGraph();
/// getNextFile returns the next file that needs to be processed by
/// the resolver. When there are no more files to be processed, an
/// nullptr is returned.
File *getNextFile();
/// \brief Adds a node into the InputGraph
void addInputElement(std::unique_ptr<InputElement>);
@ -63,14 +57,7 @@ public:
/// \brief Adds a node at the beginning of the InputGraph
void addInputElementFront(std::unique_ptr<InputElement>);
InputElementVectorT &inputElements() {
return _inputArgs;
}
// Returns the current group size if we are at an --end-group.
// Otherwise returns 0.
int getGroupSize();
void skipGroup();
InputElementVectorT &inputElements() { return _inputArgs; }
// \brief Returns the number of input files.
size_t size() const { return _inputArgs.size(); }

View File

@ -55,8 +55,8 @@ public:
private:
typedef std::function<void(StringRef, bool)> UndefCallback;
bool undefinesAdded(int count);
File *nextFile(bool &inGroup);
bool undefinesAdded(int begin, int end);
File *getFile(int &index, int &groupLevel);
/// \brief Add section group/.gnu.linkonce if it does not exist previously.
void maybeAddSectionGroupOrGnuLinkOnce(const DefinedAtom &atom);

View File

@ -13,17 +13,6 @@
using namespace lld;
InputGraph::~InputGraph() { }
File *InputGraph::getNextFile() {
for (;;) {
if (_index >= _inputArgs.size())
return nullptr;
if (FileNode *node = dyn_cast<FileNode>(_inputArgs[_index++].get()))
return node->getFile();
}
}
void InputGraph::addInputElement(std::unique_ptr<InputElement> ie) {
_inputArgs.push_back(std::move(ie));
}
@ -32,25 +21,6 @@ void InputGraph::addInputElementFront(std::unique_ptr<InputElement> ie) {
_inputArgs.insert(_inputArgs.begin(), std::move(ie));
}
// 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 (_index >= _inputArgs.size())
return 0;
InputElement *elem = _inputArgs[_index].get();
if (const GroupEnd *group = dyn_cast<GroupEnd>(elem))
return group->getSize();
return 0;
}
void InputGraph::skipGroup() {
if (_index >= _inputArgs.size())
return;
if (isa<GroupEnd>(_inputArgs[_index].get()))
_index++;
}
std::error_code FileNode::parse(const LinkingContext &, raw_ostream &) {
if (_file)
if (std::error_code ec = _file->parse())

View File

@ -231,52 +231,52 @@ void Resolver::addAtoms(const std::vector<const DefinedAtom *> &newAtoms) {
// Returns true if at least one of N previous files has created an
// undefined symbol.
bool Resolver::undefinesAdded(int n) {
for (size_t i = _fileIndex - n; i < _fileIndex; ++i)
if (_newUndefinesAdded[_files[i]])
return true;
bool Resolver::undefinesAdded(int begin, int end) {
std::vector<std::unique_ptr<InputElement>> &inputs =
_context.getInputGraph().inputElements();
for (int i = begin; i < end; ++i)
if (FileNode *node = dyn_cast<FileNode>(inputs[i].get()))
if (_newUndefinesAdded[node->getFile()])
return true;
return false;
}
File *Resolver::nextFile(bool &inGroup) {
if (size_t groupSize = _context.getInputGraph().getGroupSize()) {
File *Resolver::getFile(int &index, int &groupLevel) {
std::vector<std::unique_ptr<InputElement>> &inputs
= _context.getInputGraph().inputElements();
if ((size_t)index >= inputs.size())
return nullptr;
if (GroupEnd *group = dyn_cast<GroupEnd>(inputs[index].get())) {
// We are at the end of the current group. If one or more new
// undefined atom has been added in the last groupSize files, we
// reiterate over the files.
if (undefinesAdded(groupSize))
_fileIndex -= groupSize;
_context.getInputGraph().skipGroup();
return nextFile(inGroup);
int size = group->getSize();
if (undefinesAdded(index - size, index)) {
index -= size;
++groupLevel;
return getFile(index, groupLevel);
}
++index;
--groupLevel;
return getFile(index, groupLevel);
}
if (_fileIndex < _files.size()) {
// We are still in the current group.
inGroup = true;
return _files[_fileIndex++];
}
// We are not in a group. Get a new file.
File *file = _context.getInputGraph().getNextFile();
if (!file)
return nullptr;
_files.push_back(&*file);
++_fileIndex;
inGroup = false;
return file;
return cast<FileNode>(inputs[index++].get())->getFile();
}
// Keep adding atoms until _context.getNextFile() returns an error. This
// function is where undefined atoms are resolved.
void Resolver::resolveUndefines() {
ScopedTask task(getDefaultDomain(), "resolveUndefines");
int index = 0;
int groupLevel = 0;
for (;;) {
bool inGroup = false;
bool undefAdded = false;
File *file = nextFile(inGroup);
File *file = getFile(index, groupLevel);
if (!file)
return;
switch (file->kind()) {
case File::kindObject:
if (inGroup)
if (groupLevel > 0)
break;
assert(!file->hasOrdinal());
file->setOrdinal(_context.getNextOrdinalAndIncrement());
@ -293,7 +293,7 @@ void Resolver::resolveUndefines() {
handleSharedLibrary(*file);
break;
}
_newUndefinesAdded[&*file] = undefAdded;
_newUndefinesAdded[file] = undefAdded;
}
}

View File

@ -4,7 +4,6 @@ add_lld_unittest(DriverTests
DarwinLdDriverTest.cpp
WinLinkDriverTest.cpp
WinLinkModuleDefTest.cpp
InputGraphTest.cpp
)
target_link_libraries(DriverTests

View File

@ -1,83 +0,0 @@
//===- lld/unittest/InputGraphTest.cpp -----------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief InputGraph Tests
///
//===----------------------------------------------------------------------===//
#include "gtest/gtest.h"
#include "lld/Core/InputGraph.h"
#include "lld/Core/Resolver.h"
#include "lld/Core/Simple.h"
using namespace lld;
namespace {
class TestLinkingContext : public LinkingContext {
public:
Writer &writer() const override { llvm_unreachable("no writer!"); }
bool validateImpl(raw_ostream &) override { return true; }
};
class TestExpandFileNode : public SimpleFileNode {
public:
TestExpandFileNode(StringRef path) : SimpleFileNode(path) {}
void addElement(std::unique_ptr<InputElement> element) {
_expandElements.push_back(std::move(element));
}
private:
InputGraph::InputElementVectorT _expandElements;
};
class InputGraphTest : public testing::Test {
public:
InputGraphTest() {
_ctx.setInputGraph(std::unique_ptr<InputGraph>(new InputGraph()));
_graph = &_ctx.getInputGraph();
}
StringRef getNext() {
File *file = _graph->getNextFile();
EXPECT_TRUE(file);
return file->path();
}
void expectEnd() {
File *file = _graph->getNextFile();
EXPECT_TRUE(file == nullptr);
}
protected:
TestLinkingContext _ctx;
InputGraph *_graph;
};
} // end anonymous namespace
static std::unique_ptr<SimpleFileNode> createFile(StringRef name) {
std::vector<std::unique_ptr<File>> files;
files.push_back(std::unique_ptr<SimpleFile>(new SimpleFile(name)));
std::unique_ptr<SimpleFileNode> file(new SimpleFileNode("filenode"));
file->addFiles(std::move(files));
return file;
}
TEST_F(InputGraphTest, Empty) {
expectEnd();
}
TEST_F(InputGraphTest, File) {
_graph->addInputElement(createFile("file1"));
EXPECT_EQ("file1", getNext());
expectEnd();
}