summaryrefslogtreecommitdiffstats
path: root/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/checkout/src/compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.cpp')
-rw-r--r--gfx/angle/checkout/src/compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.cpp74
1 files changed, 74 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.cpp
new file mode 100644
index 0000000000..55e2f8b971
--- /dev/null
+++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.cpp
@@ -0,0 +1,74 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.h"
+
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/tree_util/IntermNode_util.h"
+#include "compiler/translator/tree_util/IntermTraverse.h"
+
+namespace sh
+{
+
+namespace
+{
+
+// "x || y" is equivalent to "x ? true : y".
+TIntermTernary *UnfoldOR(TIntermTyped *x, TIntermTyped *y)
+{
+ return new TIntermTernary(x, CreateBoolNode(true), y);
+}
+
+// "x && y" is equivalent to "x ? y : false".
+TIntermTernary *UnfoldAND(TIntermTyped *x, TIntermTyped *y)
+{
+ return new TIntermTernary(x, y, CreateBoolNode(false));
+}
+
+// This traverser identifies all the short circuit binary nodes that need to
+// be replaced, and creates the corresponding replacement nodes. However,
+// the actual replacements happen after the traverse through updateTree().
+
+class UnfoldShortCircuitASTTraverser : public TIntermTraverser
+{
+ public:
+ UnfoldShortCircuitASTTraverser() : TIntermTraverser(true, false, false) {}
+
+ bool visitBinary(Visit visit, TIntermBinary *) override;
+};
+
+bool UnfoldShortCircuitASTTraverser::visitBinary(Visit visit, TIntermBinary *node)
+{
+ TIntermTernary *replacement = nullptr;
+
+ switch (node->getOp())
+ {
+ case EOpLogicalOr:
+ replacement = UnfoldOR(node->getLeft(), node->getRight());
+ break;
+ case EOpLogicalAnd:
+ replacement = UnfoldAND(node->getLeft(), node->getRight());
+ break;
+ default:
+ break;
+ }
+ if (replacement)
+ {
+ queueReplacement(replacement, OriginalNode::IS_DROPPED);
+ }
+ return true;
+}
+
+} // anonymous namespace
+
+bool UnfoldShortCircuitAST(TCompiler *compiler, TIntermBlock *root)
+{
+ UnfoldShortCircuitASTTraverser traverser;
+ root->traverse(&traverser);
+ return traverser.updateTree(compiler, root);
+}
+
+} // namespace sh