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_CONSTRUCTOR
      9 #define SKSL_CONSTRUCTOR
     10 
     11 #include "SkSLExpression.h"
     12 #include "SkSLFloatLiteral.h"
     13 #include "SkSLIntLiteral.h"
     14 #include "SkSLIRGenerator.h"
     15 
     16 namespace SkSL {
     17 
     18 /**
     19  * Represents the construction of a compound type, such as "vec2(x, y)".
     20  *
     21  * Vector constructors will always consist of either exactly 1 scalar, or a collection of vectors
     22  * and scalars totalling exactly the right number of scalar components.
     23  *
     24  * Matrix constructors will always consist of either exactly 1 scalar, exactly 1 matrix, or a
     25  * collection of vectors and scalars totalling exactly the right number of scalar components.
     26  */
     27 struct Constructor : public Expression {
     28     Constructor(Position position, const Type& type,
     29                 std::vector<std::unique_ptr<Expression>> arguments)
     30     : INHERITED(position, kConstructor_Kind, type)
     31     , fArguments(std::move(arguments)) {}
     32 
     33     std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
     34                                                   const DefinitionMap& definitions) override {
     35         if (fArguments.size() == 1 && fArguments[0]->fKind == Expression::kIntLiteral_Kind) {
     36             if (fType == *irGenerator.fContext.fFloat_Type) {
     37                 // promote float(1) to 1.0
     38                 int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue;
     39                 return std::unique_ptr<Expression>(new FloatLiteral(irGenerator.fContext,
     40                                                                     fPosition,
     41                                                                     intValue));
     42             } else if (fType == *irGenerator.fContext.fUInt_Type) {
     43                 // promote uint(1) to 1u
     44                 int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue;
     45                 return std::unique_ptr<Expression>(new IntLiteral(irGenerator.fContext,
     46                                                                   fPosition,
     47                                                                   intValue,
     48                                                                   &fType));
     49             }
     50         }
     51         return nullptr;
     52     }
     53 
     54     bool hasSideEffects() const override {
     55         for (const auto& arg : fArguments) {
     56             if (arg->hasSideEffects()) {
     57                 return true;
     58             }
     59         }
     60         return false;
     61     }
     62 
     63     String description() const override {
     64         String result = fType.description() + "(";
     65         String separator;
     66         for (size_t i = 0; i < fArguments.size(); i++) {
     67             result += separator;
     68             result += fArguments[i]->description();
     69             separator = ", ";
     70         }
     71         result += ")";
     72         return result;
     73     }
     74 
     75     bool isConstant() const override {
     76         for (size_t i = 0; i < fArguments.size(); i++) {
     77             if (!fArguments[i]->isConstant()) {
     78                 return false;
     79             }
     80         }
     81         return true;
     82     }
     83 
     84     bool compareConstant(const Context& context, const Expression& other) const override {
     85         ASSERT(other.fKind == Expression::kConstructor_Kind && other.fType == fType);
     86         Constructor& c = (Constructor&) other;
     87         if (c.fType.kind() == Type::kVector_Kind) {
     88             for (int i = 0; i < fType.columns(); i++) {
     89                 if (!this->getVecComponent(i).compareConstant(context, c.getVecComponent(i))) {
     90                     return false;
     91                 }
     92             }
     93             return true;
     94         }
     95         // shouldn't be possible to have a constant constructor that isn't a vector or matrix;
     96         // a constant scalar constructor should have been collapsed down to the appropriate
     97         // literal
     98         ASSERT(fType.kind() == Type::kMatrix_Kind);
     99         const FloatLiteral fzero(context, Position(), 0);
    100         const IntLiteral izero(context, Position(), 0);
    101         const Expression* zero;
    102         if (fType.componentType() == *context.fFloat_Type) {
    103             zero = &fzero;
    104         } else {
    105             ASSERT(fType.componentType() == *context.fInt_Type);
    106             zero = &izero;
    107         }
    108         for (int col = 0; col < fType.columns(); col++) {
    109             for (int row = 0; row < fType.rows(); row++) {
    110                 const Expression* component1 = getMatComponent(col, row);
    111                 const Expression* component2 = c.getMatComponent(col, row);
    112                 if (!(component1 ? component1 : zero)->compareConstant(
    113                                                                 context,
    114                                                                 component2 ? *component2 : *zero)) {
    115                     return false;
    116                 }
    117             }
    118         }
    119         return true;
    120     }
    121 
    122     const Expression& getVecComponent(int index) const {
    123         ASSERT(fType.kind() == Type::kVector_Kind);
    124         if (fArguments.size() == 1 && fArguments[0]->fType.kind() == Type::kScalar_Kind) {
    125             return *fArguments[0];
    126         }
    127         int current = 0;
    128         for (const auto& arg : fArguments) {
    129             ASSERT(current <= index);
    130             if (arg->fType.kind() == Type::kScalar_Kind) {
    131                 if (index == current) {
    132                     return *arg;
    133                 }
    134                 current++;
    135             } else {
    136                 ASSERT(arg->fType.kind() == Type::kVector_Kind);
    137                 ASSERT(arg->fKind == Expression::kConstructor_Kind);
    138                 if (current + arg->fType.columns() > index) {
    139                     return ((const Constructor&) *arg).getVecComponent(index - current);
    140                 }
    141                 current += arg->fType.columns();
    142             }
    143         }
    144         ABORT("failed to find vector component %d in %s\n", index, description().c_str());
    145     }
    146 
    147     double getFVecComponent(int index) const {
    148         const Expression& c = this->getVecComponent(index);
    149         ASSERT(c.fKind == Expression::kFloatLiteral_Kind);
    150         return ((FloatLiteral&) c).fValue;
    151     }
    152 
    153     int64_t getIVecComponent(int index) const {
    154         const Expression& c = this->getVecComponent(index);
    155         ASSERT(c.fKind == Expression::kIntLiteral_Kind);
    156         return ((IntLiteral&) c).fValue;
    157     }
    158 
    159     // null return should be interpreted as zero
    160     const Expression* getMatComponent(int col, int row) const {
    161         ASSERT(this->isConstant());
    162         ASSERT(fType.kind() == Type::kMatrix_Kind);
    163         ASSERT(col < fType.columns() && row < fType.rows());
    164         if (fArguments.size() == 1) {
    165             if (fArguments[0]->fType.kind() == Type::kScalar_Kind) {
    166                 // single scalar argument, so matrix is of the form:
    167                 // x 0 0
    168                 // 0 x 0
    169                 // 0 0 x
    170                 // return x if col == row
    171                 return col == row ? fArguments[0].get() : nullptr;
    172             }
    173             if (fArguments[0]->fType.kind() == Type::kMatrix_Kind) {
    174                 ASSERT(fArguments[0]->fKind == Expression::kConstructor_Kind);
    175                 // single matrix argument. make sure we're within the argument's bounds.
    176                 const Type& argType = ((Constructor&) *fArguments[0]).fType;
    177                 if (col < argType.columns() && row < argType.rows()) {
    178                     // within bounds, defer to argument
    179                     return ((Constructor&) *fArguments[0]).getMatComponent(col, row);
    180                 }
    181                 // out of bounds, return 0
    182                 return nullptr;
    183             }
    184         }
    185         int currentIndex = 0;
    186         int targetIndex = col * fType.rows() + row;
    187         for (const auto& arg : fArguments) {
    188             ASSERT(targetIndex >= currentIndex);
    189             ASSERT(arg->fType.rows() == 1);
    190             if (currentIndex + arg->fType.columns() > targetIndex) {
    191                 if (arg->fType.columns() == 1) {
    192                     return arg.get();
    193                 } else {
    194                     ASSERT(arg->fType.kind() == Type::kVector_Kind);
    195                     ASSERT(arg->fKind == Expression::kConstructor_Kind);
    196                     return &((Constructor&) *arg).getVecComponent(targetIndex - currentIndex);
    197                 }
    198             }
    199             currentIndex += arg->fType.columns();
    200         }
    201         ABORT("can't happen, matrix component out of bounds");
    202     }
    203 
    204     std::vector<std::unique_ptr<Expression>> fArguments;
    205 
    206     typedef Expression INHERITED;
    207 };
    208 
    209 } // namespace
    210 
    211 #endif
    212