FoldExpressions.cpp (3330B)
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: 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 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