Flutter Engine
The Flutter Engine
SkSLBlock.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2021 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
9
10#include "src/sksl/ir/SkSLNop.h"
11
12namespace SkSL {
13
14std::unique_ptr<Statement> Block::Make(Position pos,
15 StatementArray statements,
16 Kind kind,
17 std::unique_ptr<SymbolTable> symbols) {
18 // We can't simplify away braces or populated symbol tables.
19 if (kind == Kind::kBracedScope || (symbols && symbols->count())) {
20 return std::make_unique<Block>(pos, std::move(statements), kind, std::move(symbols));
21 }
22
23 // If the Block is completely empty, synthesize a Nop.
24 if (statements.empty()) {
25 return Nop::Make();
26 }
27
28 if (statements.size() > 1) {
29 // The statement array contains multiple statements, but some of those might be no-ops.
30 // If the statement array only contains one real statement, we can return that directly and
31 // avoid creating an additional Block node.
32 std::unique_ptr<Statement>* foundStatement = nullptr;
33 for (std::unique_ptr<Statement>& stmt : statements) {
34 if (!stmt->isEmpty()) {
35 if (!foundStatement) {
36 // We found a single non-empty statement. Remember it and keep looking.
37 foundStatement = &stmt;
38 continue;
39 }
40 // We found more than one non-empty statement. We actually do need a Block.
41 return std::make_unique<Block>(pos, std::move(statements), kind,
42 /*symbols=*/nullptr);
43 }
44 }
45
46 // The array wrapped one valid Statement. Avoid allocating a Block by returning it directly.
47 if (foundStatement) {
48 return std::move(*foundStatement);
49 }
50
51 // The statement array contained nothing but empty statements!
52 // In this case, we don't actually need to allocate a Block.
53 // We can just return one of those empty statements. Fall through to...
54 }
55
56 return std::move(statements.front());
57}
58
59std::unique_ptr<Block> Block::MakeBlock(Position pos,
60 StatementArray statements,
61 Kind kind,
62 std::unique_ptr<SymbolTable> symbols) {
63 // Nothing to optimize here--eliminating empty statements doesn't actually improve the generated
64 // code, and we promise to return a Block.
65 return std::make_unique<Block>(pos, std::move(statements), kind, std::move(symbols));
66}
67
68std::unique_ptr<Statement> Block::MakeCompoundStatement(std::unique_ptr<Statement> existing,
69 std::unique_ptr<Statement> additional) {
70 // If either of the two Statements is empty, return the other.
71 if (!existing || existing->isEmpty()) {
72 return additional;
73 }
74 if (!additional || additional->isEmpty()) {
75 return existing;
76 }
77
78 // If the existing statement is a compound-statement Block, append the additional statement.
79 if (existing->is<Block>()) {
80 SkSL::Block& block = existing->as<Block>();
81 if (block.blockKind() == Block::Kind::kCompoundStatement) {
82 block.children().push_back(std::move(additional));
83 return existing;
84 }
85 }
86
87 // The existing statement was not a compound-statement Block; create one, and put both
88 // statements inside of it.
89 Position pos = existing->fPosition.rangeThrough(additional->fPosition);
90 StatementArray stmts;
91 stmts.reserve_exact(2);
92 stmts.push_back(std::move(existing));
93 stmts.push_back(std::move(additional));
94 return Block::Make(pos, std::move(stmts), Block::Kind::kCompoundStatement);
95}
96
97std::string Block::description() const {
98 std::string result;
99
100 // Write scope markers if this block is a scope, or if the block is empty (since we need to emit
101 // something here to make the code valid).
102 bool isScope = this->isScope() || this->isEmpty();
103 if (isScope) {
104 result += "{";
105 }
106 for (const std::unique_ptr<Statement>& stmt : this->children()) {
107 result += "\n";
108 result += stmt->description();
109 }
110 result += isScope ? "\n}\n" : "\n";
111 return result;
112}
113
114} // namespace SkSL
SkPoint pos
bool isEmpty() const override
Definition: SkSLBlock.h:95
static std::unique_ptr< Statement > MakeCompoundStatement(std::unique_ptr< Statement > existing, std::unique_ptr< Statement > additional)
Definition: SkSLBlock.cpp:68
const StatementArray & children() const
Definition: SkSLBlock.h:71
bool isScope() const
Definition: SkSLBlock.h:79
std::string description() const override
Definition: SkSLBlock.cpp:97
static std::unique_ptr< Statement > Make(Position pos, StatementArray statements, Kind kind=Kind::kBracedScope, std::unique_ptr< SymbolTable > symbols=nullptr)
Definition: SkSLBlock.cpp:14
static std::unique_ptr< Block > MakeBlock(Position pos, StatementArray statements, Kind kind=Kind::kBracedScope, std::unique_ptr< SymbolTable > symbols=nullptr)
Definition: SkSLBlock.cpp:59
Kind blockKind() const
Definition: SkSLBlock.h:83
const T & as() const
Definition: SkSLIRNode.h:133
static std::unique_ptr< Statement > Make()
Definition: SkSLNop.h:26
Kind kind() const
Definition: SkSLStatement.h:28
bool empty() const
Definition: SkTArray.h:199
int size() const
Definition: SkTArray.h:421
void reserve_exact(int n)
Definition: SkTArray.h:181
GAsyncResult * result