1 : //
2 : // Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
3 : // Use of this source code is governed by a BSD-style license that can be
4 : // found in the LICENSE file.
5 : //
6 :
7 : #include "compiler/DetectRecursion.h"
8 :
9 0 : DetectRecursion::FunctionNode::FunctionNode(const TString& fname)
10 : : name(fname),
11 0 : visit(PreVisit)
12 : {
13 0 : }
14 :
15 0 : const TString& DetectRecursion::FunctionNode::getName() const
16 : {
17 0 : return name;
18 : }
19 :
20 0 : void DetectRecursion::FunctionNode::addCallee(
21 : DetectRecursion::FunctionNode* callee)
22 : {
23 0 : for (size_t i = 0; i < callees.size(); ++i) {
24 0 : if (callees[i] == callee)
25 0 : return;
26 : }
27 0 : callees.push_back(callee);
28 : }
29 :
30 0 : bool DetectRecursion::FunctionNode::detectRecursion()
31 : {
32 0 : ASSERT(visit == PreVisit);
33 0 : visit = InVisit;
34 0 : for (size_t i = 0; i < callees.size(); ++i) {
35 0 : switch (callees[i]->visit) {
36 : case InVisit:
37 : // cycle detected, i.e., recursion detected.
38 0 : return true;
39 : case PostVisit:
40 0 : break;
41 : case PreVisit: {
42 0 : bool recursion = callees[i]->detectRecursion();
43 0 : if (recursion)
44 0 : return true;
45 0 : break;
46 : }
47 : default:
48 0 : UNREACHABLE();
49 : break;
50 : }
51 : }
52 0 : visit = PostVisit;
53 0 : return false;
54 : }
55 :
56 0 : DetectRecursion::DetectRecursion()
57 0 : : currentFunction(NULL)
58 : {
59 0 : }
60 :
61 0 : DetectRecursion::~DetectRecursion()
62 : {
63 0 : for (size_t i = 0; i < functions.size(); ++i)
64 0 : delete functions[i];
65 0 : }
66 :
67 0 : bool DetectRecursion::visitAggregate(Visit visit, TIntermAggregate* node)
68 : {
69 0 : switch (node->getOp())
70 : {
71 : case EOpPrototype:
72 : // Function declaration.
73 : // Don't add FunctionNode here because node->getName() is the
74 : // unmangled function name.
75 0 : break;
76 : case EOpFunction: {
77 : // Function definition.
78 0 : if (visit == PreVisit) {
79 0 : currentFunction = findFunctionByName(node->getName());
80 0 : if (currentFunction == NULL) {
81 0 : currentFunction = new FunctionNode(node->getName());
82 0 : functions.push_back(currentFunction);
83 : }
84 : }
85 0 : break;
86 : }
87 : case EOpFunctionCall: {
88 : // Function call.
89 0 : if (visit == PreVisit) {
90 0 : ASSERT(currentFunction != NULL);
91 0 : FunctionNode* func = findFunctionByName(node->getName());
92 0 : if (func == NULL) {
93 0 : func = new FunctionNode(node->getName());
94 0 : functions.push_back(func);
95 : }
96 0 : currentFunction->addCallee(func);
97 : }
98 0 : break;
99 : }
100 : default:
101 0 : break;
102 : }
103 0 : return true;
104 : }
105 :
106 0 : DetectRecursion::ErrorCode DetectRecursion::detectRecursion()
107 : {
108 0 : FunctionNode* main = findFunctionByName("main(");
109 0 : if (main == NULL)
110 0 : return kErrorMissingMain;
111 0 : if (main->detectRecursion())
112 0 : return kErrorRecursion;
113 0 : return kErrorNone;
114 : }
115 :
116 0 : DetectRecursion::FunctionNode* DetectRecursion::findFunctionByName(
117 : const TString& name)
118 : {
119 0 : for (size_t i = 0; i < functions.size(); ++i) {
120 0 : if (functions[i]->getName() == name)
121 0 : return functions[i];
122 : }
123 0 : return NULL;
124 : }
125 :
|