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 != kRead_RefKind) {
     49             fVariable.fWriteCount--;
     50         }
     51         if (fRefKind != kWrite_RefKind) {
     52             fVariable.fReadCount--;
     53         }
     54     }
     55 
     56     RefKind refKind() {
     57         return fRefKind;
     58     }
     59 
     60     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 
     76     bool hasSideEffects() const override {
     77         return false;
     78     }
     79 
     80     bool isConstant() const override {
     81         return 0 != (fVariable.fModifiers.fFlags & Modifiers::kConst_Flag);
     82     }
     83 
     84     String description() const override {
     85         return fVariable.fName;
     86     }
     87 
     88     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 
    125     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