Expand nested input elements.

Previously only the toplevel elements were expanded by expandElements().
Now we recursively call getReplacements() to expand input elements even
if they are in, say, in a group.

llvm-svn: 208144
This commit is contained in:
Rui Ueyama 2014-05-06 23:52:19 +00:00
parent dff3ef80bb
commit 3608609339
4 changed files with 41 additions and 25 deletions

View File

@ -70,8 +70,8 @@ public:
/// \brief Adds a node into the InputGraph
void addInputElement(std::unique_ptr<InputElement>);
/// Normalize the InputGraph. It visits all nodes in the tree to replace a
/// node with its children if it's shouldExpand() returns true.
/// Normalize the InputGraph. It calls expand() on each node and then replace
/// it with getReplacements() results.
void normalize();
range<InputElementIterT> inputElements() {
@ -133,11 +133,11 @@ public:
virtual void resetNextIndex() = 0;
/// Returns true if we want to replace this node with children.
virtual bool shouldExpand() const { return false; }
virtual void expand() {}
/// \brief Get the elements that we want to expand with.
virtual range<InputGraph::InputElementIterT> expandElements() {
llvm_unreachable("no element to expand");
/// Get the elements that we want to expand with.
virtual bool getReplacements(InputGraph::InputElementVectorT &) {
return false;
}
protected:
@ -194,6 +194,18 @@ public:
ErrorOr<File &> getNextFile() override;
void expand() override {
for (std::unique_ptr<InputElement> &elt : _elements)
elt->expand();
std::vector<std::unique_ptr<InputElement>> result;
for (std::unique_ptr<InputElement> &elt : _elements) {
if (elt->getReplacements(result))
continue;
result.push_back(std::move(elt));
}
_elements.swap(result);
}
protected:
InputGraph::InputElementVectorT _elements;
uint32_t _currentElementIndex;

View File

@ -127,18 +127,17 @@ public:
error_code parse(const LinkingContext &ctx, raw_ostream &diagnostics) override;
bool shouldExpand() const override { return true; }
bool getReplacements(InputGraph::InputElementVectorT &result) override {
for (std::unique_ptr<InputElement> &elt : _expandElements)
result.push_back(std::move(elt));
return true;
}
/// Unused functions for ELFGNULdScript Nodes.
ErrorOr<File &> getNextFile() override {
return make_error_code(InputGraphError::no_more_files);
}
/// Return the elements that we would want to expand with.
range<InputGraph::InputElementIterT> expandElements() override {
return make_range(_expandElements.begin(), _expandElements.end());
}
// Linker Script will be expanded and replaced with other elements
// by InputGraph::normalize(), so at link time it does not exist in
// the tree. No need to handle this message.

View File

@ -74,15 +74,13 @@ ErrorOr<InputElement *> InputGraph::getNextInputElement() {
}
void InputGraph::normalize() {
for (std::unique_ptr<InputElement> &elt : _inputArgs)
elt->expand();
std::vector<std::unique_ptr<InputElement>> vec;
for (std::unique_ptr<InputElement> &ie : _inputArgs) {
if (!ie->shouldExpand()) {
vec.push_back(std::move(ie));
for (std::unique_ptr<InputElement> &elt : _inputArgs) {
if (elt->getReplacements(vec))
continue;
}
range<InputElementIterT> expanded = ie->expandElements();
vec.insert(vec.end(), std::make_move_iterator(expanded.begin()),
std::make_move_iterator(expanded.end()));
vec.push_back(std::move(elt));
}
_inputArgs = std::move(vec);
}

View File

@ -38,12 +38,11 @@ class TestExpandFileNode : public SimpleFileNode {
public:
TestExpandFileNode(StringRef path) : SimpleFileNode(path) {}
/// Returns true as we want to expand this file
bool shouldExpand() const override { return true; }
/// Returns the elements replacing this node
range<InputGraph::InputElementIterT> expandElements() override {
return make_range(_expandElements.begin(), _expandElements.end());
bool getReplacements(InputGraph::InputElementVectorT &result) override {
for (std::unique_ptr<InputElement> &elt : _expandElements)
result.push_back(std::move(elt));
return true;
}
void addElement(std::unique_ptr<InputElement> element) {
@ -173,7 +172,15 @@ TEST_F(InputGraphTest, Normalize) {
expandFile->addElement(createFile1("file3"));
expandFile->addElement(createFile1("file4"));
_graph->addInputElement(std::move(expandFile));
_graph->addInputElement(createFile2("file5", "file6"));
std::unique_ptr<Group> group(new Group());
std::unique_ptr<TestExpandFileNode> expandFile2(
new TestExpandFileNode("node"));
expandFile2->addElement(createFile1("file5"));
group->addFile(std::move(expandFile2));
_graph->addInputElement(std::move(group));
_graph->addInputElement(createFile1("file6"));
_graph->normalize();
EXPECT_EQ("file1", getNext());