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