Migrate `SwitchCaseContainsExit` out of SkSLAnalysis.
This CL also removes `SwitchCaseFallsThrough` entirely; it was
not referenced anywhere.
Change-Id: I58298bf2a603615e37f4cced9db6d2f4c2c54d5a
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/456473
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/gn/sksl.gni b/gn/sksl.gni
index 213e364..d4419ea 100644
--- a/gn/sksl.gni
+++ b/gn/sksl.gni
@@ -77,6 +77,8 @@
"$_src/sksl/SkSLStringStream.h",
"$_src/sksl/SkSLUtil.cpp",
"$_src/sksl/SkSLUtil.h",
+ "$_src/sksl/analysis/SkSLProgramVisitor.h",
+ "$_src/sksl/analysis/SwitchCaseContainsExit.cpp",
"$_src/sksl/codegen/SkSLVMCodeGenerator.cpp",
"$_src/sksl/codegen/SkSLVMCodeGenerator.h",
"$_src/sksl/dsl/DSLBlock.cpp",
diff --git a/src/sksl/SkSLAnalysis.cpp b/src/sksl/SkSLAnalysis.cpp
index 1751315..13c6e51 100644
--- a/src/sksl/SkSLAnalysis.cpp
+++ b/src/sksl/SkSLAnalysis.cpp
@@ -371,69 +371,6 @@
using INHERITED = ProgramVisitor;
};
-class SwitchCaseContainsExit : public ProgramVisitor {
-public:
- SwitchCaseContainsExit(bool conditionalExits) : fConditionalExits(conditionalExits) {}
-
- bool visitStatement(const Statement& stmt) override {
- switch (stmt.kind()) {
- case Statement::Kind::kBlock:
- case Statement::Kind::kSwitchCase:
- return INHERITED::visitStatement(stmt);
-
- case Statement::Kind::kReturn:
- // Returns are an early exit regardless of the surrounding control structures.
- return fConditionalExits ? fInConditional : !fInConditional;
-
- case Statement::Kind::kContinue:
- // Continues are an early exit from switches, but not loops.
- return !fInLoop &&
- (fConditionalExits ? fInConditional : !fInConditional);
-
- case Statement::Kind::kBreak:
- // Breaks cannot escape from switches or loops.
- return !fInLoop && !fInSwitch &&
- (fConditionalExits ? fInConditional : !fInConditional);
-
- case Statement::Kind::kIf: {
- ++fInConditional;
- bool result = INHERITED::visitStatement(stmt);
- --fInConditional;
- return result;
- }
-
- case Statement::Kind::kFor:
- case Statement::Kind::kDo: {
- // Loops are treated as conditionals because a loop could potentially execute zero
- // times. We don't have a straightforward way to determine that a loop definitely
- // executes at least once.
- ++fInConditional;
- ++fInLoop;
- bool result = INHERITED::visitStatement(stmt);
- --fInLoop;
- --fInConditional;
- return result;
- }
-
- case Statement::Kind::kSwitch: {
- ++fInSwitch;
- bool result = INHERITED::visitStatement(stmt);
- --fInSwitch;
- return result;
- }
-
- default:
- return false;
- }
- }
-
- bool fConditionalExits = false;
- int fInConditional = 0;
- int fInLoop = 0;
- int fInSwitch = 0;
- using INHERITED = ProgramVisitor;
-};
-
class ReturnsOnAllPathsVisitor : public ProgramVisitor {
public:
bool visitExpression(const Expression& expr) override {
@@ -826,14 +763,6 @@
return NodeCountVisitor{limit}.visit(*function.body());
}
-bool Analysis::SwitchCaseContainsUnconditionalExit(Statement& stmt) {
- return SwitchCaseContainsExit{/*conditionalExits=*/false}.visitStatement(stmt);
-}
-
-bool Analysis::SwitchCaseContainsConditionalExit(Statement& stmt) {
- return SwitchCaseContainsExit{/*conditionalExits=*/true}.visitStatement(stmt);
-}
-
std::unique_ptr<ProgramUsage> Analysis::GetUsage(const Program& program) {
auto usage = std::make_unique<ProgramUsage>();
ProgramUsageVisitor addRefs(usage.get(), /*delta=*/+1);
diff --git a/src/sksl/SkSLAnalysis.h b/src/sksl/SkSLAnalysis.h
index 1af4721..34cbded 100644
--- a/src/sksl/SkSLAnalysis.h
+++ b/src/sksl/SkSLAnalysis.h
@@ -78,13 +78,6 @@
bool SwitchCaseContainsUnconditionalExit(Statement& stmt);
/**
- * A switch-case "falls through" when it doesn't have an unconditional exit.
- */
-inline bool SwitchCaseFallsThrough(Statement& stmt) {
- return !SwitchCaseContainsUnconditionalExit(stmt);
-}
-
-/**
* Finds conditional exits from a switch-case. Returns true if this statement contains a
* conditional that wraps a potential exit from the switch (via continue, break or return).
*/
diff --git a/src/sksl/analysis/SwitchCaseContainsExit.cpp b/src/sksl/analysis/SwitchCaseContainsExit.cpp
new file mode 100644
index 0000000..ffab385
--- /dev/null
+++ b/src/sksl/analysis/SwitchCaseContainsExit.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/sksl/SkSLAnalysis.h"
+
+#include "include/private/SkSLStatement.h"
+#include "src/sksl/analysis/SkSLProgramVisitor.h"
+
+namespace SkSL {
+namespace {
+
+class SwitchCaseContainsExit : public ProgramVisitor {
+public:
+ SwitchCaseContainsExit(bool conditionalExits) : fConditionalExits(conditionalExits) {}
+
+ bool visitStatement(const Statement& stmt) override {
+ switch (stmt.kind()) {
+ case Statement::Kind::kBlock:
+ case Statement::Kind::kSwitchCase:
+ return INHERITED::visitStatement(stmt);
+
+ case Statement::Kind::kReturn:
+ // Returns are an early exit regardless of the surrounding control structures.
+ return fConditionalExits ? fInConditional : !fInConditional;
+
+ case Statement::Kind::kContinue:
+ // Continues are an early exit from switches, but not loops.
+ return !fInLoop &&
+ (fConditionalExits ? fInConditional : !fInConditional);
+
+ case Statement::Kind::kBreak:
+ // Breaks cannot escape from switches or loops.
+ return !fInLoop && !fInSwitch &&
+ (fConditionalExits ? fInConditional : !fInConditional);
+
+ case Statement::Kind::kIf: {
+ ++fInConditional;
+ bool result = INHERITED::visitStatement(stmt);
+ --fInConditional;
+ return result;
+ }
+
+ case Statement::Kind::kFor:
+ case Statement::Kind::kDo: {
+ // Loops are treated as conditionals because a loop could potentially execute zero
+ // times. We don't have a straightforward way to determine that a loop definitely
+ // executes at least once.
+ ++fInConditional;
+ ++fInLoop;
+ bool result = INHERITED::visitStatement(stmt);
+ --fInLoop;
+ --fInConditional;
+ return result;
+ }
+
+ case Statement::Kind::kSwitch: {
+ ++fInSwitch;
+ bool result = INHERITED::visitStatement(stmt);
+ --fInSwitch;
+ return result;
+ }
+
+ default:
+ return false;
+ }
+ }
+
+ bool fConditionalExits = false;
+ int fInConditional = 0;
+ int fInLoop = 0;
+ int fInSwitch = 0;
+ using INHERITED = ProgramVisitor;
+};
+
+} // namespace
+
+bool Analysis::SwitchCaseContainsUnconditionalExit(Statement& stmt) {
+ return SwitchCaseContainsExit{/*conditionalExits=*/false}.visitStatement(stmt);
+}
+
+bool Analysis::SwitchCaseContainsConditionalExit(Statement& stmt) {
+ return SwitchCaseContainsExit{/*conditionalExits=*/true}.visitStatement(stmt);
+}
+
+} // namespace SkSL