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