forked from OSchip/llvm-project
[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. llvm-svn: 195515
This commit is contained in:
parent
c0845334da
commit
3ac09bcb8f
|
@ -67,6 +67,9 @@ public:
|
||||||
/// \brief Set Ordinals for all the InputElements that form the InputGraph
|
/// \brief Set Ordinals for all the InputElements that form the InputGraph
|
||||||
virtual bool assignOrdinals();
|
virtual bool assignOrdinals();
|
||||||
|
|
||||||
|
/// Normalize the InputGraph.
|
||||||
|
virtual void normalize();
|
||||||
|
|
||||||
/// Destructor
|
/// Destructor
|
||||||
virtual ~InputGraph() {}
|
virtual ~InputGraph() {}
|
||||||
|
|
||||||
|
@ -131,6 +134,13 @@ public:
|
||||||
File // Represents a type associated with File Nodes
|
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
|
/// \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,
|
/// is initially set to -1, if the user wants to override its ordinal,
|
||||||
/// let the user do it
|
/// let the user do it
|
||||||
|
@ -175,6 +185,16 @@ public:
|
||||||
/// \brief Reset the next index
|
/// \brief Reset the next index
|
||||||
virtual void resetNextIndex() = 0;
|
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:
|
protected:
|
||||||
Kind _kind; // The type of the Element
|
Kind _kind; // The type of the Element
|
||||||
int64_t _ordinal; // The ordinal value
|
int64_t _ordinal; // The ordinal value
|
||||||
|
|
|
@ -86,6 +86,38 @@ error_code InputGraph::setNextElementIndex(uint32_t index) {
|
||||||
return error_code::success();
|
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
|
/// InputElement
|
||||||
|
|
||||||
/// \brief Initialize the Input Element, The ordinal value of an input Element
|
/// \brief Initialize the Input Element, The ordinal value of an input Element
|
||||||
|
|
|
@ -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 {
|
class MyObjFile : public SimpleFile {
|
||||||
public:
|
public:
|
||||||
MyObjFile(LinkingContext &context, StringRef path)
|
MyObjFile(LinkingContext &context, StringRef path)
|
||||||
|
@ -362,4 +400,154 @@ TEST_F(InputGraphTest, AddNodeWithGroupIteration) {
|
||||||
EXPECT_NE(InputGraphError::no_more_files, error_code(objfile));
|
EXPECT_NE(InputGraphError::no_more_files, error_code(objfile));
|
||||||
EXPECT_EQ("group_objfile2", (*objfile).path());
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue