summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/compiler/UnfoldShortCircuit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/compiler/UnfoldShortCircuit.cpp')
-rw-r--r--src/3rdparty/angle/src/compiler/UnfoldShortCircuit.cpp172
1 files changed, 172 insertions, 0 deletions
diff --git a/src/3rdparty/angle/src/compiler/UnfoldShortCircuit.cpp b/src/3rdparty/angle/src/compiler/UnfoldShortCircuit.cpp
new file mode 100644
index 0000000000..1782ebc90c
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/UnfoldShortCircuit.cpp
@@ -0,0 +1,172 @@
+//
+// Copyright (c) 2002-2012 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.
+//
+// UnfoldShortCircuit is an AST traverser to output short-circuiting operators as if-else statements.
+// The results are assigned to s# temporaries, which are used by the main translator instead of
+// the original expression.
+//
+
+#include "compiler/UnfoldShortCircuit.h"
+
+#include "compiler/InfoSink.h"
+#include "compiler/OutputHLSL.h"
+
+namespace sh
+{
+UnfoldShortCircuit::UnfoldShortCircuit(TParseContext &context, OutputHLSL *outputHLSL) : mContext(context), mOutputHLSL(outputHLSL)
+{
+ mTemporaryIndex = 0;
+}
+
+void UnfoldShortCircuit::traverse(TIntermNode *node)
+{
+ int rewindIndex = mTemporaryIndex;
+ node->traverse(this);
+ mTemporaryIndex = rewindIndex;
+}
+
+bool UnfoldShortCircuit::visitBinary(Visit visit, TIntermBinary *node)
+{
+ TInfoSinkBase &out = mOutputHLSL->getBodyStream();
+
+ switch (node->getOp())
+ {
+ case EOpLogicalOr:
+ // "x || y" is equivalent to "x ? true : y", which unfolds to "bool s; if(x) s = true; else s = y;",
+ // and then further simplifies down to "bool s = x; if(!s) s = y;".
+ {
+ int i = mTemporaryIndex;
+
+ out << "bool s" << i << ";\n";
+
+ out << "{\n";
+
+ mTemporaryIndex = i + 1;
+ node->getLeft()->traverse(this);
+ out << "s" << i << " = ";
+ mTemporaryIndex = i + 1;
+ node->getLeft()->traverse(mOutputHLSL);
+ out << ";\n";
+ out << "if(!s" << i << ")\n"
+ "{\n";
+ mTemporaryIndex = i + 1;
+ node->getRight()->traverse(this);
+ out << " s" << i << " = ";
+ mTemporaryIndex = i + 1;
+ node->getRight()->traverse(mOutputHLSL);
+ out << ";\n"
+ "}\n";
+
+ out << "}\n";
+
+ mTemporaryIndex = i + 1;
+ }
+ return false;
+ case EOpLogicalAnd:
+ // "x && y" is equivalent to "x ? y : false", which unfolds to "bool s; if(x) s = y; else s = false;",
+ // and then further simplifies down to "bool s = x; if(s) s = y;".
+ {
+ int i = mTemporaryIndex;
+
+ out << "bool s" << i << ";\n";
+
+ out << "{\n";
+
+ mTemporaryIndex = i + 1;
+ node->getLeft()->traverse(this);
+ out << "s" << i << " = ";
+ mTemporaryIndex = i + 1;
+ node->getLeft()->traverse(mOutputHLSL);
+ out << ";\n";
+ out << "if(s" << i << ")\n"
+ "{\n";
+ mTemporaryIndex = i + 1;
+ node->getRight()->traverse(this);
+ out << " s" << i << " = ";
+ mTemporaryIndex = i + 1;
+ node->getRight()->traverse(mOutputHLSL);
+ out << ";\n"
+ "}\n";
+
+ out << "}\n";
+
+ mTemporaryIndex = i + 1;
+ }
+ return false;
+ }
+
+ return true;
+}
+
+bool UnfoldShortCircuit::visitSelection(Visit visit, TIntermSelection *node)
+{
+ TInfoSinkBase &out = mOutputHLSL->getBodyStream();
+
+ // Unfold "b ? x : y" into "type s; if(b) s = x; else s = y;"
+ if (node->usesTernaryOperator())
+ {
+ int i = mTemporaryIndex;
+
+ out << mOutputHLSL->typeString(node->getType()) << " s" << i << ";\n";
+
+ mTemporaryIndex = i + 1;
+ node->getCondition()->traverse(this);
+ out << "if(";
+ mTemporaryIndex = i + 1;
+ node->getCondition()->traverse(mOutputHLSL);
+ out << ")\n"
+ "{\n";
+ mTemporaryIndex = i + 1;
+ node->getTrueBlock()->traverse(this);
+ out << " s" << i << " = ";
+ mTemporaryIndex = i + 1;
+ node->getTrueBlock()->traverse(mOutputHLSL);
+ out << ";\n"
+ "}\n"
+ "else\n"
+ "{\n";
+ mTemporaryIndex = i + 1;
+ node->getFalseBlock()->traverse(this);
+ out << " s" << i << " = ";
+ mTemporaryIndex = i + 1;
+ node->getFalseBlock()->traverse(mOutputHLSL);
+ out << ";\n"
+ "}\n";
+
+ mTemporaryIndex = i + 1;
+ }
+
+ return false;
+}
+
+bool UnfoldShortCircuit::visitLoop(Visit visit, TIntermLoop *node)
+{
+ int rewindIndex = mTemporaryIndex;
+
+ if (node->getInit())
+ {
+ node->getInit()->traverse(this);
+ }
+
+ if (node->getCondition())
+ {
+ node->getCondition()->traverse(this);
+ }
+
+ if (node->getExpression())
+ {
+ node->getExpression()->traverse(this);
+ }
+
+ mTemporaryIndex = rewindIndex;
+
+ return false;
+}
+
+int UnfoldShortCircuit::getNextTemporaryIndex()
+{
+ return mTemporaryIndex++;
+}
+}