Fix recursion detection (it was detecting cycles in the call graph that were not directed cycles).

git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@23761 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
John Kessenich 2013-10-30 01:22:04 +00:00
parent d492aafad7
commit 8cbd18ecaa
4 changed files with 153 additions and 20 deletions

View File

@ -101,6 +101,59 @@ Warning, version 330 is not yet complete; some version-specific features are pre
0:28 Function Call: CDT( (void)
0:28 Function Call: CDT( (void)
0:28 Function Call: CBT( (void)
0:32 Function Definition: norA( (void)
0:32 Function Parameters:
0:33 Function Definition: norB( (void)
0:33 Function Parameters:
0:33 Sequence
0:33 Function Call: norA( (void)
0:34 Function Definition: norC( (void)
0:34 Function Parameters:
0:34 Sequence
0:34 Function Call: norA( (void)
0:35 Function Definition: norD( (void)
0:35 Function Parameters:
0:35 Sequence
0:35 Function Call: norA( (void)
0:36 Function Definition: norE( (void)
0:36 Function Parameters:
0:36 Sequence
0:36 Function Call: norB( (void)
0:37 Function Definition: norF( (void)
0:37 Function Parameters:
0:37 Sequence
0:37 Function Call: norB( (void)
0:38 Function Definition: norG( (void)
0:38 Function Parameters:
0:38 Sequence
0:38 Function Call: norE( (void)
0:39 Function Definition: norH( (void)
0:39 Function Parameters:
0:39 Sequence
0:39 Function Call: norE( (void)
0:40 Function Definition: norI( (void)
0:40 Function Parameters:
0:40 Sequence
0:40 Function Call: norE( (void)
0:44 Function Definition: norcA( (void)
0:44 Function Parameters:
0:45 Function Definition: norcB( (void)
0:45 Function Parameters:
0:45 Sequence
0:45 Function Call: norcA( (void)
0:46 Function Definition: norcC( (void)
0:46 Function Parameters:
0:46 Sequence
0:46 Function Call: norcB( (void)
0:47 Function Definition: norcD( (void)
0:47 Function Parameters:
0:47 Sequence
0:47 Function Call: norcC( (void)
0:47 Function Call: norcB( (void)
0:48 Function Definition: norcE( (void)
0:48 Function Parameters:
0:48 Sequence
0:48 Function Call: norcD( (void)
0:? Linker Objects
recurse2.frag
@ -141,11 +194,11 @@ Warning, version 330 is not yet complete; some version-specific features are pre
Linked vertex stage:
ERROR: Linking vertex stage: Recursion detected:
DT( calling AT(
BT( calling CT(
ERROR: Linking vertex stage: Recursion detected:
AT( calling BT(
ERROR: Linking vertex stage: Recursion detected:
BT( calling CT(
DT( calling AT(
ERROR: Linking vertex stage: Recursion detected:
D( calling A(
ERROR: Linking vertex stage: Recursion detected:
@ -194,6 +247,59 @@ ERROR: Linking fragment stage: Recursion detected:
0:28 Function Call: CDT( (void)
0:28 Function Call: CDT( (void)
0:28 Function Call: CBT( (void)
0:32 Function Definition: norA( (void)
0:32 Function Parameters:
0:33 Function Definition: norB( (void)
0:33 Function Parameters:
0:33 Sequence
0:33 Function Call: norA( (void)
0:34 Function Definition: norC( (void)
0:34 Function Parameters:
0:34 Sequence
0:34 Function Call: norA( (void)
0:35 Function Definition: norD( (void)
0:35 Function Parameters:
0:35 Sequence
0:35 Function Call: norA( (void)
0:36 Function Definition: norE( (void)
0:36 Function Parameters:
0:36 Sequence
0:36 Function Call: norB( (void)
0:37 Function Definition: norF( (void)
0:37 Function Parameters:
0:37 Sequence
0:37 Function Call: norB( (void)
0:38 Function Definition: norG( (void)
0:38 Function Parameters:
0:38 Sequence
0:38 Function Call: norE( (void)
0:39 Function Definition: norH( (void)
0:39 Function Parameters:
0:39 Sequence
0:39 Function Call: norE( (void)
0:40 Function Definition: norI( (void)
0:40 Function Parameters:
0:40 Sequence
0:40 Function Call: norE( (void)
0:44 Function Definition: norcA( (void)
0:44 Function Parameters:
0:45 Function Definition: norcB( (void)
0:45 Function Parameters:
0:45 Sequence
0:45 Function Call: norcA( (void)
0:46 Function Definition: norcC( (void)
0:46 Function Parameters:
0:46 Sequence
0:46 Function Call: norcB( (void)
0:47 Function Definition: norcD( (void)
0:47 Function Parameters:
0:47 Sequence
0:47 Function Call: norcC( (void)
0:47 Function Call: norcB( (void)
0:48 Function Definition: norcE( (void)
0:48 Function Parameters:
0:48 Sequence
0:48 Function Call: norcD( (void)
0:9 Function Definition: cbar(i1; (float)
0:9 Function Parameters:
0:9 '' (in int)

View File

@ -26,3 +26,23 @@ void CBT();
void CDT();
void CAT() { CBT(); CBT(); CBT(); }
void CCT() { CDT(); CDT(); CBT(); }
// not recursive
void norA() {}
void norB() { norA(); }
void norC() { norA(); }
void norD() { norA(); }
void norE() { norB(); }
void norF() { norB(); }
void norG() { norE(); }
void norH() { norE(); }
void norI() { norE(); }
// not recursive, but with a call leading into a cycle if ignoring direction
void norcA() { }
void norcB() { norcA(); }
void norcC() { norcB(); }
void norcD() { norcC(); norcB(); } // head of cycle
void norcE() { norcD(); } // lead into cycle

View File

@ -259,7 +259,7 @@ void TIntermediate::checkCallGraphCycles(TInfoSink& infoSink)
// Reset everything, once.
for (TGraph::iterator call = callGraph.begin(); call != callGraph.end(); ++call) {
call->visited = false;
call->subGraph = false;
call->currentPath = false;
call->errorGiven = false;
}
@ -284,42 +284,49 @@ void TIntermediate::checkCallGraphCycles(TInfoSink& infoSink)
// Otherwise, we found a new subgraph, process it:
// See what all can be reached by this new root, and if any of
// that is recursive. This is done by marking processed calls as active,
// and if a new call is found that is already active, we looped,
// that is recursive. This is done by depth-first traversals, seeing
// if a new call is found that was already in the currentPath (a back edge),
// thereby detecting recursion.
std::list<TCall*> stack;
newRoot->currentPath = true; // currentPath will be true iff it is on the stack
stack.push_back(newRoot);
newRoot->subGraph = true;
while (! stack.empty()) {
// get a caller
TCall* call = stack.back();
stack.pop_back();
// Add to the stack all the callees of the last subgraph node popped from the stack.
// This algorithm always terminates, because only subGraph == false causes a push
// and all pushes change subGraph to true, and nothing changes subGraph to false.
for (TGraph::iterator child = callGraph.begin(); child != callGraph.end(); ++child) {
// Add to the stack just one callee.
// This algorithm always terminates, because only ! visited and ! currentPath causes a push
// and all pushes change currentPath to true, and all pops change visited to true.
TGraph::iterator child = callGraph.begin();
for (; child != callGraph.end(); ++child) {
// If we already visited this node, its whole subgraph has already been processed, so skip it.
if (child->visited)
continue;
if (call->callee == child->caller) {
if (child->subGraph) {
if (child->currentPath) {
// Then, we found a back edge
if (! child->errorGiven) {
error(infoSink, "Recursion detected:");
infoSink.info << " " << call->callee << " calling " << child->callee << "\n";
child->errorGiven = true;
}
} else {
child->subGraph = true;
child->currentPath = true;
stack.push_back(&(*child));
break;
}
}
}
if (child == callGraph.end()) {
// no more callees, we bottomed out, never look at this node again
stack.back()->currentPath = false;
stack.back()->visited = true;
stack.pop_back();
}
} // end while, meaning nothing left to process in this subtree
// Mark all the subGraph nodes as visited, closing out this subgraph.
for (TGraph::iterator call = callGraph.begin(); call != callGraph.end(); ++call) {
if (call->subGraph)
call->visited = true;
}
} while (newRoot); // redundant loop check; should always exit via the 'break' above
}

View File

@ -164,7 +164,7 @@ protected:
TString caller;
TString callee;
bool visited;
bool subGraph;
bool currentPath;
bool errorGiven;
};
typedef std::list<TCall> TGraph;