aboutsummaryrefslogtreecommitdiff
path: root/tools/llvmc2/CompilationGraph.cpp
diff options
context:
space:
mode:
authorMikhail Glushenkov <foldr@codedgers.com>2008-05-06 16:35:25 +0000
committerMikhail Glushenkov <foldr@codedgers.com>2008-05-06 16:35:25 +0000
commit0d08db03459b088a094d791c4a68b37d810c365c (patch)
tree18af7e9839706678bef174d28d856a62d5c5d5c5 /tools/llvmc2/CompilationGraph.cpp
parentaa4948f9924a001fb151608deb18ff11de362053 (diff)
Convert internal representation to use DAG. This gives us more flexibility and enables future improvements.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50724 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/llvmc2/CompilationGraph.cpp')
-rw-r--r--tools/llvmc2/CompilationGraph.cpp163
1 files changed, 135 insertions, 28 deletions
diff --git a/tools/llvmc2/CompilationGraph.cpp b/tools/llvmc2/CompilationGraph.cpp
index 36e5fc7c0a..bff1aa5627 100644
--- a/tools/llvmc2/CompilationGraph.cpp
+++ b/tools/llvmc2/CompilationGraph.cpp
@@ -14,46 +14,120 @@
#include "CompilationGraph.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/DOTGraphTraits.h"
+#include "llvm/Support/GraphWriter.h"
#include <stdexcept>
using namespace llvm;
+using namespace llvmcc;
extern cl::list<std::string> InputFilenames;
extern cl::opt<std::string> OutputFilename;
-int llvmcc::CompilationGraph::Build (const sys::Path& tempDir) const {
- sys::Path In(InputFilenames.at(0)), Out;
+CompilationGraph::CompilationGraph() {
+ NodesMap["root"] = Node(this);
+}
+
+Node& CompilationGraph::getNode(const std::string& ToolName) {
+ nodes_map_type::iterator I = NodesMap.find(ToolName);
+ if (I == NodesMap.end())
+ throw std::runtime_error("Node " + ToolName + " is not in graph");
+ return I->second;
+}
+
+const Node& CompilationGraph::getNode(const std::string& ToolName) const {
+ nodes_map_type::const_iterator I = NodesMap.find(ToolName);
+ if (I == NodesMap.end())
+ throw std::runtime_error("Node " + ToolName + " is not in graph!");
+ return I->second;
+}
- // Find out which language corresponds to the suffix of the first input file
- LanguageMap::const_iterator Lang = ExtsToLangs.find(In.getSuffix());
+const std::string& CompilationGraph::getLanguage(const sys::Path& File) const {
+ LanguageMap::const_iterator Lang = ExtsToLangs.find(File.getSuffix());
if (Lang == ExtsToLangs.end())
- throw std::runtime_error("Unknown suffix!");
+ throw std::runtime_error("Unknown suffix: " + File.getSuffix() + '!');
+ return Lang->second;
+}
+
+const CompilationGraph::tools_vector_type&
+CompilationGraph::getToolsVector(const std::string& LangName) const
+{
+ tools_map_type::const_iterator I = ToolsMap.find(LangName);
+ if (I == ToolsMap.end())
+ throw std::runtime_error("No tools corresponding to " + LangName
+ + " found!");
+ return I->second;
+}
+
+void CompilationGraph::insertVertex(const IntrusiveRefCntPtr<Tool> V) {
+ if (!NodesMap.count(V->Name())) {
+ Node N;
+ N.OwningGraph = this;
+ N.ToolPtr = V;
+ NodesMap[V->Name()] = N;
+ }
+}
+
+void CompilationGraph::insertEdge(const std::string& A,
+ const std::string& B) {
+ // TOTHINK: check this at compile-time?
+ if (B == "root")
+ throw std::runtime_error("Edges back to the root are not allowed!"
+ "Compilation graph should be acyclic!");
- // Find the toolchain corresponding to this language
- ToolChainMap::const_iterator ToolsIt = ToolChains.find(Lang->second);
- if (ToolsIt == ToolChains.end())
- throw std::runtime_error("Unknown language!");
- ToolChain Tools = ToolsIt->second;
+ if (A == "root") {
+ const Node& N = getNode(B);
+ const std::string& InputLanguage = N.ToolPtr->InputLanguage();
+ ToolsMap[InputLanguage].push_back(B);
+ // Needed to support iteration via GraphTraits.
+ NodesMap["root"].Children.push_back(B);
+ }
+ else {
+ Node& NA = getNode(A);
+ // Check that there is a node at B.
+ getNode(B);
+ NA.Children.push_back(B);
+ }
+}
+
+// TOFIX: extend, add an ability to choose between different
+// toolchains, support more interesting graph topologies.
+int CompilationGraph::Build (const sys::Path& tempDir) const {
PathVector JoinList;
+ const Tool* JoinTool = 0;
+ sys::Path In, Out;
+ // For each input file
for (cl::list<std::string>::const_iterator B = InputFilenames.begin(),
E = InputFilenames.end(); B != E; ++B) {
In = sys::Path(*B);
- // Pass input file through the toolchain
- for (ToolChain::const_iterator B = Tools.begin(), E = Tools.end();
- B != E; ++B) {
+ // Get to the head of the toolchain.
+ const tools_vector_type& TV = getToolsVector(getLanguage(In));
+ if(TV.empty())
+ throw std::runtime_error("Tool names vector is empty!");
+ const Node* N = &getNode(*TV.begin());
- const Tool* CurTool = B->getPtr();
+ // Pass it through the chain until we bump into a Join node or a
+ // node that says that it is the last.
+ bool Last = false;
+ while(!Last) {
+ const Tool* CurTool = N->ToolPtr.getPtr();
- // Is this the last step in the chain?
- if (llvm::next(B) == E || CurTool->IsLast()) {
+ if(CurTool->IsJoin()) {
JoinList.push_back(In);
+ JoinTool = CurTool;
break;
}
+
+ // Is this the last tool?
+ if (N->Children.empty() || CurTool->IsLast()) {
+ Out.appendComponent(In.getBasename());
+ Out.appendSuffix(CurTool->OutputSuffix());
+ Last = true;
+ }
else {
Out = tempDir;
Out.appendComponent(In.getBasename());
@@ -65,24 +139,57 @@ int llvmcc::CompilationGraph::Build (const sys::Path& tempDir) const {
if (CurTool->GenerateAction(In, Out).Execute() != 0)
throw std::runtime_error("Tool returned error code!");
+ N = &getNode(*N->Children.begin());
In = Out; Out.clear();
}
}
- // Pass .o files to linker
- const Tool* JoinNode = (--Tools.end())->getPtr();
+ if(JoinTool) {
+ // If the final output name is empty, set it to "a.out"
+ if (!OutputFilename.empty()) {
+ Out = sys::Path(OutputFilename);
+ }
+ else {
+ Out = sys::Path("a");
+ Out.appendSuffix(JoinTool->OutputSuffix());
+ }
- // If the final output name is empty, set it to "a.out"
- if (!OutputFilename.empty()) {
- Out = sys::Path(OutputFilename);
+ if (JoinTool->GenerateAction(JoinList, Out).Execute() != 0)
+ throw std::runtime_error("Tool returned error code!");
}
- else {
- Out = sys::Path("a");
- Out.appendSuffix(JoinNode->OutputSuffix());
+
+ return 0;
+}
+
+namespace llvm {
+ template <>
+ struct DOTGraphTraits<llvmcc::CompilationGraph*>
+ : public DefaultDOTGraphTraits
+ {
+
+ template<typename GraphType>
+ static std::string getNodeLabel(const Node* N, const GraphType&) {
+ if (N->ToolPtr)
+ return N->ToolPtr->Name();
+ else
+ return "root";
}
- if (JoinNode->GenerateAction(JoinList, Out).Execute() != 0)
- throw std::runtime_error("Tool returned error code!");
+ };
+}
- return 0;
+void CompilationGraph::writeGraph() {
+ std::ofstream O("CompilationGraph.dot");
+
+ if(O.good()) {
+ llvm::WriteGraph(this, "CompilationGraph");
+ O.close();
+ }
+ else {
+ throw std::runtime_error("");
+ }
+}
+
+void CompilationGraph::viewGraph() {
+ llvm::ViewGraph(this, "CompilationGraph");
}