Hide RemoveSwitchFallThrough implementation in the .cpp file
This cleans up the API provided by RemoveSwitchFallThrough.h, and adds
documentation about caveats of RemoveSwitchFallThrough. This change is
pure refactoring without any functional changes.
BUG=angleproject:2177
TEST=angle_end2end_tests
Change-Id: I2646e4fe3b53130b07977823cb1344e5096f67e4
Reviewed-on: https://chromium-review.googlesource.com/709194
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/RemoveSwitchFallThrough.cpp b/src/compiler/translator/RemoveSwitchFallThrough.cpp
index 6c108a1..6abf7cd 100644
--- a/src/compiler/translator/RemoveSwitchFallThrough.cpp
+++ b/src/compiler/translator/RemoveSwitchFallThrough.cpp
@@ -3,15 +3,55 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
+// RemoveSwitchFallThrough.cpp: Remove fall-through from switch statements.
+// Note that it is unsafe to do further AST transformations on the AST generated
+// by this function. It leaves duplicate nodes in the AST making replacements
+// unreliable.
#include "compiler/translator/RemoveSwitchFallThrough.h"
+#include "compiler/translator/IntermTraverse.h"
+
namespace sh
{
-TIntermBlock *RemoveSwitchFallThrough::removeFallThrough(TIntermBlock *statementList)
+namespace
{
- RemoveSwitchFallThrough rm(statementList);
+
+class RemoveSwitchFallThroughTraverser : public TIntermTraverser
+{
+ public:
+ static TIntermBlock *removeFallThrough(TIntermBlock *statementList);
+
+ private:
+ RemoveSwitchFallThroughTraverser(TIntermBlock *statementList);
+
+ void visitSymbol(TIntermSymbol *node) override;
+ void visitConstantUnion(TIntermConstantUnion *node) override;
+ bool visitBinary(Visit, TIntermBinary *node) override;
+ bool visitUnary(Visit, TIntermUnary *node) override;
+ bool visitTernary(Visit visit, TIntermTernary *node) override;
+ bool visitIfElse(Visit visit, TIntermIfElse *node) override;
+ bool visitSwitch(Visit, TIntermSwitch *node) override;
+ bool visitCase(Visit, TIntermCase *node) override;
+ bool visitAggregate(Visit, TIntermAggregate *node) override;
+ bool visitBlock(Visit, TIntermBlock *node) override;
+ bool visitLoop(Visit, TIntermLoop *node) override;
+ bool visitBranch(Visit, TIntermBranch *node) override;
+
+ void outputSequence(TIntermSequence *sequence, size_t startIndex);
+ void handlePreviousCase();
+
+ TIntermBlock *mStatementList;
+ TIntermBlock *mStatementListOut;
+ bool mLastStatementWasBreak;
+ TIntermBlock *mPreviousCase;
+ std::vector<TIntermBlock *> mCasesSharingBreak;
+};
+
+TIntermBlock *RemoveSwitchFallThroughTraverser::removeFallThrough(TIntermBlock *statementList)
+{
+ RemoveSwitchFallThroughTraverser rm(statementList);
ASSERT(statementList);
statementList->traverse(&rm);
bool lastStatementWasBreak = rm.mLastStatementWasBreak;
@@ -25,7 +65,7 @@
return rm.mStatementListOut;
}
-RemoveSwitchFallThrough::RemoveSwitchFallThrough(TIntermBlock *statementList)
+RemoveSwitchFallThroughTraverser::RemoveSwitchFallThroughTraverser(TIntermBlock *statementList)
: TIntermTraverser(true, false, false),
mStatementList(statementList),
mLastStatementWasBreak(false),
@@ -34,7 +74,7 @@
mStatementListOut = new TIntermBlock();
}
-void RemoveSwitchFallThrough::visitSymbol(TIntermSymbol *node)
+void RemoveSwitchFallThroughTraverser::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.
@@ -42,7 +82,7 @@
mLastStatementWasBreak = false;
}
-void RemoveSwitchFallThrough::visitConstantUnion(TIntermConstantUnion *node)
+void RemoveSwitchFallThroughTraverser::visitConstantUnion(TIntermConstantUnion *node)
{
// Conditions of case labels are not traversed, so this is some other constant
// Could be just a statement like "0;"
@@ -50,35 +90,35 @@
mLastStatementWasBreak = false;
}
-bool RemoveSwitchFallThrough::visitBinary(Visit, TIntermBinary *node)
+bool RemoveSwitchFallThroughTraverser::visitBinary(Visit, TIntermBinary *node)
{
mPreviousCase->getSequence()->push_back(node);
mLastStatementWasBreak = false;
return false;
}
-bool RemoveSwitchFallThrough::visitUnary(Visit, TIntermUnary *node)
+bool RemoveSwitchFallThroughTraverser::visitUnary(Visit, TIntermUnary *node)
{
mPreviousCase->getSequence()->push_back(node);
mLastStatementWasBreak = false;
return false;
}
-bool RemoveSwitchFallThrough::visitTernary(Visit, TIntermTernary *node)
+bool RemoveSwitchFallThroughTraverser::visitTernary(Visit, TIntermTernary *node)
{
mPreviousCase->getSequence()->push_back(node);
mLastStatementWasBreak = false;
return false;
}
-bool RemoveSwitchFallThrough::visitIfElse(Visit, TIntermIfElse *node)
+bool RemoveSwitchFallThroughTraverser::visitIfElse(Visit, TIntermIfElse *node)
{
mPreviousCase->getSequence()->push_back(node);
mLastStatementWasBreak = false;
return false;
}
-bool RemoveSwitchFallThrough::visitSwitch(Visit, TIntermSwitch *node)
+bool RemoveSwitchFallThroughTraverser::visitSwitch(Visit, TIntermSwitch *node)
{
mPreviousCase->getSequence()->push_back(node);
mLastStatementWasBreak = false;
@@ -86,7 +126,7 @@
return false;
}
-void RemoveSwitchFallThrough::outputSequence(TIntermSequence *sequence, size_t startIndex)
+void RemoveSwitchFallThroughTraverser::outputSequence(TIntermSequence *sequence, size_t startIndex)
{
for (size_t i = startIndex; i < sequence->size(); ++i)
{
@@ -94,7 +134,7 @@
}
}
-void RemoveSwitchFallThrough::handlePreviousCase()
+void RemoveSwitchFallThroughTraverser::handlePreviousCase()
{
if (mPreviousCase)
mCasesSharingBreak.push_back(mPreviousCase);
@@ -129,7 +169,7 @@
mPreviousCase = nullptr;
}
-bool RemoveSwitchFallThrough::visitCase(Visit, TIntermCase *node)
+bool RemoveSwitchFallThroughTraverser::visitCase(Visit, TIntermCase *node)
{
handlePreviousCase();
mPreviousCase = new TIntermBlock();
@@ -138,14 +178,14 @@
return false;
}
-bool RemoveSwitchFallThrough::visitAggregate(Visit, TIntermAggregate *node)
+bool RemoveSwitchFallThroughTraverser::visitAggregate(Visit, TIntermAggregate *node)
{
mPreviousCase->getSequence()->push_back(node);
mLastStatementWasBreak = false;
return false;
}
-bool RemoveSwitchFallThrough::visitBlock(Visit, TIntermBlock *node)
+bool RemoveSwitchFallThroughTraverser::visitBlock(Visit, TIntermBlock *node)
{
if (node != mStatementList)
{
@@ -156,14 +196,14 @@
return true;
}
-bool RemoveSwitchFallThrough::visitLoop(Visit, TIntermLoop *node)
+bool RemoveSwitchFallThroughTraverser::visitLoop(Visit, TIntermLoop *node)
{
mPreviousCase->getSequence()->push_back(node);
mLastStatementWasBreak = false;
return false;
}
-bool RemoveSwitchFallThrough::visitBranch(Visit, TIntermBranch *node)
+bool RemoveSwitchFallThroughTraverser::visitBranch(Visit, TIntermBranch *node)
{
mPreviousCase->getSequence()->push_back(node);
// TODO: Verify that accepting return or continue statements here doesn't cause problems.
@@ -171,4 +211,11 @@
return false;
}
+} // anonymous namespace
+
+TIntermBlock *RemoveSwitchFallThrough(TIntermBlock *statementList)
+{
+ return RemoveSwitchFallThroughTraverser::removeFallThrough(statementList);
+}
+
} // namespace sh