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 #include "src/sksl/ir/SkSLType.h"
9
10 #include "src/sksl/SkSLContext.h"
11 #include "src/sksl/ir/SkSLConstructor.h"
12 #include "src/sksl/ir/SkSLConstructorCompoundCast.h"
13 #include "src/sksl/ir/SkSLConstructorScalarCast.h"
14 #include "src/sksl/ir/SkSLFunctionReference.h"
15 #include "src/sksl/ir/SkSLSymbolTable.h"
16 #include "src/sksl/ir/SkSLType.h"
17 #include "src/sksl/ir/SkSLTypeReference.h"
18
19 namespace SkSL {
20
coercionCost(const Type & other) const21 CoercionCost Type::coercionCost(const Type& other) const {
22 if (*this == other) {
23 return CoercionCost::Free();
24 }
25 if (this->isVector() && other.isVector()) {
26 if (this->columns() == other.columns()) {
27 return this->componentType().coercionCost(other.componentType());
28 }
29 return CoercionCost::Impossible();
30 }
31 if (this->isMatrix()) {
32 if (this->columns() == other.columns() && this->rows() == other.rows()) {
33 return this->componentType().coercionCost(other.componentType());
34 }
35 return CoercionCost::Impossible();
36 }
37 if (this->isNumber() && other.isNumber()) {
38 if (this->isLiteral() && this->isInteger()) {
39 return CoercionCost::Free();
40 } else if (this->numberKind() != other.numberKind()) {
41 return CoercionCost::Impossible();
42 } else if (other.priority() >= this->priority()) {
43 return CoercionCost::Normal(other.priority() - this->priority());
44 } else {
45 return CoercionCost::Narrowing(this->priority() - other.priority());
46 }
47 }
48 for (size_t i = 0; i < fCoercibleTypes.size(); i++) {
49 if (*fCoercibleTypes[i] == other) {
50 return CoercionCost::Normal((int) i + 1);
51 }
52 }
53 return CoercionCost::Impossible();
54 }
55
toCompound(const Context & context,int columns,int rows) const56 const Type& Type::toCompound(const Context& context, int columns, int rows) const {
57 SkASSERT(this->isScalar());
58 if (columns == 1 && rows == 1) {
59 return *this;
60 }
61 if (*this == *context.fTypes.fFloat || *this == *context.fTypes.fFloatLiteral) {
62 switch (rows) {
63 case 1:
64 switch (columns) {
65 case 1: return *context.fTypes.fFloat;
66 case 2: return *context.fTypes.fFloat2;
67 case 3: return *context.fTypes.fFloat3;
68 case 4: return *context.fTypes.fFloat4;
69 default: SK_ABORT("unsupported vector column count (%d)", columns);
70 }
71 case 2:
72 switch (columns) {
73 case 2: return *context.fTypes.fFloat2x2;
74 case 3: return *context.fTypes.fFloat3x2;
75 case 4: return *context.fTypes.fFloat4x2;
76 default: SK_ABORT("unsupported matrix column count (%d)", columns);
77 }
78 case 3:
79 switch (columns) {
80 case 2: return *context.fTypes.fFloat2x3;
81 case 3: return *context.fTypes.fFloat3x3;
82 case 4: return *context.fTypes.fFloat4x3;
83 default: SK_ABORT("unsupported matrix column count (%d)", columns);
84 }
85 case 4:
86 switch (columns) {
87 case 2: return *context.fTypes.fFloat2x4;
88 case 3: return *context.fTypes.fFloat3x4;
89 case 4: return *context.fTypes.fFloat4x4;
90 default: SK_ABORT("unsupported matrix column count (%d)", columns);
91 }
92 default: SK_ABORT("unsupported row count (%d)", rows);
93 }
94 } else if (*this == *context.fTypes.fHalf) {
95 switch (rows) {
96 case 1:
97 switch (columns) {
98 case 1: return *context.fTypes.fHalf;
99 case 2: return *context.fTypes.fHalf2;
100 case 3: return *context.fTypes.fHalf3;
101 case 4: return *context.fTypes.fHalf4;
102 default: SK_ABORT("unsupported vector column count (%d)", columns);
103 }
104 case 2:
105 switch (columns) {
106 case 2: return *context.fTypes.fHalf2x2;
107 case 3: return *context.fTypes.fHalf3x2;
108 case 4: return *context.fTypes.fHalf4x2;
109 default: SK_ABORT("unsupported matrix column count (%d)", columns);
110 }
111 case 3:
112 switch (columns) {
113 case 2: return *context.fTypes.fHalf2x3;
114 case 3: return *context.fTypes.fHalf3x3;
115 case 4: return *context.fTypes.fHalf4x3;
116 default: SK_ABORT("unsupported matrix column count (%d)", columns);
117 }
118 case 4:
119 switch (columns) {
120 case 2: return *context.fTypes.fHalf2x4;
121 case 3: return *context.fTypes.fHalf3x4;
122 case 4: return *context.fTypes.fHalf4x4;
123 default: SK_ABORT("unsupported matrix column count (%d)", columns);
124 }
125 default: SK_ABORT("unsupported row count (%d)", rows);
126 }
127 } else if (*this == *context.fTypes.fInt || *this == *context.fTypes.fIntLiteral) {
128 switch (rows) {
129 case 1:
130 switch (columns) {
131 case 1: return *context.fTypes.fInt;
132 case 2: return *context.fTypes.fInt2;
133 case 3: return *context.fTypes.fInt3;
134 case 4: return *context.fTypes.fInt4;
135 default: SK_ABORT("unsupported vector column count (%d)", columns);
136 }
137 default: SK_ABORT("unsupported row count (%d)", rows);
138 }
139 } else if (*this == *context.fTypes.fShort) {
140 switch (rows) {
141 case 1:
142 switch (columns) {
143 case 1: return *context.fTypes.fShort;
144 case 2: return *context.fTypes.fShort2;
145 case 3: return *context.fTypes.fShort3;
146 case 4: return *context.fTypes.fShort4;
147 default: SK_ABORT("unsupported vector column count (%d)", columns);
148 }
149 default: SK_ABORT("unsupported row count (%d)", rows);
150 }
151 } else if (*this == *context.fTypes.fUInt) {
152 switch (rows) {
153 case 1:
154 switch (columns) {
155 case 1: return *context.fTypes.fUInt;
156 case 2: return *context.fTypes.fUInt2;
157 case 3: return *context.fTypes.fUInt3;
158 case 4: return *context.fTypes.fUInt4;
159 default: SK_ABORT("unsupported vector column count (%d)", columns);
160 }
161 default: SK_ABORT("unsupported row count (%d)", rows);
162 }
163 } else if (*this == *context.fTypes.fUShort) {
164 switch (rows) {
165 case 1:
166 switch (columns) {
167 case 1: return *context.fTypes.fUShort;
168 case 2: return *context.fTypes.fUShort2;
169 case 3: return *context.fTypes.fUShort3;
170 case 4: return *context.fTypes.fUShort4;
171 default: SK_ABORT("unsupported vector column count (%d)", columns);
172 }
173 default: SK_ABORT("unsupported row count (%d)", rows);
174 }
175 } else if (*this == *context.fTypes.fBool) {
176 switch (rows) {
177 case 1:
178 switch (columns) {
179 case 1: return *context.fTypes.fBool;
180 case 2: return *context.fTypes.fBool2;
181 case 3: return *context.fTypes.fBool3;
182 case 4: return *context.fTypes.fBool4;
183 default: SK_ABORT("unsupported vector column count (%d)", columns);
184 }
185 default: SK_ABORT("unsupported row count (%d)", rows);
186 }
187 }
188 SkDEBUGFAILF("unsupported toCompound type %s", this->description().c_str());
189 return *context.fTypes.fVoid;
190 }
191
clone(SymbolTable * symbolTable) const192 const Type* Type::clone(SymbolTable* symbolTable) const {
193 // Many types are built-ins, and exist in every SymbolTable by default.
194 if (this->isInBuiltinTypes()) {
195 return this;
196 }
197 // Even if the type isn't a built-in, it might already exist in the SymbolTable.
198 const Symbol* clonedSymbol = (*symbolTable)[this->name()];
199 if (clonedSymbol != nullptr) {
200 const Type& clonedType = clonedSymbol->as<Type>();
201 SkASSERT(clonedType.typeKind() == this->typeKind());
202 return &clonedType;
203 }
204 // This type actually needs to be cloned into the destination SymbolTable.
205 switch (this->typeKind()) {
206 case TypeKind::kArray:
207 return symbolTable->add(Type::MakeArrayType(this->name(), this->componentType(),
208 this->columns()));
209
210 case TypeKind::kStruct:
211 return symbolTable->add(Type::MakeStructType(this->fOffset, this->name(),
212 this->fields()));
213
214 case TypeKind::kEnum:
215 return symbolTable->add(Type::MakeEnumType(this->name()));
216
217 default:
218 SkDEBUGFAILF("don't know how to clone type '%s'", this->description().c_str());
219 return nullptr;
220 }
221 }
222
coerceExpression(std::unique_ptr<Expression> expr,const Context & context) const223 std::unique_ptr<Expression> Type::coerceExpression(std::unique_ptr<Expression> expr,
224 const Context& context) const {
225 if (!expr) {
226 return nullptr;
227 }
228 const int offset = expr->fOffset;
229 if (expr->is<FunctionReference>()) {
230 context.fErrors.error(offset, "expected '(' to begin function call");
231 return nullptr;
232 }
233 if (expr->is<TypeReference>()) {
234 context.fErrors.error(offset, "expected '(' to begin constructor invocation");
235 return nullptr;
236 }
237 if (expr->type() == *this) {
238 return expr;
239 }
240
241 const Program::Settings& settings = context.fConfig->fSettings;
242 if (!expr->coercionCost(*this).isPossible(settings.fAllowNarrowingConversions)) {
243 context.fErrors.error(offset, "expected '" + this->displayName() + "', but found '" +
244 expr->type().displayName() + "'");
245 return nullptr;
246 }
247
248 if (this->isScalar()) {
249 return ConstructorScalarCast::Make(context, offset, *this, std::move(expr));
250 }
251 if (this->isVector() || this->isMatrix()) {
252 return ConstructorCompoundCast::Make(context, offset, *this, std::move(expr));
253 }
254 context.fErrors.error(offset, "cannot construct '" + this->displayName() + "'");
255 return nullptr;
256 }
257
isOrContainsArray() const258 bool Type::isOrContainsArray() const {
259 if (this->isStruct()) {
260 for (const Field& f : this->fields()) {
261 if (f.fType->isOrContainsArray()) {
262 return true;
263 }
264 }
265 return false;
266 }
267
268 return this->isArray();
269 }
270
271
272 } // namespace SkSL
273