michael@0: // michael@0: // Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: // michael@0: michael@0: #ifndef COMPILER_DETECT_RECURSION_H_ michael@0: #define COMPILER_DETECT_RECURSION_H_ michael@0: michael@0: #include "GLSLANG/ShaderLang.h" michael@0: michael@0: #include michael@0: #include "compiler/intermediate.h" michael@0: #include "compiler/VariableInfo.h" michael@0: michael@0: class TInfoSink; michael@0: michael@0: // Traverses intermediate tree to detect function recursion. michael@0: class DetectCallDepth : public TIntermTraverser { michael@0: public: michael@0: enum ErrorCode { michael@0: kErrorMissingMain, michael@0: kErrorRecursion, michael@0: kErrorMaxDepthExceeded, michael@0: kErrorNone michael@0: }; michael@0: michael@0: DetectCallDepth(TInfoSink& infoSync, bool limitCallStackDepth, int maxCallStackDepth); michael@0: ~DetectCallDepth(); michael@0: michael@0: virtual bool visitAggregate(Visit, TIntermAggregate*); michael@0: michael@0: bool checkExceedsMaxDepth(int depth); michael@0: michael@0: ErrorCode detectCallDepth(); michael@0: michael@0: private: michael@0: class FunctionNode { michael@0: public: michael@0: static const int kInfiniteCallDepth = INT_MAX; michael@0: michael@0: FunctionNode(const TString& fname); michael@0: michael@0: const TString& getName() const; michael@0: michael@0: // If a function is already in the callee list, this becomes a no-op. michael@0: void addCallee(FunctionNode* callee); michael@0: michael@0: // Returns kInifinityCallDepth if recursive function calls are detected. michael@0: int detectCallDepth(DetectCallDepth* detectCallDepth, int depth); michael@0: michael@0: // Reset state. michael@0: void reset(); michael@0: michael@0: private: michael@0: // mangled function name is unique. michael@0: TString name; michael@0: michael@0: // functions that are directly called by this function. michael@0: TVector callees; michael@0: michael@0: Visit visit; michael@0: }; michael@0: michael@0: ErrorCode detectCallDepthForFunction(FunctionNode* func); michael@0: FunctionNode* findFunctionByName(const TString& name); michael@0: void resetFunctionNodes(); michael@0: michael@0: TInfoSink& getInfoSink() { return infoSink; } michael@0: michael@0: TVector functions; michael@0: FunctionNode* currentFunction; michael@0: TInfoSink& infoSink; michael@0: int maxDepth; michael@0: michael@0: DetectCallDepth(const DetectCallDepth&); michael@0: void operator=(const DetectCallDepth&); michael@0: }; michael@0: michael@0: #endif // COMPILER_DETECT_RECURSION_H_