diff --git a/Test/baseResults/recurse1.vert.out b/Test/baseResults/recurse1.vert.out index 8c7cb8fe..c095a425 100644 --- a/Test/baseResults/recurse1.vert.out +++ b/Test/baseResults/recurse1.vert.out @@ -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) diff --git a/Test/recurse1.frag b/Test/recurse1.frag index 3b0ef45b..66b4c3fe 100644 --- a/Test/recurse1.frag +++ b/Test/recurse1.frag @@ -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 diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp index d37b078e..47d8cb1e 100644 --- a/glslang/MachineIndependent/linkValidate.cpp +++ b/glslang/MachineIndependent/linkValidate.cpp @@ -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 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 } diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index cdcf177d..7617d9e3 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -164,7 +164,7 @@ protected: TString caller; TString callee; bool visited; - bool subGraph; + bool currentPath; bool errorGiven; }; typedef std::list TGraph;