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#ifndef COMPILER_DETECT_RECURSION_H_
8#define COMPILER_DETECT_RECURSION_H_
9
10#include <limits.h>
11#include "compiler/translator/IntermNode.h"
12#include "compiler/translator/VariableInfo.h"
13
14class TInfoSink;
15
16// Traverses intermediate tree to detect function recursion.
17class DetectCallDepth : public TIntermTraverser {
18public:
19    enum ErrorCode {
20        kErrorMissingMain,
21        kErrorRecursion,
22        kErrorMaxDepthExceeded,
23        kErrorNone
24    };
25
26    DetectCallDepth(TInfoSink& infoSync, bool limitCallStackDepth, int maxCallStackDepth);
27    ~DetectCallDepth();
28
29    virtual bool visitAggregate(Visit, TIntermAggregate*);
30
31    bool checkExceedsMaxDepth(int depth);
32
33    ErrorCode detectCallDepth();
34
35private:
36    class FunctionNode {
37    public:
38        static const int kInfiniteCallDepth = INT_MAX;
39
40        FunctionNode(const TString& fname);
41
42        const TString& getName() const;
43
44        // If a function is already in the callee list, this becomes a no-op.
45        void addCallee(FunctionNode* callee);
46
47        // Returns kInifinityCallDepth if recursive function calls are detected.
48        int detectCallDepth(DetectCallDepth* detectCallDepth, int depth);
49
50        // Reset state.
51        void reset();
52
53    private:
54        // mangled function name is unique.
55        TString name;
56
57        // functions that are directly called by this function.
58        TVector<FunctionNode*> callees;
59
60        Visit visit;
61    };
62
63    ErrorCode detectCallDepthForFunction(FunctionNode* func);
64    FunctionNode* findFunctionByName(const TString& name);
65    void resetFunctionNodes();
66
67    TInfoSink& getInfoSink() { return infoSink; }
68
69    TVector<FunctionNode*> functions;
70    FunctionNode* currentFunction;
71    TInfoSink& infoSink;
72    int maxDepth;
73
74    DetectCallDepth(const DetectCallDepth&);
75    void operator=(const DetectCallDepth&);
76};
77
78#endif  // COMPILER_DETECT_RECURSION_H_
79