forked from OSchip/llvm-project
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:
parent
332e8b1cd4
commit
b34838424a
|
@ -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(); }
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ add_lld_unittest(DriverTests
|
|||
DarwinLdDriverTest.cpp
|
||||
WinLinkDriverTest.cpp
|
||||
WinLinkModuleDefTest.cpp
|
||||
InputGraphTest.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(DriverTests
|
||||
|
|
|
@ -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();
|
||||
}
|
Loading…
Reference in New Issue