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
12namespace sh
13{
14
15namespace
16{
17
18class 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
32void 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
46Traverser::Traverser() : TIntermTraverser(true, false, false) {}
47
48void Traverser::nextIteration()
49{
50 mFound = false;
51}
52
53bool 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
87void RewriteUnaryMinusOperatorFloat(TIntermNode *root)
88{
89 Traverser::Apply(root);
90}
91
92} // namespace sh
93