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 | |
parent | b24380804cdaab8b2ecc044acf7ee239027b3094 (diff) |
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')
-rw-r--r-- | tools/llvmc/doc/LLVMC-Reference.rst | 12 | ||||
-rw-r--r-- | tools/llvmc/driver/CompilationGraph.cpp | 131 | ||||
-rw-r--r-- | tools/llvmc/driver/llvmc.cpp | 16 |
3 files changed, 155 insertions, 4 deletions
diff --git a/tools/llvmc/doc/LLVMC-Reference.rst b/tools/llvmc/doc/LLVMC-Reference.rst index 6189ec2182..1c0da18189 100644 --- a/tools/llvmc/doc/LLVMC-Reference.rst +++ b/tools/llvmc/doc/LLVMC-Reference.rst @@ -92,6 +92,10 @@ configuration libraries: * ``-v`` - Enable verbose mode, i.e. print out all executed commands. +* ``--check-graph`` - Check the compilation for common errors like + mismatched output/input language names, multiple default edges and + cycles. Hidden option, useful for debugging. + * ``--view-graph`` - Show a graphical representation of the compilation graph. Requires that you have ``dot`` and ``gv`` programs installed. Hidden option, useful for debugging. @@ -605,6 +609,14 @@ Ghostview_ are installed. There is also a ``--dump-graph`` option that creates a Graphviz source file (``compilation-graph.dot``) in the current directory. +Another useful option is ``--check-graph``. It checks the compilation +graph for common errors like mismatched output/input language names, +multiple default edges and cycles. These checks can't be performed at +compile-time because the plugins can load code dynamically. When +invoked with ``--check-graph``, ``llvmc`` doesn't perform any +compilation tasks and returns the number of encountered errors as its +status code. + .. _Graphviz: http://www.graphviz.org/ .. _Ghostview: http://pages.cs.wisc.edu/~ghost/ diff --git a/tools/llvmc/driver/CompilationGraph.cpp b/tools/llvmc/driver/CompilationGraph.cpp index 758268f79b..2c59ee6314 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 f3a1e57192..b295c633d9 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; } |