Hash :
0e99b7a3
Author :
Date :
2018-01-12T12:05:48
Prevent changing AST expression type from outside TIntermNode classes now contain all the logic for setting node types. Changing the constant values of constant union nodes from outside is also not necessary anymore. BUG=angleproject:2267 TEST=angle_unittests Change-Id: Ic10d41b1e5f93152df440a655057591dc1b783b0 Reviewed-on: https://chromium-review.googlesource.com/863626 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
//
// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Implementation of evaluating unary integer variable bug workaround.
// See header for more info.
#include "compiler/translator/RewriteUnaryMinusOperatorInt.h"
#include "compiler/translator/IntermTraverse.h"
namespace sh
{
namespace
{
class Traverser : public TIntermTraverser
{
public:
static void Apply(TIntermNode *root);
private:
Traverser();
bool visitUnary(Visit visit, TIntermUnary *node) override;
void nextIteration();
bool mFound = false;
};
// static
void Traverser::Apply(TIntermNode *root)
{
Traverser traverser;
do
{
traverser.nextIteration();
root->traverse(&traverser);
if (traverser.mFound)
{
traverser.updateTree();
}
} while (traverser.mFound);
}
Traverser::Traverser() : TIntermTraverser(true, false, false)
{
}
void Traverser::nextIteration()
{
mFound = false;
}
bool Traverser::visitUnary(Visit visit, TIntermUnary *node)
{
if (mFound)
{
return false;
}
// Decide if the current unary operator is unary minus.
if (node->getOp() != EOpNegative)
{
return true;
}
// Decide if the current operand is an integer variable.
TIntermTyped *opr = node->getOperand();
if (!opr->getType().isScalarInt())
{
return true;
}
// Potential problem case detected, apply workaround: -(int) -> ~(int) + 1.
// ~(int)
TIntermUnary *bitwiseNot = new TIntermUnary(EOpBitwiseNot, opr);
bitwiseNot->setLine(opr->getLine());
// Constant 1 (or 1u)
TConstantUnion *one = new TConstantUnion();
if (opr->getType().getBasicType() == EbtInt)
{
one->setIConst(1);
}
else
{
one->setUConst(1u);
}
TIntermConstantUnion *oneNode =
new TIntermConstantUnion(one, TType(opr->getBasicType(), opr->getPrecision(), EvqConst));
oneNode->setLine(opr->getLine());
// ~(int) + 1
TIntermBinary *add = new TIntermBinary(EOpAdd, bitwiseNot, oneNode);
add->setLine(opr->getLine());
queueReplacement(add, OriginalNode::IS_DROPPED);
mFound = true;
return false;
}
} // anonymous namespace
void RewriteUnaryMinusOperatorInt(TIntermNode *root)
{
Traverser::Apply(root);
}
} // namespace sh