blob: ba17437e24c28e44ecf791044a1b9c1e2c8900bb [file] [log] [blame]
ethannicholasb3058bd2016-07-01 08:22:01 -07001/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
Ethan Nicholas0df1b042017-03-31 13:56:23 -04007
ethannicholasb3058bd2016-07-01 08:22:01 -07008#ifndef SKSL_VARIABLEREFERENCE
9#define SKSL_VARIABLEREFERENCE
10
Hal Canaryce78bad2017-05-04 14:15:40 -040011#include "SkSLBoolLiteral.h"
12#include "SkSLConstructor.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070013#include "SkSLExpression.h"
Hal Canary6b20a552017-02-07 14:09:38 -050014#include "SkSLFloatLiteral.h"
15#include "SkSLIRGenerator.h"
16#include "SkSLIntLiteral.h"
Ethan Nicholas762466e2017-06-29 10:03:38 -040017#include "SkSLSetting.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070018
19namespace SkSL {
20
21/**
22 * A reference to a variable, through which it can be read or written. In the statement:
23 *
24 * x = x + 1;
25 *
26 * there is only one Variable 'x', but two VariableReferences to it.
27 */
28struct VariableReference : public Expression {
Ethan Nicholas86a43402017-01-19 13:32:00 -050029 enum RefKind {
30 kRead_RefKind,
31 kWrite_RefKind,
32 kReadWrite_RefKind
33 };
34
35 VariableReference(Position position, const Variable& variable, RefKind refKind = kRead_RefKind)
ethannicholasd598f792016-07-25 10:08:54 -070036 : INHERITED(position, kVariableReference_Kind, variable.fType)
Ethan Nicholas86a43402017-01-19 13:32:00 -050037 , fVariable(variable)
38 , fRefKind(refKind) {
39 if (refKind != kRead_RefKind) {
40 fVariable.fWriteCount++;
41 }
42 if (refKind != kWrite_RefKind) {
43 fVariable.fReadCount++;
44 }
45 }
46
Ethan Nicholascb670962017-04-20 19:31:52 -040047 ~VariableReference() override {
Ethan Nicholas86a43402017-01-19 13:32:00 -050048 if (fRefKind != kWrite_RefKind) {
49 fVariable.fReadCount--;
50 }
51 }
52
53 RefKind refKind() {
54 return fRefKind;
55 }
56
57 void setRefKind(RefKind refKind) {
58 if (fRefKind != kRead_RefKind) {
59 fVariable.fWriteCount--;
60 }
61 if (fRefKind != kWrite_RefKind) {
62 fVariable.fReadCount--;
63 }
64 if (refKind != kRead_RefKind) {
65 fVariable.fWriteCount++;
66 }
67 if (refKind != kWrite_RefKind) {
68 fVariable.fReadCount++;
69 }
70 fRefKind = refKind;
71 }
ethannicholasb3058bd2016-07-01 08:22:01 -070072
Ethan Nicholascb670962017-04-20 19:31:52 -040073 bool hasSideEffects() const override {
74 return false;
75 }
76
Ethan Nicholas0df1b042017-03-31 13:56:23 -040077 String description() const override {
ethannicholasd598f792016-07-25 10:08:54 -070078 return fVariable.fName;
ethannicholasb3058bd2016-07-01 08:22:01 -070079 }
80
Ethan Nicholascb670962017-04-20 19:31:52 -040081 static std::unique_ptr<Expression> copy_constant(const IRGenerator& irGenerator,
82 const Expression* expr) {
83 ASSERT(expr->isConstant());
84 switch (expr->fKind) {
85 case Expression::kIntLiteral_Kind:
86 return std::unique_ptr<Expression>(new IntLiteral(
87 irGenerator.fContext,
88 Position(),
89 ((IntLiteral*) expr)->fValue));
90 case Expression::kFloatLiteral_Kind:
91 return std::unique_ptr<Expression>(new FloatLiteral(
92 irGenerator.fContext,
93 Position(),
94 ((FloatLiteral*) expr)->fValue));
95 case Expression::kBoolLiteral_Kind:
96 return std::unique_ptr<Expression>(new BoolLiteral(irGenerator.fContext,
Ethan Nicholas86a43402017-01-19 13:32:00 -050097 Position(),
Ethan Nicholascb670962017-04-20 19:31:52 -040098 ((BoolLiteral*) expr)->fValue));
99 case Expression::kConstructor_Kind: {
100 const Constructor* c = (const Constructor*) expr;
101 std::vector<std::unique_ptr<Expression>> args;
102 for (const auto& arg : c->fArguments) {
103 args.push_back(copy_constant(irGenerator, arg.get()));
104 }
105 return std::unique_ptr<Expression>(new Constructor(Position(), c->fType,
106 std::move(args)));
Ethan Nicholas86a43402017-01-19 13:32:00 -0500107 }
Ethan Nicholas762466e2017-06-29 10:03:38 -0400108 case Expression::kSetting_Kind: {
109 const Setting* s = (const Setting*) expr;
110 return std::unique_ptr<Expression>(new Setting(Position(), s->fName,
111 copy_constant(irGenerator,
112 s->fValue.get())));
113 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400114 default:
115 ABORT("unsupported constant\n");
116 }
117 }
118
119 std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
120 const DefinitionMap& definitions) override {
121 if (fRefKind != kRead_RefKind) {
122 return nullptr;
123 }
124 auto exprIter = definitions.find(&fVariable);
125 if (exprIter != definitions.end() && exprIter->second &&
126 (*exprIter->second)->isConstant()) {
127 return copy_constant(irGenerator, exprIter->second->get());
Ethan Nicholas86a43402017-01-19 13:32:00 -0500128 }
129 return nullptr;
130 }
131
ethannicholasd598f792016-07-25 10:08:54 -0700132 const Variable& fVariable;
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000133 RefKind fRefKind;
134
Ethan Nicholascb670962017-04-20 19:31:52 -0400135private:
ethannicholasb3058bd2016-07-01 08:22:01 -0700136 typedef Expression INHERITED;
137};
138
139} // namespace
140
141#endif