[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