Flutter Engine
The Flutter Engine
SkSLEliminateUnnecessaryBraces.cpp
Go to the documentation of this file.
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
17#include "src/sksl/ir/SkSLNop.h"
22
23#include <memory>
24#include <utility>
25#include <vector>
26
27namespace SkSL {
28
29class Expression;
30
31static 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 }
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
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
109}
110
111} // namespace SkSL
#define INHERITED(method,...)
Definition: SkRecorder.cpp:128
SkSpan(Container &&) -> SkSpan< std::remove_pointer_t< decltype(std::data(std::declval< Container >()))> >
const StatementArray & children() const
Definition: SkSLBlock.h:71
std::unique_ptr< Statement > & statement()
std::unique_ptr< Statement > & statement()
std::unique_ptr< Statement > & body()
const T & as() const
Definition: SkSLIRNode.h:133
std::unique_ptr< Statement > & ifTrue()
std::unique_ptr< Statement > & ifFalse()
static std::unique_ptr< Statement > Make()
Definition: SkSLNop.h:26
void EliminateUnnecessaryBraces(Module &module)
static void eliminate_unnecessary_braces(SkSpan< std::unique_ptr< ProgramElement > > elements)
std::vector< std::unique_ptr< ProgramElement > > fElements
Definition: SkSLCompiler.h:59