1 //
2 // Copyright (c) 2002-2013 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/UnfoldShortCircuitAST.h"
8
9 namespace
10 {
11
12 // "x || y" is equivalent to "x ? true : y".
UnfoldOR(TIntermTyped * x,TIntermTyped * y)13 TIntermSelection *UnfoldOR(TIntermTyped *x, TIntermTyped *y)
14 {
15 const TType boolType(EbtBool, EbpUndefined);
16 ConstantUnion *u = new ConstantUnion;
17 u->setBConst(true);
18 TIntermConstantUnion *trueNode = new TIntermConstantUnion(
19 u, TType(EbtBool, EbpUndefined, EvqConst, 1));
20 return new TIntermSelection(x, trueNode, y, boolType);
21 }
22
23 // "x && y" is equivalent to "x ? y : false".
UnfoldAND(TIntermTyped * x,TIntermTyped * y)24 TIntermSelection *UnfoldAND(TIntermTyped *x, TIntermTyped *y)
25 {
26 const TType boolType(EbtBool, EbpUndefined);
27 ConstantUnion *u = new ConstantUnion;
28 u->setBConst(false);
29 TIntermConstantUnion *falseNode = new TIntermConstantUnion(
30 u, TType(EbtBool, EbpUndefined, EvqConst, 1));
31 return new TIntermSelection(x, y, falseNode, boolType);
32 }
33
34 } // namespace anonymous
35
visitBinary(Visit visit,TIntermBinary * node)36 bool UnfoldShortCircuitAST::visitBinary(Visit visit, TIntermBinary *node)
37 {
38 TIntermSelection *replacement = NULL;
39
40 switch (node->getOp())
41 {
42 case EOpLogicalOr:
43 replacement = UnfoldOR(node->getLeft(), node->getRight());
44 break;
45 case EOpLogicalAnd:
46 replacement = UnfoldAND(node->getLeft(), node->getRight());
47 break;
48 default:
49 break;
50 }
51 if (replacement)
52 {
53 replacements.push_back(
54 NodeUpdateEntry(getParentNode(), node, replacement));
55 }
56 return true;
57 }
58
updateTree()59 void UnfoldShortCircuitAST::updateTree()
60 {
61 for (size_t ii = 0; ii < replacements.size(); ++ii)
62 {
63 const NodeUpdateEntry& entry = replacements[ii];
64 ASSERT(entry.parent);
65 bool replaced = entry.parent->replaceChildNode(
66 entry.original, entry.replacement);
67 ASSERT(replaced);
68
69 // In AST traversing, a parent is visited before its children.
70 // After we replace a node, if an immediate child is to
71 // be replaced, we need to make sure we don't update the replaced
72 // node; instead, we update the replacement node.
73 for (size_t jj = ii + 1; jj < replacements.size(); ++jj)
74 {
75 NodeUpdateEntry& entry2 = replacements[jj];
76 if (entry2.parent == entry.original)
77 entry2.parent = entry.replacement;
78 }
79 }
80 }
81
82