diff options
author | Mikhail Glushenkov <foldr@codedgers.com> | 2009-01-09 16:16:27 +0000 |
---|---|---|
committer | Mikhail Glushenkov <foldr@codedgers.com> | 2009-01-09 16:16:27 +0000 |
commit | f8c430b3da9a9f6ebd9fc070bf409435d65bb4f2 (patch) | |
tree | a3d5dc61c2579b6e0eae1edafddc27bb96f00d87 /tools/llvmc/driver | |
parent | b24380804cdaab8b2ecc044acf7ee239027b3094 (diff) | |
download | external_llvm-f8c430b3da9a9f6ebd9fc070bf409435d65bb4f2.zip external_llvm-f8c430b3da9a9f6ebd9fc070bf409435d65bb4f2.tar.gz external_llvm-f8c430b3da9a9f6ebd9fc070bf409435d65bb4f2.tar.bz2 |
Add a --check-graph option to llvmc.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@61989 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/llvmc/driver')
-rw-r--r-- | tools/llvmc/driver/CompilationGraph.cpp | 131 | ||||
-rw-r--r-- | tools/llvmc/driver/llvmc.cpp | 16 |
2 files changed, 143 insertions, 4 deletions
diff --git a/tools/llvmc/driver/CompilationGraph.cpp b/tools/llvmc/driver/CompilationGraph.cpp index 758268f..2c59ee6 100644 --- a/tools/llvmc/driver/CompilationGraph.cpp +++ b/tools/llvmc/driver/CompilationGraph.cpp @@ -20,6 +20,8 @@ #include "llvm/Support/GraphWriter.h" #include <algorithm> +#include <cstring> +#include <iostream> #include <iterator> #include <limits> #include <queue> @@ -333,6 +335,135 @@ int CompilationGraph::Build (const sys::Path& TempDir, return 0; } +int CompilationGraph::CheckLanguageNames() const { + int ret = 0; + // Check that names for output and input languages on all edges do match. + for (const_nodes_iterator B = this->NodesMap.begin(), + E = this->NodesMap.end(); B != E; ++B) { + + const Node & N1 = B->second; + if (N1.ToolPtr) { + for (Node::const_iterator EB = N1.EdgesBegin(), EE = N1.EdgesEnd(); + EB != EE; ++EB) { + const Node& N2 = this->getNode((*EB)->ToolName()); + + if (!N2.ToolPtr) { + ++ret; + std::cerr << "Error: there is an edge from '" << N1.ToolPtr->Name() + << "' back to the root!\n\n"; + continue; + } + + const char* OutLang = N1.ToolPtr->OutputLanguage(); + const char** InLangs = N2.ToolPtr->InputLanguages(); + bool eq = false; + for (;*InLangs; ++InLangs) { + if (std::strcmp(OutLang, *InLangs) == 0) { + eq = true; + break; + } + } + + if (!eq) { + ++ret; + std::cerr << "Error: Output->input language mismatch in the edge '" << + N1.ToolPtr->Name() << "' -> '" << N2.ToolPtr->Name() << "'!\n"; + + std::cerr << "Expected one of { "; + + InLangs = N2.ToolPtr->InputLanguages(); + for (;*InLangs; ++InLangs) { + std::cerr << '\'' << *InLangs << (*(InLangs+1) ? "', " : "'"); + } + + std::cerr << " }, but got '" << OutLang << "'!\n\n"; + } + + } + } + } + + return ret; +} + +int CompilationGraph::CheckMultipleDefaultEdges() const { + int ret = 0; + InputLanguagesSet Dummy; + + for (const_nodes_iterator B = this->NodesMap.begin(), + E = this->NodesMap.end(); B != E; ++B) { + const Node& N = B->second; + unsigned MaxWeight = 0; + + // Ignore the root node. + if (!N.ToolPtr) + continue; + + for (Node::const_iterator EB = N.EdgesBegin(), EE = N.EdgesEnd(); + EB != EE; ++EB) { + unsigned EdgeWeight = (*EB)->Weight(Dummy); + if (EdgeWeight > MaxWeight) { + MaxWeight = EdgeWeight; + } + else if (EdgeWeight == MaxWeight) { + ++ret; + std::cerr + << "Error: there are multiple maximal edges stemming from the '" + << N.ToolPtr->Name() << "' node!\n\n"; + break; + } + } + } + + return ret; +} + +int CompilationGraph::CheckCycles() { + unsigned deleted = 0; + std::queue<Node*> Q; + Q.push(&getNode("root")); + + while (!Q.empty()) { + Node* A = Q.front(); + Q.pop(); + ++deleted; + + for (Node::iterator EB = A->EdgesBegin(), EE = A->EdgesEnd(); + EB != EE; ++EB) { + Node* B = &getNode((*EB)->ToolName()); + B->DecrInEdges(); + if (B->HasNoInEdges()) + Q.push(B); + } + } + + if (deleted != NodesMap.size()) { + std::cerr << "Error: there are cycles in the compilation graph!\n" + << "Try inspecting the diagram produced by " + "'llvmc --view-graph'.\n\n"; + return 1; + } + + return 0; +} + + +int CompilationGraph::Check () { + // We try to catch as many errors as we can in one go. + int ret = 0; + + // Check that output/input language names match. + ret += this->CheckLanguageNames(); + + // Check for multiple default edges. + ret += this->CheckMultipleDefaultEdges(); + + // Check for cycles. + ret += this->CheckCycles(); + + return ret; +} + // Code related to graph visualization. namespace llvm { diff --git a/tools/llvmc/driver/llvmc.cpp b/tools/llvmc/driver/llvmc.cpp index f3a1e57..b295c63 100644 --- a/tools/llvmc/driver/llvmc.cpp +++ b/tools/llvmc/driver/llvmc.cpp @@ -45,6 +45,10 @@ cl::opt<bool> DryRun("dry-run", cl::desc("Only pretend to run commands")); cl::opt<bool> VerboseMode("v", cl::desc("Enable verbose mode")); + +cl::opt<bool> CheckGraph("check-graph", + cl::desc("Check the compilation graph for errors"), + cl::Hidden); cl::opt<bool> WriteGraph("write-graph", cl::desc("Write compilation-graph.dot file"), cl::Hidden); @@ -89,14 +93,18 @@ int main(int argc, char** argv) { Plugins.PopulateLanguageMap(langMap); Plugins.PopulateCompilationGraph(graph); - if (WriteGraph) { - graph.writeGraph(); - if (!ViewGraph) - return 0; + if (CheckGraph) { + return graph.Check(); } if (ViewGraph) { graph.viewGraph(); + if (!WriteGraph) + return 0; + } + + if (WriteGraph) { + graph.writeGraph(); return 0; } |