1 //
2 // Copyright 2002 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/tree_ops/gl/mac/UnfoldShortCircuitAST.h"
8 
9 #include "compiler/translator/IntermNode.h"
10 #include "compiler/translator/tree_util/IntermNode_util.h"
11 #include "compiler/translator/tree_util/IntermTraverse.h"
12 
13 namespace sh
14 {
15 
16 namespace
17 {
18 
19 // "x || y" is equivalent to "x ? true : y".
UnfoldOR(TIntermTyped * x,TIntermTyped * y)20 TIntermTernary *UnfoldOR(TIntermTyped *x, TIntermTyped *y)
21 {
22     return new TIntermTernary(x, CreateBoolNode(true), y);
23 }
24 
25 // "x && y" is equivalent to "x ? y : false".
UnfoldAND(TIntermTyped * x,TIntermTyped * y)26 TIntermTernary *UnfoldAND(TIntermTyped *x, TIntermTyped *y)
27 {
28     return new TIntermTernary(x, y, CreateBoolNode(false));
29 }
30 
31 // This traverser identifies all the short circuit binary  nodes that need to
32 // be replaced, and creates the corresponding replacement nodes. However,
33 // the actual replacements happen after the traverse through updateTree().
34 
35 class UnfoldShortCircuitASTTraverser : public TIntermTraverser
36 {
37   public:
UnfoldShortCircuitASTTraverser()38     UnfoldShortCircuitASTTraverser() : TIntermTraverser(true, false, false) {}
39 
40     bool visitBinary(Visit visit, TIntermBinary *) override;
41 };
42 
visitBinary(Visit visit,TIntermBinary * node)43 bool UnfoldShortCircuitASTTraverser::visitBinary(Visit visit, TIntermBinary *node)
44 {
45     TIntermTernary *replacement = nullptr;
46 
47     switch (node->getOp())
48     {
49         case EOpLogicalOr:
50             replacement = UnfoldOR(node->getLeft(), node->getRight());
51             break;
52         case EOpLogicalAnd:
53             replacement = UnfoldAND(node->getLeft(), node->getRight());
54             break;
55         default:
56             break;
57     }
58     if (replacement)
59     {
60         queueReplacement(replacement, OriginalNode::IS_DROPPED);
61     }
62     return true;
63 }
64 
65 }  // anonymous namespace
66 
UnfoldShortCircuitAST(TCompiler * compiler,TIntermBlock * root)67 bool UnfoldShortCircuitAST(TCompiler *compiler, TIntermBlock *root)
68 {
69     UnfoldShortCircuitASTTraverser traverser;
70     root->traverse(&traverser);
71     return traverser.updateTree(compiler, root);
72 }
73 
74 }  // namespace sh
75