Add an "allow-unreachable" flag to CFG basic blocks.
In some cases, it's okay if we can't find a path to a CFG block. Two
such cases are:
- The starting block. This is reached implicitly.
- For-loop increment expressions. These are sometimes required due to
GLSL ES2 restrictions, even if they can't actually be reached.
Change-Id: I626c424361a7339d4fb1ab0809f60df3f2f72173
Bug: skia:11097
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/345162
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
diff --git a/src/sksl/SkSLCFGGenerator.cpp b/src/sksl/SkSLCFGGenerator.cpp
index 49ca3cd..aabd3a8 100644
--- a/src/sksl/SkSLCFGGenerator.cpp
+++ b/src/sksl/SkSLCFGGenerator.cpp
@@ -593,6 +593,11 @@
if (f.next()) {
this->addExpression(cfg, &f.next(), /*constantPropagate=*/true);
}
+ // The increment expression of a for loop is allowed to be unreachable, because GLSL
+ // ES2 requires us to provide an increment expression for our for-loops whether or not
+ // it can be reached. Reporting it as "unreachable" isn't helpful if the alternative
+ // is an invalid program.
+ cfg.currentBlock().fAllowUnreachable = true;
cfg.addExit(cfg.fCurrent, loopStart);
cfg.addExit(cfg.fCurrent, loopExit);
fLoopContinues.pop();
@@ -644,6 +649,8 @@
CFG result;
result.fStart = result.newBlock();
result.fCurrent = result.fStart;
+ // The starting block is "reached" implicitly, even if nothing points to it.
+ result.currentBlock().fAllowUnreachable = true;
this->addStatement(result, &f.body());
result.newBlock();
result.fExit = result.fCurrent;
diff --git a/src/sksl/SkSLCFGGenerator.h b/src/sksl/SkSLCFGGenerator.h
index 9b824a9..f1dc52c 100644
--- a/src/sksl/SkSLCFGGenerator.h
+++ b/src/sksl/SkSLCFGGenerator.h
@@ -130,6 +130,7 @@
std::vector<Node> fNodes;
bool fIsReachable = false;
+ bool fAllowUnreachable = false;
using ExitArray = SkSTArray<4, BlockId>;
ExitArray fExits;
// variable definitions upon entering this basic block (null expression = undefined)
diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp
index f18c05a..6b1d5e2 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -1629,7 +1629,7 @@
// check for unreachable code
for (size_t i = 0; i < cfg.fBlocks.size(); i++) {
const BasicBlock& block = cfg.fBlocks[i];
- if (i != cfg.fStart && !block.fIsReachable && block.fNodes.size()) {
+ if (!block.fIsReachable && !block.fAllowUnreachable && block.fNodes.size()) {
int offset;
const BasicBlock::Node& node = block.fNodes[0];
if (node.isStatement()) {