Home | History | Annotate | Download | only in ir
      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 
     47     ~VariableReference() override {
     48         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     }
     72 
     73     bool hasSideEffects() const override {
     74         return false;
     75     }
     76 
     77     bool isConstant() const override {
     78         return 0 != (fVariable.fModifiers.fFlags & Modifiers::kConst_Flag);
     79     }
     80 
     81     String description() const override {
     82         return fVariable.fName;
     83     }
     84 
     85     static std::unique_ptr<Expression> copy_constant(const IRGenerator& irGenerator,
     86                                                      const Expression* expr) {
     87         ASSERT(expr->isConstant());
     88         switch (expr->fKind) {
     89             case Expression::kIntLiteral_Kind:
     90                 return std::unique_ptr<Expression>(new IntLiteral(irGenerator.fContext,
     91                                                                   -1,
     92                                                                   ((IntLiteral*) expr)->fValue));
     93             case Expression::kFloatLiteral_Kind:
     94                 return std::unique_ptr<Expression>(new FloatLiteral(
     95                                                                    irGenerator.fContext,
     96                                                                    -1,
     97                                                                    ((FloatLiteral*) expr)->fValue));
     98             case Expression::kBoolLiteral_Kind:
     99                 return std::unique_ptr<Expression>(new BoolLiteral(irGenerator.fContext,
    100                                                                    -1,
    101                                                                    ((BoolLiteral*) expr)->fValue));
    102             case Expression::kConstructor_Kind: {
    103                 const Constructor* c = (const Constructor*) expr;
    104                 std::vector<std::unique_ptr<Expression>> args;
    105                 for (const auto& arg : c->fArguments) {
    106                     args.push_back(copy_constant(irGenerator, arg.get()));
    107                 }
    108                 return std::unique_ptr<Expression>(new Constructor(-1, c->fType,
    109                                                                    std::move(args)));
    110             }
    111             case Expression::kSetting_Kind: {
    112                 const Setting* s = (const Setting*) expr;
    113                 return std::unique_ptr<Expression>(new Setting(-1, s->fName,
    114                                                                copy_constant(irGenerator,
    115                                                                              s->fValue.get())));
    116             }
    117             default:
    118                 ABORT("unsupported constant\n");
    119         }
    120     }
    121 
    122     std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
    123                                                   const DefinitionMap& definitions) override {
    124         if (fRefKind != kRead_RefKind) {
    125             return nullptr;
    126         }
    127         if ((fVariable.fModifiers.fFlags & Modifiers::kConst_Flag) && fVariable.fInitialValue &&
    128             fVariable.fInitialValue->isConstant()) {
    129             return copy_constant(irGenerator, fVariable.fInitialValue);
    130         }
    131         auto exprIter = definitions.find(&fVariable);
    132         if (exprIter != definitions.end() && exprIter->second &&
    133             (*exprIter->second)->isConstant()) {
    134             return copy_constant(irGenerator, exprIter->second->get());
    135         }
    136         return nullptr;
    137     }
    138 
    139     const Variable& fVariable;
    140     RefKind fRefKind;
    141 
    142 private:
    143     typedef Expression INHERITED;
    144 };
    145 
    146 } // namespace
    147 
    148 #endif
    149