From f8c430b3da9a9f6ebd9fc070bf409435d65bb4f2 Mon Sep 17 00:00:00 2001 From: Mikhail Glushenkov Date: Fri, 9 Jan 2009 16:16:27 +0000 Subject: Add a --check-graph option to llvmc. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@61989 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/llvmc/driver/CompilationGraph.cpp | 131 ++++++++++++++++++++++++++++++++ tools/llvmc/driver/llvmc.cpp | 16 +++- 2 files changed, 143 insertions(+), 4 deletions(-) (limited to 'tools/llvmc/driver') 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 +#include +#include #include #include #include @@ -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 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 DryRun("dry-run", cl::desc("Only pretend to run commands")); cl::opt VerboseMode("v", cl::desc("Enable verbose mode")); + +cl::opt CheckGraph("check-graph", + cl::desc("Check the compilation graph for errors"), + cl::Hidden); cl::opt 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; } -- cgit v1.1