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/SkSLExpressionStatement.h"
9
10 #include "include/core/SkTypes.h"
11 #include "src/sksl/SkSLAnalysis.h"
12 #include "src/sksl/SkSLContext.h"
13 #include "src/sksl/SkSLProgramSettings.h"
14 #include "src/sksl/ir/SkSLBinaryExpression.h"
15 #include "src/sksl/ir/SkSLNop.h"
16 #include "src/sksl/ir/SkSLVariableReference.h"
17
18 namespace SkSL {
19
Convert(const Context & context,std::unique_ptr<Expression> expr)20 std::unique_ptr<Statement> ExpressionStatement::Convert(const Context& context,
21 std::unique_ptr<Expression> expr) {
22 // Expression-statements need to represent a complete expression.
23 // Report an error on intermediate expressions, like FunctionReference or TypeReference.
24 if (expr->isIncomplete(context)) {
25 return nullptr;
26 }
27 return ExpressionStatement::Make(context, std::move(expr));
28 }
29
Make(const Context & context,std::unique_ptr<Expression> expr)30 std::unique_ptr<Statement> ExpressionStatement::Make(const Context& context,
31 std::unique_ptr<Expression> expr) {
32 SkASSERT(!expr->isIncomplete(context));
33
34 if (context.fConfig->fSettings.fOptimize) {
35 // Expression-statements without any side effect can be replaced with a Nop.
36 if (!Analysis::HasSideEffects(*expr)) {
37 return Nop::Make();
38 }
39
40 // If this is an assignment statement like `a += b;`, the ref-kind of `a` will be set as
41 // read-write; `a` is written-to by the +=, and read-from by the consumer of the expression.
42 // We can demote the ref-kind to "write" safely, because the result of the expression is
43 // discarded; that is, `a` is never actually read-from.
44 if (expr->is<BinaryExpression>()) {
45 BinaryExpression& binary = expr->as<BinaryExpression>();
46 if (VariableReference* assignedVar = binary.isAssignmentIntoVariable()) {
47 if (assignedVar->refKind() == VariableRefKind::kReadWrite) {
48 assignedVar->setRefKind(VariableRefKind::kWrite);
49 }
50 }
51 }
52 }
53
54 return std::make_unique<ExpressionStatement>(std::move(expr));
55 }
56
57 } // namespace SkSL
58