1 /*
2  * Copyright 2018 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 #include "SkSLVariableReference.h"
9 
10 #include "SkSLConstructor.h"
11 #include "SkSLFloatLiteral.h"
12 #include "SkSLIRGenerator.h"
13 #include "SkSLSetting.h"
14 
15 namespace SkSL {
16 
VariableReference(int offset,const Variable & variable,RefKind refKind)17 VariableReference::VariableReference(int offset, const Variable& variable, RefKind refKind)
18 : INHERITED(offset, kVariableReference_Kind, variable.fType)
19 , fVariable(variable)
20 , fRefKind(refKind) {
21     if (refKind != kRead_RefKind) {
22         fVariable.fWriteCount++;
23     }
24     if (refKind != kWrite_RefKind) {
25         fVariable.fReadCount++;
26     }
27 }
28 
~VariableReference()29 VariableReference::~VariableReference() {
30     if (fRefKind != kRead_RefKind) {
31         fVariable.fWriteCount--;
32     }
33     if (fRefKind != kWrite_RefKind) {
34         fVariable.fReadCount--;
35     }
36 }
37 
setRefKind(RefKind refKind)38 void VariableReference::setRefKind(RefKind refKind) {
39     if (fRefKind != kRead_RefKind) {
40         fVariable.fWriteCount--;
41     }
42     if (fRefKind != kWrite_RefKind) {
43         fVariable.fReadCount--;
44     }
45     if (refKind != kRead_RefKind) {
46         fVariable.fWriteCount++;
47     }
48     if (refKind != kWrite_RefKind) {
49         fVariable.fReadCount++;
50     }
51     fRefKind = refKind;
52 }
53 
copy_constant(const IRGenerator & irGenerator,const Expression * expr)54 std::unique_ptr<Expression> VariableReference::copy_constant(const IRGenerator& irGenerator,
55                                                              const Expression* expr) {
56     SkASSERT(expr->isConstant());
57     switch (expr->fKind) {
58         case Expression::kIntLiteral_Kind:
59             return std::unique_ptr<Expression>(new IntLiteral(irGenerator.fContext,
60                                                               -1,
61                                                               ((IntLiteral*) expr)->fValue));
62         case Expression::kFloatLiteral_Kind:
63             return std::unique_ptr<Expression>(new FloatLiteral(
64                                                                irGenerator.fContext,
65                                                                -1,
66                                                                ((FloatLiteral*) expr)->fValue));
67         case Expression::kBoolLiteral_Kind:
68             return std::unique_ptr<Expression>(new BoolLiteral(irGenerator.fContext,
69                                                                -1,
70                                                                ((BoolLiteral*) expr)->fValue));
71         case Expression::kConstructor_Kind: {
72             const Constructor* c = (const Constructor*) expr;
73             std::vector<std::unique_ptr<Expression>> args;
74             for (const auto& arg : c->fArguments) {
75                 args.push_back(copy_constant(irGenerator, arg.get()));
76             }
77             return std::unique_ptr<Expression>(new Constructor(-1, c->fType,
78                                                                std::move(args)));
79         }
80         case Expression::kSetting_Kind: {
81             const Setting* s = (const Setting*) expr;
82             return std::unique_ptr<Expression>(new Setting(-1, s->fName,
83                                                            copy_constant(irGenerator,
84                                                                          s->fValue.get())));
85         }
86         default:
87             ABORT("unsupported constant\n");
88     }
89 }
90 
constantPropagate(const IRGenerator & irGenerator,const DefinitionMap & definitions)91 std::unique_ptr<Expression> VariableReference::constantPropagate(const IRGenerator& irGenerator,
92                                                                  const DefinitionMap& definitions) {
93     if (fRefKind != kRead_RefKind) {
94         return nullptr;
95     }
96     if (irGenerator.fKind == Program::kPipelineStage_Kind &&
97         fVariable.fStorage == Variable::kGlobal_Storage &&
98         (fVariable.fModifiers.fFlags & Modifiers::kIn_Flag)) {
99         return irGenerator.getArg(fOffset, fVariable.fName);
100     }
101     if ((fVariable.fModifiers.fFlags & Modifiers::kConst_Flag) && fVariable.fInitialValue &&
102         fVariable.fInitialValue->isConstant()) {
103         return copy_constant(irGenerator, fVariable.fInitialValue);
104     }
105     auto exprIter = definitions.find(&fVariable);
106     if (exprIter != definitions.end() && exprIter->second &&
107         (*exprIter->second)->isConstant()) {
108         return copy_constant(irGenerator, exprIter->second->get());
109     }
110     return nullptr;
111 }
112 
113 } // namespace
114