• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2018 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 // FoldExpressions.cpp: Fold expressions. This may fold expressions so that the qualifier of the
7 // folded node differs from the qualifier of the original expression, so it needs to be done after
8 // parsing and validation of qualifiers is complete. Expressions that are folded:
9 //  1. Ternary ops with a constant condition.
10 //  2. Sequence aka comma ops where the left side has no side effects.
11 //  3. Any expressions containing any of the above.
12 
13 #include "compiler/translator/tree_ops/FoldExpressions.h"
14 
15 #include "compiler/translator/Diagnostics.h"
16 #include "compiler/translator/IntermNode.h"
17 #include "compiler/translator/tree_util/IntermTraverse.h"
18 
19 namespace sh
20 {
21 
22 namespace
23 {
24 
25 class FoldExpressionsTraverser : public TIntermTraverser
26 {
27   public:
FoldExpressionsTraverser(TDiagnostics * diagnostics)28     FoldExpressionsTraverser(TDiagnostics *diagnostics)
29         : TIntermTraverser(true, false, false), mDiagnostics(diagnostics), mDidReplace(false)
30     {}
31 
didReplace()32     bool didReplace() { return mDidReplace; }
33 
nextIteration()34     void nextIteration() { mDidReplace = false; }
35 
36   protected:
visitTernary(Visit visit,TIntermTernary * node)37     bool visitTernary(Visit visit, TIntermTernary *node) override
38     {
39         TIntermTyped *folded = node->fold(mDiagnostics);
40         if (folded != node)
41         {
42             queueReplacement(folded, OriginalNode::IS_DROPPED);
43             mDidReplace = true;
44             return false;
45         }
46         return true;
47     }
48 
visitAggregate(Visit visit,TIntermAggregate * node)49     bool visitAggregate(Visit visit, TIntermAggregate *node) override
50     {
51         TIntermTyped *folded = node->fold(mDiagnostics);
52         if (folded != node)
53         {
54             queueReplacement(folded, OriginalNode::IS_DROPPED);
55             mDidReplace = true;
56             return false;
57         }
58         return true;
59     }
60 
visitBinary(Visit visit,TIntermBinary * node)61     bool visitBinary(Visit visit, TIntermBinary *node) override
62     {
63         TIntermTyped *folded = node->fold(mDiagnostics);
64         if (folded != node)
65         {
66             queueReplacement(folded, OriginalNode::IS_DROPPED);
67             mDidReplace = true;
68             return false;
69         }
70         return true;
71     }
72 
visitUnary(Visit visit,TIntermUnary * node)73     bool visitUnary(Visit visit, TIntermUnary *node) override
74     {
75         TIntermTyped *folded = node->fold(mDiagnostics);
76         if (folded != node)
77         {
78             queueReplacement(folded, OriginalNode::IS_DROPPED);
79             mDidReplace = true;
80             return false;
81         }
82         return true;
83     }
84 
visitSwizzle(Visit visit,TIntermSwizzle * node)85     bool visitSwizzle(Visit visit, TIntermSwizzle *node) override
86     {
87         TIntermTyped *folded = node->fold(mDiagnostics);
88         if (folded != node)
89         {
90             queueReplacement(folded, OriginalNode::IS_DROPPED);
91             mDidReplace = true;
92             return false;
93         }
94         return true;
95     }
96 
97   private:
98     TDiagnostics *mDiagnostics;
99     bool mDidReplace;
100 };
101 
102 }  // anonymous namespace
103 
FoldExpressions(TCompiler * compiler,TIntermBlock * root,TDiagnostics * diagnostics)104 bool FoldExpressions(TCompiler *compiler, TIntermBlock *root, TDiagnostics *diagnostics)
105 {
106     FoldExpressionsTraverser traverser(diagnostics);
107     do
108     {
109         traverser.nextIteration();
110         root->traverse(&traverser);
111         if (!traverser.updateTree(compiler, root))
112         {
113             return false;
114         }
115     } while (traverser.didReplace());
116 
117     return true;
118 }
119 
120 }  // namespace sh
121