Line data Source code
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 "SkSLIRGenerator.h"
9 :
10 : #include "limits.h"
11 : #include <unordered_set>
12 :
13 : #include "SkSLCompiler.h"
14 : #include "ast/SkSLASTBoolLiteral.h"
15 : #include "ast/SkSLASTFieldSuffix.h"
16 : #include "ast/SkSLASTFloatLiteral.h"
17 : #include "ast/SkSLASTIndexSuffix.h"
18 : #include "ast/SkSLASTIntLiteral.h"
19 : #include "ir/SkSLBinaryExpression.h"
20 : #include "ir/SkSLBoolLiteral.h"
21 : #include "ir/SkSLBreakStatement.h"
22 : #include "ir/SkSLConstructor.h"
23 : #include "ir/SkSLContinueStatement.h"
24 : #include "ir/SkSLDiscardStatement.h"
25 : #include "ir/SkSLDoStatement.h"
26 : #include "ir/SkSLExpressionStatement.h"
27 : #include "ir/SkSLField.h"
28 : #include "ir/SkSLFieldAccess.h"
29 : #include "ir/SkSLFloatLiteral.h"
30 : #include "ir/SkSLForStatement.h"
31 : #include "ir/SkSLFunctionCall.h"
32 : #include "ir/SkSLFunctionDeclaration.h"
33 : #include "ir/SkSLFunctionDefinition.h"
34 : #include "ir/SkSLFunctionReference.h"
35 : #include "ir/SkSLIfStatement.h"
36 : #include "ir/SkSLIndexExpression.h"
37 : #include "ir/SkSLInterfaceBlock.h"
38 : #include "ir/SkSLIntLiteral.h"
39 : #include "ir/SkSLLayout.h"
40 : #include "ir/SkSLPostfixExpression.h"
41 : #include "ir/SkSLPrefixExpression.h"
42 : #include "ir/SkSLReturnStatement.h"
43 : #include "ir/SkSLSwitchCase.h"
44 : #include "ir/SkSLSwitchStatement.h"
45 : #include "ir/SkSLSwizzle.h"
46 : #include "ir/SkSLTernaryExpression.h"
47 : #include "ir/SkSLUnresolvedFunction.h"
48 : #include "ir/SkSLVariable.h"
49 : #include "ir/SkSLVarDeclarations.h"
50 : #include "ir/SkSLVarDeclarationsStatement.h"
51 : #include "ir/SkSLVariableReference.h"
52 : #include "ir/SkSLWhileStatement.h"
53 :
54 : namespace SkSL {
55 :
56 : class AutoSymbolTable {
57 : public:
58 0 : AutoSymbolTable(IRGenerator* ir)
59 0 : : fIR(ir)
60 0 : , fPrevious(fIR->fSymbolTable) {
61 0 : fIR->pushSymbolTable();
62 0 : }
63 :
64 0 : ~AutoSymbolTable() {
65 0 : fIR->popSymbolTable();
66 0 : ASSERT(fPrevious == fIR->fSymbolTable);
67 0 : }
68 :
69 : IRGenerator* fIR;
70 : std::shared_ptr<SymbolTable> fPrevious;
71 : };
72 :
73 : class AutoLoopLevel {
74 : public:
75 0 : AutoLoopLevel(IRGenerator* ir)
76 0 : : fIR(ir) {
77 0 : fIR->fLoopLevel++;
78 0 : }
79 :
80 0 : ~AutoLoopLevel() {
81 0 : fIR->fLoopLevel--;
82 0 : }
83 :
84 : IRGenerator* fIR;
85 : };
86 :
87 : class AutoSwitchLevel {
88 : public:
89 0 : AutoSwitchLevel(IRGenerator* ir)
90 0 : : fIR(ir) {
91 0 : fIR->fSwitchLevel++;
92 0 : }
93 :
94 0 : ~AutoSwitchLevel() {
95 0 : fIR->fSwitchLevel--;
96 0 : }
97 :
98 : IRGenerator* fIR;
99 : };
100 :
101 0 : IRGenerator::IRGenerator(const Context* context, std::shared_ptr<SymbolTable> symbolTable,
102 0 : ErrorReporter& errorReporter)
103 : : fContext(*context)
104 : , fCurrentFunction(nullptr)
105 0 : , fSymbolTable(std::move(symbolTable))
106 : , fLoopLevel(0)
107 : , fSwitchLevel(0)
108 0 : , fErrors(errorReporter) {}
109 :
110 0 : void IRGenerator::pushSymbolTable() {
111 0 : fSymbolTable.reset(new SymbolTable(std::move(fSymbolTable), &fErrors));
112 0 : }
113 :
114 0 : void IRGenerator::popSymbolTable() {
115 0 : fSymbolTable = fSymbolTable->fParent;
116 0 : }
117 :
118 0 : static void fill_caps(const SKSL_CAPS_CLASS& caps, std::unordered_map<String, CapValue>* capsMap) {
119 : #define CAP(name) capsMap->insert(std::make_pair(String(#name), CapValue(caps.name())));
120 0 : CAP(fbFetchSupport);
121 0 : CAP(fbFetchNeedsCustomOutput);
122 0 : CAP(bindlessTextureSupport);
123 0 : CAP(dropsTileOnZeroDivide);
124 0 : CAP(flatInterpolationSupport);
125 0 : CAP(noperspectiveInterpolationSupport);
126 0 : CAP(multisampleInterpolationSupport);
127 0 : CAP(sampleVariablesSupport);
128 0 : CAP(sampleMaskOverrideCoverageSupport);
129 0 : CAP(externalTextureSupport);
130 0 : CAP(texelFetchSupport);
131 0 : CAP(imageLoadStoreSupport);
132 0 : CAP(mustEnableAdvBlendEqs);
133 0 : CAP(mustEnableSpecificAdvBlendEqs);
134 0 : CAP(mustDeclareFragmentShaderOutput);
135 0 : CAP(canUseAnyFunctionInShader);
136 : #undef CAP
137 0 : }
138 :
139 0 : void IRGenerator::start(const Program::Settings* settings) {
140 0 : fSettings = settings;
141 0 : fCapsMap.clear();
142 0 : if (settings->fCaps) {
143 0 : fill_caps(*settings->fCaps, &fCapsMap);
144 : }
145 0 : this->pushSymbolTable();
146 0 : fInputs.reset();
147 0 : }
148 :
149 0 : void IRGenerator::finish() {
150 0 : this->popSymbolTable();
151 0 : fSettings = nullptr;
152 0 : }
153 :
154 0 : std::unique_ptr<Extension> IRGenerator::convertExtension(const ASTExtension& extension) {
155 0 : return std::unique_ptr<Extension>(new Extension(extension.fPosition, extension.fName));
156 : }
157 :
158 0 : std::unique_ptr<Statement> IRGenerator::convertStatement(const ASTStatement& statement) {
159 0 : switch (statement.fKind) {
160 : case ASTStatement::kBlock_Kind:
161 0 : return this->convertBlock((ASTBlock&) statement);
162 : case ASTStatement::kVarDeclaration_Kind:
163 0 : return this->convertVarDeclarationStatement((ASTVarDeclarationStatement&) statement);
164 : case ASTStatement::kExpression_Kind:
165 0 : return this->convertExpressionStatement((ASTExpressionStatement&) statement);
166 : case ASTStatement::kIf_Kind:
167 0 : return this->convertIf((ASTIfStatement&) statement);
168 : case ASTStatement::kFor_Kind:
169 0 : return this->convertFor((ASTForStatement&) statement);
170 : case ASTStatement::kWhile_Kind:
171 0 : return this->convertWhile((ASTWhileStatement&) statement);
172 : case ASTStatement::kDo_Kind:
173 0 : return this->convertDo((ASTDoStatement&) statement);
174 : case ASTStatement::kSwitch_Kind:
175 0 : return this->convertSwitch((ASTSwitchStatement&) statement);
176 : case ASTStatement::kReturn_Kind:
177 0 : return this->convertReturn((ASTReturnStatement&) statement);
178 : case ASTStatement::kBreak_Kind:
179 0 : return this->convertBreak((ASTBreakStatement&) statement);
180 : case ASTStatement::kContinue_Kind:
181 0 : return this->convertContinue((ASTContinueStatement&) statement);
182 : case ASTStatement::kDiscard_Kind:
183 0 : return this->convertDiscard((ASTDiscardStatement&) statement);
184 : default:
185 0 : ABORT("unsupported statement type: %d\n", statement.fKind);
186 : }
187 : }
188 :
189 0 : std::unique_ptr<Block> IRGenerator::convertBlock(const ASTBlock& block) {
190 0 : AutoSymbolTable table(this);
191 0 : std::vector<std::unique_ptr<Statement>> statements;
192 0 : for (size_t i = 0; i < block.fStatements.size(); i++) {
193 0 : std::unique_ptr<Statement> statement = this->convertStatement(*block.fStatements[i]);
194 0 : if (!statement) {
195 0 : return nullptr;
196 : }
197 0 : statements.push_back(std::move(statement));
198 : }
199 0 : return std::unique_ptr<Block>(new Block(block.fPosition, std::move(statements), fSymbolTable));
200 : }
201 :
202 0 : std::unique_ptr<Statement> IRGenerator::convertVarDeclarationStatement(
203 : const ASTVarDeclarationStatement& s) {
204 0 : auto decl = this->convertVarDeclarations(*s.fDeclarations, Variable::kLocal_Storage);
205 0 : if (!decl) {
206 0 : return nullptr;
207 : }
208 0 : return std::unique_ptr<Statement>(new VarDeclarationsStatement(std::move(decl)));
209 : }
210 :
211 0 : std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVarDeclarations& decl,
212 : Variable::Storage storage) {
213 0 : std::vector<VarDeclaration> variables;
214 0 : const Type* baseType = this->convertType(*decl.fType);
215 0 : if (!baseType) {
216 0 : return nullptr;
217 : }
218 0 : for (const auto& varDecl : decl.fVars) {
219 0 : const Type* type = baseType;
220 0 : std::vector<std::unique_ptr<Expression>> sizes;
221 0 : for (const auto& rawSize : varDecl.fSizes) {
222 0 : if (rawSize) {
223 0 : auto size = this->coerce(this->convertExpression(*rawSize), *fContext.fInt_Type);
224 0 : if (!size) {
225 0 : return nullptr;
226 : }
227 0 : String name = type->fName;
228 : int64_t count;
229 0 : if (size->fKind == Expression::kIntLiteral_Kind) {
230 0 : count = ((IntLiteral&) *size).fValue;
231 0 : if (count <= 0) {
232 0 : fErrors.error(size->fPosition, "array size must be positive");
233 : }
234 0 : name += "[" + to_string(count) + "]";
235 : } else {
236 0 : count = -1;
237 0 : name += "[]";
238 : }
239 0 : type = new Type(name, Type::kArray_Kind, *type, (int) count);
240 0 : fSymbolTable->takeOwnership((Type*) type);
241 0 : sizes.push_back(std::move(size));
242 : } else {
243 0 : type = new Type(type->fName + "[]", Type::kArray_Kind, *type, -1);
244 0 : fSymbolTable->takeOwnership((Type*) type);
245 0 : sizes.push_back(nullptr);
246 : }
247 : }
248 0 : auto var = std::unique_ptr<Variable>(new Variable(decl.fPosition, decl.fModifiers,
249 0 : varDecl.fName, *type, storage));
250 0 : std::unique_ptr<Expression> value;
251 0 : if (varDecl.fValue) {
252 0 : value = this->convertExpression(*varDecl.fValue);
253 0 : if (!value) {
254 0 : return nullptr;
255 : }
256 0 : value = this->coerce(std::move(value), *type);
257 : }
258 0 : if (storage == Variable::kGlobal_Storage && varDecl.fName == String("sk_FragColor") &&
259 0 : (*fSymbolTable)[varDecl.fName]) {
260 : // already defined, ignore
261 0 : } else if (storage == Variable::kGlobal_Storage && (*fSymbolTable)[varDecl.fName] &&
262 0 : (*fSymbolTable)[varDecl.fName]->fKind == Symbol::kVariable_Kind &&
263 0 : ((Variable*) (*fSymbolTable)[varDecl.fName])->fModifiers.fLayout.fBuiltin >= 0) {
264 : // already defined, just update the modifiers
265 0 : Variable* old = (Variable*) (*fSymbolTable)[varDecl.fName];
266 0 : old->fModifiers = var->fModifiers;
267 : } else {
268 0 : variables.emplace_back(var.get(), std::move(sizes), std::move(value));
269 0 : fSymbolTable->add(varDecl.fName, std::move(var));
270 : }
271 : }
272 0 : return std::unique_ptr<VarDeclarations>(new VarDeclarations(decl.fPosition,
273 : baseType,
274 0 : std::move(variables)));
275 : }
276 :
277 0 : std::unique_ptr<ModifiersDeclaration> IRGenerator::convertModifiersDeclaration(
278 : const ASTModifiersDeclaration& m) {
279 0 : return std::unique_ptr<ModifiersDeclaration>(new ModifiersDeclaration(m.fModifiers));
280 : }
281 :
282 0 : std::unique_ptr<Statement> IRGenerator::convertIf(const ASTIfStatement& s) {
283 0 : std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*s.fTest),
284 0 : *fContext.fBool_Type);
285 0 : if (!test) {
286 0 : return nullptr;
287 : }
288 0 : std::unique_ptr<Statement> ifTrue = this->convertStatement(*s.fIfTrue);
289 0 : if (!ifTrue) {
290 0 : return nullptr;
291 : }
292 0 : std::unique_ptr<Statement> ifFalse;
293 0 : if (s.fIfFalse) {
294 0 : ifFalse = this->convertStatement(*s.fIfFalse);
295 0 : if (!ifFalse) {
296 0 : return nullptr;
297 : }
298 : }
299 0 : if (test->fKind == Expression::kBoolLiteral_Kind) {
300 : // static boolean value, fold down to a single branch
301 0 : if (((BoolLiteral&) *test).fValue) {
302 0 : return ifTrue;
303 0 : } else if (s.fIfFalse) {
304 0 : return ifFalse;
305 : } else {
306 : // False & no else clause. Not an error, so don't return null!
307 0 : std::vector<std::unique_ptr<Statement>> empty;
308 0 : return std::unique_ptr<Statement>(new Block(s.fPosition, std::move(empty),
309 0 : fSymbolTable));
310 : }
311 : }
312 0 : return std::unique_ptr<Statement>(new IfStatement(s.fPosition, std::move(test),
313 0 : std::move(ifTrue), std::move(ifFalse)));
314 : }
315 :
316 0 : std::unique_ptr<Statement> IRGenerator::convertFor(const ASTForStatement& f) {
317 0 : AutoLoopLevel level(this);
318 0 : AutoSymbolTable table(this);
319 0 : std::unique_ptr<Statement> initializer;
320 0 : if (f.fInitializer) {
321 0 : initializer = this->convertStatement(*f.fInitializer);
322 0 : if (!initializer) {
323 0 : return nullptr;
324 : }
325 : }
326 0 : std::unique_ptr<Expression> test;
327 0 : if (f.fTest) {
328 0 : test = this->coerce(this->convertExpression(*f.fTest), *fContext.fBool_Type);
329 0 : if (!test) {
330 0 : return nullptr;
331 : }
332 : }
333 0 : std::unique_ptr<Expression> next;
334 0 : if (f.fNext) {
335 0 : next = this->convertExpression(*f.fNext);
336 0 : if (!next) {
337 0 : return nullptr;
338 : }
339 0 : this->checkValid(*next);
340 : }
341 0 : std::unique_ptr<Statement> statement = this->convertStatement(*f.fStatement);
342 0 : if (!statement) {
343 0 : return nullptr;
344 : }
345 0 : return std::unique_ptr<Statement>(new ForStatement(f.fPosition, std::move(initializer),
346 0 : std::move(test), std::move(next),
347 0 : std::move(statement), fSymbolTable));
348 : }
349 :
350 0 : std::unique_ptr<Statement> IRGenerator::convertWhile(const ASTWhileStatement& w) {
351 0 : AutoLoopLevel level(this);
352 0 : std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*w.fTest),
353 0 : *fContext.fBool_Type);
354 0 : if (!test) {
355 0 : return nullptr;
356 : }
357 0 : std::unique_ptr<Statement> statement = this->convertStatement(*w.fStatement);
358 0 : if (!statement) {
359 0 : return nullptr;
360 : }
361 0 : return std::unique_ptr<Statement>(new WhileStatement(w.fPosition, std::move(test),
362 0 : std::move(statement)));
363 : }
364 :
365 0 : std::unique_ptr<Statement> IRGenerator::convertDo(const ASTDoStatement& d) {
366 0 : AutoLoopLevel level(this);
367 0 : std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*d.fTest),
368 0 : *fContext.fBool_Type);
369 0 : if (!test) {
370 0 : return nullptr;
371 : }
372 0 : std::unique_ptr<Statement> statement = this->convertStatement(*d.fStatement);
373 0 : if (!statement) {
374 0 : return nullptr;
375 : }
376 0 : return std::unique_ptr<Statement>(new DoStatement(d.fPosition, std::move(statement),
377 0 : std::move(test)));
378 : }
379 :
380 0 : std::unique_ptr<Statement> IRGenerator::convertSwitch(const ASTSwitchStatement& s) {
381 0 : AutoSwitchLevel level(this);
382 0 : std::unique_ptr<Expression> value = this->convertExpression(*s.fValue);
383 0 : if (!value) {
384 0 : return nullptr;
385 : }
386 0 : if (value->fType != *fContext.fUInt_Type) {
387 0 : value = this->coerce(std::move(value), *fContext.fInt_Type);
388 0 : if (!value) {
389 0 : return nullptr;
390 : }
391 : }
392 0 : AutoSymbolTable table(this);
393 0 : std::unordered_set<int> caseValues;
394 0 : std::vector<std::unique_ptr<SwitchCase>> cases;
395 0 : for (const auto& c : s.fCases) {
396 0 : std::unique_ptr<Expression> caseValue;
397 0 : if (c->fValue) {
398 0 : caseValue = this->convertExpression(*c->fValue);
399 0 : if (!caseValue) {
400 0 : return nullptr;
401 : }
402 0 : if (caseValue->fType != *fContext.fUInt_Type) {
403 0 : caseValue = this->coerce(std::move(caseValue), *fContext.fInt_Type);
404 0 : if (!caseValue) {
405 0 : return nullptr;
406 : }
407 : }
408 0 : if (!caseValue->isConstant()) {
409 0 : fErrors.error(caseValue->fPosition, "case value must be a constant");
410 0 : return nullptr;
411 : }
412 0 : ASSERT(caseValue->fKind == Expression::kIntLiteral_Kind);
413 0 : int64_t v = ((IntLiteral&) *caseValue).fValue;
414 0 : if (caseValues.find(v) != caseValues.end()) {
415 0 : fErrors.error(caseValue->fPosition, "duplicate case value");
416 : }
417 0 : caseValues.insert(v);
418 : }
419 0 : std::vector<std::unique_ptr<Statement>> statements;
420 0 : for (const auto& s : c->fStatements) {
421 0 : std::unique_ptr<Statement> converted = this->convertStatement(*s);
422 0 : if (!converted) {
423 0 : return nullptr;
424 : }
425 0 : statements.push_back(std::move(converted));
426 : }
427 0 : cases.emplace_back(new SwitchCase(c->fPosition, std::move(caseValue),
428 0 : std::move(statements)));
429 : }
430 0 : return std::unique_ptr<Statement>(new SwitchStatement(s.fPosition, std::move(value),
431 0 : std::move(cases)));
432 : }
433 :
434 0 : std::unique_ptr<Statement> IRGenerator::convertExpressionStatement(
435 : const ASTExpressionStatement& s) {
436 0 : std::unique_ptr<Expression> e = this->convertExpression(*s.fExpression);
437 0 : if (!e) {
438 0 : return nullptr;
439 : }
440 0 : this->checkValid(*e);
441 0 : return std::unique_ptr<Statement>(new ExpressionStatement(std::move(e)));
442 : }
443 :
444 0 : std::unique_ptr<Statement> IRGenerator::convertReturn(const ASTReturnStatement& r) {
445 0 : ASSERT(fCurrentFunction);
446 0 : if (r.fExpression) {
447 0 : std::unique_ptr<Expression> result = this->convertExpression(*r.fExpression);
448 0 : if (!result) {
449 0 : return nullptr;
450 : }
451 0 : if (fCurrentFunction->fReturnType == *fContext.fVoid_Type) {
452 0 : fErrors.error(result->fPosition, "may not return a value from a void function");
453 : } else {
454 0 : result = this->coerce(std::move(result), fCurrentFunction->fReturnType);
455 0 : if (!result) {
456 0 : return nullptr;
457 : }
458 : }
459 0 : return std::unique_ptr<Statement>(new ReturnStatement(std::move(result)));
460 : } else {
461 0 : if (fCurrentFunction->fReturnType != *fContext.fVoid_Type) {
462 0 : fErrors.error(r.fPosition, "expected function to return '" +
463 0 : fCurrentFunction->fReturnType.description() + "'");
464 : }
465 0 : return std::unique_ptr<Statement>(new ReturnStatement(r.fPosition));
466 : }
467 : }
468 :
469 0 : std::unique_ptr<Statement> IRGenerator::convertBreak(const ASTBreakStatement& b) {
470 0 : if (fLoopLevel > 0 || fSwitchLevel > 0) {
471 0 : return std::unique_ptr<Statement>(new BreakStatement(b.fPosition));
472 : } else {
473 0 : fErrors.error(b.fPosition, "break statement must be inside a loop or switch");
474 0 : return nullptr;
475 : }
476 : }
477 :
478 0 : std::unique_ptr<Statement> IRGenerator::convertContinue(const ASTContinueStatement& c) {
479 0 : if (fLoopLevel > 0) {
480 0 : return std::unique_ptr<Statement>(new ContinueStatement(c.fPosition));
481 : } else {
482 0 : fErrors.error(c.fPosition, "continue statement must be inside a loop");
483 0 : return nullptr;
484 : }
485 : }
486 :
487 0 : std::unique_ptr<Statement> IRGenerator::convertDiscard(const ASTDiscardStatement& d) {
488 0 : return std::unique_ptr<Statement>(new DiscardStatement(d.fPosition));
489 : }
490 :
491 0 : std::unique_ptr<FunctionDefinition> IRGenerator::convertFunction(const ASTFunction& f) {
492 0 : const Type* returnType = this->convertType(*f.fReturnType);
493 0 : if (!returnType) {
494 0 : return nullptr;
495 : }
496 0 : std::vector<const Variable*> parameters;
497 0 : for (const auto& param : f.fParameters) {
498 0 : const Type* type = this->convertType(*param->fType);
499 0 : if (!type) {
500 0 : return nullptr;
501 : }
502 0 : for (int j = (int) param->fSizes.size() - 1; j >= 0; j--) {
503 0 : int size = param->fSizes[j];
504 0 : String name = type->name() + "[" + to_string(size) + "]";
505 0 : Type* newType = new Type(std::move(name), Type::kArray_Kind, *type, size);
506 0 : fSymbolTable->takeOwnership(newType);
507 0 : type = newType;
508 : }
509 0 : String name = param->fName;
510 0 : Position pos = param->fPosition;
511 0 : Variable* var = new Variable(pos, param->fModifiers, std::move(name), *type,
512 0 : Variable::kParameter_Storage);
513 0 : fSymbolTable->takeOwnership(var);
514 0 : parameters.push_back(var);
515 : }
516 :
517 : // find existing declaration
518 0 : const FunctionDeclaration* decl = nullptr;
519 0 : auto entry = (*fSymbolTable)[f.fName];
520 0 : if (entry) {
521 0 : std::vector<const FunctionDeclaration*> functions;
522 0 : switch (entry->fKind) {
523 : case Symbol::kUnresolvedFunction_Kind:
524 0 : functions = ((UnresolvedFunction*) entry)->fFunctions;
525 0 : break;
526 : case Symbol::kFunctionDeclaration_Kind:
527 0 : functions.push_back((FunctionDeclaration*) entry);
528 0 : break;
529 : default:
530 0 : fErrors.error(f.fPosition, "symbol '" + f.fName + "' was already defined");
531 0 : return nullptr;
532 : }
533 0 : for (const auto& other : functions) {
534 0 : ASSERT(other->fName == f.fName);
535 0 : if (parameters.size() == other->fParameters.size()) {
536 0 : bool match = true;
537 0 : for (size_t i = 0; i < parameters.size(); i++) {
538 0 : if (parameters[i]->fType != other->fParameters[i]->fType) {
539 0 : match = false;
540 0 : break;
541 : }
542 : }
543 0 : if (match) {
544 0 : if (*returnType != other->fReturnType) {
545 0 : FunctionDeclaration newDecl(f.fPosition, f.fName, parameters, *returnType);
546 0 : fErrors.error(f.fPosition, "functions '" + newDecl.description() +
547 0 : "' and '" + other->description() +
548 0 : "' differ only in return type");
549 0 : return nullptr;
550 : }
551 0 : decl = other;
552 0 : for (size_t i = 0; i < parameters.size(); i++) {
553 0 : if (parameters[i]->fModifiers != other->fParameters[i]->fModifiers) {
554 0 : fErrors.error(f.fPosition, "modifiers on parameter " +
555 0 : to_string((uint64_t) i + 1) +
556 : " differ between declaration and "
557 0 : "definition");
558 0 : return nullptr;
559 : }
560 : }
561 0 : if (other->fDefined) {
562 0 : fErrors.error(f.fPosition, "duplicate definition of " +
563 0 : other->description());
564 : }
565 0 : break;
566 : }
567 : }
568 : }
569 : }
570 0 : if (!decl) {
571 : // couldn't find an existing declaration
572 0 : auto newDecl = std::unique_ptr<FunctionDeclaration>(new FunctionDeclaration(f.fPosition,
573 : f.fName,
574 : parameters,
575 0 : *returnType));
576 0 : decl = newDecl.get();
577 0 : fSymbolTable->add(decl->fName, std::move(newDecl));
578 : }
579 0 : if (f.fBody) {
580 0 : ASSERT(!fCurrentFunction);
581 0 : fCurrentFunction = decl;
582 0 : decl->fDefined = true;
583 0 : std::shared_ptr<SymbolTable> old = fSymbolTable;
584 0 : AutoSymbolTable table(this);
585 0 : for (size_t i = 0; i < parameters.size(); i++) {
586 0 : fSymbolTable->addWithoutOwnership(parameters[i]->fName, decl->fParameters[i]);
587 : }
588 0 : std::unique_ptr<Block> body = this->convertBlock(*f.fBody);
589 0 : fCurrentFunction = nullptr;
590 0 : if (!body) {
591 0 : return nullptr;
592 : }
593 0 : return std::unique_ptr<FunctionDefinition>(new FunctionDefinition(f.fPosition, *decl,
594 0 : std::move(body)));
595 : }
596 0 : return nullptr;
597 : }
598 :
599 0 : std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInterfaceBlock& intf) {
600 0 : std::shared_ptr<SymbolTable> old = fSymbolTable;
601 0 : AutoSymbolTable table(this);
602 0 : std::vector<Type::Field> fields;
603 0 : for (size_t i = 0; i < intf.fDeclarations.size(); i++) {
604 : std::unique_ptr<VarDeclarations> decl = this->convertVarDeclarations(
605 0 : *intf.fDeclarations[i],
606 0 : Variable::kGlobal_Storage);
607 0 : if (!decl) {
608 0 : return nullptr;
609 : }
610 0 : for (const auto& var : decl->fVars) {
611 0 : fields.push_back(Type::Field(var.fVar->fModifiers, var.fVar->fName,
612 0 : &var.fVar->fType));
613 0 : if (var.fValue) {
614 0 : fErrors.error(decl->fPosition,
615 0 : "initializers are not permitted on interface block fields");
616 : }
617 0 : if (var.fVar->fModifiers.fFlags & (Modifiers::kIn_Flag |
618 : Modifiers::kOut_Flag |
619 : Modifiers::kUniform_Flag |
620 : Modifiers::kConst_Flag)) {
621 0 : fErrors.error(decl->fPosition,
622 0 : "interface block fields may not have storage qualifiers");
623 : }
624 : }
625 : }
626 0 : Type* type = new Type(intf.fPosition, intf.fTypeName, fields);
627 0 : old->takeOwnership(type);
628 0 : std::vector<std::unique_ptr<Expression>> sizes;
629 0 : for (const auto& size : intf.fSizes) {
630 0 : if (size) {
631 0 : std::unique_ptr<Expression> converted = this->convertExpression(*size);
632 0 : if (!converted) {
633 0 : return nullptr;
634 : }
635 0 : String name = type->fName;
636 : int64_t count;
637 0 : if (converted->fKind == Expression::kIntLiteral_Kind) {
638 0 : count = ((IntLiteral&) *converted).fValue;
639 0 : if (count <= 0) {
640 0 : fErrors.error(converted->fPosition, "array size must be positive");
641 : }
642 0 : name += "[" + to_string(count) + "]";
643 : } else {
644 0 : count = -1;
645 0 : name += "[]";
646 : }
647 0 : type = new Type(name, Type::kArray_Kind, *type, (int) count);
648 0 : fSymbolTable->takeOwnership((Type*) type);
649 0 : sizes.push_back(std::move(converted));
650 : } else {
651 0 : type = new Type(type->fName + "[]", Type::kArray_Kind, *type, -1);
652 0 : fSymbolTable->takeOwnership((Type*) type);
653 0 : sizes.push_back(nullptr);
654 : }
655 : }
656 0 : Variable* var = new Variable(intf.fPosition, intf.fModifiers,
657 0 : intf.fInstanceName.size() ? intf.fInstanceName : intf.fTypeName,
658 0 : *type, Variable::kGlobal_Storage);
659 0 : old->takeOwnership(var);
660 0 : if (intf.fInstanceName.size()) {
661 0 : old->addWithoutOwnership(intf.fInstanceName, var);
662 : } else {
663 0 : for (size_t i = 0; i < fields.size(); i++) {
664 0 : old->add(fields[i].fName, std::unique_ptr<Field>(new Field(intf.fPosition, *var,
665 0 : (int) i)));
666 : }
667 : }
668 0 : return std::unique_ptr<InterfaceBlock>(new InterfaceBlock(intf.fPosition,
669 : var,
670 : intf.fTypeName,
671 : intf.fInstanceName,
672 0 : std::move(sizes),
673 0 : fSymbolTable));
674 : }
675 :
676 0 : const Type* IRGenerator::convertType(const ASTType& type) {
677 0 : const Symbol* result = (*fSymbolTable)[type.fName];
678 0 : if (result && result->fKind == Symbol::kType_Kind) {
679 0 : for (int size : type.fSizes) {
680 0 : String name = result->fName + "[";
681 0 : if (size != -1) {
682 0 : name += to_string(size);
683 : }
684 0 : name += "]";
685 0 : result = new Type(name, Type::kArray_Kind, (const Type&) *result, size);
686 0 : fSymbolTable->takeOwnership((Type*) result);
687 : }
688 0 : return (const Type*) result;
689 : }
690 0 : fErrors.error(type.fPosition, "unknown type '" + type.fName + "'");
691 0 : return nullptr;
692 : }
693 :
694 0 : std::unique_ptr<Expression> IRGenerator::convertExpression(const ASTExpression& expr) {
695 0 : switch (expr.fKind) {
696 : case ASTExpression::kIdentifier_Kind:
697 0 : return this->convertIdentifier((ASTIdentifier&) expr);
698 : case ASTExpression::kBool_Kind:
699 0 : return std::unique_ptr<Expression>(new BoolLiteral(fContext, expr.fPosition,
700 0 : ((ASTBoolLiteral&) expr).fValue));
701 : case ASTExpression::kInt_Kind:
702 0 : return std::unique_ptr<Expression>(new IntLiteral(fContext, expr.fPosition,
703 0 : ((ASTIntLiteral&) expr).fValue));
704 : case ASTExpression::kFloat_Kind:
705 0 : return std::unique_ptr<Expression>(new FloatLiteral(fContext, expr.fPosition,
706 0 : ((ASTFloatLiteral&) expr).fValue));
707 : case ASTExpression::kBinary_Kind:
708 0 : return this->convertBinaryExpression((ASTBinaryExpression&) expr);
709 : case ASTExpression::kPrefix_Kind:
710 0 : return this->convertPrefixExpression((ASTPrefixExpression&) expr);
711 : case ASTExpression::kSuffix_Kind:
712 0 : return this->convertSuffixExpression((ASTSuffixExpression&) expr);
713 : case ASTExpression::kTernary_Kind:
714 0 : return this->convertTernaryExpression((ASTTernaryExpression&) expr);
715 : default:
716 0 : ABORT("unsupported expression type: %d\n", expr.fKind);
717 : }
718 : }
719 :
720 0 : std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier& identifier) {
721 0 : const Symbol* result = (*fSymbolTable)[identifier.fText];
722 0 : if (!result) {
723 0 : fErrors.error(identifier.fPosition, "unknown identifier '" + identifier.fText + "'");
724 0 : return nullptr;
725 : }
726 0 : switch (result->fKind) {
727 : case Symbol::kFunctionDeclaration_Kind: {
728 : std::vector<const FunctionDeclaration*> f = {
729 : (const FunctionDeclaration*) result
730 0 : };
731 0 : return std::unique_ptr<FunctionReference>(new FunctionReference(fContext,
732 0 : identifier.fPosition,
733 0 : f));
734 : }
735 : case Symbol::kUnresolvedFunction_Kind: {
736 0 : const UnresolvedFunction* f = (const UnresolvedFunction*) result;
737 0 : return std::unique_ptr<FunctionReference>(new FunctionReference(fContext,
738 0 : identifier.fPosition,
739 0 : f->fFunctions));
740 : }
741 : case Symbol::kVariable_Kind: {
742 0 : const Variable* var = (const Variable*) result;
743 0 : if (var->fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN) {
744 0 : fInputs.fFlipY = true;
745 0 : if (fSettings->fFlipY &&
746 0 : (!fSettings->fCaps ||
747 0 : !fSettings->fCaps->fragCoordConventionsExtensionString())) {
748 0 : fInputs.fRTHeight = true;
749 : }
750 : }
751 : // default to kRead_RefKind; this will be corrected later if the variable is written to
752 0 : return std::unique_ptr<VariableReference>(new VariableReference(
753 0 : identifier.fPosition,
754 : *var,
755 0 : VariableReference::kRead_RefKind));
756 : }
757 : case Symbol::kField_Kind: {
758 0 : const Field* field = (const Field*) result;
759 0 : VariableReference* base = new VariableReference(identifier.fPosition, field->fOwner,
760 0 : VariableReference::kRead_RefKind);
761 : return std::unique_ptr<Expression>(new FieldAccess(
762 0 : std::unique_ptr<Expression>(base),
763 0 : field->fFieldIndex,
764 0 : FieldAccess::kAnonymousInterfaceBlock_OwnerKind));
765 : }
766 : case Symbol::kType_Kind: {
767 0 : const Type* t = (const Type*) result;
768 0 : return std::unique_ptr<TypeReference>(new TypeReference(fContext, identifier.fPosition,
769 0 : *t));
770 : }
771 : default:
772 0 : ABORT("unsupported symbol type %d\n", result->fKind);
773 : }
774 :
775 : }
776 :
777 0 : std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr,
778 : const Type& type) {
779 0 : if (!expr) {
780 0 : return nullptr;
781 : }
782 0 : if (expr->fType == type) {
783 0 : return expr;
784 : }
785 0 : this->checkValid(*expr);
786 0 : if (expr->fType == *fContext.fInvalid_Type) {
787 0 : return nullptr;
788 : }
789 0 : if (!expr->fType.canCoerceTo(type)) {
790 0 : fErrors.error(expr->fPosition, "expected '" + type.description() + "', but found '" +
791 0 : expr->fType.description() + "'");
792 0 : return nullptr;
793 : }
794 0 : if (type.kind() == Type::kScalar_Kind) {
795 0 : std::vector<std::unique_ptr<Expression>> args;
796 0 : args.push_back(std::move(expr));
797 0 : ASTIdentifier id(Position(), type.description());
798 0 : std::unique_ptr<Expression> ctor = this->convertIdentifier(id);
799 0 : ASSERT(ctor);
800 0 : return this->call(Position(), std::move(ctor), std::move(args));
801 : }
802 0 : std::vector<std::unique_ptr<Expression>> args;
803 0 : args.push_back(std::move(expr));
804 0 : return std::unique_ptr<Expression>(new Constructor(Position(), type, std::move(args)));
805 : }
806 :
807 0 : static bool is_matrix_multiply(const Type& left, const Type& right) {
808 0 : if (left.kind() == Type::kMatrix_Kind) {
809 0 : return right.kind() == Type::kMatrix_Kind || right.kind() == Type::kVector_Kind;
810 : }
811 0 : return left.kind() == Type::kVector_Kind && right.kind() == Type::kMatrix_Kind;
812 : }
813 :
814 : /**
815 : * Determines the operand and result types of a binary expression. Returns true if the expression is
816 : * legal, false otherwise. If false, the values of the out parameters are undefined.
817 : */
818 0 : static bool determine_binary_type(const Context& context,
819 : Token::Kind op,
820 : const Type& left,
821 : const Type& right,
822 : const Type** outLeftType,
823 : const Type** outRightType,
824 : const Type** outResultType,
825 : bool tryFlipped) {
826 : bool isLogical;
827 : bool validMatrixOrVectorOp;
828 0 : switch (op) {
829 : case Token::EQ:
830 0 : *outLeftType = &left;
831 0 : *outRightType = &left;
832 0 : *outResultType = &left;
833 0 : return right.canCoerceTo(left);
834 : case Token::EQEQ: // fall through
835 : case Token::NEQ:
836 0 : isLogical = true;
837 0 : validMatrixOrVectorOp = true;
838 0 : break;
839 : case Token::LT: // fall through
840 : case Token::GT: // fall through
841 : case Token::LTEQ: // fall through
842 : case Token::GTEQ:
843 0 : isLogical = true;
844 0 : validMatrixOrVectorOp = false;
845 0 : break;
846 : case Token::LOGICALOR: // fall through
847 : case Token::LOGICALAND: // fall through
848 : case Token::LOGICALXOR: // fall through
849 : case Token::LOGICALOREQ: // fall through
850 : case Token::LOGICALANDEQ: // fall through
851 : case Token::LOGICALXOREQ:
852 0 : *outLeftType = context.fBool_Type.get();
853 0 : *outRightType = context.fBool_Type.get();
854 0 : *outResultType = context.fBool_Type.get();
855 0 : return left.canCoerceTo(*context.fBool_Type) &&
856 0 : right.canCoerceTo(*context.fBool_Type);
857 : case Token::STAR: // fall through
858 : case Token::STAREQ:
859 0 : if (is_matrix_multiply(left, right)) {
860 : // determine final component type
861 0 : if (determine_binary_type(context, Token::STAR, left.componentType(),
862 : right.componentType(), outLeftType, outRightType,
863 : outResultType, false)) {
864 0 : *outLeftType = &(*outResultType)->toCompound(context, left.columns(),
865 0 : left.rows());;
866 0 : *outRightType = &(*outResultType)->toCompound(context, right.columns(),
867 0 : right.rows());;
868 0 : int leftColumns = left.columns();
869 0 : int leftRows = left.rows();
870 : int rightColumns;
871 : int rightRows;
872 0 : if (right.kind() == Type::kVector_Kind) {
873 : // matrix * vector treats the vector as a column vector, so we need to
874 : // transpose it
875 0 : rightColumns = right.rows();
876 0 : rightRows = right.columns();
877 0 : ASSERT(rightColumns == 1);
878 : } else {
879 0 : rightColumns = right.columns();
880 0 : rightRows = right.rows();
881 : }
882 0 : if (rightColumns > 1) {
883 0 : *outResultType = &(*outResultType)->toCompound(context, rightColumns,
884 0 : leftRows);
885 : } else {
886 : // result was a column vector, transpose it back to a row
887 0 : *outResultType = &(*outResultType)->toCompound(context, leftRows,
888 0 : rightColumns);
889 : }
890 0 : return leftColumns == rightRows;
891 : } else {
892 0 : return false;
893 : }
894 : }
895 0 : isLogical = false;
896 0 : validMatrixOrVectorOp = true;
897 0 : break;
898 : case Token::PLUS: // fall through
899 : case Token::PLUSEQ: // fall through
900 : case Token::MINUS: // fall through
901 : case Token::MINUSEQ: // fall through
902 : case Token::SLASH: // fall through
903 : case Token::SLASHEQ:
904 0 : isLogical = false;
905 0 : validMatrixOrVectorOp = true;
906 0 : break;
907 : default:
908 0 : isLogical = false;
909 0 : validMatrixOrVectorOp = false;
910 : }
911 0 : bool isVectorOrMatrix = left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind;
912 : // FIXME: incorrect for shift
913 0 : if (right.canCoerceTo(left) && (left.kind() == Type::kScalar_Kind ||
914 0 : (isVectorOrMatrix && validMatrixOrVectorOp))) {
915 0 : *outLeftType = &left;
916 0 : *outRightType = &left;
917 0 : if (isLogical) {
918 0 : *outResultType = context.fBool_Type.get();
919 : } else {
920 0 : *outResultType = &left;
921 : }
922 0 : return true;
923 : }
924 0 : if ((left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind) &&
925 0 : (right.kind() == Type::kScalar_Kind)) {
926 0 : if (determine_binary_type(context, op, left.componentType(), right, outLeftType,
927 : outRightType, outResultType, false)) {
928 0 : *outLeftType = &(*outLeftType)->toCompound(context, left.columns(), left.rows());
929 0 : if (!isLogical) {
930 0 : *outResultType = &(*outResultType)->toCompound(context, left.columns(),
931 0 : left.rows());
932 : }
933 0 : return true;
934 : }
935 0 : return false;
936 : }
937 0 : if (tryFlipped) {
938 : return determine_binary_type(context, op, right, left, outRightType, outLeftType,
939 0 : outResultType, false);
940 : }
941 0 : return false;
942 : }
943 :
944 0 : std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
945 : Token::Kind op,
946 : const Expression& right) const {
947 : // Note that we expressly do not worry about precision and overflow here -- we use the maximum
948 : // precision to calculate the results and hope the result makes sense. The plan is to move the
949 : // Skia caps into SkSL, so we have access to all of them including the precisions of the various
950 : // types, which will let us be more intelligent about this.
951 0 : if (left.fKind == Expression::kBoolLiteral_Kind &&
952 0 : right.fKind == Expression::kBoolLiteral_Kind) {
953 0 : bool leftVal = ((BoolLiteral&) left).fValue;
954 0 : bool rightVal = ((BoolLiteral&) right).fValue;
955 : bool result;
956 0 : switch (op) {
957 0 : case Token::LOGICALAND: result = leftVal && rightVal; break;
958 0 : case Token::LOGICALOR: result = leftVal || rightVal; break;
959 0 : case Token::LOGICALXOR: result = leftVal ^ rightVal; break;
960 0 : default: return nullptr;
961 : }
962 0 : return std::unique_ptr<Expression>(new BoolLiteral(fContext, left.fPosition, result));
963 : }
964 : #define RESULT(t, op) std::unique_ptr<Expression>(new t ## Literal(fContext, left.fPosition, \
965 : leftVal op rightVal))
966 0 : if (left.fKind == Expression::kIntLiteral_Kind && right.fKind == Expression::kIntLiteral_Kind) {
967 0 : int64_t leftVal = ((IntLiteral&) left).fValue;
968 0 : int64_t rightVal = ((IntLiteral&) right).fValue;
969 0 : switch (op) {
970 0 : case Token::PLUS: return RESULT(Int, +);
971 0 : case Token::MINUS: return RESULT(Int, -);
972 0 : case Token::STAR: return RESULT(Int, *);
973 : case Token::SLASH:
974 0 : if (rightVal) {
975 0 : return RESULT(Int, /);
976 : }
977 0 : fErrors.error(right.fPosition, "division by zero");
978 0 : return nullptr;
979 : case Token::PERCENT:
980 0 : if (rightVal) {
981 0 : return RESULT(Int, %);
982 : }
983 0 : fErrors.error(right.fPosition, "division by zero");
984 0 : return nullptr;
985 0 : case Token::BITWISEAND: return RESULT(Int, &);
986 0 : case Token::BITWISEOR: return RESULT(Int, |);
987 0 : case Token::BITWISEXOR: return RESULT(Int, ^);
988 0 : case Token::SHL: return RESULT(Int, <<);
989 0 : case Token::SHR: return RESULT(Int, >>);
990 0 : case Token::EQEQ: return RESULT(Bool, ==);
991 0 : case Token::NEQ: return RESULT(Bool, !=);
992 0 : case Token::GT: return RESULT(Bool, >);
993 0 : case Token::GTEQ: return RESULT(Bool, >=);
994 0 : case Token::LT: return RESULT(Bool, <);
995 0 : case Token::LTEQ: return RESULT(Bool, <=);
996 0 : default: return nullptr;
997 : }
998 : }
999 0 : if (left.fKind == Expression::kFloatLiteral_Kind &&
1000 0 : right.fKind == Expression::kFloatLiteral_Kind) {
1001 0 : double leftVal = ((FloatLiteral&) left).fValue;
1002 0 : double rightVal = ((FloatLiteral&) right).fValue;
1003 0 : switch (op) {
1004 0 : case Token::PLUS: return RESULT(Float, +);
1005 0 : case Token::MINUS: return RESULT(Float, -);
1006 0 : case Token::STAR: return RESULT(Float, *);
1007 : case Token::SLASH:
1008 0 : if (rightVal) {
1009 0 : return RESULT(Float, /);
1010 : }
1011 0 : fErrors.error(right.fPosition, "division by zero");
1012 0 : return nullptr;
1013 0 : case Token::EQEQ: return RESULT(Bool, ==);
1014 0 : case Token::NEQ: return RESULT(Bool, !=);
1015 0 : case Token::GT: return RESULT(Bool, >);
1016 0 : case Token::GTEQ: return RESULT(Bool, >=);
1017 0 : case Token::LT: return RESULT(Bool, <);
1018 0 : case Token::LTEQ: return RESULT(Bool, <=);
1019 0 : default: return nullptr;
1020 : }
1021 : }
1022 : #undef RESULT
1023 0 : return nullptr;
1024 : }
1025 :
1026 0 : std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(
1027 : const ASTBinaryExpression& expression) {
1028 0 : std::unique_ptr<Expression> left = this->convertExpression(*expression.fLeft);
1029 0 : if (!left) {
1030 0 : return nullptr;
1031 : }
1032 0 : std::unique_ptr<Expression> right = this->convertExpression(*expression.fRight);
1033 0 : if (!right) {
1034 0 : return nullptr;
1035 : }
1036 : const Type* leftType;
1037 : const Type* rightType;
1038 : const Type* resultType;
1039 0 : if (!determine_binary_type(fContext, expression.fOperator, left->fType, right->fType, &leftType,
1040 : &rightType, &resultType,
1041 0 : !Token::IsAssignment(expression.fOperator))) {
1042 0 : fErrors.error(expression.fPosition, "type mismatch: '" +
1043 0 : Token::OperatorName(expression.fOperator) +
1044 0 : "' cannot operate on '" + left->fType.fName +
1045 0 : "', '" + right->fType.fName + "'");
1046 0 : return nullptr;
1047 : }
1048 0 : if (Token::IsAssignment(expression.fOperator)) {
1049 0 : this->markWrittenTo(*left, expression.fOperator != Token::EQ);
1050 : }
1051 0 : left = this->coerce(std::move(left), *leftType);
1052 0 : right = this->coerce(std::move(right), *rightType);
1053 0 : if (!left || !right) {
1054 0 : return nullptr;
1055 : }
1056 0 : std::unique_ptr<Expression> result = this->constantFold(*left.get(), expression.fOperator,
1057 0 : *right.get());
1058 0 : if (!result) {
1059 0 : result = std::unique_ptr<Expression>(new BinaryExpression(expression.fPosition,
1060 0 : std::move(left),
1061 0 : expression.fOperator,
1062 0 : std::move(right),
1063 0 : *resultType));
1064 : }
1065 0 : return result;
1066 : }
1067 :
1068 0 : std::unique_ptr<Expression> IRGenerator::convertTernaryExpression(
1069 : const ASTTernaryExpression& expression) {
1070 0 : std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*expression.fTest),
1071 0 : *fContext.fBool_Type);
1072 0 : if (!test) {
1073 0 : return nullptr;
1074 : }
1075 0 : std::unique_ptr<Expression> ifTrue = this->convertExpression(*expression.fIfTrue);
1076 0 : if (!ifTrue) {
1077 0 : return nullptr;
1078 : }
1079 0 : std::unique_ptr<Expression> ifFalse = this->convertExpression(*expression.fIfFalse);
1080 0 : if (!ifFalse) {
1081 0 : return nullptr;
1082 : }
1083 : const Type* trueType;
1084 : const Type* falseType;
1085 : const Type* resultType;
1086 0 : if (!determine_binary_type(fContext, Token::EQEQ, ifTrue->fType, ifFalse->fType, &trueType,
1087 0 : &falseType, &resultType, true) || trueType != falseType) {
1088 0 : fErrors.error(expression.fPosition, "ternary operator result mismatch: '" +
1089 0 : ifTrue->fType.fName + "', '" +
1090 0 : ifFalse->fType.fName + "'");
1091 0 : return nullptr;
1092 : }
1093 0 : ifTrue = this->coerce(std::move(ifTrue), *trueType);
1094 0 : if (!ifTrue) {
1095 0 : return nullptr;
1096 : }
1097 0 : ifFalse = this->coerce(std::move(ifFalse), *falseType);
1098 0 : if (!ifFalse) {
1099 0 : return nullptr;
1100 : }
1101 0 : if (test->fKind == Expression::kBoolLiteral_Kind) {
1102 : // static boolean test, just return one of the branches
1103 0 : if (((BoolLiteral&) *test).fValue) {
1104 0 : return ifTrue;
1105 : } else {
1106 0 : return ifFalse;
1107 : }
1108 : }
1109 0 : return std::unique_ptr<Expression>(new TernaryExpression(expression.fPosition,
1110 0 : std::move(test),
1111 0 : std::move(ifTrue),
1112 0 : std::move(ifFalse)));
1113 : }
1114 :
1115 0 : std::unique_ptr<Expression> IRGenerator::call(Position position,
1116 : const FunctionDeclaration& function,
1117 : std::vector<std::unique_ptr<Expression>> arguments) {
1118 0 : if (function.fParameters.size() != arguments.size()) {
1119 0 : String msg = "call to '" + function.fName + "' expected " +
1120 0 : to_string((uint64_t) function.fParameters.size()) +
1121 0 : " argument";
1122 0 : if (function.fParameters.size() != 1) {
1123 0 : msg += "s";
1124 : }
1125 0 : msg += ", but found " + to_string((uint64_t) arguments.size());
1126 0 : fErrors.error(position, msg);
1127 0 : return nullptr;
1128 : }
1129 0 : std::vector<const Type*> types;
1130 : const Type* returnType;
1131 0 : if (!function.determineFinalTypes(arguments, &types, &returnType)) {
1132 0 : String msg = "no match for " + function.fName + "(";
1133 0 : String separator;
1134 0 : for (size_t i = 0; i < arguments.size(); i++) {
1135 0 : msg += separator;
1136 0 : separator = ", ";
1137 0 : msg += arguments[i]->fType.description();
1138 : }
1139 0 : msg += ")";
1140 0 : fErrors.error(position, msg);
1141 0 : return nullptr;
1142 : }
1143 0 : for (size_t i = 0; i < arguments.size(); i++) {
1144 0 : arguments[i] = this->coerce(std::move(arguments[i]), *types[i]);
1145 0 : if (!arguments[i]) {
1146 0 : return nullptr;
1147 : }
1148 0 : if (arguments[i] && (function.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag)) {
1149 0 : this->markWrittenTo(*arguments[i], true);
1150 : }
1151 : }
1152 0 : return std::unique_ptr<FunctionCall>(new FunctionCall(position, *returnType, function,
1153 0 : std::move(arguments)));
1154 : }
1155 :
1156 : /**
1157 : * Determines the cost of coercing the arguments of a function to the required types. Returns true
1158 : * if the cost could be computed, false if the call is not valid. Cost has no particular meaning
1159 : * other than "lower costs are preferred".
1160 : */
1161 0 : bool IRGenerator::determineCallCost(const FunctionDeclaration& function,
1162 : const std::vector<std::unique_ptr<Expression>>& arguments,
1163 : int* outCost) {
1164 0 : if (function.fParameters.size() != arguments.size()) {
1165 0 : return false;
1166 : }
1167 0 : int total = 0;
1168 0 : std::vector<const Type*> types;
1169 : const Type* ignored;
1170 0 : if (!function.determineFinalTypes(arguments, &types, &ignored)) {
1171 0 : return false;
1172 : }
1173 0 : for (size_t i = 0; i < arguments.size(); i++) {
1174 : int cost;
1175 0 : if (arguments[i]->fType.determineCoercionCost(*types[i], &cost)) {
1176 0 : total += cost;
1177 : } else {
1178 0 : return false;
1179 : }
1180 : }
1181 0 : *outCost = total;
1182 0 : return true;
1183 : }
1184 :
1185 0 : std::unique_ptr<Expression> IRGenerator::call(Position position,
1186 : std::unique_ptr<Expression> functionValue,
1187 : std::vector<std::unique_ptr<Expression>> arguments) {
1188 0 : if (functionValue->fKind == Expression::kTypeReference_Kind) {
1189 : return this->convertConstructor(position,
1190 0 : ((TypeReference&) *functionValue).fValue,
1191 0 : std::move(arguments));
1192 : }
1193 0 : if (functionValue->fKind != Expression::kFunctionReference_Kind) {
1194 0 : fErrors.error(position, "'" + functionValue->description() + "' is not a function");
1195 0 : return nullptr;
1196 : }
1197 0 : FunctionReference* ref = (FunctionReference*) functionValue.get();
1198 0 : int bestCost = INT_MAX;
1199 0 : const FunctionDeclaration* best = nullptr;
1200 0 : if (ref->fFunctions.size() > 1) {
1201 0 : for (const auto& f : ref->fFunctions) {
1202 : int cost;
1203 0 : if (this->determineCallCost(*f, arguments, &cost) && cost < bestCost) {
1204 0 : bestCost = cost;
1205 0 : best = f;
1206 : }
1207 : }
1208 0 : if (best) {
1209 0 : return this->call(position, *best, std::move(arguments));
1210 : }
1211 0 : String msg = "no match for " + ref->fFunctions[0]->fName + "(";
1212 0 : String separator;
1213 0 : for (size_t i = 0; i < arguments.size(); i++) {
1214 0 : msg += separator;
1215 0 : separator = ", ";
1216 0 : msg += arguments[i]->fType.description();
1217 : }
1218 0 : msg += ")";
1219 0 : fErrors.error(position, msg);
1220 0 : return nullptr;
1221 : }
1222 0 : return this->call(position, *ref->fFunctions[0], std::move(arguments));
1223 : }
1224 :
1225 0 : std::unique_ptr<Expression> IRGenerator::convertNumberConstructor(
1226 : Position position,
1227 : const Type& type,
1228 : std::vector<std::unique_ptr<Expression>> args) {
1229 0 : ASSERT(type.isNumber());
1230 0 : if (args.size() != 1) {
1231 0 : fErrors.error(position, "invalid arguments to '" + type.description() +
1232 0 : "' constructor, (expected exactly 1 argument, but found " +
1233 0 : to_string((uint64_t) args.size()) + ")");
1234 0 : return nullptr;
1235 : }
1236 0 : if (type == *fContext.fFloat_Type && args.size() == 1 &&
1237 0 : args[0]->fKind == Expression::kIntLiteral_Kind) {
1238 0 : int64_t value = ((IntLiteral&) *args[0]).fValue;
1239 0 : return std::unique_ptr<Expression>(new FloatLiteral(fContext, position, (double) value));
1240 : }
1241 0 : if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext.fInt_Type ||
1242 0 : type == *fContext.fUInt_Type)) {
1243 : return std::unique_ptr<Expression>(new IntLiteral(fContext,
1244 : position,
1245 0 : ((IntLiteral&) *args[0]).fValue,
1246 0 : &type));
1247 : }
1248 0 : if (args[0]->fType == *fContext.fBool_Type) {
1249 0 : std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, position, 0));
1250 0 : std::unique_ptr<IntLiteral> one(new IntLiteral(fContext, position, 1));
1251 : return std::unique_ptr<Expression>(
1252 0 : new TernaryExpression(position, std::move(args[0]),
1253 0 : this->coerce(std::move(one), type),
1254 0 : this->coerce(std::move(zero),
1255 0 : type)));
1256 : }
1257 0 : if (!args[0]->fType.isNumber()) {
1258 0 : fErrors.error(position, "invalid argument to '" + type.description() +
1259 0 : "' constructor (expected a number or bool, but found '" +
1260 0 : args[0]->fType.description() + "')");
1261 0 : return nullptr;
1262 : }
1263 0 : return std::unique_ptr<Expression>(new Constructor(position, std::move(type), std::move(args)));
1264 : }
1265 :
1266 0 : int component_count(const Type& type) {
1267 0 : switch (type.kind()) {
1268 : case Type::kVector_Kind:
1269 0 : return type.columns();
1270 : case Type::kMatrix_Kind:
1271 0 : return type.columns() * type.rows();
1272 : default:
1273 0 : return 1;
1274 : }
1275 : }
1276 :
1277 0 : std::unique_ptr<Expression> IRGenerator::convertCompoundConstructor(
1278 : Position position,
1279 : const Type& type,
1280 : std::vector<std::unique_ptr<Expression>> args) {
1281 0 : ASSERT(type.kind() == Type::kVector_Kind || type.kind() == Type::kMatrix_Kind);
1282 0 : if (type.kind() == Type::kMatrix_Kind && args.size() == 1 &&
1283 0 : args[0]->fType.kind() == Type::kMatrix_Kind) {
1284 : // matrix from matrix is always legal
1285 : return std::unique_ptr<Expression>(new Constructor(position, std::move(type),
1286 0 : std::move(args)));
1287 : }
1288 0 : int actual = 0;
1289 0 : int expected = type.rows() * type.columns();
1290 0 : if (args.size() != 1 || expected != component_count(args[0]->fType) ||
1291 0 : type.componentType().isNumber() != args[0]->fType.componentType().isNumber()) {
1292 0 : for (size_t i = 0; i < args.size(); i++) {
1293 0 : if (args[i]->fType.kind() == Type::kVector_Kind) {
1294 0 : if (type.componentType().isNumber() !=
1295 0 : args[i]->fType.componentType().isNumber()) {
1296 0 : fErrors.error(position, "'" + args[i]->fType.description() + "' is not a valid "
1297 0 : "parameter to '" + type.description() +
1298 0 : "' constructor");
1299 0 : return nullptr;
1300 : }
1301 0 : actual += args[i]->fType.columns();
1302 0 : } else if (args[i]->fType.kind() == Type::kScalar_Kind) {
1303 0 : actual += 1;
1304 0 : if (type.kind() != Type::kScalar_Kind) {
1305 0 : args[i] = this->coerce(std::move(args[i]), type.componentType());
1306 0 : if (!args[i]) {
1307 0 : return nullptr;
1308 : }
1309 : }
1310 : } else {
1311 0 : fErrors.error(position, "'" + args[i]->fType.description() + "' is not a valid "
1312 0 : "parameter to '" + type.description() + "' constructor");
1313 0 : return nullptr;
1314 : }
1315 : }
1316 0 : if (actual != 1 && actual != expected) {
1317 0 : fErrors.error(position, "invalid arguments to '" + type.description() +
1318 0 : "' constructor (expected " + to_string(expected) +
1319 0 : " scalars, but found " + to_string(actual) + ")");
1320 0 : return nullptr;
1321 : }
1322 : }
1323 0 : return std::unique_ptr<Expression>(new Constructor(position, std::move(type), std::move(args)));
1324 : }
1325 :
1326 0 : std::unique_ptr<Expression> IRGenerator::convertConstructor(
1327 : Position position,
1328 : const Type& type,
1329 : std::vector<std::unique_ptr<Expression>> args) {
1330 : // FIXME: add support for structs
1331 0 : Type::Kind kind = type.kind();
1332 0 : if (args.size() == 1 && args[0]->fType == type) {
1333 : // argument is already the right type, just return it
1334 0 : return std::move(args[0]);
1335 : }
1336 0 : if (type.isNumber()) {
1337 0 : return this->convertNumberConstructor(position, type, std::move(args));
1338 0 : } else if (kind == Type::kArray_Kind) {
1339 0 : const Type& base = type.componentType();
1340 0 : for (size_t i = 0; i < args.size(); i++) {
1341 0 : args[i] = this->coerce(std::move(args[i]), base);
1342 0 : if (!args[i]) {
1343 0 : return nullptr;
1344 : }
1345 : }
1346 : return std::unique_ptr<Expression>(new Constructor(position, std::move(type),
1347 0 : std::move(args)));
1348 0 : } else if (kind == Type::kVector_Kind || kind == Type::kMatrix_Kind) {
1349 0 : return this->convertCompoundConstructor(position, type, std::move(args));
1350 : } else {
1351 0 : fErrors.error(position, "cannot construct '" + type.description() + "'");
1352 0 : return nullptr;
1353 : }
1354 : }
1355 :
1356 0 : std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(
1357 : const ASTPrefixExpression& expression) {
1358 0 : std::unique_ptr<Expression> base = this->convertExpression(*expression.fOperand);
1359 0 : if (!base) {
1360 0 : return nullptr;
1361 : }
1362 0 : switch (expression.fOperator) {
1363 : case Token::PLUS:
1364 0 : if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) {
1365 0 : fErrors.error(expression.fPosition,
1366 0 : "'+' cannot operate on '" + base->fType.description() + "'");
1367 0 : return nullptr;
1368 : }
1369 0 : return base;
1370 : case Token::MINUS:
1371 0 : if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) {
1372 0 : fErrors.error(expression.fPosition,
1373 0 : "'-' cannot operate on '" + base->fType.description() + "'");
1374 0 : return nullptr;
1375 : }
1376 0 : if (base->fKind == Expression::kIntLiteral_Kind) {
1377 0 : return std::unique_ptr<Expression>(new IntLiteral(fContext, base->fPosition,
1378 0 : -((IntLiteral&) *base).fValue));
1379 : }
1380 0 : if (base->fKind == Expression::kFloatLiteral_Kind) {
1381 0 : double value = -((FloatLiteral&) *base).fValue;
1382 0 : return std::unique_ptr<Expression>(new FloatLiteral(fContext, base->fPosition,
1383 0 : value));
1384 : }
1385 0 : return std::unique_ptr<Expression>(new PrefixExpression(Token::MINUS, std::move(base)));
1386 : case Token::PLUSPLUS:
1387 0 : if (!base->fType.isNumber()) {
1388 0 : fErrors.error(expression.fPosition,
1389 0 : "'" + Token::OperatorName(expression.fOperator) +
1390 0 : "' cannot operate on '" + base->fType.description() + "'");
1391 0 : return nullptr;
1392 : }
1393 0 : this->markWrittenTo(*base, true);
1394 0 : break;
1395 : case Token::MINUSMINUS:
1396 0 : if (!base->fType.isNumber()) {
1397 0 : fErrors.error(expression.fPosition,
1398 0 : "'" + Token::OperatorName(expression.fOperator) +
1399 0 : "' cannot operate on '" + base->fType.description() + "'");
1400 0 : return nullptr;
1401 : }
1402 0 : this->markWrittenTo(*base, true);
1403 0 : break;
1404 : case Token::LOGICALNOT:
1405 0 : if (base->fType != *fContext.fBool_Type) {
1406 0 : fErrors.error(expression.fPosition,
1407 0 : "'" + Token::OperatorName(expression.fOperator) +
1408 0 : "' cannot operate on '" + base->fType.description() + "'");
1409 0 : return nullptr;
1410 : }
1411 0 : if (base->fKind == Expression::kBoolLiteral_Kind) {
1412 0 : return std::unique_ptr<Expression>(new BoolLiteral(fContext, base->fPosition,
1413 0 : !((BoolLiteral&) *base).fValue));
1414 : }
1415 0 : break;
1416 : case Token::BITWISENOT:
1417 0 : if (base->fType != *fContext.fInt_Type) {
1418 0 : fErrors.error(expression.fPosition,
1419 0 : "'" + Token::OperatorName(expression.fOperator) +
1420 0 : "' cannot operate on '" + base->fType.description() + "'");
1421 0 : return nullptr;
1422 : }
1423 0 : break;
1424 : default:
1425 0 : ABORT("unsupported prefix operator\n");
1426 : }
1427 0 : return std::unique_ptr<Expression>(new PrefixExpression(expression.fOperator,
1428 0 : std::move(base)));
1429 : }
1430 :
1431 0 : std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression> base,
1432 : const ASTExpression& index) {
1433 0 : if (base->fKind == Expression::kTypeReference_Kind) {
1434 0 : if (index.fKind == ASTExpression::kInt_Kind) {
1435 0 : const Type& oldType = ((TypeReference&) *base).fValue;
1436 0 : int64_t size = ((const ASTIntLiteral&) index).fValue;
1437 0 : Type* newType = new Type(oldType.name() + "[" + to_string(size) + "]",
1438 0 : Type::kArray_Kind, oldType, size);
1439 0 : fSymbolTable->takeOwnership(newType);
1440 0 : return std::unique_ptr<Expression>(new TypeReference(fContext, base->fPosition,
1441 0 : *newType));
1442 :
1443 : } else {
1444 0 : fErrors.error(base->fPosition, "array size must be a constant");
1445 0 : return nullptr;
1446 : }
1447 : }
1448 0 : if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::kMatrix_Kind &&
1449 0 : base->fType.kind() != Type::kVector_Kind) {
1450 0 : fErrors.error(base->fPosition, "expected array, but found '" + base->fType.description() +
1451 0 : "'");
1452 0 : return nullptr;
1453 : }
1454 0 : std::unique_ptr<Expression> converted = this->convertExpression(index);
1455 0 : if (!converted) {
1456 0 : return nullptr;
1457 : }
1458 0 : if (converted->fType != *fContext.fUInt_Type) {
1459 0 : converted = this->coerce(std::move(converted), *fContext.fInt_Type);
1460 0 : if (!converted) {
1461 0 : return nullptr;
1462 : }
1463 : }
1464 0 : return std::unique_ptr<Expression>(new IndexExpression(fContext, std::move(base),
1465 0 : std::move(converted)));
1466 : }
1467 :
1468 0 : std::unique_ptr<Expression> IRGenerator::convertField(std::unique_ptr<Expression> base,
1469 : const String& field) {
1470 0 : auto fields = base->fType.fields();
1471 0 : for (size_t i = 0; i < fields.size(); i++) {
1472 0 : if (fields[i].fName == field) {
1473 0 : return std::unique_ptr<Expression>(new FieldAccess(std::move(base), (int) i));
1474 : }
1475 : }
1476 0 : fErrors.error(base->fPosition, "type '" + base->fType.description() + "' does not have a "
1477 0 : "field named '" + field + "");
1478 0 : return nullptr;
1479 : }
1480 :
1481 0 : std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expression> base,
1482 : const String& fields) {
1483 0 : if (base->fType.kind() != Type::kVector_Kind) {
1484 0 : fErrors.error(base->fPosition, "cannot swizzle type '" + base->fType.description() + "'");
1485 0 : return nullptr;
1486 : }
1487 0 : std::vector<int> swizzleComponents;
1488 0 : for (size_t i = 0; i < fields.size(); i++) {
1489 0 : switch (fields[i]) {
1490 : case 'x': // fall through
1491 : case 'r': // fall through
1492 : case 's':
1493 0 : swizzleComponents.push_back(0);
1494 0 : break;
1495 : case 'y': // fall through
1496 : case 'g': // fall through
1497 : case 't':
1498 0 : if (base->fType.columns() >= 2) {
1499 0 : swizzleComponents.push_back(1);
1500 0 : break;
1501 : }
1502 : // fall through
1503 : case 'z': // fall through
1504 : case 'b': // fall through
1505 : case 'p':
1506 0 : if (base->fType.columns() >= 3) {
1507 0 : swizzleComponents.push_back(2);
1508 0 : break;
1509 : }
1510 : // fall through
1511 : case 'w': // fall through
1512 : case 'a': // fall through
1513 : case 'q':
1514 0 : if (base->fType.columns() >= 4) {
1515 0 : swizzleComponents.push_back(3);
1516 0 : break;
1517 : }
1518 : // fall through
1519 : default:
1520 0 : fErrors.error(base->fPosition, String::printf("invalid swizzle component '%c'",
1521 0 : fields[i]));
1522 0 : return nullptr;
1523 : }
1524 : }
1525 0 : ASSERT(swizzleComponents.size() > 0);
1526 0 : if (swizzleComponents.size() > 4) {
1527 0 : fErrors.error(base->fPosition, "too many components in swizzle mask '" + fields + "'");
1528 0 : return nullptr;
1529 : }
1530 0 : return std::unique_ptr<Expression>(new Swizzle(fContext, std::move(base), swizzleComponents));
1531 : }
1532 :
1533 0 : std::unique_ptr<Expression> IRGenerator::getCap(Position position, String name) {
1534 0 : auto found = fCapsMap.find(name);
1535 0 : if (found == fCapsMap.end()) {
1536 0 : fErrors.error(position, "unknown capability flag '" + name + "'");
1537 0 : return nullptr;
1538 : }
1539 0 : switch (found->second.fKind) {
1540 : case CapValue::kBool_Kind:
1541 : return std::unique_ptr<Expression>(new BoolLiteral(fContext, position,
1542 0 : (bool) found->second.fValue));
1543 : case CapValue::kInt_Kind:
1544 : return std::unique_ptr<Expression>(new IntLiteral(fContext, position,
1545 0 : found->second.fValue));
1546 : }
1547 0 : ASSERT(false);
1548 0 : return nullptr;
1549 : }
1550 :
1551 0 : std::unique_ptr<Expression> IRGenerator::convertSuffixExpression(
1552 : const ASTSuffixExpression& expression) {
1553 0 : std::unique_ptr<Expression> base = this->convertExpression(*expression.fBase);
1554 0 : if (!base) {
1555 0 : return nullptr;
1556 : }
1557 0 : switch (expression.fSuffix->fKind) {
1558 : case ASTSuffix::kIndex_Kind: {
1559 0 : const ASTExpression* expr = ((ASTIndexSuffix&) *expression.fSuffix).fExpression.get();
1560 0 : if (expr) {
1561 0 : return this->convertIndex(std::move(base), *expr);
1562 0 : } else if (base->fKind == Expression::kTypeReference_Kind) {
1563 0 : const Type& oldType = ((TypeReference&) *base).fValue;
1564 0 : Type* newType = new Type(oldType.name() + "[]", Type::kArray_Kind, oldType,
1565 0 : -1);
1566 0 : fSymbolTable->takeOwnership(newType);
1567 0 : return std::unique_ptr<Expression>(new TypeReference(fContext, base->fPosition,
1568 0 : *newType));
1569 : } else {
1570 0 : fErrors.error(expression.fPosition, "'[]' must follow a type name");
1571 0 : return nullptr;
1572 : }
1573 : }
1574 : case ASTSuffix::kCall_Kind: {
1575 0 : auto rawArguments = &((ASTCallSuffix&) *expression.fSuffix).fArguments;
1576 0 : std::vector<std::unique_ptr<Expression>> arguments;
1577 0 : for (size_t i = 0; i < rawArguments->size(); i++) {
1578 : std::unique_ptr<Expression> converted =
1579 0 : this->convertExpression(*(*rawArguments)[i]);
1580 0 : if (!converted) {
1581 0 : return nullptr;
1582 : }
1583 0 : arguments.push_back(std::move(converted));
1584 : }
1585 0 : return this->call(expression.fPosition, std::move(base), std::move(arguments));
1586 : }
1587 : case ASTSuffix::kField_Kind: {
1588 0 : if (base->fType == *fContext.fSkCaps_Type) {
1589 : return this->getCap(expression.fPosition,
1590 0 : ((ASTFieldSuffix&) *expression.fSuffix).fField);
1591 : }
1592 0 : switch (base->fType.kind()) {
1593 : case Type::kVector_Kind:
1594 0 : return this->convertSwizzle(std::move(base),
1595 0 : ((ASTFieldSuffix&) *expression.fSuffix).fField);
1596 : case Type::kStruct_Kind:
1597 0 : return this->convertField(std::move(base),
1598 0 : ((ASTFieldSuffix&) *expression.fSuffix).fField);
1599 : default:
1600 0 : fErrors.error(base->fPosition, "cannot swizzle value of type '" +
1601 0 : base->fType.description() + "'");
1602 0 : return nullptr;
1603 : }
1604 : }
1605 : case ASTSuffix::kPostIncrement_Kind:
1606 0 : if (!base->fType.isNumber()) {
1607 0 : fErrors.error(expression.fPosition,
1608 0 : "'++' cannot operate on '" + base->fType.description() + "'");
1609 0 : return nullptr;
1610 : }
1611 0 : this->markWrittenTo(*base, true);
1612 0 : return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
1613 0 : Token::PLUSPLUS));
1614 : case ASTSuffix::kPostDecrement_Kind:
1615 0 : if (!base->fType.isNumber()) {
1616 0 : fErrors.error(expression.fPosition,
1617 0 : "'--' cannot operate on '" + base->fType.description() + "'");
1618 0 : return nullptr;
1619 : }
1620 0 : this->markWrittenTo(*base, true);
1621 0 : return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
1622 0 : Token::MINUSMINUS));
1623 : default:
1624 0 : ABORT("unsupported suffix operator");
1625 : }
1626 : }
1627 :
1628 0 : void IRGenerator::checkValid(const Expression& expr) {
1629 0 : switch (expr.fKind) {
1630 : case Expression::kFunctionReference_Kind:
1631 0 : fErrors.error(expr.fPosition, "expected '(' to begin function call");
1632 0 : break;
1633 : case Expression::kTypeReference_Kind:
1634 0 : fErrors.error(expr.fPosition, "expected '(' to begin constructor invocation");
1635 0 : break;
1636 : default:
1637 0 : if (expr.fType == *fContext.fInvalid_Type) {
1638 0 : fErrors.error(expr.fPosition, "invalid expression");
1639 : }
1640 : }
1641 0 : }
1642 :
1643 0 : static bool has_duplicates(const Swizzle& swizzle) {
1644 0 : int bits = 0;
1645 0 : for (int idx : swizzle.fComponents) {
1646 0 : ASSERT(idx >= 0 && idx <= 3);
1647 0 : int bit = 1 << idx;
1648 0 : if (bits & bit) {
1649 0 : return true;
1650 : }
1651 0 : bits |= bit;
1652 : }
1653 0 : return false;
1654 : }
1655 :
1656 0 : void IRGenerator::markWrittenTo(const Expression& expr, bool readWrite) {
1657 0 : switch (expr.fKind) {
1658 : case Expression::kVariableReference_Kind: {
1659 0 : const Variable& var = ((VariableReference&) expr).fVariable;
1660 0 : if (var.fModifiers.fFlags & (Modifiers::kConst_Flag | Modifiers::kUniform_Flag)) {
1661 0 : fErrors.error(expr.fPosition,
1662 0 : "cannot modify immutable variable '" + var.fName + "'");
1663 : }
1664 0 : ((VariableReference&) expr).setRefKind(readWrite ? VariableReference::kReadWrite_RefKind
1665 0 : : VariableReference::kWrite_RefKind);
1666 0 : break;
1667 : }
1668 : case Expression::kFieldAccess_Kind:
1669 0 : this->markWrittenTo(*((FieldAccess&) expr).fBase, readWrite);
1670 0 : break;
1671 : case Expression::kSwizzle_Kind:
1672 0 : if (has_duplicates((Swizzle&) expr)) {
1673 0 : fErrors.error(expr.fPosition,
1674 0 : "cannot write to the same swizzle field more than once");
1675 : }
1676 0 : this->markWrittenTo(*((Swizzle&) expr).fBase, readWrite);
1677 0 : break;
1678 : case Expression::kIndex_Kind:
1679 0 : this->markWrittenTo(*((IndexExpression&) expr).fBase, readWrite);
1680 0 : break;
1681 : default:
1682 0 : fErrors.error(expr.fPosition, "cannot assign to '" + expr.description() + "'");
1683 0 : break;
1684 : }
1685 0 : }
1686 :
1687 : }
|