• 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 // RewriteRepeatedAssignToSwizzled.cpp: Rewrite expressions that assign an assignment to a swizzled
7 // vector, like:
8 //     v.x = z = expression;
9 // to:
10 //     z = expression;
11 //     v.x = z;
12 //
13 // Note that this doesn't handle some corner cases: expressions nested inside other expressions,
14 // inside loop headers, or inside if conditions.
15 
16 #include "compiler/translator/tree_ops/RewriteRepeatedAssignToSwizzled.h"
17 
18 #include "compiler/translator/tree_util/IntermNode_util.h"
19 #include "compiler/translator/tree_util/IntermTraverse.h"
20 
21 namespace sh
22 {
23 
24 namespace
25 {
26 
27 class RewriteAssignToSwizzledTraverser : public TIntermTraverser
28 {
29   public:
30     ANGLE_NO_DISCARD static bool rewrite(TCompiler *compiler, TIntermBlock *root);
31 
32   private:
33     RewriteAssignToSwizzledTraverser();
34 
35     bool visitBinary(Visit, TIntermBinary *node) override;
36 
37     void nextIteration();
38 
didRewrite()39     bool didRewrite() { return mDidRewrite; }
40 
41     bool mDidRewrite;
42 };
43 
44 // static
rewrite(TCompiler * compiler,TIntermBlock * root)45 bool RewriteAssignToSwizzledTraverser::rewrite(TCompiler *compiler, TIntermBlock *root)
46 {
47     RewriteAssignToSwizzledTraverser rewrite;
48     do
49     {
50         rewrite.nextIteration();
51         root->traverse(&rewrite);
52         if (!rewrite.updateTree(compiler, root))
53         {
54             return false;
55         }
56     } while (rewrite.didRewrite());
57 
58     return true;
59 }
60 
RewriteAssignToSwizzledTraverser()61 RewriteAssignToSwizzledTraverser::RewriteAssignToSwizzledTraverser()
62     : TIntermTraverser(true, false, false), mDidRewrite(false)
63 {}
64 
nextIteration()65 void RewriteAssignToSwizzledTraverser::nextIteration()
66 {
67     mDidRewrite = false;
68 }
69 
visitBinary(Visit,TIntermBinary * node)70 bool RewriteAssignToSwizzledTraverser::visitBinary(Visit, TIntermBinary *node)
71 {
72     TIntermBinary *rightBinary = node->getRight()->getAsBinaryNode();
73     TIntermBlock *parentBlock  = getParentNode()->getAsBlock();
74     if (parentBlock && node->isAssignment() && node->getLeft()->getAsSwizzleNode() && rightBinary &&
75         rightBinary->isAssignment())
76     {
77         TIntermSequence replacements;
78         replacements.push_back(rightBinary);
79         TIntermTyped *rightAssignmentTargetCopy = rightBinary->getLeft()->deepCopy();
80         TIntermBinary *lastAssign =
81             new TIntermBinary(EOpAssign, node->getLeft(), rightAssignmentTargetCopy);
82         replacements.push_back(lastAssign);
83         mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(parentBlock, node, replacements));
84         mDidRewrite = true;
85         return false;
86     }
87     return true;
88 }
89 
90 }  // anonymous namespace
91 
RewriteRepeatedAssignToSwizzled(TCompiler * compiler,TIntermBlock * root)92 bool RewriteRepeatedAssignToSwizzled(TCompiler *compiler, TIntermBlock *root)
93 {
94     return RewriteAssignToSwizzledTraverser::rewrite(compiler, root);
95 }
96 
97 }  // namespace sh
98