1 //
2 // Copyright (c) 2017 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/translator/IsASTDepthBelowLimit.h"
8 
9 #include "compiler/translator/IntermTraverse.h"
10 
11 namespace sh
12 {
13 
14 namespace
15 {
16 
17 // Traverse the tree and compute max depth. Takes a maximum depth limit to prevent stack overflow.
18 class MaxDepthTraverser : public TIntermTraverser
19 {
20   public:
MaxDepthTraverser(int depthLimit)21     MaxDepthTraverser(int depthLimit) : TIntermTraverser(true, true, false), mDepthLimit(depthLimit)
22     {
23     }
24 
visitBinary(Visit,TIntermBinary *)25     bool visitBinary(Visit, TIntermBinary *) override { return depthCheck(); }
visitUnary(Visit,TIntermUnary *)26     bool visitUnary(Visit, TIntermUnary *) override { return depthCheck(); }
visitTernary(Visit,TIntermTernary *)27     bool visitTernary(Visit, TIntermTernary *) override { return depthCheck(); }
visitSwizzle(Visit,TIntermSwizzle *)28     bool visitSwizzle(Visit, TIntermSwizzle *) override { return depthCheck(); }
visitIfElse(Visit,TIntermIfElse *)29     bool visitIfElse(Visit, TIntermIfElse *) override { return depthCheck(); }
visitAggregate(Visit,TIntermAggregate *)30     bool visitAggregate(Visit, TIntermAggregate *) override { return depthCheck(); }
visitBlock(Visit,TIntermBlock *)31     bool visitBlock(Visit, TIntermBlock *) override { return depthCheck(); }
visitLoop(Visit,TIntermLoop *)32     bool visitLoop(Visit, TIntermLoop *) override { return depthCheck(); }
visitBranch(Visit,TIntermBranch *)33     bool visitBranch(Visit, TIntermBranch *) override { return depthCheck(); }
34 
35   protected:
depthCheck() const36     bool depthCheck() const { return mMaxDepth < mDepthLimit; }
37 
38     int mDepthLimit;
39 };
40 
41 }  // anonymous namespace
42 
IsASTDepthBelowLimit(TIntermNode * root,int maxDepth)43 bool IsASTDepthBelowLimit(TIntermNode *root, int maxDepth)
44 {
45     MaxDepthTraverser traverser(maxDepth + 1);
46     root->traverse(&traverser);
47 
48     return traverser.getMaxDepth() <= maxDepth;
49 }
50 
51 }  // namespace sh
52