• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2024 Google LLC
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "include/core/SkSpan.h"
9 #include "src/sksl/SkSLCompiler.h"
10 #include "src/sksl/SkSLDefines.h"
11 #include "src/sksl/ir/SkSLBlock.h"
12 #include "src/sksl/ir/SkSLDoStatement.h"
13 #include "src/sksl/ir/SkSLForStatement.h"
14 #include "src/sksl/ir/SkSLFunctionDefinition.h"
15 #include "src/sksl/ir/SkSLIRNode.h"
16 #include "src/sksl/ir/SkSLIfStatement.h"
17 #include "src/sksl/ir/SkSLNop.h"
18 #include "src/sksl/ir/SkSLProgramElement.h"
19 #include "src/sksl/ir/SkSLStatement.h"
20 #include "src/sksl/transform/SkSLProgramWriter.h"
21 #include "src/sksl/transform/SkSLTransform.h"
22 
23 #include <memory>
24 #include <utility>
25 #include <vector>
26 
27 namespace SkSL {
28 
29 class Expression;
30 
eliminate_unnecessary_braces(SkSpan<std::unique_ptr<ProgramElement>> elements)31 static void eliminate_unnecessary_braces(SkSpan<std::unique_ptr<ProgramElement>> elements) {
32     class UnnecessaryBraceEliminator : public ProgramWriter {
33     public:
34         bool visitExpressionPtr(std::unique_ptr<Expression>& expr) override {
35             // We don't need to look inside expressions at all.
36             return false;
37         }
38 
39         bool visitStatementPtr(std::unique_ptr<Statement>& stmt) override {
40             // Work from the innermost blocks to the outermost.
41             INHERITED::visitStatementPtr(stmt);
42 
43             switch (stmt->kind()) {
44                 case StatementKind::kIf: {
45                     IfStatement& ifStmt = stmt->as<IfStatement>();
46                     EliminateBracesFrom(ifStmt.ifTrue());
47                     EliminateBracesFrom(ifStmt.ifFalse());
48                     break;
49                 }
50                 case StatementKind::kFor: {
51                     ForStatement& forStmt = stmt->as<ForStatement>();
52                     EliminateBracesFrom(forStmt.statement());
53                     break;
54                 }
55                 case StatementKind::kDo: {
56                     DoStatement& doStmt = stmt->as<DoStatement>();
57                     EliminateBracesFrom(doStmt.statement());
58                     break;
59                 }
60                 default:
61                     break;
62             }
63 
64             // We always check the entire program.
65             return false;
66         }
67 
68         static void EliminateBracesFrom(std::unique_ptr<Statement>& stmt) {
69             if (!stmt || !stmt->is<Block>()) {
70                 return;
71             }
72             Block& block = stmt->as<Block>();
73             std::unique_ptr<Statement>* usefulStmt = nullptr;
74             for (std::unique_ptr<Statement>& childStmt : block.children()) {
75                 if (childStmt->isEmpty()) {
76                     continue;
77                 }
78                 if (usefulStmt) {
79                     // We found two non-empty statements. We can't eliminate braces from
80                     // this block.
81                     return;
82                 }
83                 // We found one non-empty statement.
84                 usefulStmt = &childStmt;
85             }
86 
87             if (!usefulStmt) {
88                 // This block held zero useful statements. Replace the block with a nop.
89                 stmt = Nop::Make();
90             } else {
91                 // This block held one useful statement. Replace the block with that statement.
92                 stmt = std::move(*usefulStmt);
93             }
94         }
95 
96         using INHERITED = ProgramWriter;
97     };
98 
99     for (std::unique_ptr<ProgramElement>& pe : elements) {
100         if (pe->is<FunctionDefinition>()) {
101             UnnecessaryBraceEliminator visitor;
102             visitor.visitStatementPtr(pe->as<FunctionDefinition>().body());
103         }
104     }
105 }
106 
EliminateUnnecessaryBraces(Module & module)107 void Transform::EliminateUnnecessaryBraces(Module& module) {
108     return eliminate_unnecessary_braces(SkSpan(module.fElements));
109 }
110 
111 }  // namespace SkSL
112