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
8 #include "src/sksl/ir/SkSLBlock.h"
9 #include "src/sksl/ir/SkSLNop.h"
10
11 #include <iterator>
12
13 namespace SkSL {
14
MakeUnscoped(int line,StatementArray statements)15 std::unique_ptr<Statement> Block::MakeUnscoped(int line, StatementArray statements) {
16 // If the Block is completely empty, synthesize a Nop.
17 if (statements.empty()) {
18 return Nop::Make();
19 }
20
21 if (statements.size() > 1) {
22 // The statement array contains multiple statements, but some of those might be no-ops.
23 // If the statement array only contains one real statement, we can return that directly and
24 // avoid creating an additional Block node.
25 std::unique_ptr<Statement>* foundStatement = nullptr;
26 for (std::unique_ptr<Statement>& stmt : statements) {
27 if (!stmt->isEmpty()) {
28 if (!foundStatement) {
29 // We found a single non-empty statement. Remember it and keep looking.
30 foundStatement = &stmt;
31 continue;
32 }
33 // We found more than one non-empty statement. We actually do need a Block.
34 return std::make_unique<Block>(line, std::move(statements),
35 /*symbols=*/nullptr, /*isScope=*/false);
36 }
37 }
38
39 // The array wrapped one valid Statement. Avoid allocating a Block by returning it directly.
40 if (foundStatement) {
41 return std::move(*foundStatement);
42 }
43
44 // The statement array contained nothing but empty statements!
45 // In this case, we don't actually need to allocate a Block.
46 // We can just return one of those empty statements. Fall through to...
47 }
48
49 return std::move(statements.front());
50 }
51
Make(int line,StatementArray statements,std::shared_ptr<SymbolTable> symbols,bool isScope)52 std::unique_ptr<Block> Block::Make(int line,
53 StatementArray statements,
54 std::shared_ptr<SymbolTable> symbols,
55 bool isScope) {
56 // Nothing to optimize here--eliminating empty statements doesn't actually improve the generated
57 // code, and we promise to return a Block.
58 return std::make_unique<Block>(line, std::move(statements), std::move(symbols), isScope);
59 }
60
clone() const61 std::unique_ptr<Statement> Block::clone() const {
62 StatementArray cloned;
63 cloned.reserve_back(this->children().size());
64 for (const std::unique_ptr<Statement>& stmt : this->children()) {
65 cloned.push_back(stmt->clone());
66 }
67 return std::make_unique<Block>(fLine,
68 std::move(cloned),
69 SymbolTable::WrapIfBuiltin(this->symbolTable()),
70 this->isScope());
71 }
72
description() const73 String Block::description() const {
74 String result;
75 if (fIsScope) {
76 result += "{";
77 }
78 for (const std::unique_ptr<Statement>& stmt : this->children()) {
79 result += "\n";
80 result += stmt->description();
81 }
82 result += fIsScope ? "\n}\n" : "\n";
83 return result;
84 }
85
86 } // namespace SkSL
87