aboutsummaryrefslogtreecommitdiffstats
path: root/tools/llvmc/driver
diff options
context:
space:
mode:
authorMikhail Glushenkov <foldr@codedgers.com>2009-01-09 16:16:27 +0000
committerMikhail Glushenkov <foldr@codedgers.com>2009-01-09 16:16:27 +0000
commitf8c430b3da9a9f6ebd9fc070bf409435d65bb4f2 (patch)
treea3d5dc61c2579b6e0eae1edafddc27bb96f00d87 /tools/llvmc/driver
parentb24380804cdaab8b2ecc044acf7ee239027b3094 (diff)
downloadexternal_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.cpp131
-rw-r--r--tools/llvmc/driver/llvmc.cpp16
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;
}