Incorporate top-level DSL blocks into fragment processors.

A Block() at the top-level scope would previously disappear silently.

Change-Id: Ic3bac058361658d2e5bd8de1e3718dedf4cef1f7
Bug: skia:11854
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/397516
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
diff --git a/include/sksl/DSLBlock.h b/include/sksl/DSLBlock.h
index 27769ce..187148e 100644
--- a/include/sksl/DSLBlock.h
+++ b/include/sksl/DSLBlock.h
@@ -34,8 +34,19 @@
         static_cast<void>(unused);
     }
 
+    DSLBlock(DSLBlock&& other) {
+        fStatements = std::move(other.fStatements);
+    }
+
+    DSLBlock& operator=(DSLBlock&& other) {
+        fStatements = std::move(other.fStatements);
+        return *this;
+    }
+
     DSLBlock(SkSL::StatementArray statements);
 
+    ~DSLBlock();
+
     void append(DSLStatement stmt);
 
 private:
diff --git a/src/sksl/dsl/DSLBlock.cpp b/src/sksl/dsl/DSLBlock.cpp
index e5c8092..25274f2 100644
--- a/src/sksl/dsl/DSLBlock.cpp
+++ b/src/sksl/dsl/DSLBlock.cpp
@@ -17,6 +17,15 @@
 DSLBlock::DSLBlock(SkSL::StatementArray statements)
     : fStatements(std::move(statements)) {}
 
+DSLBlock::~DSLBlock() {
+    if (!fStatements.empty()) {
+        // This will convert our Block into a DSLStatement, which is then immediately freed.
+        // If an FP is being generated, this will naturally incorporate the Block's Statement into
+        // our FP. If not, this will assert that unused code wasn't incorporated into the program.
+        DSLStatement(this->release());
+    }
+}
+
 std::unique_ptr<SkSL::Statement> DSLBlock::release() {
     return std::make_unique<SkSL::Block>(/*offset=*/-1, std::move(fStatements));
 }