Home | History | Annotate | Download | only in compiler
      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".
     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".
     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 
     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 
     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