1//
2// Copyright (c) 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
19namespace sh
20{
21
22namespace
23{
24
25class FoldExpressionsTraverser : public TIntermTraverser
26{
27 public:
28 FoldExpressionsTraverser(TDiagnostics *diagnostics)
29 : TIntermTraverser(true, false, false), mDiagnostics(diagnostics), mDidReplace(false)
30 {}
31
32 bool didReplace() { return mDidReplace; }
33
34 void nextIteration() { mDidReplace = false; }
35
36 protected:
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
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
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
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
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
104void FoldExpressions(TIntermBlock *root, TDiagnostics *diagnostics)
105{
106 FoldExpressionsTraverser traverser(diagnostics);
107 do
108 {
109 traverser.nextIteration();
110 root->traverse(&traverser);
111 traverser.updateTree();
112 } while (traverser.didReplace());
113}
114
115} // namespace sh
116