mirror of
https://github.com/KhronosGroup/glslang
synced 2024-11-09 12:00:05 +00:00
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:
parent
d492aafad7
commit
8cbd18ecaa
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -164,7 +164,7 @@ protected:
|
||||
TString caller;
|
||||
TString callee;
|
||||
bool visited;
|
||||
bool subGraph;
|
||||
bool currentPath;
|
||||
bool errorGiven;
|
||||
};
|
||||
typedef std::list<TCall> TGraph;
|
||||
|
Loading…
Reference in New Issue
Block a user