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 { ConstructorConstructor28 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 constantPropagateConstructor33 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 hasSideEffectsConstructor54 bool hasSideEffects() const override { 55 for (const auto& arg : fArguments) { 56 if (arg->hasSideEffects()) { 57 return true; 58 } 59 } 60 return false; 61 } 62 descriptionConstructor63 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 isConstantConstructor75 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 compareConstantConstructor84 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 getVecComponentConstructor122 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 getFVecComponentConstructor147 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 getIVecComponentConstructor153 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 getMatComponentConstructor160 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