Convert IRGenerator::convertFor to ForStatement::Make.
Since while statements are implemented in terms of a for loop, also added ForStatement::MakeWhile() which assumes null for the init-stmt and the next-expr. We currently don't have any optimizations for for-statements so the primary benefit is moving code out of IRGenerator. Change-Id: I4b3fc3482e28b7d28065e85670a6037b511847ff Bug: skia:11342 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/375203 Reviewed-by: Ethan Nicholas <ethannicholas@google.com> Commit-Queue: Ethan Nicholas <ethannicholas@google.com> Auto-Submit: John Stiles <johnstiles@google.com>
This commit is contained in:
parent
76d13bbdf8
commit
b321a07f16
@ -100,6 +100,7 @@ skia_sksl_sources = [
|
||||
"$_src/sksl/ir/SkSLField.h",
|
||||
"$_src/sksl/ir/SkSLFieldAccess.h",
|
||||
"$_src/sksl/ir/SkSLFloatLiteral.h",
|
||||
"$_src/sksl/ir/SkSLForStatement.cpp",
|
||||
"$_src/sksl/ir/SkSLForStatement.h",
|
||||
"$_src/sksl/ir/SkSLFunctionCall.h",
|
||||
"$_src/sksl/ir/SkSLFunctionDeclaration.h",
|
||||
|
@ -579,30 +579,6 @@ std::unique_ptr<Statement> IRGenerator::convertIf(const ASTNode& n) {
|
||||
std::move(ifTrue), std::move(ifFalse));
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement> IRGenerator::convertFor(int offset,
|
||||
std::unique_ptr<Statement> initializer,
|
||||
std::unique_ptr<Expression> test,
|
||||
std::unique_ptr<Expression> next,
|
||||
std::unique_ptr<Statement> statement) {
|
||||
if (test) {
|
||||
test = this->coerce(std::move(test), *fContext.fTypes.fBool);
|
||||
if (!test) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
auto forStmt =
|
||||
std::make_unique<ForStatement>(offset, std::move(initializer), std::move(test),
|
||||
std::move(next), std::move(statement), fSymbolTable);
|
||||
if (this->strictES2Mode()) {
|
||||
if (!Analysis::ForLoopIsValidForES2(*forStmt, /*outLoopInfo=*/nullptr,
|
||||
&this->errorReporter())) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return std::move(forStmt);
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement> IRGenerator::convertFor(const ASTNode& f) {
|
||||
SkASSERT(f.fKind == ASTNode::Kind::kFor);
|
||||
AutoSymbolTable table(this);
|
||||
@ -636,27 +612,8 @@ std::unique_ptr<Statement> IRGenerator::convertFor(const ASTNode& f) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return this->convertFor(f.fOffset, std::move(initializer), std::move(test), std::move(next),
|
||||
std::move(statement));
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement> IRGenerator::convertWhile(int offset, std::unique_ptr<Expression> test,
|
||||
std::unique_ptr<Statement> statement) {
|
||||
if (this->strictES2Mode()) {
|
||||
this->errorReporter().error(offset, "while loops are not supported");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
test = this->coerce(std::move(test), *fContext.fTypes.fBool);
|
||||
if (!test) {
|
||||
return nullptr;
|
||||
}
|
||||
if (this->detectVarDeclarationWithoutScope(*statement)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_unique<ForStatement>(offset, /*initializer=*/nullptr, std::move(test),
|
||||
/*next=*/nullptr, std::move(statement), fSymbolTable);
|
||||
return ForStatement::Make(fContext, f.fOffset, std::move(initializer), std::move(test),
|
||||
std::move(next), std::move(statement), fSymbolTable);
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement> IRGenerator::convertWhile(const ASTNode& w) {
|
||||
@ -670,7 +627,11 @@ std::unique_ptr<Statement> IRGenerator::convertWhile(const ASTNode& w) {
|
||||
if (!statement) {
|
||||
return nullptr;
|
||||
}
|
||||
return this->convertWhile(w.fOffset, std::move(test), std::move(statement));
|
||||
if (this->detectVarDeclarationWithoutScope(*statement)) {
|
||||
return nullptr;
|
||||
}
|
||||
return ForStatement::MakeWhile(fContext, w.fOffset, std::move(test), std::move(statement),
|
||||
fSymbolTable);
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement> IRGenerator::convertDo(std::unique_ptr<Statement> stmt,
|
||||
@ -838,11 +799,9 @@ std::unique_ptr<Block> IRGenerator::applyInvocationIDWorkaround(std::unique_ptr<
|
||||
std::make_unique<IntLiteral>(fContext, /*offset=*/-1, /*value=*/0),
|
||||
fContext.fTypes.fInt.get());
|
||||
auto initializer = std::make_unique<ExpressionStatement>(std::move(assignment));
|
||||
auto loop = std::make_unique<ForStatement>(/*offset=*/-1,
|
||||
std::move(initializer),
|
||||
std::move(test), std::move(next),
|
||||
std::make_unique<Block>(-1, std::move(loopBody)),
|
||||
fSymbolTable);
|
||||
auto loop = ForStatement::Make(
|
||||
fContext, /*offset=*/-1, std::move(initializer), std::move(test), std::move(next),
|
||||
std::make_unique<Block>(/*offset=*/-1, std::move(loopBody)), fSymbolTable);
|
||||
StatementArray children;
|
||||
children.push_back(std::move(loop));
|
||||
return std::make_unique<Block>(/*offset=*/-1, std::move(children));
|
||||
|
@ -203,11 +203,6 @@ private:
|
||||
std::unique_ptr<Statement> convertExpressionStatement(const ASTNode& s);
|
||||
std::unique_ptr<Expression> convertField(std::unique_ptr<Expression> base,
|
||||
StringFragment field);
|
||||
std::unique_ptr<Statement> convertFor(int offset,
|
||||
std::unique_ptr<Statement> initializer,
|
||||
std::unique_ptr<Expression> test,
|
||||
std::unique_ptr<Expression> next,
|
||||
std::unique_ptr<Statement> statement);
|
||||
std::unique_ptr<Statement> convertFor(const ASTNode& f);
|
||||
std::unique_ptr<Expression> convertIdentifier(int offset, StringFragment identifier);
|
||||
std::unique_ptr<Expression> convertIdentifier(const ASTNode& identifier);
|
||||
@ -238,8 +233,6 @@ private:
|
||||
std::unique_ptr<Expression> ifFalse);
|
||||
std::unique_ptr<Expression> convertTernaryExpression(const ASTNode& expression);
|
||||
std::unique_ptr<Statement> convertVarDeclarationStatement(const ASTNode& s);
|
||||
std::unique_ptr<Statement> convertWhile(int offset, std::unique_ptr<Expression> test,
|
||||
std::unique_ptr<Statement> statement);
|
||||
std::unique_ptr<Statement> convertWhile(const ASTNode& w);
|
||||
void convertGlobalVarDeclarations(const ASTNode& decl);
|
||||
void convertEnum(const ASTNode& e);
|
||||
|
@ -461,9 +461,9 @@ std::unique_ptr<Statement> Inliner::inlineStatement(int offset,
|
||||
// need to ensure initializer is evaluated first so that we've already remapped its
|
||||
// declarations by the time we evaluate test & next
|
||||
std::unique_ptr<Statement> initializer = stmt(f.initializer());
|
||||
return std::make_unique<ForStatement>(offset, std::move(initializer), expr(f.test()),
|
||||
expr(f.next()), stmt(f.statement()),
|
||||
SymbolTable::WrapIfBuiltin(f.symbols()));
|
||||
return ForStatement::Make(*fContext, offset, std::move(initializer), expr(f.test()),
|
||||
expr(f.next()), stmt(f.statement()),
|
||||
SymbolTable::WrapIfBuiltin(f.symbols()));
|
||||
}
|
||||
case Statement::Kind::kIf: {
|
||||
const IfStatement& i = statement.as<IfStatement>();
|
||||
@ -726,12 +726,12 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
|
||||
inlineStatements = &innerBlock->children();
|
||||
|
||||
// for (int _1_loop = 0; _1_loop < 1; _1_loop++) {...}
|
||||
inlinedBody.children().push_back(std::make_unique<ForStatement>(/*offset=*/-1,
|
||||
std::move(loopVar.fVarDecl),
|
||||
std::move(test),
|
||||
std::move(increment),
|
||||
std::move(innerBlock),
|
||||
symbolTable));
|
||||
inlinedBody.children().push_back(ForStatement::Make(*fContext, /*offset=*/-1,
|
||||
std::move(loopVar.fVarDecl),
|
||||
std::move(test),
|
||||
std::move(increment),
|
||||
std::move(innerBlock),
|
||||
symbolTable));
|
||||
} else {
|
||||
// No early returns, so we can just dump the code into our existing scopeless block.
|
||||
inlineStatements = &inlinedBody.children();
|
||||
|
@ -93,8 +93,9 @@ public:
|
||||
|
||||
static DSLStatement For(DSLStatement initializer, DSLExpression test, DSLExpression next,
|
||||
DSLStatement stmt) {
|
||||
return DSLWriter::IRGenerator().convertFor(/*offset=*/-1, initializer.release(),
|
||||
test.release(), next.release(), stmt.release());
|
||||
return ForStatement::Make(DSLWriter::Context(), /*offset=*/-1, initializer.release(),
|
||||
test.release(), next.release(), stmt.release(),
|
||||
DSLWriter::SymbolTable());
|
||||
}
|
||||
|
||||
static DSLStatement If(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse) {
|
||||
@ -146,7 +147,8 @@ public:
|
||||
}
|
||||
|
||||
static DSLStatement While(DSLExpression test, DSLStatement stmt) {
|
||||
return DSLWriter::IRGenerator().convertWhile(/*offset=*/-1, test.release(), stmt.release());
|
||||
return ForStatement::MakeWhile(DSLWriter::Context(), /*offset=*/-1, test.release(),
|
||||
stmt.release(), DSLWriter::SymbolTable());
|
||||
}
|
||||
};
|
||||
|
||||
|
82
src/sksl/ir/SkSLForStatement.cpp
Normal file
82
src/sksl/ir/SkSLForStatement.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2021 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "src/sksl/SkSLAnalysis.h"
|
||||
#include "src/sksl/SkSLContext.h"
|
||||
#include "src/sksl/SkSLProgramSettings.h"
|
||||
#include "src/sksl/ir/SkSLForStatement.h"
|
||||
#include "src/sksl/ir/SkSLSymbolTable.h"
|
||||
#include "src/sksl/ir/SkSLType.h"
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
std::unique_ptr<Statement> ForStatement::clone() const {
|
||||
return std::make_unique<ForStatement>(
|
||||
fOffset,
|
||||
this->initializer() ? this->initializer()->clone() : nullptr,
|
||||
this->test() ? this->test()->clone() : nullptr,
|
||||
this->next() ? this->next()->clone() : nullptr,
|
||||
this->statement()->clone(),
|
||||
SymbolTable::WrapIfBuiltin(this->symbols()));
|
||||
}
|
||||
|
||||
String ForStatement::description() const {
|
||||
String result("for (");
|
||||
if (this->initializer()) {
|
||||
result += this->initializer()->description();
|
||||
} else {
|
||||
result += ";";
|
||||
}
|
||||
result += " ";
|
||||
if (this->test()) {
|
||||
result += this->test()->description();
|
||||
}
|
||||
result += "; ";
|
||||
if (this->next()) {
|
||||
result += this->next()->description();
|
||||
}
|
||||
result += ") " + this->statement()->description();
|
||||
return result;
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement> ForStatement::Make(const Context& context, int offset,
|
||||
std::unique_ptr<Statement> initializer,
|
||||
std::unique_ptr<Expression> test,
|
||||
std::unique_ptr<Expression> next,
|
||||
std::unique_ptr<Statement> statement,
|
||||
std::shared_ptr<SymbolTable> symbolTable) {
|
||||
if (test) {
|
||||
test = context.fTypes.fBool->coerceExpression(std::move(test), context);
|
||||
if (!test) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
auto forStmt = std::make_unique<ForStatement>(offset, std::move(initializer), std::move(test),
|
||||
std::move(next), std::move(statement),
|
||||
std::move(symbolTable));
|
||||
if (context.fConfig->strictES2Mode()) {
|
||||
if (!Analysis::ForLoopIsValidForES2(*forStmt, /*outLoopInfo=*/nullptr, &context.fErrors)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return std::move(forStmt);
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement> ForStatement::MakeWhile(const Context& context, int offset,
|
||||
std::unique_ptr<Expression> test,
|
||||
std::unique_ptr<Statement> statement,
|
||||
std::shared_ptr<SymbolTable> symbolTable) {
|
||||
if (context.fConfig->strictES2Mode()) {
|
||||
context.fErrors.error(offset, "while loops are not supported");
|
||||
return nullptr;
|
||||
}
|
||||
return Make(context, offset, /*initializer=*/nullptr, std::move(test), /*next=*/nullptr,
|
||||
std::move(statement), std::move(symbolTable));
|
||||
}
|
||||
|
||||
} // namespace SkSL
|
@ -31,6 +31,20 @@ public:
|
||||
, fNext(std::move(next))
|
||||
, fStatement(std::move(statement)) {}
|
||||
|
||||
// Creates an SkSL for loop.
|
||||
static std::unique_ptr<Statement> Make(const Context& context, int offset,
|
||||
std::unique_ptr<Statement> initializer,
|
||||
std::unique_ptr<Expression> test,
|
||||
std::unique_ptr<Expression> next,
|
||||
std::unique_ptr<Statement> statement,
|
||||
std::shared_ptr<SymbolTable> symbolTable);
|
||||
|
||||
// A while statement is represented in SkSL as a for loop with no init-stmt or next-expr.
|
||||
static std::unique_ptr<Statement> MakeWhile(const Context& context, int offset,
|
||||
std::unique_ptr<Expression> test,
|
||||
std::unique_ptr<Statement> statement,
|
||||
std::shared_ptr<SymbolTable> symbolTable);
|
||||
|
||||
std::unique_ptr<Statement>& initializer() {
|
||||
return fInitializer;
|
||||
}
|
||||
@ -67,34 +81,9 @@ public:
|
||||
return fSymbolTable;
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement> clone() const override {
|
||||
return std::make_unique<ForStatement>(
|
||||
fOffset,
|
||||
this->initializer() ? this->initializer()->clone() : nullptr,
|
||||
this->test() ? this->test()->clone() : nullptr,
|
||||
this->next() ? this->next()->clone() : nullptr,
|
||||
this->statement()->clone(),
|
||||
SymbolTable::WrapIfBuiltin(this->symbols()));
|
||||
}
|
||||
std::unique_ptr<Statement> clone() const override;
|
||||
|
||||
String description() const override {
|
||||
String result("for (");
|
||||
if (this->initializer()) {
|
||||
result += this->initializer()->description();
|
||||
} else {
|
||||
result += ";";
|
||||
}
|
||||
result += " ";
|
||||
if (this->test()) {
|
||||
result += this->test()->description();
|
||||
}
|
||||
result += "; ";
|
||||
if (this->next()) {
|
||||
result += this->next()->description();
|
||||
}
|
||||
result += ") " + this->statement()->description();
|
||||
return result;
|
||||
}
|
||||
String description() const override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<SymbolTable> fSymbolTable;
|
||||
|
Loading…
Reference in New Issue
Block a user