• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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