• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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