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 "float2(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 {
ConstructorConstructor28     Constructor(int offset, const Type& type, std::vector<std::unique_ptr<Expression>> arguments)
29     : INHERITED(offset, kConstructor_Kind, type)
30     , fArguments(std::move(arguments)) {}
31 
constantPropagateConstructor32     std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
33                                                   const DefinitionMap& definitions) override {
34         if (fArguments.size() == 1 && fArguments[0]->fKind == Expression::kIntLiteral_Kind) {
35             if (fType.isFloat()) {
36                 // promote float(1) to 1.0
37                 int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue;
38                 return std::unique_ptr<Expression>(new FloatLiteral(irGenerator.fContext,
39                                                                     fOffset,
40                                                                     intValue));
41             } else if (fType.isInteger()) {
42                 // promote uint(1) to 1u
43                 int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue;
44                 return std::unique_ptr<Expression>(new IntLiteral(fOffset,
45                                                                   intValue,
46                                                                   &fType));
47             }
48         }
49         return nullptr;
50     }
51 
hasSideEffectsConstructor52     bool hasSideEffects() const override {
53         for (const auto& arg : fArguments) {
54             if (arg->hasSideEffects()) {
55                 return true;
56             }
57         }
58         return false;
59     }
60 
cloneConstructor61     std::unique_ptr<Expression> clone() const override {
62         std::vector<std::unique_ptr<Expression>> cloned;
63         for (const auto& arg : fArguments) {
64             cloned.push_back(arg->clone());
65         }
66         return std::unique_ptr<Expression>(new Constructor(fOffset, fType, std::move(cloned)));
67     }
68 
descriptionConstructor69     String description() const override {
70         String result = fType.description() + "(";
71         String separator;
72         for (size_t i = 0; i < fArguments.size(); i++) {
73             result += separator;
74             result += fArguments[i]->description();
75             separator = ", ";
76         }
77         result += ")";
78         return result;
79     }
80 
isConstantConstructor81     bool isConstant() const override {
82         for (size_t i = 0; i < fArguments.size(); i++) {
83             if (!fArguments[i]->isConstant()) {
84                 return false;
85             }
86         }
87         return true;
88     }
89 
compareConstantConstructor90     bool compareConstant(const Context& context, const Expression& other) const override {
91         SkASSERT(other.fKind == Expression::kConstructor_Kind && other.fType == fType);
92         Constructor& c = (Constructor&) other;
93         if (c.fType.kind() == Type::kVector_Kind) {
94             for (int i = 0; i < fType.columns(); i++) {
95                 if (!this->getVecComponent(i).compareConstant(context, c.getVecComponent(i))) {
96                     return false;
97                 }
98             }
99             return true;
100         }
101         // shouldn't be possible to have a constant constructor that isn't a vector or matrix;
102         // a constant scalar constructor should have been collapsed down to the appropriate
103         // literal
104         SkASSERT(fType.kind() == Type::kMatrix_Kind);
105         const FloatLiteral fzero(context, -1, 0);
106         const IntLiteral izero(context, -1, 0);
107         const Expression* zero;
108         if (fType.componentType().isFloat()) {
109             zero = &fzero;
110         } else {
111             SkASSERT(fType.componentType().isInteger());
112             zero = &izero;
113         }
114         for (int col = 0; col < fType.columns(); col++) {
115             for (int row = 0; row < fType.rows(); row++) {
116                 const Expression* component1 = getMatComponent(col, row);
117                 const Expression* component2 = c.getMatComponent(col, row);
118                 if (!(component1 ? component1 : zero)->compareConstant(
119                                                                 context,
120                                                                 component2 ? *component2 : *zero)) {
121                     return false;
122                 }
123             }
124         }
125         return true;
126     }
127 
getVecComponentConstructor128     const Expression& getVecComponent(int index) const {
129         SkASSERT(fType.kind() == Type::kVector_Kind);
130         if (fArguments.size() == 1 && fArguments[0]->fType.kind() == Type::kScalar_Kind) {
131             return *fArguments[0];
132         }
133         int current = 0;
134         for (const auto& arg : fArguments) {
135             SkASSERT(current <= index);
136             if (arg->fType.kind() == Type::kScalar_Kind) {
137                 if (index == current) {
138                     return *arg;
139                 }
140                 current++;
141             } else {
142                 SkASSERT(arg->fType.kind() == Type::kVector_Kind);
143                 SkASSERT(arg->fKind == Expression::kConstructor_Kind);
144                 if (current + arg->fType.columns() > index) {
145                     return ((const Constructor&) *arg).getVecComponent(index - current);
146                 }
147                 current += arg->fType.columns();
148             }
149         }
150         ABORT("failed to find vector component %d in %s\n", index, description().c_str());
151     }
152 
getFVecComponentConstructor153     double getFVecComponent(int index) const {
154         return this->getVecComponent(index).getConstantFloat();
155     }
156 
getIVecComponentConstructor157     int64_t getIVecComponent(int index) const {
158         return this->getVecComponent(index).getConstantInt();
159     }
160 
161     // null return should be interpreted as zero
getMatComponentConstructor162     const Expression* getMatComponent(int col, int row) const {
163         SkASSERT(this->isConstant());
164         SkASSERT(fType.kind() == Type::kMatrix_Kind);
165         SkASSERT(col < fType.columns() && row < fType.rows());
166         if (fArguments.size() == 1) {
167             if (fArguments[0]->fType.kind() == Type::kScalar_Kind) {
168                 // single scalar argument, so matrix is of the form:
169                 // x 0 0
170                 // 0 x 0
171                 // 0 0 x
172                 // return x if col == row
173                 return col == row ? fArguments[0].get() : nullptr;
174             }
175             if (fArguments[0]->fType.kind() == Type::kMatrix_Kind) {
176                 SkASSERT(fArguments[0]->fKind == Expression::kConstructor_Kind);
177                 // single matrix argument. make sure we're within the argument's bounds.
178                 const Type& argType = ((Constructor&) *fArguments[0]).fType;
179                 if (col < argType.columns() && row < argType.rows()) {
180                     // within bounds, defer to argument
181                     return ((Constructor&) *fArguments[0]).getMatComponent(col, row);
182                 }
183                 // out of bounds, return 0
184                 return nullptr;
185             }
186         }
187         int currentIndex = 0;
188         int targetIndex = col * fType.rows() + row;
189         for (const auto& arg : fArguments) {
190             SkASSERT(targetIndex >= currentIndex);
191             SkASSERT(arg->fType.rows() == 1);
192             if (currentIndex + arg->fType.columns() > targetIndex) {
193                 if (arg->fType.columns() == 1) {
194                     return arg.get();
195                 } else {
196                     SkASSERT(arg->fType.kind() == Type::kVector_Kind);
197                     SkASSERT(arg->fKind == Expression::kConstructor_Kind);
198                     return &((Constructor&) *arg).getVecComponent(targetIndex - currentIndex);
199                 }
200             }
201             currentIndex += arg->fType.columns();
202         }
203         ABORT("can't happen, matrix component out of bounds");
204     }
205 
206     std::vector<std::unique_ptr<Expression>> fArguments;
207 
208     typedef Expression INHERITED;
209 };
210 
211 } // namespace
212 
213 #endif
214