• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "SkSLBoolLiteral.h"
12 #include "SkSLConstructor.h"
13 #include "SkSLExpression.h"
14 #include "SkSLFloatLiteral.h"
15 #include "SkSLIRGenerator.h"
16 #include "SkSLIntLiteral.h"
17 #include "SkSLSetting.h"
18 
19 namespace 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  */
28 struct VariableReference : public Expression {
29     enum RefKind {
30         kRead_RefKind,
31         kWrite_RefKind,
32         kReadWrite_RefKind
33     };
34 
35     VariableReference(int offset, const Variable& variable, RefKind refKind = kRead_RefKind)
36     : INHERITED(offset, kVariableReference_Kind, variable.fType)
37     , 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 
~VariableReferenceVariableReference47     ~VariableReference() override {
48         if (fRefKind != kRead_RefKind) {
49             fVariable.fWriteCount--;
50         }
51         if (fRefKind != kWrite_RefKind) {
52             fVariable.fReadCount--;
53         }
54     }
55 
refKindVariableReference56     RefKind refKind() {
57         return fRefKind;
58     }
59 
setRefKindVariableReference60     void setRefKind(RefKind refKind) {
61         if (fRefKind != kRead_RefKind) {
62             fVariable.fWriteCount--;
63         }
64         if (fRefKind != kWrite_RefKind) {
65             fVariable.fReadCount--;
66         }
67         if (refKind != kRead_RefKind) {
68             fVariable.fWriteCount++;
69         }
70         if (refKind != kWrite_RefKind) {
71             fVariable.fReadCount++;
72         }
73         fRefKind = refKind;
74     }
75 
hasSideEffectsVariableReference76     bool hasSideEffects() const override {
77         return false;
78     }
79 
isConstantVariableReference80     bool isConstant() const override {
81         return 0 != (fVariable.fModifiers.fFlags & Modifiers::kConst_Flag);
82     }
83 
descriptionVariableReference84     String description() const override {
85         return fVariable.fName;
86     }
87 
copy_constantVariableReference88     static std::unique_ptr<Expression> copy_constant(const IRGenerator& irGenerator,
89                                                      const Expression* expr) {
90         ASSERT(expr->isConstant());
91         switch (expr->fKind) {
92             case Expression::kIntLiteral_Kind:
93                 return std::unique_ptr<Expression>(new IntLiteral(irGenerator.fContext,
94                                                                   -1,
95                                                                   ((IntLiteral*) expr)->fValue));
96             case Expression::kFloatLiteral_Kind:
97                 return std::unique_ptr<Expression>(new FloatLiteral(
98                                                                    irGenerator.fContext,
99                                                                    -1,
100                                                                    ((FloatLiteral*) expr)->fValue));
101             case Expression::kBoolLiteral_Kind:
102                 return std::unique_ptr<Expression>(new BoolLiteral(irGenerator.fContext,
103                                                                    -1,
104                                                                    ((BoolLiteral*) expr)->fValue));
105             case Expression::kConstructor_Kind: {
106                 const Constructor* c = (const Constructor*) expr;
107                 std::vector<std::unique_ptr<Expression>> args;
108                 for (const auto& arg : c->fArguments) {
109                     args.push_back(copy_constant(irGenerator, arg.get()));
110                 }
111                 return std::unique_ptr<Expression>(new Constructor(-1, c->fType,
112                                                                    std::move(args)));
113             }
114             case Expression::kSetting_Kind: {
115                 const Setting* s = (const Setting*) expr;
116                 return std::unique_ptr<Expression>(new Setting(-1, s->fName,
117                                                                copy_constant(irGenerator,
118                                                                              s->fValue.get())));
119             }
120             default:
121                 ABORT("unsupported constant\n");
122         }
123     }
124 
constantPropagateVariableReference125     std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
126                                                   const DefinitionMap& definitions) override {
127         if (fRefKind != kRead_RefKind) {
128             return nullptr;
129         }
130         if ((fVariable.fModifiers.fFlags & Modifiers::kConst_Flag) && fVariable.fInitialValue &&
131             fVariable.fInitialValue->isConstant()) {
132             return copy_constant(irGenerator, fVariable.fInitialValue);
133         }
134         auto exprIter = definitions.find(&fVariable);
135         if (exprIter != definitions.end() && exprIter->second &&
136             (*exprIter->second)->isConstant()) {
137             return copy_constant(irGenerator, exprIter->second->get());
138         }
139         return nullptr;
140     }
141 
142     const Variable& fVariable;
143     RefKind fRefKind;
144 
145 private:
146     typedef Expression INHERITED;
147 };
148 
149 } // namespace
150 
151 #endif
152