Migrate program finalization logic out of IRGenerator.
Most of the logic in IRGenerator::finish has moved to
Compiler::finalize. The @if/@switch pass has been combined with the pass
that verifies no dangling FunctionReference/TypeReference expressions,
saving one walk through the IR tree. Most program-finalization logic now
exists in Compiler and Analysis.
This change reorders our error generation logic slightly, and manages to
squeeze a few extra (valid) errors out of one of our fuzzer-generated
tests, but is not really intended to affect results in any significant
way.
Change-Id: I461de7c31f3980dedf74424e7826c032b1f40fd2
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/444757
Commit-Queue: John Stiles <johnstiles@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp
index dbb7d5c..f514d11 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -473,7 +473,7 @@
ir.fInputs);
this->errorReporter().reportPendingErrors(PositionInfo());
bool success = false;
- if (this->errorCount()) {
+ if (!this->finalize(*program)) {
// Do not return programs that failed to compile.
} else if (!this->optimize(*program)) {
// Do not return programs that failed to optimize.
@@ -804,8 +804,25 @@
this->removeDeadGlobalVariables(program, usage);
}
- if (this->errorCount() == 0) {
- Analysis::VerifyStaticTests(program);
+ return this->errorCount() == 0;
+}
+
+bool Compiler::finalize(Program& program) {
+ // Do a pass looking for @if/@switch statements that didn't optimize away, or dangling
+ // FunctionReference or TypeReference expressions. Report these as errors.
+ Analysis::VerifyStaticTestsAndExpressions(program);
+
+ // If we're in ES2 mode (runtime effects), do a pass to enforce Appendix A, Section 5 of the
+ // GLSL ES 1.00 spec -- Indexing. Don't bother if we've already found errors - this logic
+ // assumes that all loops meet the criteria of Section 4, and if they don't, could crash.
+ if (fContext->fConfig->strictES2Mode() && this->errorCount() == 0) {
+ for (const auto& pe : program.ownedElements()) {
+ Analysis::ValidateIndexingForES2(*pe, this->errorReporter());
+ }
+ }
+
+ if (fContext->fConfig->strictES2Mode()) {
+ Analysis::DetectStaticRecursion(SkMakeSpan(program.ownedElements()), this->errorReporter());
}
return this->errorCount() == 0;