1 | // |
---|---|
2 | // Copyright (c) 2016 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 | |
7 | #include "compiler/translator/tree_ops/RewriteUnaryMinusOperatorFloat.h" |
8 | |
9 | #include "compiler/translator/tree_util/IntermNode_util.h" |
10 | #include "compiler/translator/tree_util/IntermTraverse.h" |
11 | |
12 | namespace sh |
13 | { |
14 | |
15 | namespace |
16 | { |
17 | |
18 | class Traverser : public TIntermTraverser |
19 | { |
20 | public: |
21 | static void Apply(TIntermNode *root); |
22 | |
23 | private: |
24 | Traverser(); |
25 | bool visitUnary(Visit visit, TIntermUnary *node) override; |
26 | void nextIteration(); |
27 | |
28 | bool mFound = false; |
29 | }; |
30 | |
31 | // static |
32 | void Traverser::Apply(TIntermNode *root) |
33 | { |
34 | Traverser traverser; |
35 | do |
36 | { |
37 | traverser.nextIteration(); |
38 | root->traverse(&traverser); |
39 | if (traverser.mFound) |
40 | { |
41 | traverser.updateTree(); |
42 | } |
43 | } while (traverser.mFound); |
44 | } |
45 | |
46 | Traverser::Traverser() : TIntermTraverser(true, false, false) {} |
47 | |
48 | void Traverser::nextIteration() |
49 | { |
50 | mFound = false; |
51 | } |
52 | |
53 | bool Traverser::visitUnary(Visit visit, TIntermUnary *node) |
54 | { |
55 | if (mFound) |
56 | { |
57 | return false; |
58 | } |
59 | |
60 | // Detect if the current operator is unary minus operator. |
61 | if (node->getOp() != EOpNegative) |
62 | { |
63 | return true; |
64 | } |
65 | |
66 | // Detect if the current operand is a float variable. |
67 | TIntermTyped *fValue = node->getOperand(); |
68 | if (!fValue->getType().isScalarFloat()) |
69 | { |
70 | return true; |
71 | } |
72 | |
73 | // 0.0 - float |
74 | TIntermTyped *zero = CreateZeroNode(fValue->getType()); |
75 | zero->setLine(fValue->getLine()); |
76 | TIntermBinary *sub = new TIntermBinary(EOpSub, zero, fValue); |
77 | sub->setLine(fValue->getLine()); |
78 | |
79 | queueReplacement(sub, OriginalNode::IS_DROPPED); |
80 | |
81 | mFound = true; |
82 | return false; |
83 | } |
84 | |
85 | } // anonymous namespace |
86 | |
87 | void RewriteUnaryMinusOperatorFloat(TIntermNode *root) |
88 | { |
89 | Traverser::Apply(root); |
90 | } |
91 | |
92 | } // namespace sh |
93 |