mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-28 22:24:28 +00:00
Add a --check-graph option to llvmc.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@61989 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -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 {
|
||||
|
Reference in New Issue
Block a user