summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@theqtcompany.com>2015-04-22 09:04:29 +0200
committerLiang Qi <liang.qi@theqtcompany.com>2015-04-22 09:25:54 +0200
commitaed5a7168354c6ae47687d20b4bd3f0adcc14f8e (patch)
treed2060479a7c12fdba8c1955e5d363754feffabb8 /src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp
parentd3d10cf23d61f4a011f1a7e9abdee1a92717e80f (diff)
parent628fa13ea4d6ff0e2e2ee76c9adfc78676de3c59 (diff)
Merge remote-tracking branch 'origin/5.5' into dev
Conflicts: src/corelib/statemachine/qstatemachine.cpp src/corelib/statemachine/qstatemachine_p.h src/gui/painting/qdrawhelper.cpp src/plugins/platforms/xcb/qxcbnativeinterface.cpp src/plugins/platforms/xcb/qxcbwindow.cpp src/plugins/platforms/xcb/qxcbwindow.h src/testlib/qtestblacklist.cpp src/tools/qdoc/node.cpp src/tools/qdoc/node.h tests/auto/gui/painting/qcolor/tst_qcolor.cpp Change-Id: I6c78b7b162001712d5774293f501b06b4ff32684
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp')
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp157
1 files changed, 157 insertions, 0 deletions
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp
new file mode 100644
index 0000000000..b278b53436
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp
@@ -0,0 +1,157 @@
+//
+// Copyright (c) 2002-2015 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/RemoveSwitchFallThrough.h"
+
+TIntermAggregate *RemoveSwitchFallThrough::removeFallThrough(TIntermAggregate *statementList)
+{
+ RemoveSwitchFallThrough rm(statementList);
+ ASSERT(statementList);
+ statementList->traverse(&rm);
+ bool lastStatementWasBreak = rm.mLastStatementWasBreak;
+ rm.mLastStatementWasBreak = true;
+ rm.handlePreviousCase();
+ if (!lastStatementWasBreak)
+ {
+ TIntermBranch *finalBreak = new TIntermBranch(EOpBreak, nullptr);
+ rm.mStatementListOut->getSequence()->push_back(finalBreak);
+ }
+ return rm.mStatementListOut;
+}
+
+RemoveSwitchFallThrough::RemoveSwitchFallThrough(TIntermAggregate *statementList)
+ : TIntermTraverser(true, false, false),
+ mStatementList(statementList),
+ mLastStatementWasBreak(false),
+ mPreviousCase(nullptr)
+{
+ mStatementListOut = new TIntermAggregate();
+ mStatementListOut->setOp(EOpSequence);
+}
+
+void RemoveSwitchFallThrough::visitSymbol(TIntermSymbol *node)
+{
+ // Note that this assumes that switch statements which don't begin by a case statement
+ // have already been weeded out in validation.
+ mPreviousCase->getSequence()->push_back(node);
+ mLastStatementWasBreak = false;
+}
+
+void RemoveSwitchFallThrough::visitConstantUnion(TIntermConstantUnion *node)
+{
+ // Conditions of case labels are not traversed, so this is some other constant
+ // Could be just a statement like "0;"
+ mPreviousCase->getSequence()->push_back(node);
+ mLastStatementWasBreak = false;
+}
+
+bool RemoveSwitchFallThrough::visitBinary(Visit, TIntermBinary *node)
+{
+ mPreviousCase->getSequence()->push_back(node);
+ mLastStatementWasBreak = false;
+ return false;
+}
+
+bool RemoveSwitchFallThrough::visitUnary(Visit, TIntermUnary *node)
+{
+ mPreviousCase->getSequence()->push_back(node);
+ mLastStatementWasBreak = false;
+ return false;
+}
+
+bool RemoveSwitchFallThrough::visitSelection(Visit, TIntermSelection *node)
+{
+ mPreviousCase->getSequence()->push_back(node);
+ mLastStatementWasBreak = false;
+ return false;
+}
+
+bool RemoveSwitchFallThrough::visitSwitch(Visit, TIntermSwitch *node)
+{
+ mPreviousCase->getSequence()->push_back(node);
+ mLastStatementWasBreak = false;
+ // Don't go into nested switch statements
+ return false;
+}
+
+void RemoveSwitchFallThrough::outputSequence(TIntermSequence *sequence, size_t startIndex)
+{
+ for (size_t i = startIndex; i < sequence->size(); ++i)
+ {
+ mStatementListOut->getSequence()->push_back(sequence->at(i));
+ }
+}
+
+void RemoveSwitchFallThrough::handlePreviousCase()
+{
+ if (mPreviousCase)
+ mCasesSharingBreak.push_back(mPreviousCase);
+ if (mLastStatementWasBreak)
+ {
+ bool labelsWithNoStatements = true;
+ for (size_t i = 0; i < mCasesSharingBreak.size(); ++i)
+ {
+ if (mCasesSharingBreak.at(i)->getSequence()->size() > 1)
+ {
+ labelsWithNoStatements = false;
+ }
+ if (labelsWithNoStatements)
+ {
+ // Fall-through is allowed in case the label has no statements.
+ outputSequence(mCasesSharingBreak.at(i)->getSequence(), 0);
+ }
+ else
+ {
+ // Include all the statements that this case can fall through under the same label.
+ for (size_t j = i; j < mCasesSharingBreak.size(); ++j)
+ {
+ size_t startIndex = j > i ? 1 : 0; // Add the label only from the first sequence.
+ outputSequence(mCasesSharingBreak.at(j)->getSequence(), startIndex);
+
+ }
+ }
+ }
+ mCasesSharingBreak.clear();
+ }
+ mLastStatementWasBreak = false;
+ mPreviousCase = nullptr;
+}
+
+bool RemoveSwitchFallThrough::visitCase(Visit, TIntermCase *node)
+{
+ handlePreviousCase();
+ mPreviousCase = new TIntermAggregate();
+ mPreviousCase->setOp(EOpSequence);
+ mPreviousCase->getSequence()->push_back(node);
+ // Don't traverse the condition of the case statement
+ return false;
+}
+
+bool RemoveSwitchFallThrough::visitAggregate(Visit, TIntermAggregate *node)
+{
+ if (node != mStatementList)
+ {
+ mPreviousCase->getSequence()->push_back(node);
+ mLastStatementWasBreak = false;
+ return false;
+ }
+ return true;
+}
+
+bool RemoveSwitchFallThrough::visitLoop(Visit, TIntermLoop *node)
+{
+ mPreviousCase->getSequence()->push_back(node);
+ mLastStatementWasBreak = false;
+ return false;
+}
+
+bool RemoveSwitchFallThrough::visitBranch(Visit, TIntermBranch *node)
+{
+ mPreviousCase->getSequence()->push_back(node);
+ // TODO: Verify that accepting return or continue statements here doesn't cause problems.
+ mLastStatementWasBreak = true;
+ return false;
+}