2 * Copyright 2021 Google LLC
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "src/sksl/ir/SkSLBlock.h"
9 #include "src/sksl/ir/SkSLNop.h"
15 std::unique_ptr<Statement> Block::Make(Position pos,
16 StatementArray statements,
18 std::shared_ptr<SymbolTable> symbols) {
19 // We can't simplify away braces or populated symbol tables.
20 if (kind == Kind::kBracedScope || (symbols && symbols->count())) {
21 return std::make_unique<Block>(pos, std::move(statements), kind, std::move(symbols));
24 // If the Block is completely empty, synthesize a Nop.
25 if (statements.empty()) {
29 if (statements.size() > 1) {
30 // The statement array contains multiple statements, but some of those might be no-ops.
31 // If the statement array only contains one real statement, we can return that directly and
32 // avoid creating an additional Block node.
33 std::unique_ptr<Statement>* foundStatement = nullptr;
34 for (std::unique_ptr<Statement>& stmt : statements) {
35 if (!stmt->isEmpty()) {
36 if (!foundStatement) {
37 // We found a single non-empty statement. Remember it and keep looking.
38 foundStatement = &stmt;
41 // We found more than one non-empty statement. We actually do need a Block.
42 return std::make_unique<Block>(pos, std::move(statements), kind,
47 // The array wrapped one valid Statement. Avoid allocating a Block by returning it directly.
49 return std::move(*foundStatement);
52 // The statement array contained nothing but empty statements!
53 // In this case, we don't actually need to allocate a Block.
54 // We can just return one of those empty statements. Fall through to...
57 return std::move(statements.front());
60 std::unique_ptr<Block> Block::MakeBlock(Position pos,
61 StatementArray statements,
63 std::shared_ptr<SymbolTable> symbols) {
64 // Nothing to optimize here--eliminating empty statements doesn't actually improve the generated
65 // code, and we promise to return a Block.
66 return std::make_unique<Block>(pos, std::move(statements), kind, std::move(symbols));
69 std::unique_ptr<Statement> Block::clone() const {
70 StatementArray cloned;
71 cloned.reserve_back(this->children().size());
72 for (const std::unique_ptr<Statement>& stmt : this->children()) {
73 cloned.push_back(stmt->clone());
75 return std::make_unique<Block>(fPosition,
78 SymbolTable::WrapIfBuiltin(this->symbolTable()));
81 std::string Block::description() const {
84 // Write scope markers if this block is a scope, or if the block is empty (since we need to emit
85 // something here to make the code valid).
86 bool isScope = this->isScope() || this->isEmpty();
90 for (const std::unique_ptr<Statement>& stmt : this->children()) {
92 result += stmt->description();
94 result += isScope ? "\n}\n" : "\n";