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: CDT( (void)
|
0:28 Function Call: CDT( (void)
|
||||||
0:28 Function Call: CBT( (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
|
0:? Linker Objects
|
||||||
|
|
||||||
recurse2.frag
|
recurse2.frag
|
||||||
@ -141,11 +194,11 @@ Warning, version 330 is not yet complete; some version-specific features are pre
|
|||||||
Linked vertex stage:
|
Linked vertex stage:
|
||||||
|
|
||||||
ERROR: Linking vertex stage: Recursion detected:
|
ERROR: Linking vertex stage: Recursion detected:
|
||||||
DT( calling AT(
|
BT( calling CT(
|
||||||
ERROR: Linking vertex stage: Recursion detected:
|
ERROR: Linking vertex stage: Recursion detected:
|
||||||
AT( calling BT(
|
AT( calling BT(
|
||||||
ERROR: Linking vertex stage: Recursion detected:
|
ERROR: Linking vertex stage: Recursion detected:
|
||||||
BT( calling CT(
|
DT( calling AT(
|
||||||
ERROR: Linking vertex stage: Recursion detected:
|
ERROR: Linking vertex stage: Recursion detected:
|
||||||
D( calling A(
|
D( calling A(
|
||||||
ERROR: Linking vertex stage: Recursion detected:
|
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: CDT( (void)
|
0:28 Function Call: CDT( (void)
|
||||||
0:28 Function Call: CBT( (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 Definition: cbar(i1; (float)
|
||||||
0:9 Function Parameters:
|
0:9 Function Parameters:
|
||||||
0:9 '' (in int)
|
0:9 '' (in int)
|
||||||
|
@ -26,3 +26,23 @@ void CBT();
|
|||||||
void CDT();
|
void CDT();
|
||||||
void CAT() { CBT(); CBT(); CBT(); }
|
void CAT() { CBT(); CBT(); CBT(); }
|
||||||
void CCT() { CDT(); CDT(); 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.
|
// Reset everything, once.
|
||||||
for (TGraph::iterator call = callGraph.begin(); call != callGraph.end(); ++call) {
|
for (TGraph::iterator call = callGraph.begin(); call != callGraph.end(); ++call) {
|
||||||
call->visited = false;
|
call->visited = false;
|
||||||
call->subGraph = false;
|
call->currentPath = false;
|
||||||
call->errorGiven = false;
|
call->errorGiven = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,42 +284,49 @@ void TIntermediate::checkCallGraphCycles(TInfoSink& infoSink)
|
|||||||
|
|
||||||
// Otherwise, we found a new subgraph, process it:
|
// Otherwise, we found a new subgraph, process it:
|
||||||
// See what all can be reached by this new root, and if any of
|
// 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,
|
// that is recursive. This is done by depth-first traversals, seeing
|
||||||
// and if a new call is found that is already active, we looped,
|
// if a new call is found that was already in the currentPath (a back edge),
|
||||||
// thereby detecting recursion.
|
// thereby detecting recursion.
|
||||||
std::list<TCall*> stack;
|
std::list<TCall*> stack;
|
||||||
|
newRoot->currentPath = true; // currentPath will be true iff it is on the stack
|
||||||
stack.push_back(newRoot);
|
stack.push_back(newRoot);
|
||||||
newRoot->subGraph = true;
|
|
||||||
while (! stack.empty()) {
|
while (! stack.empty()) {
|
||||||
// get a caller
|
// get a caller
|
||||||
TCall* call = stack.back();
|
TCall* call = stack.back();
|
||||||
stack.pop_back();
|
|
||||||
|
|
||||||
// Add to the stack all the callees of the last subgraph node popped from the stack.
|
// Add to the stack just one callee.
|
||||||
// This algorithm always terminates, because only subGraph == false causes a push
|
// This algorithm always terminates, because only ! visited and ! currentPath causes a push
|
||||||
// and all pushes change subGraph to true, and nothing changes subGraph to false.
|
// and all pushes change currentPath to true, and all pops change visited to true.
|
||||||
for (TGraph::iterator child = callGraph.begin(); child != callGraph.end(); ++child) {
|
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 (call->callee == child->caller) {
|
||||||
if (child->subGraph) {
|
if (child->currentPath) {
|
||||||
|
// Then, we found a back edge
|
||||||
if (! child->errorGiven) {
|
if (! child->errorGiven) {
|
||||||
error(infoSink, "Recursion detected:");
|
error(infoSink, "Recursion detected:");
|
||||||
infoSink.info << " " << call->callee << " calling " << child->callee << "\n";
|
infoSink.info << " " << call->callee << " calling " << child->callee << "\n";
|
||||||
child->errorGiven = true;
|
child->errorGiven = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
child->subGraph = true;
|
child->currentPath = true;
|
||||||
stack.push_back(&(*child));
|
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
|
} // 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
|
} while (newRoot); // redundant loop check; should always exit via the 'break' above
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,7 +164,7 @@ protected:
|
|||||||
TString caller;
|
TString caller;
|
||||||
TString callee;
|
TString callee;
|
||||||
bool visited;
|
bool visited;
|
||||||
bool subGraph;
|
bool currentPath;
|
||||||
bool errorGiven;
|
bool errorGiven;
|
||||||
};
|
};
|
||||||
typedef std::list<TCall> TGraph;
|
typedef std::list<TCall> TGraph;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user