blob: 71e04d0eee3a2cbdacc40a1953c572a62fcbb3ad [file] [log] [blame]
Olli Etuaho765924f2018-01-04 12:48:36 +02001//
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/FoldExpressions.h"
14
15#include "compiler/translator/Diagnostics.h"
16#include "compiler/translator/IntermNode.h"
17#include "compiler/translator/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
33 bool didReplace() { return mDidReplace; }
34
35 void nextIteration() { mDidReplace = false; }
36
37 protected:
38 bool visitTernary(Visit visit, TIntermTernary *node) override
39 {
40 TIntermTyped *folded = node->fold(mDiagnostics);
41 if (folded != node)
42 {
43 queueReplacement(folded, OriginalNode::IS_DROPPED);
44 mDidReplace = true;
45 return false;
46 }
47 return true;
48 }
49
50 bool visitAggregate(Visit visit, TIntermAggregate *node) override
51 {
52 TIntermTyped *folded = node->fold(mDiagnostics);
53 if (folded != node)
54 {
55 queueReplacement(folded, OriginalNode::IS_DROPPED);
56 mDidReplace = true;
57 return false;
58 }
59 return true;
60 }
61
62 bool visitBinary(Visit visit, TIntermBinary *node) override
63 {
64 TIntermTyped *folded = node->fold(mDiagnostics);
65 if (folded != node)
66 {
67 queueReplacement(folded, OriginalNode::IS_DROPPED);
68 mDidReplace = true;
69 return false;
70 }
71 return true;
72 }
73
74 bool visitUnary(Visit visit, TIntermUnary *node) override
75 {
76 TIntermTyped *folded = node->fold(mDiagnostics);
77 if (folded != node)
78 {
79 queueReplacement(folded, OriginalNode::IS_DROPPED);
80 mDidReplace = true;
81 return false;
82 }
83 return true;
84 }
85
86 bool visitSwizzle(Visit visit, TIntermSwizzle *node) override
87 {
88 TIntermTyped *folded = node->fold(mDiagnostics);
89 if (folded != node)
90 {
91 queueReplacement(folded, OriginalNode::IS_DROPPED);
92 mDidReplace = true;
93 return false;
94 }
95 return true;
96 }
97
98 private:
99 TDiagnostics *mDiagnostics;
100 bool mDidReplace;
101};
102
103} // anonymous namespace
104
105void FoldExpressions(TIntermBlock *root, TDiagnostics *diagnostics)
106{
107 FoldExpressionsTraverser traverser(diagnostics);
108 do
109 {
110 traverser.nextIteration();
111 root->traverse(&traverser);
112 traverser.updateTree();
113 } while (traverser.didReplace());
114}
115
116} // namespace sh