Commit af5070f7 by Olli Etuaho Committed by Commit Bot

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/709194Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent c853804c
...@@ -2137,8 +2137,7 @@ bool OutputHLSL::visitSwitch(Visit visit, TIntermSwitch *node) ...@@ -2137,8 +2137,7 @@ bool OutputHLSL::visitSwitch(Visit visit, TIntermSwitch *node)
if (node->getStatementList()) if (node->getStatementList())
{ {
node->setStatementList( node->setStatementList(RemoveSwitchFallThrough(node->getStatementList()));
RemoveSwitchFallThrough::removeFallThrough(node->getStatementList()));
outputTriplet(out, visit, "switch (", ") ", ""); outputTriplet(out, visit, "switch (", ") ", "");
// The curly braces get written when visiting the statementList aggregate // The curly braces get written when visiting the statementList aggregate
} }
......
...@@ -3,15 +3,55 @@ ...@@ -3,15 +3,55 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // 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/RemoveSwitchFallThrough.h"
#include "compiler/translator/IntermTraverse.h"
namespace sh namespace sh
{ {
TIntermBlock *RemoveSwitchFallThrough::removeFallThrough(TIntermBlock *statementList) namespace
{
class RemoveSwitchFallThroughTraverser : public TIntermTraverser
{ {
RemoveSwitchFallThrough rm(statementList); 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); ASSERT(statementList);
statementList->traverse(&rm); statementList->traverse(&rm);
bool lastStatementWasBreak = rm.mLastStatementWasBreak; bool lastStatementWasBreak = rm.mLastStatementWasBreak;
...@@ -25,7 +65,7 @@ TIntermBlock *RemoveSwitchFallThrough::removeFallThrough(TIntermBlock *statement ...@@ -25,7 +65,7 @@ TIntermBlock *RemoveSwitchFallThrough::removeFallThrough(TIntermBlock *statement
return rm.mStatementListOut; return rm.mStatementListOut;
} }
RemoveSwitchFallThrough::RemoveSwitchFallThrough(TIntermBlock *statementList) RemoveSwitchFallThroughTraverser::RemoveSwitchFallThroughTraverser(TIntermBlock *statementList)
: TIntermTraverser(true, false, false), : TIntermTraverser(true, false, false),
mStatementList(statementList), mStatementList(statementList),
mLastStatementWasBreak(false), mLastStatementWasBreak(false),
...@@ -34,7 +74,7 @@ RemoveSwitchFallThrough::RemoveSwitchFallThrough(TIntermBlock *statementList) ...@@ -34,7 +74,7 @@ RemoveSwitchFallThrough::RemoveSwitchFallThrough(TIntermBlock *statementList)
mStatementListOut = new TIntermBlock(); 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 // Note that this assumes that switch statements which don't begin by a case statement
// have already been weeded out in validation. // have already been weeded out in validation.
...@@ -42,7 +82,7 @@ void RemoveSwitchFallThrough::visitSymbol(TIntermSymbol *node) ...@@ -42,7 +82,7 @@ void RemoveSwitchFallThrough::visitSymbol(TIntermSymbol *node)
mLastStatementWasBreak = false; 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 // Conditions of case labels are not traversed, so this is some other constant
// Could be just a statement like "0;" // Could be just a statement like "0;"
...@@ -50,35 +90,35 @@ void RemoveSwitchFallThrough::visitConstantUnion(TIntermConstantUnion *node) ...@@ -50,35 +90,35 @@ void RemoveSwitchFallThrough::visitConstantUnion(TIntermConstantUnion *node)
mLastStatementWasBreak = false; mLastStatementWasBreak = false;
} }
bool RemoveSwitchFallThrough::visitBinary(Visit, TIntermBinary *node) bool RemoveSwitchFallThroughTraverser::visitBinary(Visit, TIntermBinary *node)
{ {
mPreviousCase->getSequence()->push_back(node); mPreviousCase->getSequence()->push_back(node);
mLastStatementWasBreak = false; mLastStatementWasBreak = false;
return false; return false;
} }
bool RemoveSwitchFallThrough::visitUnary(Visit, TIntermUnary *node) bool RemoveSwitchFallThroughTraverser::visitUnary(Visit, TIntermUnary *node)
{ {
mPreviousCase->getSequence()->push_back(node); mPreviousCase->getSequence()->push_back(node);
mLastStatementWasBreak = false; mLastStatementWasBreak = false;
return false; return false;
} }
bool RemoveSwitchFallThrough::visitTernary(Visit, TIntermTernary *node) bool RemoveSwitchFallThroughTraverser::visitTernary(Visit, TIntermTernary *node)
{ {
mPreviousCase->getSequence()->push_back(node); mPreviousCase->getSequence()->push_back(node);
mLastStatementWasBreak = false; mLastStatementWasBreak = false;
return false; return false;
} }
bool RemoveSwitchFallThrough::visitIfElse(Visit, TIntermIfElse *node) bool RemoveSwitchFallThroughTraverser::visitIfElse(Visit, TIntermIfElse *node)
{ {
mPreviousCase->getSequence()->push_back(node); mPreviousCase->getSequence()->push_back(node);
mLastStatementWasBreak = false; mLastStatementWasBreak = false;
return false; return false;
} }
bool RemoveSwitchFallThrough::visitSwitch(Visit, TIntermSwitch *node) bool RemoveSwitchFallThroughTraverser::visitSwitch(Visit, TIntermSwitch *node)
{ {
mPreviousCase->getSequence()->push_back(node); mPreviousCase->getSequence()->push_back(node);
mLastStatementWasBreak = false; mLastStatementWasBreak = false;
...@@ -86,7 +126,7 @@ bool RemoveSwitchFallThrough::visitSwitch(Visit, TIntermSwitch *node) ...@@ -86,7 +126,7 @@ bool RemoveSwitchFallThrough::visitSwitch(Visit, TIntermSwitch *node)
return false; 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) for (size_t i = startIndex; i < sequence->size(); ++i)
{ {
...@@ -94,7 +134,7 @@ void RemoveSwitchFallThrough::outputSequence(TIntermSequence *sequence, size_t s ...@@ -94,7 +134,7 @@ void RemoveSwitchFallThrough::outputSequence(TIntermSequence *sequence, size_t s
} }
} }
void RemoveSwitchFallThrough::handlePreviousCase() void RemoveSwitchFallThroughTraverser::handlePreviousCase()
{ {
if (mPreviousCase) if (mPreviousCase)
mCasesSharingBreak.push_back(mPreviousCase); mCasesSharingBreak.push_back(mPreviousCase);
...@@ -129,7 +169,7 @@ void RemoveSwitchFallThrough::handlePreviousCase() ...@@ -129,7 +169,7 @@ void RemoveSwitchFallThrough::handlePreviousCase()
mPreviousCase = nullptr; mPreviousCase = nullptr;
} }
bool RemoveSwitchFallThrough::visitCase(Visit, TIntermCase *node) bool RemoveSwitchFallThroughTraverser::visitCase(Visit, TIntermCase *node)
{ {
handlePreviousCase(); handlePreviousCase();
mPreviousCase = new TIntermBlock(); mPreviousCase = new TIntermBlock();
...@@ -138,14 +178,14 @@ bool RemoveSwitchFallThrough::visitCase(Visit, TIntermCase *node) ...@@ -138,14 +178,14 @@ bool RemoveSwitchFallThrough::visitCase(Visit, TIntermCase *node)
return false; return false;
} }
bool RemoveSwitchFallThrough::visitAggregate(Visit, TIntermAggregate *node) bool RemoveSwitchFallThroughTraverser::visitAggregate(Visit, TIntermAggregate *node)
{ {
mPreviousCase->getSequence()->push_back(node); mPreviousCase->getSequence()->push_back(node);
mLastStatementWasBreak = false; mLastStatementWasBreak = false;
return false; return false;
} }
bool RemoveSwitchFallThrough::visitBlock(Visit, TIntermBlock *node) bool RemoveSwitchFallThroughTraverser::visitBlock(Visit, TIntermBlock *node)
{ {
if (node != mStatementList) if (node != mStatementList)
{ {
...@@ -156,14 +196,14 @@ bool RemoveSwitchFallThrough::visitBlock(Visit, TIntermBlock *node) ...@@ -156,14 +196,14 @@ bool RemoveSwitchFallThrough::visitBlock(Visit, TIntermBlock *node)
return true; return true;
} }
bool RemoveSwitchFallThrough::visitLoop(Visit, TIntermLoop *node) bool RemoveSwitchFallThroughTraverser::visitLoop(Visit, TIntermLoop *node)
{ {
mPreviousCase->getSequence()->push_back(node); mPreviousCase->getSequence()->push_back(node);
mLastStatementWasBreak = false; mLastStatementWasBreak = false;
return false; return false;
} }
bool RemoveSwitchFallThrough::visitBranch(Visit, TIntermBranch *node) bool RemoveSwitchFallThroughTraverser::visitBranch(Visit, TIntermBranch *node)
{ {
mPreviousCase->getSequence()->push_back(node); mPreviousCase->getSequence()->push_back(node);
// TODO: Verify that accepting return or continue statements here doesn't cause problems. // TODO: Verify that accepting return or continue statements here doesn't cause problems.
...@@ -171,4 +211,11 @@ bool RemoveSwitchFallThrough::visitBranch(Visit, TIntermBranch *node) ...@@ -171,4 +211,11 @@ bool RemoveSwitchFallThrough::visitBranch(Visit, TIntermBranch *node)
return false; return false;
} }
} // anonymous namespace
TIntermBlock *RemoveSwitchFallThrough(TIntermBlock *statementList)
{
return RemoveSwitchFallThroughTraverser::removeFallThrough(statementList);
}
} // namespace sh } // namespace sh
...@@ -3,47 +3,22 @@ ...@@ -3,47 +3,22 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
// RemoveSwitchFallThrough.h: 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.
#ifndef COMPILER_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_ #ifndef COMPILER_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_
#define COMPILER_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_ #define COMPILER_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_
#include "compiler/translator/IntermTraverse.h"
namespace sh namespace sh
{ {
class RemoveSwitchFallThrough : public TIntermTraverser class TIntermBlock;
{
public:
// When given a statementList from a switch AST node, return an updated
// statementList that has fall-through removed.
static TIntermBlock *removeFallThrough(TIntermBlock *statementList);
private:
RemoveSwitchFallThrough(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; // When given a statementList from a switch AST node, return an updated
TIntermBlock *mStatementListOut; // statementList that has fall-through removed.
bool mLastStatementWasBreak; TIntermBlock *RemoveSwitchFallThrough(TIntermBlock *statementList);
TIntermBlock *mPreviousCase;
std::vector<TIntermBlock *> mCasesSharingBreak;
};
} // namespace sh } // namespace sh
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment