1 /*
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  */
7 
8 #ifndef SKSL_VARIABLEREFERENCE
9 #define SKSL_VARIABLEREFERENCE
10 
11 #include "SkSLExpression.h"
12 #include "SkSLFloatLiteral.h"
13 #include "SkSLIRGenerator.h"
14 #include "SkSLIntLiteral.h"
15 
16 namespace SkSL {
17 
18 /**
19  * A reference to a variable, through which it can be read or written. In the statement:
20  *
21  * x = x + 1;
22  *
23  * there is only one Variable 'x', but two VariableReferences to it.
24  */
25 struct VariableReference : public Expression {
26     enum RefKind {
27         kRead_RefKind,
28         kWrite_RefKind,
29         kReadWrite_RefKind
30     };
31 
32     VariableReference(Position position, const Variable& variable, RefKind refKind = kRead_RefKind)
33     : INHERITED(position, kVariableReference_Kind, variable.fType)
34     , fVariable(variable)
35     , fRefKind(refKind) {
36         if (refKind != kRead_RefKind) {
37             fVariable.fWriteCount++;
38         }
39         if (refKind != kWrite_RefKind) {
40             fVariable.fReadCount++;
41         }
42     }
43 
~VariableReferenceVariableReference44     virtual ~VariableReference() override {
45         if (fRefKind != kWrite_RefKind) {
46             fVariable.fReadCount--;
47         }
48     }
49 
refKindVariableReference50     RefKind refKind() {
51         return fRefKind;
52     }
53 
setRefKindVariableReference54     void setRefKind(RefKind refKind) {
55         if (fRefKind != kRead_RefKind) {
56             fVariable.fWriteCount--;
57         }
58         if (fRefKind != kWrite_RefKind) {
59             fVariable.fReadCount--;
60         }
61         if (refKind != kRead_RefKind) {
62             fVariable.fWriteCount++;
63         }
64         if (refKind != kWrite_RefKind) {
65             fVariable.fReadCount++;
66         }
67         fRefKind = refKind;
68     }
69 
descriptionVariableReference70     SkString description() const override {
71         return fVariable.fName;
72     }
73 
constantPropagateVariableReference74     virtual std::unique_ptr<Expression> constantPropagate(
75                                                         const IRGenerator& irGenerator,
76                                                         const DefinitionMap& definitions) override {
77         auto exprIter = definitions.find(&fVariable);
78         if (exprIter != definitions.end() && exprIter->second) {
79             const Expression* expr = exprIter->second->get();
80             switch (expr->fKind) {
81                 case Expression::kIntLiteral_Kind:
82                     return std::unique_ptr<Expression>(new IntLiteral(
83                                                                      irGenerator.fContext,
84                                                                      Position(),
85                                                                      ((IntLiteral*) expr)->fValue));
86                 case Expression::kFloatLiteral_Kind:
87                     return std::unique_ptr<Expression>(new FloatLiteral(
88                                                                    irGenerator.fContext,
89                                                                    Position(),
90                                                                    ((FloatLiteral*) expr)->fValue));
91                 default:
92                     break;
93             }
94         }
95         return nullptr;
96     }
97 
98     const Variable& fVariable;
99 
100 private:
101     RefKind fRefKind;
102 
103     typedef Expression INHERITED;
104 };
105 
106 } // namespace
107 
108 #endif
109