1 //
2 // Copyright 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/gl/mac/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 ANGLE_NO_DISCARD static bool Apply(TCompiler *compiler, 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
Apply(TCompiler * compiler,TIntermNode * root)32 bool Traverser::Apply(TCompiler *compiler, TIntermNode *root)
33 {
34 Traverser traverser;
35 do
36 {
37 traverser.nextIteration();
38 root->traverse(&traverser);
39 if (traverser.mFound)
40 {
41 if (!traverser.updateTree(compiler, root))
42 {
43 return false;
44 }
45 }
46 } while (traverser.mFound);
47
48 return true;
49 }
50
Traverser()51 Traverser::Traverser() : TIntermTraverser(true, false, false) {}
52
nextIteration()53 void Traverser::nextIteration()
54 {
55 mFound = false;
56 }
57
visitUnary(Visit visit,TIntermUnary * node)58 bool Traverser::visitUnary(Visit visit, TIntermUnary *node)
59 {
60 if (mFound)
61 {
62 return false;
63 }
64
65 // Detect if the current operator is unary minus operator.
66 if (node->getOp() != EOpNegative)
67 {
68 return true;
69 }
70
71 // Detect if the current operand is a float variable.
72 TIntermTyped *fValue = node->getOperand();
73 if (!fValue->getType().isScalarFloat())
74 {
75 return true;
76 }
77
78 // 0.0 - float
79 TIntermTyped *zero = CreateZeroNode(fValue->getType());
80 zero->setLine(fValue->getLine());
81 TIntermBinary *sub = new TIntermBinary(EOpSub, zero, fValue);
82 sub->setLine(fValue->getLine());
83
84 queueReplacement(sub, OriginalNode::IS_DROPPED);
85
86 mFound = true;
87 return false;
88 }
89
90 } // anonymous namespace
91
RewriteUnaryMinusOperatorFloat(TCompiler * compiler,TIntermNode * root)92 bool RewriteUnaryMinusOperatorFloat(TCompiler *compiler, TIntermNode *root)
93 {
94 return Traverser::Apply(compiler, root);
95 }
96
97 } // namespace sh
98