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/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