[lld] r195515 - [InputGraph] Expand InputGraph nodes.
Shankar Easwaran
shankare at codeaurora.org
Fri Nov 22 15:08:24 PST 2013
Author: shankare
Date: Fri Nov 22 17:08:24 2013
New Revision: 195515
URL: http://llvm.org/viewvc/llvm-project?rev=195515&view=rev
Log:
[InputGraph] Expand InputGraph nodes.
Flavors may like to expand InputGraph nodes, when a filenode after parsing
results in more elements. One such example is while parsing GNU linker scripts.
The linker scripts after parsing would result in a lot of filenodes and probably
controlnodes too.
Adds unittests to verify functionality.
Modified:
lld/trunk/include/lld/Core/InputGraph.h
lld/trunk/lib/Core/InputGraph.cpp
lld/trunk/unittests/DriverTests/InputGraphTest.cpp
Modified: lld/trunk/include/lld/Core/InputGraph.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/InputGraph.h?rev=195515&r1=195514&r2=195515&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/InputGraph.h (original)
+++ lld/trunk/include/lld/Core/InputGraph.h Fri Nov 22 17:08:24 2013
@@ -67,6 +67,9 @@ public:
/// \brief Set Ordinals for all the InputElements that form the InputGraph
virtual bool assignOrdinals();
+ /// Normalize the InputGraph.
+ virtual void normalize();
+
/// Destructor
virtual ~InputGraph() {}
@@ -131,6 +134,13 @@ public:
File // Represents a type associated with File Nodes
};
+ /// How does the inputGraph expand the InputElement
+ enum class ExpandType : uint8_t {
+ None, // Do nothing(Default)
+ ReplaceAndExpand, // Replace current node and expand
+ ExpandOnly // Expand the current node
+ };
+
/// \brief Initialize the Input Element, The ordinal value of an input Element
/// is initially set to -1, if the user wants to override its ordinal,
/// let the user do it
@@ -175,6 +185,16 @@ public:
/// \brief Reset the next index
virtual void resetNextIndex() = 0;
+ /// Normalize functions
+
+ /// \brief How do we want to expand the current node ?
+ virtual ExpandType expandType() const { return ExpandType::None; }
+
+ /// \brief Get the elements that we want to expand with.
+ virtual range<InputGraph::InputElementIterT> expandElements() {
+ llvm_unreachable("no element to expand");
+ }
+
protected:
Kind _kind; // The type of the Element
int64_t _ordinal; // The ordinal value
Modified: lld/trunk/lib/Core/InputGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/InputGraph.cpp?rev=195515&r1=195514&r2=195515&view=diff
==============================================================================
--- lld/trunk/lib/Core/InputGraph.cpp (original)
+++ lld/trunk/lib/Core/InputGraph.cpp Fri Nov 22 17:08:24 2013
@@ -86,6 +86,38 @@ error_code InputGraph::setNextElementInd
return error_code::success();
}
+// Normalize the InputGraph.
+void InputGraph::normalize() {
+ auto iterb = _inputArgs.begin();
+ auto itere = _inputArgs.end();
+ auto currentIter = _inputArgs.begin();
+ bool replaceCurrentNode = false;
+ bool expand = false;
+
+ std::vector<std::unique_ptr<InputElement> > _workInputArgs;
+ while (iterb != itere) {
+ replaceCurrentNode = false;
+ expand = false;
+ InputElement::ExpandType expandType = (*iterb)->expandType();
+ if (expandType == InputElement::ExpandType::ReplaceAndExpand) {
+ replaceCurrentNode = true;
+ expand = true;
+ } else if (expandType == InputElement::ExpandType::ExpandOnly) {
+ replaceCurrentNode = false;
+ expand = true;
+ }
+ currentIter = iterb++;
+ if (expand)
+ _workInputArgs.insert(
+ _workInputArgs.end(),
+ std::make_move_iterator((*currentIter)->expandElements().begin()),
+ std::make_move_iterator((*currentIter)->expandElements().end()));
+ if (!replaceCurrentNode)
+ _workInputArgs.push_back(std::move(*currentIter));
+ }
+ _inputArgs = std::move(_workInputArgs);
+}
+
/// InputElement
/// \brief Initialize the Input Element, The ordinal value of an input Element
Modified: lld/trunk/unittests/DriverTests/InputGraphTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/InputGraphTest.cpp?rev=195515&r1=195514&r2=195515&view=diff
==============================================================================
--- lld/trunk/unittests/DriverTests/InputGraphTest.cpp (original)
+++ lld/trunk/unittests/DriverTests/InputGraphTest.cpp Fri Nov 22 17:08:24 2013
@@ -78,6 +78,44 @@ public:
}
};
+class MyExpandFileNode : public FileNode {
+public:
+ MyExpandFileNode(StringRef path, int64_t ordinal, ExpandType expandType)
+ : FileNode(path, ordinal), _expandType(expandType) {}
+
+ bool validate() { return true; }
+
+ bool dump(raw_ostream &) { return true; }
+
+ virtual error_code parse(const LinkingContext &, raw_ostream &) {
+ return error_code::success();
+ }
+
+ virtual ErrorOr<File &> getNextFile() {
+ if (_nextFileIndex == _files.size())
+ return make_error_code(InputGraphError::no_more_files);
+ return *_files[_nextFileIndex++];
+ }
+
+ /// \brief How do we want to expand the current node ?
+ virtual ExpandType expandType() const { return _expandType; }
+
+ /// \brief Get the elements that we want to expand with.
+ virtual range<InputGraph::InputElementIterT> expandElements() {
+ return make_range(_expandElements.begin(), _expandElements.end());
+ }
+
+ /// Process the input Elemenet
+ virtual bool addElement(std::unique_ptr<InputElement> element) {
+ _expandElements.push_back(std::move(element));
+ return true;
+ }
+
+private:
+ InputGraph::InputElementVectorT _expandElements;
+ ExpandType _expandType;
+};
+
class MyObjFile : public SimpleFile {
public:
MyObjFile(LinkingContext &context, StringRef path)
@@ -362,4 +400,154 @@ TEST_F(InputGraphTest, AddNodeWithGroupI
EXPECT_NE(InputGraphError::no_more_files, error_code(objfile));
EXPECT_EQ("group_objfile2", (*objfile).path());
}
+
+// Node expansion tests.
+TEST_F(InputGraphTest, ExpandInputGraphNode) {
+ std::unique_ptr<MyFileNode> myfile(new MyFileNode("multi_files1", 0));
+ std::vector<std::unique_ptr<File> > objfiles;
+ std::unique_ptr<MyObjFile> obj1(new MyObjFile(_context, "objfile1"));
+ std::unique_ptr<MyObjFile> obj2(new MyObjFile(_context, "objfile2"));
+ objfiles.push_back(std::move(obj1));
+ objfiles.push_back(std::move(obj2));
+ myfile->addFiles(std::move(objfiles));
+ EXPECT_EQ(true, inputGraph().addInputElement(std::move(myfile)));
+ objfiles.clear();
+
+ std::unique_ptr<MyExpandFileNode> expandFile(new MyExpandFileNode(
+ "expand_node", 1, InputElement::ExpandType::ExpandOnly));
+
+ std::unique_ptr<MyFileNode> filenode1(new MyFileNode("expand_file1", 2));
+ std::unique_ptr<MyObjFile> obj3(new MyObjFile(_context, "objfile3"));
+ objfiles.push_back(std::move(obj3));
+ filenode1->addFiles(std::move(objfiles));
+ expandFile->addElement(std::move(filenode1));
+ objfiles.clear();
+
+ std::unique_ptr<MyFileNode> filenode2(new MyFileNode("expand_file2", 3));
+ std::unique_ptr<MyObjFile> obj4(new MyObjFile(_context, "objfile4"));
+ objfiles.push_back(std::move(obj4));
+ filenode2->addFiles(std::move(objfiles));
+ expandFile->addElement(std::move(filenode2));
+ objfiles.clear();
+
+ // Add expand file to InputGraph
+ EXPECT_EQ(true, inputGraph().addInputElement(std::move(expandFile)));
+
+ std::unique_ptr<MyFileNode> filenode3(new MyFileNode("obj_after_expand", 4));
+ std::unique_ptr<MyObjFile> obj5(new MyObjFile(_context, "objfile5"));
+ std::unique_ptr<MyObjFile> obj6(new MyObjFile(_context, "objfile6"));
+ objfiles.push_back(std::move(obj5));
+ objfiles.push_back(std::move(obj6));
+ filenode3->addFiles(std::move(objfiles));
+
+ // Add an extra obj after the expand node
+ EXPECT_EQ(true, inputGraph().addInputElement(std::move(filenode3)));
+
+ inputGraph().normalize();
+
+ ErrorOr<InputElement *> nextElement = inputGraph().getNextInputElement();
+ EXPECT_NE(InputGraphError::no_more_elements, error_code(nextElement));
+ EXPECT_EQ(InputElement::Kind::File, (*nextElement)->kind());
+ FileNode *fileNode = llvm::dyn_cast<FileNode>(*nextElement);
+ EXPECT_EQ("multi_files1", (*fileNode).getUserPath());
+
+ nextElement = inputGraph().getNextInputElement();
+ EXPECT_NE(InputGraphError::no_more_elements, error_code(nextElement));
+ EXPECT_EQ(InputElement::Kind::File, (*nextElement)->kind());
+ fileNode = llvm::dyn_cast<FileNode>(*nextElement);
+ EXPECT_EQ("expand_file1", (*fileNode).getUserPath());
+
+ nextElement = inputGraph().getNextInputElement();
+ EXPECT_NE(InputGraphError::no_more_elements, error_code(nextElement));
+ EXPECT_EQ(InputElement::Kind::File, (*nextElement)->kind());
+ fileNode = llvm::dyn_cast<FileNode>(*nextElement);
+ EXPECT_EQ("expand_file2", (*fileNode).getUserPath());
+
+ nextElement = inputGraph().getNextInputElement();
+ EXPECT_NE(InputGraphError::no_more_elements, error_code(nextElement));
+ EXPECT_EQ(InputElement::Kind::File, (*nextElement)->kind());
+ fileNode = llvm::dyn_cast<FileNode>(*nextElement);
+ EXPECT_EQ("expand_node", (*fileNode).getUserPath());
+
+ nextElement = inputGraph().getNextInputElement();
+ EXPECT_NE(InputGraphError::no_more_elements, error_code(nextElement));
+ EXPECT_EQ(InputElement::Kind::File, (*nextElement)->kind());
+ fileNode = llvm::dyn_cast<FileNode>(*nextElement);
+ EXPECT_EQ("obj_after_expand", (*fileNode).getUserPath());
+
+ nextElement = inputGraph().getNextInputElement();
+ EXPECT_EQ(InputGraphError::no_more_elements, error_code(nextElement));
+}
+
+// Node expansion tests.
+TEST_F(InputGraphTest, ExpandAndReplaceInputGraphNode) {
+ std::unique_ptr<MyFileNode> myfile(new MyFileNode("multi_files1", 0));
+ std::vector<std::unique_ptr<File> > objfiles;
+ std::unique_ptr<MyObjFile> obj1(new MyObjFile(_context, "objfile1"));
+ std::unique_ptr<MyObjFile> obj2(new MyObjFile(_context, "objfile2"));
+ objfiles.push_back(std::move(obj1));
+ objfiles.push_back(std::move(obj2));
+ myfile->addFiles(std::move(objfiles));
+ EXPECT_EQ(true, inputGraph().addInputElement(std::move(myfile)));
+ objfiles.clear();
+
+ std::unique_ptr<MyExpandFileNode> expandFile(new MyExpandFileNode(
+ "expand_node", 1, InputElement::ExpandType::ReplaceAndExpand));
+
+ std::unique_ptr<MyFileNode> filenode1(new MyFileNode("expand_file1", 2));
+ std::unique_ptr<MyObjFile> obj3(new MyObjFile(_context, "objfile3"));
+ objfiles.push_back(std::move(obj3));
+ filenode1->addFiles(std::move(objfiles));
+ expandFile->addElement(std::move(filenode1));
+ objfiles.clear();
+
+ std::unique_ptr<MyFileNode> filenode2(new MyFileNode("expand_file2", 3));
+ std::unique_ptr<MyObjFile> obj4(new MyObjFile(_context, "objfile4"));
+ objfiles.push_back(std::move(obj4));
+ filenode2->addFiles(std::move(objfiles));
+ expandFile->addElement(std::move(filenode2));
+ objfiles.clear();
+
+ // Add expand file to InputGraph
+ EXPECT_EQ(true, inputGraph().addInputElement(std::move(expandFile)));
+
+ std::unique_ptr<MyFileNode> filenode3(new MyFileNode("obj_after_expand", 4));
+ std::unique_ptr<MyObjFile> obj5(new MyObjFile(_context, "objfile5"));
+ std::unique_ptr<MyObjFile> obj6(new MyObjFile(_context, "objfile6"));
+ objfiles.push_back(std::move(obj5));
+ objfiles.push_back(std::move(obj6));
+ filenode3->addFiles(std::move(objfiles));
+
+ // Add an extra obj after the expand node
+ EXPECT_EQ(true, inputGraph().addInputElement(std::move(filenode3)));
+
+ inputGraph().normalize();
+
+ ErrorOr<InputElement *> nextElement = inputGraph().getNextInputElement();
+ EXPECT_NE(InputGraphError::no_more_elements, error_code(nextElement));
+ EXPECT_EQ(InputElement::Kind::File, (*nextElement)->kind());
+ FileNode *fileNode = llvm::dyn_cast<FileNode>(*nextElement);
+ EXPECT_EQ("multi_files1", (*fileNode).getUserPath());
+
+ nextElement = inputGraph().getNextInputElement();
+ EXPECT_NE(InputGraphError::no_more_elements, error_code(nextElement));
+ EXPECT_EQ(InputElement::Kind::File, (*nextElement)->kind());
+ fileNode = llvm::dyn_cast<FileNode>(*nextElement);
+ EXPECT_EQ("expand_file1", (*fileNode).getUserPath());
+
+ nextElement = inputGraph().getNextInputElement();
+ EXPECT_NE(InputGraphError::no_more_elements, error_code(nextElement));
+ EXPECT_EQ(InputElement::Kind::File, (*nextElement)->kind());
+ fileNode = llvm::dyn_cast<FileNode>(*nextElement);
+ EXPECT_EQ("expand_file2", (*fileNode).getUserPath());
+
+ nextElement = inputGraph().getNextInputElement();
+ EXPECT_NE(InputGraphError::no_more_elements, error_code(nextElement));
+ EXPECT_EQ(InputElement::Kind::File, (*nextElement)->kind());
+ fileNode = llvm::dyn_cast<FileNode>(*nextElement);
+ EXPECT_EQ("obj_after_expand", (*fileNode).getUserPath());
+
+ nextElement = inputGraph().getNextInputElement();
+ EXPECT_EQ(InputGraphError::no_more_elements, error_code(nextElement));
+}
}
More information about the llvm-commits
mailing list