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/translator/UnfoldShortCircuitAST.h" 8 9namespace 10{ 11 12// "x || y" is equivalent to "x ? true : y". 13TIntermSelection *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". 24TIntermSelection *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 36bool 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 59void 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