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/SkSLConstantFolder.h"
11 #include "src/sksl/SkSLContext.h"
12 #include "src/sksl/SkSLProgramSettings.h"
13 #include "src/sksl/ir/SkSLConstructor.h"
14 #include "src/sksl/ir/SkSLConstructorArrayCast.h"
15 #include "src/sksl/ir/SkSLConstructorCompoundCast.h"
16 #include "src/sksl/ir/SkSLConstructorScalarCast.h"
17 #include "src/sksl/ir/SkSLProgram.h"
18 #include "src/sksl/ir/SkSLSymbolTable.h"
19 #include "src/sksl/ir/SkSLType.h"
20
21 namespace SkSL {
22
23 static constexpr int kMaxStructDepth = 8;
24
25 class ArrayType final : public Type {
26 public:
27 inline static constexpr TypeKind kTypeKind = TypeKind::kArray;
28
ArrayType(skstd::string_view name,const char * abbrev,const Type & componentType,int count)29 ArrayType(skstd::string_view name, const char* abbrev, const Type& componentType, int count)
30 : INHERITED(name, abbrev, kTypeKind)
31 , fComponentType(componentType)
32 , fCount(count) {
33 #ifdef SKSL_EXT
34 SkASSERT(count > 0 || count == kUnsizedArray);
35 #else
36 // Only allow explicitly-sized arrays.
37 SkASSERT(count > 0);
38 #endif
39 // Disallow multi-dimensional arrays.
40 SkASSERT(!componentType.is<ArrayType>());
41 }
42
isArray() const43 bool isArray() const override {
44 return true;
45 }
46
47 #ifdef SKSL_EXT
isUnsizedArray() const48 bool isUnsizedArray() const override {
49 return fCount == kUnsizedArray;
50 }
51 #endif
52
componentType() const53 const Type& componentType() const override {
54 return fComponentType;
55 }
56
columns() const57 int columns() const override {
58 return fCount;
59 }
60
bitWidth() const61 int bitWidth() const override {
62 return this->componentType().bitWidth();
63 }
64
isPrivate() const65 bool isPrivate() const override {
66 return fComponentType.isPrivate();
67 }
68
isAllowedInES2() const69 bool isAllowedInES2() const override {
70 return fComponentType.isAllowedInES2();
71 }
72
slotCount() const73 size_t slotCount() const override {
74 SkASSERT(fCount > 0);
75 return fCount * fComponentType.slotCount();
76 }
77
78 private:
79 using INHERITED = Type;
80
81 const Type& fComponentType;
82 int fCount;
83 };
84
85 class GenericType final : public Type {
86 public:
87 inline static constexpr TypeKind kTypeKind = TypeKind::kGeneric;
88
GenericType(const char * name,std::vector<const Type * > coercibleTypes)89 GenericType(const char* name, std::vector<const Type*> coercibleTypes)
90 : INHERITED(name, "G", kTypeKind)
91 , fCoercibleTypes(std::move(coercibleTypes)) {}
92
coercibleTypes() const93 const std::vector<const Type*>& coercibleTypes() const override {
94 return fCoercibleTypes;
95 }
96
97 private:
98 using INHERITED = Type;
99
100 std::vector<const Type*> fCoercibleTypes;
101 };
102
103 class LiteralType : public Type {
104 public:
105 inline static constexpr TypeKind kTypeKind = TypeKind::kLiteral;
106
LiteralType(const char * name,const Type & scalarType,int8_t priority)107 LiteralType(const char* name, const Type& scalarType, int8_t priority)
108 : INHERITED(name, "L", kTypeKind)
109 , fScalarType(scalarType)
110 , fPriority(priority) {}
111
scalarTypeForLiteral() const112 const Type& scalarTypeForLiteral() const override {
113 return fScalarType;
114 }
115
priority() const116 int priority() const override {
117 return fPriority;
118 }
119
columns() const120 int columns() const override {
121 return 1;
122 }
123
rows() const124 int rows() const override {
125 return 1;
126 }
127
numberKind() const128 NumberKind numberKind() const override {
129 return fScalarType.numberKind();
130 }
131
bitWidth() const132 int bitWidth() const override {
133 return fScalarType.bitWidth();
134 }
135
isScalar() const136 bool isScalar() const override {
137 return true;
138 }
139
isLiteral() const140 bool isLiteral() const override {
141 return true;
142 }
143
slotCount() const144 size_t slotCount() const override {
145 return 1;
146 }
147
148 private:
149 using INHERITED = Type;
150
151 const Type& fScalarType;
152 int8_t fPriority;
153 };
154
155
156 class ScalarType final : public Type {
157 public:
158 inline static constexpr TypeKind kTypeKind = TypeKind::kScalar;
159
ScalarType(skstd::string_view name,const char * abbrev,NumberKind numberKind,int8_t priority,int8_t bitWidth)160 ScalarType(skstd::string_view name, const char* abbrev, NumberKind numberKind, int8_t priority,
161 int8_t bitWidth)
162 : INHERITED(name, abbrev, kTypeKind)
163 , fNumberKind(numberKind)
164 , fPriority(priority)
165 , fBitWidth(bitWidth) {}
166
numberKind() const167 NumberKind numberKind() const override {
168 return fNumberKind;
169 }
170
priority() const171 int priority() const override {
172 return fPriority;
173 }
174
bitWidth() const175 int bitWidth() const override {
176 return fBitWidth;
177 }
178
columns() const179 int columns() const override {
180 return 1;
181 }
182
rows() const183 int rows() const override {
184 return 1;
185 }
186
isScalar() const187 bool isScalar() const override {
188 return true;
189 }
190
isAllowedInES2() const191 bool isAllowedInES2() const override {
192 return fNumberKind != NumberKind::kUnsigned;
193 }
194
slotCount() const195 size_t slotCount() const override {
196 return 1;
197 }
198
199 private:
200 using INHERITED = Type;
201
202 NumberKind fNumberKind;
203 int8_t fPriority;
204 int8_t fBitWidth;
205 };
206
207 class MatrixType final : public Type {
208 public:
209 inline static constexpr TypeKind kTypeKind = TypeKind::kMatrix;
210
MatrixType(skstd::string_view name,const char * abbrev,const Type & componentType,int8_t columns,int8_t rows)211 MatrixType(skstd::string_view name, const char* abbrev, const Type& componentType,
212 int8_t columns, int8_t rows)
213 : INHERITED(name, abbrev, kTypeKind)
214 , fComponentType(componentType.as<ScalarType>())
215 , fColumns(columns)
216 , fRows(rows) {
217 SkASSERT(columns >= 2 && columns <= 4);
218 SkASSERT(rows >= 2 && rows <= 4);
219 }
220
componentType() const221 const ScalarType& componentType() const override {
222 return fComponentType;
223 }
224
columns() const225 int columns() const override {
226 return fColumns;
227 }
228
rows() const229 int rows() const override {
230 return fRows;
231 }
232
bitWidth() const233 int bitWidth() const override {
234 return this->componentType().bitWidth();
235 }
236
isMatrix() const237 bool isMatrix() const override {
238 return true;
239 }
240
isAllowedInES2() const241 bool isAllowedInES2() const override {
242 return fColumns == fRows;
243 }
244
slotCount() const245 size_t slotCount() const override {
246 return fColumns * fRows;
247 }
248
249 private:
250 using INHERITED = Type;
251
252 const ScalarType& fComponentType;
253 int8_t fColumns;
254 int8_t fRows;
255 };
256
257 class TextureType final : public Type {
258 public:
259 inline static constexpr TypeKind kTypeKind = TypeKind::kTexture;
260
TextureType(const char * name,SpvDim_ dimensions,bool isDepth,bool isArrayed,bool isMultisampled,bool isSampled)261 TextureType(const char* name, SpvDim_ dimensions, bool isDepth, bool isArrayed,
262 bool isMultisampled, bool isSampled)
263 : INHERITED(name, "T", kTypeKind)
264 , fDimensions(dimensions)
265 , fIsDepth(isDepth)
266 , fIsArrayed(isArrayed)
267 , fIsMultisampled(isMultisampled)
268 , fIsSampled(isSampled) {}
269
dimensions() const270 SpvDim_ dimensions() const override {
271 return fDimensions;
272 }
273
isDepth() const274 bool isDepth() const override {
275 return fIsDepth;
276 }
277
isArrayedTexture() const278 bool isArrayedTexture() const override {
279 return fIsArrayed;
280 }
281
isMultisampled() const282 bool isMultisampled() const override {
283 return fIsMultisampled;
284 }
285
isSampled() const286 bool isSampled() const override {
287 return fIsSampled;
288 }
289
290 private:
291 using INHERITED = Type;
292
293 SpvDim_ fDimensions;
294 bool fIsDepth;
295 bool fIsArrayed;
296 bool fIsMultisampled;
297 bool fIsSampled;
298 };
299
300 class SamplerType final : public Type {
301 public:
302 inline static constexpr TypeKind kTypeKind = TypeKind::kSampler;
303
SamplerType(const char * name,const Type & textureType)304 SamplerType(const char* name, const Type& textureType)
305 : INHERITED(name, "Z", kTypeKind)
306 , fTextureType(textureType.as<TextureType>()) {}
307
textureType() const308 const TextureType& textureType() const override {
309 return fTextureType;
310 }
311
dimensions() const312 SpvDim_ dimensions() const override {
313 return fTextureType.dimensions();
314 }
315
isDepth() const316 bool isDepth() const override {
317 return fTextureType.isDepth();
318 }
319
isArrayedTexture() const320 bool isArrayedTexture() const override {
321 return fTextureType.isArrayedTexture();
322 }
323
isMultisampled() const324 bool isMultisampled() const override {
325 return fTextureType.isMultisampled();
326 }
327
isSampled() const328 bool isSampled() const override {
329 return fTextureType.isSampled();
330 }
331
332 private:
333 using INHERITED = Type;
334
335 const TextureType& fTextureType;
336 };
337
338 class StructType final : public Type {
339 public:
340 inline static constexpr TypeKind kTypeKind = TypeKind::kStruct;
341
StructType(int line,skstd::string_view name,std::vector<Field> fields)342 StructType(int line, skstd::string_view name, std::vector<Field> fields)
343 : INHERITED(std::move(name), "S", kTypeKind, line)
344 , fFields(std::move(fields)) {}
345
fields() const346 const std::vector<Field>& fields() const override {
347 return fFields;
348 }
349
isStruct() const350 bool isStruct() const override {
351 return true;
352 }
353
isPrivate() const354 bool isPrivate() const override {
355 return std::any_of(fFields.begin(), fFields.end(), [](const Field& f) {
356 return f.fType->isPrivate();
357 });
358 }
359
isAllowedInES2() const360 bool isAllowedInES2() const override {
361 return std::all_of(fFields.begin(), fFields.end(), [](const Field& f) {
362 return f.fType->isAllowedInES2();
363 });
364 }
365
slotCount() const366 size_t slotCount() const override {
367 size_t slots = 0;
368 for (const Field& field : fFields) {
369 slots += field.fType->slotCount();
370 }
371 return slots;
372 }
373
374 private:
375 using INHERITED = Type;
376
377 std::vector<Field> fFields;
378 };
379
380 class VectorType final : public Type {
381 public:
382 inline static constexpr TypeKind kTypeKind = TypeKind::kVector;
383
VectorType(skstd::string_view name,const char * abbrev,const Type & componentType,int8_t columns)384 VectorType(skstd::string_view name, const char* abbrev, const Type& componentType,
385 int8_t columns)
386 : INHERITED(name, abbrev, kTypeKind)
387 , fComponentType(componentType.as<ScalarType>())
388 , fColumns(columns) {
389 SkASSERT(columns >= 2 && columns <= 4);
390 }
391
componentType() const392 const ScalarType& componentType() const override {
393 return fComponentType;
394 }
395
columns() const396 int columns() const override {
397 return fColumns;
398 }
399
rows() const400 int rows() const override {
401 return 1;
402 }
403
bitWidth() const404 int bitWidth() const override {
405 return this->componentType().bitWidth();
406 }
407
isVector() const408 bool isVector() const override {
409 return true;
410 }
411
isAllowedInES2() const412 bool isAllowedInES2() const override {
413 return fComponentType.isAllowedInES2();
414 }
415
slotCount() const416 size_t slotCount() const override {
417 return fColumns;
418 }
419
420 private:
421 using INHERITED = Type;
422
423 const ScalarType& fComponentType;
424 int8_t fColumns;
425 };
426
getArrayName(int arraySize) const427 String Type::getArrayName(int arraySize) const {
428 skstd::string_view name = this->name();
429 return String::printf("%.*s[%d]", (int)name.size(), name.data(), arraySize);
430 }
431
MakeArrayType(skstd::string_view name,const Type & componentType,int columns)432 std::unique_ptr<Type> Type::MakeArrayType(skstd::string_view name, const Type& componentType,
433 int columns) {
434 return std::make_unique<ArrayType>(std::move(name), componentType.abbreviatedName(),
435 componentType, columns);
436 }
437
MakeGenericType(const char * name,std::vector<const Type * > types)438 std::unique_ptr<Type> Type::MakeGenericType(const char* name, std::vector<const Type*> types) {
439 return std::make_unique<GenericType>(name, std::move(types));
440 }
441
MakeLiteralType(const char * name,const Type & scalarType,int8_t priority)442 std::unique_ptr<Type> Type::MakeLiteralType(const char* name, const Type& scalarType,
443 int8_t priority) {
444 return std::make_unique<LiteralType>(name, scalarType, priority);
445 }
446
MakeMatrixType(skstd::string_view name,const char * abbrev,const Type & componentType,int columns,int8_t rows)447 std::unique_ptr<Type> Type::MakeMatrixType(skstd::string_view name, const char* abbrev,
448 const Type& componentType, int columns, int8_t rows) {
449 return std::make_unique<MatrixType>(name, abbrev, componentType, columns, rows);
450 }
451
MakeSamplerType(const char * name,const Type & textureType)452 std::unique_ptr<Type> Type::MakeSamplerType(const char* name, const Type& textureType) {
453 return std::make_unique<SamplerType>(name, textureType);
454 }
455
MakeSpecialType(const char * name,const char * abbrev,Type::TypeKind typeKind)456 std::unique_ptr<Type> Type::MakeSpecialType(const char* name, const char* abbrev,
457 Type::TypeKind typeKind) {
458 return std::unique_ptr<Type>(new Type(name, abbrev, typeKind));
459 }
460
MakeScalarType(skstd::string_view name,const char * abbrev,Type::NumberKind numberKind,int8_t priority,int8_t bitWidth)461 std::unique_ptr<Type> Type::MakeScalarType(skstd::string_view name, const char* abbrev,
462 Type::NumberKind numberKind, int8_t priority,
463 int8_t bitWidth) {
464 return std::make_unique<ScalarType>(name, abbrev, numberKind, priority, bitWidth);
465
466 }
467
MakeStructType(int line,skstd::string_view name,std::vector<Field> fields)468 std::unique_ptr<Type> Type::MakeStructType(int line, skstd::string_view name,
469 std::vector<Field> fields) {
470 return std::make_unique<StructType>(line, name, std::move(fields));
471 }
472
MakeTextureType(const char * name,SpvDim_ dimensions,bool isDepth,bool isArrayedTexture,bool isMultisampled,bool isSampled)473 std::unique_ptr<Type> Type::MakeTextureType(const char* name, SpvDim_ dimensions, bool isDepth,
474 bool isArrayedTexture, bool isMultisampled,
475 bool isSampled) {
476 return std::make_unique<TextureType>(name, dimensions, isDepth, isArrayedTexture,
477 isMultisampled, isSampled);
478 }
479
MakeVectorType(skstd::string_view name,const char * abbrev,const Type & componentType,int columns)480 std::unique_ptr<Type> Type::MakeVectorType(skstd::string_view name, const char* abbrev,
481 const Type& componentType, int columns) {
482 return std::make_unique<VectorType>(name, abbrev, componentType, columns);
483 }
484
coercionCost(const Type & other) const485 CoercionCost Type::coercionCost(const Type& other) const {
486 if (*this == other) {
487 return CoercionCost::Free();
488 }
489 if (this->typeKind() == other.typeKind() &&
490 (this->isVector() || this->isMatrix() || this->isArray())) {
491 // Vectors/matrices/arrays of the same size can be coerced if their component type can be.
492 if (this->isMatrix() && (this->rows() != other.rows())) {
493 return CoercionCost::Impossible();
494 }
495 if (this->columns() != other.columns()) {
496 return CoercionCost::Impossible();
497 }
498 return this->componentType().coercionCost(other.componentType());
499 }
500 if (this->isNumber() && other.isNumber()) {
501 if (this->isLiteral() && this->isInteger()) {
502 return CoercionCost::Free();
503 #ifndef SKSL_EXT
504 } else if (this->numberKind() != other.numberKind()) {
505 return CoercionCost::Impossible();
506 #endif
507 } else if (other.priority() >= this->priority()) {
508 return CoercionCost::Normal(other.priority() - this->priority());
509 } else {
510 return CoercionCost::Narrowing(this->priority() - other.priority());
511 }
512 }
513 if (fTypeKind == TypeKind::kGeneric) {
514 const std::vector<const Type*>& types = this->coercibleTypes();
515 for (size_t i = 0; i < types.size(); i++) {
516 if (*types[i] == other) {
517 return CoercionCost::Normal((int) i + 1);
518 }
519 }
520 }
521 return CoercionCost::Impossible();
522 }
523
applyPrecisionQualifiers(const Context & context,Modifiers * modifiers,SymbolTable * symbols,int line) const524 const Type* Type::applyPrecisionQualifiers(const Context& context,
525 Modifiers* modifiers,
526 SymbolTable* symbols,
527 int line) const {
528 // SkSL doesn't support low precision, so `lowp` is interpreted as medium precision.
529 bool highp = modifiers->fFlags & Modifiers::kHighp_Flag;
530 bool mediump = modifiers->fFlags & Modifiers::kMediump_Flag;
531 bool lowp = modifiers->fFlags & Modifiers::kLowp_Flag;
532
533 if (!lowp && !mediump && !highp) {
534 // No precision qualifiers here. Return the type as-is.
535 return this;
536 }
537
538 if (!ProgramConfig::IsRuntimeEffect(context.fConfig->fKind)) {
539 // We want to discourage precision modifiers internally. Instead, use the type that
540 // corresponds to the precision you need. (e.g. half vs float, short vs int)
541 context.fErrors->error(line, "precision qualifiers are not allowed");
542 return nullptr;
543 }
544
545 if ((int(lowp) + int(mediump) + int(highp)) != 1) {
546 context.fErrors->error(line, "only one precision qualifier can be used");
547 return nullptr;
548 }
549
550 // We're going to return a whole new type, so the modifier bits can be cleared out.
551 modifiers->fFlags &= ~(Modifiers::kHighp_Flag |
552 Modifiers::kMediump_Flag |
553 Modifiers::kLowp_Flag);
554
555 const Type& component = this->componentType();
556 if (component.highPrecision()) {
557 if (highp) {
558 // Type is already high precision, and we are requesting high precision. Return as-is.
559 return this;
560 }
561
562 // Ascertain the mediump equivalent type for this type, if any.
563 const Type* mediumpType;
564 switch (component.numberKind()) {
565 case Type::NumberKind::kFloat:
566 mediumpType = context.fTypes.fHalf.get();
567 break;
568
569 case Type::NumberKind::kSigned:
570 mediumpType = context.fTypes.fShort.get();
571 break;
572
573 case Type::NumberKind::kUnsigned:
574 mediumpType = context.fTypes.fUShort.get();
575 break;
576
577 default:
578 mediumpType = nullptr;
579 break;
580 }
581
582 if (mediumpType) {
583 // Convert the mediump component type into the final vector/matrix/array type as needed.
584 return this->isArray()
585 ? symbols->addArrayDimension(mediumpType, this->columns())
586 : &mediumpType->toCompound(context, this->columns(), this->rows());
587 }
588 }
589
590 context.fErrors->error(line, "type '" + this->displayName() +
591 "' does not support precision qualifiers");
592 return nullptr;
593 }
594
toCompound(const Context & context,int columns,int rows) const595 const Type& Type::toCompound(const Context& context, int columns, int rows) const {
596 SkASSERT(this->isScalar());
597 if (columns == 1 && rows == 1) {
598 return *this;
599 }
600 if (*this == *context.fTypes.fFloat || *this == *context.fTypes.fFloatLiteral) {
601 switch (rows) {
602 case 1:
603 switch (columns) {
604 case 1: return *context.fTypes.fFloat;
605 case 2: return *context.fTypes.fFloat2;
606 case 3: return *context.fTypes.fFloat3;
607 case 4: return *context.fTypes.fFloat4;
608 default: SK_ABORT("unsupported vector column count (%d)", columns);
609 }
610 case 2:
611 switch (columns) {
612 case 2: return *context.fTypes.fFloat2x2;
613 case 3: return *context.fTypes.fFloat3x2;
614 case 4: return *context.fTypes.fFloat4x2;
615 default: SK_ABORT("unsupported matrix column count (%d)", columns);
616 }
617 case 3:
618 switch (columns) {
619 case 2: return *context.fTypes.fFloat2x3;
620 case 3: return *context.fTypes.fFloat3x3;
621 case 4: return *context.fTypes.fFloat4x3;
622 default: SK_ABORT("unsupported matrix column count (%d)", columns);
623 }
624 case 4:
625 switch (columns) {
626 case 2: return *context.fTypes.fFloat2x4;
627 case 3: return *context.fTypes.fFloat3x4;
628 case 4: return *context.fTypes.fFloat4x4;
629 default: SK_ABORT("unsupported matrix column count (%d)", columns);
630 }
631 default: SK_ABORT("unsupported row count (%d)", rows);
632 }
633 } else if (*this == *context.fTypes.fHalf) {
634 switch (rows) {
635 case 1:
636 switch (columns) {
637 case 1: return *context.fTypes.fHalf;
638 case 2: return *context.fTypes.fHalf2;
639 case 3: return *context.fTypes.fHalf3;
640 case 4: return *context.fTypes.fHalf4;
641 default: SK_ABORT("unsupported vector column count (%d)", columns);
642 }
643 case 2:
644 switch (columns) {
645 case 2: return *context.fTypes.fHalf2x2;
646 case 3: return *context.fTypes.fHalf3x2;
647 case 4: return *context.fTypes.fHalf4x2;
648 default: SK_ABORT("unsupported matrix column count (%d)", columns);
649 }
650 case 3:
651 switch (columns) {
652 case 2: return *context.fTypes.fHalf2x3;
653 case 3: return *context.fTypes.fHalf3x3;
654 case 4: return *context.fTypes.fHalf4x3;
655 default: SK_ABORT("unsupported matrix column count (%d)", columns);
656 }
657 case 4:
658 switch (columns) {
659 case 2: return *context.fTypes.fHalf2x4;
660 case 3: return *context.fTypes.fHalf3x4;
661 case 4: return *context.fTypes.fHalf4x4;
662 default: SK_ABORT("unsupported matrix column count (%d)", columns);
663 }
664 default: SK_ABORT("unsupported row count (%d)", rows);
665 }
666 } else if (*this == *context.fTypes.fInt || *this == *context.fTypes.fIntLiteral) {
667 switch (rows) {
668 case 1:
669 switch (columns) {
670 case 1: return *context.fTypes.fInt;
671 case 2: return *context.fTypes.fInt2;
672 case 3: return *context.fTypes.fInt3;
673 case 4: return *context.fTypes.fInt4;
674 default: SK_ABORT("unsupported vector column count (%d)", columns);
675 }
676 default: SK_ABORT("unsupported row count (%d)", rows);
677 }
678 } else if (*this == *context.fTypes.fShort) {
679 switch (rows) {
680 case 1:
681 switch (columns) {
682 case 1: return *context.fTypes.fShort;
683 case 2: return *context.fTypes.fShort2;
684 case 3: return *context.fTypes.fShort3;
685 case 4: return *context.fTypes.fShort4;
686 default: SK_ABORT("unsupported vector column count (%d)", columns);
687 }
688 default: SK_ABORT("unsupported row count (%d)", rows);
689 }
690 } else if (*this == *context.fTypes.fUInt) {
691 switch (rows) {
692 case 1:
693 switch (columns) {
694 case 1: return *context.fTypes.fUInt;
695 case 2: return *context.fTypes.fUInt2;
696 case 3: return *context.fTypes.fUInt3;
697 case 4: return *context.fTypes.fUInt4;
698 default: SK_ABORT("unsupported vector column count (%d)", columns);
699 }
700 default: SK_ABORT("unsupported row count (%d)", rows);
701 }
702 } else if (*this == *context.fTypes.fUShort) {
703 switch (rows) {
704 case 1:
705 switch (columns) {
706 case 1: return *context.fTypes.fUShort;
707 case 2: return *context.fTypes.fUShort2;
708 case 3: return *context.fTypes.fUShort3;
709 case 4: return *context.fTypes.fUShort4;
710 default: SK_ABORT("unsupported vector column count (%d)", columns);
711 }
712 default: SK_ABORT("unsupported row count (%d)", rows);
713 }
714 } else if (*this == *context.fTypes.fBool) {
715 switch (rows) {
716 case 1:
717 switch (columns) {
718 case 1: return *context.fTypes.fBool;
719 case 2: return *context.fTypes.fBool2;
720 case 3: return *context.fTypes.fBool3;
721 case 4: return *context.fTypes.fBool4;
722 default: SK_ABORT("unsupported vector column count (%d)", columns);
723 }
724 default: SK_ABORT("unsupported row count (%d)", rows);
725 }
726 }
727 SkDEBUGFAILF("unsupported toCompound type %s", this->description().c_str());
728 return *context.fTypes.fVoid;
729 }
730
clone(SymbolTable * symbolTable) const731 const Type* Type::clone(SymbolTable* symbolTable) const {
732 // Many types are built-ins, and exist in every SymbolTable by default.
733 if (this->isInBuiltinTypes()) {
734 return this;
735 }
736 // Even if the type isn't a built-in, it might already exist in the SymbolTable.
737 const Symbol* clonedSymbol = (*symbolTable)[this->name()];
738 if (clonedSymbol != nullptr) {
739 const Type& clonedType = clonedSymbol->as<Type>();
740 SkASSERT(clonedType.typeKind() == this->typeKind());
741 return &clonedType;
742 }
743 // This type actually needs to be cloned into the destination SymbolTable.
744 switch (this->typeKind()) {
745 case TypeKind::kArray: {
746 return symbolTable->addArrayDimension(&this->componentType(), this->columns());
747 }
748 case TypeKind::kStruct: {
749 const String* name = symbolTable->takeOwnershipOfString(String(this->name()));
750 return symbolTable->add(Type::MakeStructType(this->fLine, *name, this->fields()));
751 }
752 default:
753 SkDEBUGFAILF("don't know how to clone type '%s'", this->description().c_str());
754 return nullptr;
755 }
756 }
757
coerceExpression(std::unique_ptr<Expression> expr,const Context & context) const758 std::unique_ptr<Expression> Type::coerceExpression(std::unique_ptr<Expression> expr,
759 const Context& context) const {
760 if (!expr || expr->isIncomplete(context)) {
761 return nullptr;
762 }
763 if (expr->type() == *this) {
764 return expr;
765 }
766
767 const int line = expr->fLine;
768 const Program::Settings& settings = context.fConfig->fSettings;
769 if (!expr->coercionCost(*this).isPossible(settings.fAllowNarrowingConversions)) {
770 context.fErrors->error(line, "expected '" + this->displayName() + "', but found '" +
771 expr->type().displayName() + "'");
772 return nullptr;
773 }
774
775 if (this->isScalar()) {
776 return ConstructorScalarCast::Make(context, line, *this, std::move(expr));
777 }
778 if (this->isVector() || this->isMatrix()) {
779 return ConstructorCompoundCast::Make(context, line, *this, std::move(expr));
780 }
781 if (this->isArray()) {
782 return ConstructorArrayCast::Make(context, line, *this, std::move(expr));
783 }
784 context.fErrors->error(line, "cannot construct '" + this->displayName() + "'");
785 return nullptr;
786 }
787
isOrContainsArray() const788 bool Type::isOrContainsArray() const {
789 if (this->isStruct()) {
790 for (const Field& f : this->fields()) {
791 if (f.fType->isOrContainsArray()) {
792 return true;
793 }
794 }
795 return false;
796 }
797
798 return this->isArray();
799 }
800
isTooDeeplyNested(int limit) const801 bool Type::isTooDeeplyNested(int limit) const {
802 if (limit < 0) {
803 return true;
804 }
805
806 if (this->isStruct()) {
807 for (const Type::Field& f : this->fields()) {
808 if (f.fType->isTooDeeplyNested(limit - 1)) {
809 return true;
810 }
811 }
812 }
813
814 return false;
815 }
816
isTooDeeplyNested() const817 bool Type::isTooDeeplyNested() const {
818 return this->isTooDeeplyNested(kMaxStructDepth);
819 }
820
isAllowedInES2(const Context & context) const821 bool Type::isAllowedInES2(const Context& context) const {
822 return !context.fConfig->strictES2Mode() || this->isAllowedInES2();
823 }
824
checkForOutOfRangeLiteral(const Context & context,const Expression & expr) const825 bool Type::checkForOutOfRangeLiteral(const Context& context, const Expression& expr) const {
826 bool foundError = false;
827 const Type& baseType = this->componentType();
828 if (baseType.isInteger()) {
829 // Replace constant expressions with their corresponding values.
830 const Expression* valueExpr = ConstantFolder::GetConstantValueForVariable(expr);
831 if (valueExpr->supportsConstantValues()) {
832 // Iterate over every constant subexpression in the value.
833 int numSlots = valueExpr->type().slotCount();
834 for (int slot = 0; slot < numSlots; ++slot) {
835 skstd::optional<double> slotVal = valueExpr->getConstantValue(slot);
836 // Check for Literal values that are out of range for the base type.
837 if (slotVal.has_value() &&
838 baseType.checkForOutOfRangeLiteral(context, *slotVal, valueExpr->fLine)) {
839 foundError = true;
840 }
841 }
842 }
843 }
844
845 // We don't need range checks for floats or booleans; any matched-type value is acceptable.
846 return foundError;
847 }
848
checkForOutOfRangeLiteral(const Context & context,double value,int line) const849 bool Type::checkForOutOfRangeLiteral(const Context& context, double value, int line) const {
850 SkASSERT(this->isScalar());
851 if (this->isInteger()) {
852 if (value < this->minimumValue() || value > this->maximumValue()) {
853 // We found a value that can't fit in the type. Flag it as an error.
854 context.fErrors->error(line, String("integer is out of range for type '") +
855 this->displayName().c_str() +
856 "': " + to_string((SKSL_INT)value));
857 return true;
858 }
859 }
860 return false;
861 }
862
convertArraySize(const Context & context,std::unique_ptr<Expression> size) const863 SKSL_INT Type::convertArraySize(const Context& context, std::unique_ptr<Expression> size) const {
864 size = context.fTypes.fInt->coerceExpression(std::move(size), context);
865 if (!size) {
866 return 0;
867 }
868 if (this->isArray()) {
869 context.fErrors->error(size->fLine, "multi-dimensional arrays are not supported");
870 return 0;
871 }
872 if (this->isVoid()) {
873 context.fErrors->error(size->fLine, "type 'void' may not be used in an array");
874 return 0;
875 }
876 #ifdef SKSL_EXT
877 if (this->isOpaque() && this->name() != "sampler2D") {
878 #else
879 if (this->isOpaque()) {
880 #endif
881 context.fErrors->error(size->fLine, "opaque type '" + this->name() +
882 "' may not be used in an array");
883 return 0;
884 }
885 SKSL_INT count;
886 if (!ConstantFolder::GetConstantInt(*size, &count)) {
887 context.fErrors->error(size->fLine, "array size must be an integer");
888 return 0;
889 }
890 if (count <= 0) {
891 context.fErrors->error(size->fLine, "array size must be positive");
892 return 0;
893 }
894 if (!SkTFitsIn<int32_t>(count)) {
895 context.fErrors->error(size->fLine, "array size is too large");
896 return 0;
897 }
898 return static_cast<int>(count);
899 }
900
901 } // namespace SkSL
902