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