Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Side by Side Diff: src/sksl/SkSLIRGenerator.cpp

Issue 1984363002: initial checkin of SkSL compiler (Closed) Base URL: https://skia.googlesource.com/skia@master
Patch Set: changed SkSLType to follow Vulkan spec Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
12 #include "ast/SkSLASTBoolLiteral.h"
13 #include "ast/SkSLASTFieldSuffix.h"
14 #include "ast/SkSLASTFloatLiteral.h"
15 #include "ast/SkSLASTIndexSuffix.h"
16 #include "ast/SkSLASTIntLiteral.h"
17 #include "ir/SkSLBinaryExpression.h"
18 #include "ir/SkSLBoolLiteral.h"
19 #include "ir/SkSLBreakStatement.h"
20 #include "ir/SkSLConstructor.h"
21 #include "ir/SkSLContinueStatement.h"
22 #include "ir/SkSLDiscardStatement.h"
23 #include "ir/SkSLDoStatement.h"
24 #include "ir/SkSLExpressionStatement.h"
25 #include "ir/SkSLField.h"
26 #include "ir/SkSLFieldAccess.h"
27 #include "ir/SkSLFloatLiteral.h"
28 #include "ir/SkSLForStatement.h"
29 #include "ir/SkSLFunctionCall.h"
30 #include "ir/SkSLFunctionDeclaration.h"
31 #include "ir/SkSLFunctionDefinition.h"
32 #include "ir/SkSLFunctionReference.h"
33 #include "ir/SkSLIfStatement.h"
34 #include "ir/SkSLIndexExpression.h"
35 #include "ir/SkSLInterfaceBlock.h"
36 #include "ir/SkSLIntLiteral.h"
37 #include "ir/SkSLLayout.h"
38 #include "ir/SkSLPostfixExpression.h"
39 #include "ir/SkSLPrefixExpression.h"
40 #include "ir/SkSLReturnStatement.h"
41 #include "ir/SkSLSwizzle.h"
42 #include "ir/SkSLTernaryExpression.h"
43 #include "ir/SkSLUnresolvedFunction.h"
44 #include "ir/SkSLVariable.h"
45 #include "ir/SkSLVarDeclaration.h"
46 #include "ir/SkSLVarDeclarationStatement.h"
47 #include "ir/SkSLVariableReference.h"
48 #include "ir/SkSLWhileStatement.h"
49
50 namespace SkSL {
51
52 class AutoSymbolTable {
53 public:
54 AutoSymbolTable(IRGenerator* ir)
55 : fIR(ir)
56 , fPrevious(fIR->fSymbolTable) {
57 fIR->pushSymbolTable();
58 }
59
60 ~AutoSymbolTable() {
61 fIR->popSymbolTable();
62 ASSERT(fPrevious == fIR->fSymbolTable);
63 }
64
65 IRGenerator* fIR;
66 std::shared_ptr<SymbolTable> fPrevious;
67 };
68
69 IRGenerator::IRGenerator(std::shared_ptr<SymbolTable> symbolTable,
70 ErrorReporter& errorReporter)
71 : fSymbolTable(std::move(symbolTable))
72 , fErrors(errorReporter) {
73 }
74
75 void IRGenerator::pushSymbolTable() {
76 fSymbolTable.reset(new SymbolTable(std::move(fSymbolTable), fErrors));
77 }
78
79 void IRGenerator::popSymbolTable() {
80 fSymbolTable = fSymbolTable->fParent;
81 }
82
83 std::unique_ptr<Extension> IRGenerator::convertExtension(const ASTExtension& ext ension) {
84 return std::unique_ptr<Extension>(new Extension(extension.fPosition, extensi on.fName));
85 }
86
87 std::unique_ptr<Statement> IRGenerator::convertStatement(const ASTStatement& sta tement) {
88 switch (statement.fKind) {
89 case ASTStatement::kBlock_Kind:
90 return this->convertBlock((ASTBlock&) statement);
91 case ASTStatement::kVarDeclaration_Kind:
92 return this->convertVarDeclarationStatement((ASTVarDeclarationStatem ent&) statement);
93 case ASTStatement::kExpression_Kind:
94 return this->convertExpressionStatement((ASTExpressionStatement&) st atement);
95 case ASTStatement::kIf_Kind:
96 return this->convertIf((ASTIfStatement&) statement);
97 case ASTStatement::kFor_Kind:
98 return this->convertFor((ASTForStatement&) statement);
99 case ASTStatement::kWhile_Kind:
100 return this->convertWhile((ASTWhileStatement&) statement);
101 case ASTStatement::kDo_Kind:
102 return this->convertDo((ASTDoStatement&) statement);
103 case ASTStatement::kReturn_Kind:
104 return this->convertReturn((ASTReturnStatement&) statement);
105 case ASTStatement::kBreak_Kind:
106 return this->convertBreak((ASTBreakStatement&) statement);
107 case ASTStatement::kContinue_Kind:
108 return this->convertContinue((ASTContinueStatement&) statement);
109 case ASTStatement::kDiscard_Kind:
110 return this->convertDiscard((ASTDiscardStatement&) statement);
111 default:
112 ABORT("unsupported statement type: %d\n", statement.fKind);
113 }
114 }
115
116 std::unique_ptr<Block> IRGenerator::convertBlock(const ASTBlock& block) {
117 AutoSymbolTable table(this);
118 std::vector<std::unique_ptr<Statement>> statements;
119 for (size_t i = 0; i < block.fStatements.size(); i++) {
120 std::unique_ptr<Statement> statement = this->convertStatement(*block.fSt atements[i]);
121 if (!statement) {
122 return nullptr;
123 }
124 statements.push_back(std::move(statement));
125 }
126 return std::unique_ptr<Block>(new Block(block.fPosition, std::move(statement s)));
127 }
128
129 std::unique_ptr<Statement> IRGenerator::convertVarDeclarationStatement(
130 const ASTVarDeclar ationStatement& s) {
131 auto decl = this->convertVarDeclaration(*s.fDeclaration, Variable::kLocal_St orage);
132 if (!decl) {
133 return nullptr;
134 }
135 return std::unique_ptr<Statement>(new VarDeclarationStatement(std::move(decl )));
136 }
137
138 Modifiers IRGenerator::convertModifiers(const ASTModifiers& modifiers) {
139 return Modifiers(modifiers);
140 }
141
142 std::unique_ptr<VarDeclaration> IRGenerator::convertVarDeclaration(const ASTVarD eclaration& decl,
143 Variable::Sto rage storage) {
144 std::vector<std::shared_ptr<Variable>> variables;
145 std::vector<std::vector<std::unique_ptr<Expression>>> sizes;
146 std::vector<std::unique_ptr<Expression>> values;
147 std::shared_ptr<Type> baseType = this->convertType(*decl.fType);
148 if (!baseType) {
149 return nullptr;
150 }
151 for (size_t i = 0; i < decl.fNames.size(); i++) {
152 Modifiers modifiers = this->convertModifiers(decl.fModifiers);
153 std::shared_ptr<Type> type = baseType;
154 ASSERT(type->kind() != Type::kArray_Kind);
155 std::vector<std::unique_ptr<Expression>> currentVarSizes;
156 for (size_t j = 0; j < decl.fSizes[i].size(); j++) {
157 if (decl.fSizes[i][j]) {
158 ASTExpression& rawSize = *decl.fSizes[i][j];
159 auto size = this->coerce(this->convertExpression(rawSize), kInt_ Type);
160 if (!size) {
161 return nullptr;
162 }
163 std::string name = type->fName;
164 uint64_t count;
165 if (size->fKind == Expression::kIntLiteral_Kind) {
166 count = ((IntLiteral&) *size).fValue;
167 if (count <= 0) {
168 fErrors.error(size->fPosition, "array size must be posit ive");
169 }
170 name += "[" + to_string(count) + "]";
171 } else {
172 count = -1;
173 name += "[]";
174 }
175 type = std::shared_ptr<Type>(new Type(name, Type::kArray_Kind, t ype, (int) count));
176 currentVarSizes.push_back(std::move(size));
177 } else {
178 type = std::shared_ptr<Type>(new Type(type->fName + "[]", Type:: kArray_Kind, type,
179 -1));
180 currentVarSizes.push_back(nullptr);
181 }
182 }
183 sizes.push_back(std::move(currentVarSizes));
184 auto var = std::make_shared<Variable>(decl.fPosition, modifiers, decl.fN ames[i], type,
185 storage);
186 variables.push_back(var);
187 std::unique_ptr<Expression> value;
188 if (decl.fValues[i]) {
189 value = this->convertExpression(*decl.fValues[i]);
190 if (!value) {
191 return nullptr;
192 }
193 value = this->coerce(std::move(value), type);
194 }
195 fSymbolTable->add(var->fName, var);
196 values.push_back(std::move(value));
197 }
198 return std::unique_ptr<VarDeclaration>(new VarDeclaration(decl.fPosition, st d::move(variables),
199 std::move(sizes), std::move(values)));
200 }
201
202 std::unique_ptr<Statement> IRGenerator::convertIf(const ASTIfStatement& s) {
203 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*s.f Test), kBool_Type);
204 if (!test) {
205 return nullptr;
206 }
207 std::unique_ptr<Statement> ifTrue = this->convertStatement(*s.fIfTrue);
208 if (!ifTrue) {
209 return nullptr;
210 }
211 std::unique_ptr<Statement> ifFalse;
212 if (s.fIfFalse) {
213 ifFalse = this->convertStatement(*s.fIfFalse);
214 if (!ifFalse) {
215 return nullptr;
216 }
217 }
218 return std::unique_ptr<Statement>(new IfStatement(s.fPosition, std::move(tes t),
219 std::move(ifTrue), std::mo ve(ifFalse)));
220 }
221
222 std::unique_ptr<Statement> IRGenerator::convertFor(const ASTForStatement& f) {
223 AutoSymbolTable table(this);
224 std::unique_ptr<Statement> initializer = this->convertStatement(*f.fInitiali zer);
225 if (!initializer) {
226 return nullptr;
227 }
228 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*f.f Test), kBool_Type);
229 if (!test) {
230 return nullptr;
231 }
232 std::unique_ptr<Expression> next = this->convertExpression(*f.fNext);
233 if (!next) {
234 return nullptr;
235 }
236 this->checkValid(*next);
237 std::unique_ptr<Statement> statement = this->convertStatement(*f.fStatement) ;
238 if (!statement) {
239 return nullptr;
240 }
241 return std::unique_ptr<Statement>(new ForStatement(f.fPosition, std::move(in itializer),
242 std::move(test), std::mov e(next),
243 std::move(statement)));
244 }
245
246 std::unique_ptr<Statement> IRGenerator::convertWhile(const ASTWhileStatement& w) {
247 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*w.f Test), kBool_Type);
248 if (!test) {
249 return nullptr;
250 }
251 std::unique_ptr<Statement> statement = this->convertStatement(*w.fStatement) ;
252 if (!statement) {
253 return nullptr;
254 }
255 return std::unique_ptr<Statement>(new WhileStatement(w.fPosition, std::move( test),
256 std::move(statement)));
257 }
258
259 std::unique_ptr<Statement> IRGenerator::convertDo(const ASTDoStatement& d) {
260 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*d.f Test), kBool_Type);
261 if (!test) {
262 return nullptr;
263 }
264 std::unique_ptr<Statement> statement = this->convertStatement(*d.fStatement) ;
265 if (!statement) {
266 return nullptr;
267 }
268 return std::unique_ptr<Statement>(new DoStatement(d.fPosition, std::move(sta tement),
269 std::move(test)));
270 }
271
272 std::unique_ptr<Statement> IRGenerator::convertExpressionStatement(
273 const ASTExpre ssionStatement& s) {
274 std::unique_ptr<Expression> e = this->convertExpression(*s.fExpression);
275 if (!e) {
276 return nullptr;
277 }
278 this->checkValid(*e);
279 return std::unique_ptr<Statement>(new ExpressionStatement(std::move(e)));
280 }
281
282 std::unique_ptr<Statement> IRGenerator::convertReturn(const ASTReturnStatement& r) {
283 ASSERT(fCurrentFunction);
284 if (r.fExpression) {
285 std::unique_ptr<Expression> result = this->convertExpression(*r.fExpress ion);
286 if (!result) {
287 return nullptr;
288 }
289 if (fCurrentFunction->fReturnType == kVoid_Type) {
290 fErrors.error(result->fPosition, "may not return a value from a void function");
291 } else {
292 result = this->coerce(std::move(result), fCurrentFunction->fReturnTy pe);
293 if (!result) {
294 return nullptr;
295 }
296 }
297 return std::unique_ptr<Statement>(new ReturnStatement(std::move(result)) );
298 } else {
299 if (fCurrentFunction->fReturnType != kVoid_Type) {
300 fErrors.error(r.fPosition, "expected function to return '" +
301 fCurrentFunction->fReturnType->descriptio n() + "'");
302 }
303 return std::unique_ptr<Statement>(new ReturnStatement(r.fPosition));
304 }
305 }
306
307 std::unique_ptr<Statement> IRGenerator::convertBreak(const ASTBreakStatement& b) {
308 return std::unique_ptr<Statement>(new BreakStatement(b.fPosition));
309 }
310
311 std::unique_ptr<Statement> IRGenerator::convertContinue(const ASTContinueStateme nt& c) {
312 return std::unique_ptr<Statement>(new ContinueStatement(c.fPosition));
313 }
314
315 std::unique_ptr<Statement> IRGenerator::convertDiscard(const ASTDiscardStatement & d) {
316 return std::unique_ptr<Statement>(new DiscardStatement(d.fPosition));
317 }
318
319 static std::shared_ptr<Type> expand_generics(std::shared_ptr<Type> type, int i) {
320 if (type->kind() == Type::kGeneric_Kind) {
321 return type->coercibleTypes()[i];
322 }
323 return type;
324 }
325
326 static void expand_generics(FunctionDeclaration& decl,
327 SymbolTable& symbolTable) {
328 for (int i = 0; i < 4; i++) {
329 std::shared_ptr<Type> returnType = expand_generics(decl.fReturnType, i);
330 std::vector<std::shared_ptr<Variable>> arguments;
331 for (const auto& p : decl.fParameters) {
332 arguments.push_back(std::shared_ptr<Variable>(new Variable(
333 p->fPosition ,
334 Modifiers(p- >fModifiers),
335 p->fName,
336 expand_gener ics(p->fType, i),
337 Variable::kP arameter_Storage)));
338 }
339 std::shared_ptr<FunctionDeclaration> expanded(new FunctionDeclaration(
340 decl .fPosition,
341 decl .fName,
342 std: :move(arguments),
343 std: :move(returnType)));
344 symbolTable.add(expanded->fName, expanded);
345 }
346 }
347
348 std::unique_ptr<FunctionDefinition> IRGenerator::convertFunction(const ASTFuncti on& f) {
349 std::shared_ptr<SymbolTable> old = fSymbolTable;
350 AutoSymbolTable table(this);
351 bool isGeneric;
352 std::shared_ptr<Type> returnType = this->convertType(*f.fReturnType);
353 if (!returnType) {
354 return nullptr;
355 }
356 isGeneric = returnType->kind() == Type::kGeneric_Kind;
357 std::vector<std::shared_ptr<Variable>> parameters;
358 for (const auto& param : f.fParameters) {
359 std::shared_ptr<Type> type = this->convertType(*param->fType);
360 if (!type) {
361 return nullptr;
362 }
363 for (int j = (int) param->fSizes.size() - 1; j >= 0; j--) {
364 int size = param->fSizes[j];
365 std::string name = type->name() + "[" + to_string(size) + "]";
366 type = std::shared_ptr<Type>(new Type(std::move(name), Type::kArray_ Kind,
367 std::move(type), size));
368 }
369 std::string name = param->fName;
370 Modifiers modifiers = this->convertModifiers(param->fModifiers);
371 Position pos = param->fPosition;
372 std::shared_ptr<Variable> var = std::shared_ptr<Variable>(new Variable(
373 pos,
374 modifiers,
375 std::move(n ame),
376 type,
377 Variable::k Parameter_Storage));
378 parameters.push_back(std::move(var));
379 isGeneric |= type->kind() == Type::kGeneric_Kind;
380 }
381
382 // find existing declaration
383 std::shared_ptr<FunctionDeclaration> decl;
384 auto entry = (*old)[f.fName];
385 if (entry) {
386 std::vector<std::shared_ptr<FunctionDeclaration>> functions;
387 switch (entry->fKind) {
388 case Symbol::kUnresolvedFunction_Kind:
389 functions = std::static_pointer_cast<UnresolvedFunction>(entry)- >fFunctions;
390 break;
391 case Symbol::kFunctionDeclaration_Kind:
392 functions.push_back(std::static_pointer_cast<FunctionDeclaration >(entry));
393 break;
394 default:
395 fErrors.error(f.fPosition, "symbol '" + f.fName + "' was already defined");
396 return nullptr;
397 }
398 for (const auto& other : functions) {
399 ASSERT(other->fName == f.fName);
400 if (parameters.size() == other->fParameters.size()) {
401 bool match = true;
402 for (size_t i = 0; i < parameters.size(); i++) {
403 if (parameters[i]->fType != other->fParameters[i]->fType) {
404 match = false;
405 break;
406 }
407 }
408 if (match) {
409 if (returnType != other->fReturnType) {
410 FunctionDeclaration newDecl = FunctionDeclaration(f.fPos ition,
411 f.fNam e,
412 parame ters,
413 return Type);
414 fErrors.error(f.fPosition, "functions '" + newDecl.descr iption() +
415 "' and '" + other->descriptio n() +
416 "' differ only in return type ");
417 return nullptr;
418 }
419 decl = other;
420 for (size_t i = 0; i < parameters.size(); i++) {
421 if (parameters[i]->fModifiers != other->fParameters[i]-> fModifiers) {
422 fErrors.error(f.fPosition, "modifiers on parameter " +
423 to_string(i + 1) + " diff er between " +
424 "declaration and definiti on");
425 return nullptr;
426 }
427 fSymbolTable->add(parameters[i]->fName, decl->fParameter s[i]);
428 }
429 if (other->fDefined) {
430 fErrors.error(f.fPosition, "duplicate definition of " +
431 other->description());
432 }
433 break;
434 }
435 }
436 }
437 }
438 if (!decl) {
439 // couldn't find an existing declaration
440 decl.reset(new FunctionDeclaration(f.fPosition, f.fName, parameters, ret urnType));
441 for (auto var : parameters) {
442 fSymbolTable->add(var->fName, var);
443 }
444 }
445 if (isGeneric) {
446 ASSERT(!f.fBody);
447 expand_generics(*decl, *old);
448 } else {
449 old->add(decl->fName, decl);
450 if (f.fBody) {
451 ASSERT(!fCurrentFunction);
452 fCurrentFunction = decl;
453 decl->fDefined = true;
454 std::unique_ptr<Block> body = this->convertBlock(*f.fBody);
455 fCurrentFunction = nullptr;
456 if (!body) {
457 return nullptr;
458 }
459 return std::unique_ptr<FunctionDefinition>(new FunctionDefinition(f. fPosition, decl,
460 st d::move(body)));
461 }
462 }
463 return nullptr;
464 }
465
466 std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInte rfaceBlock& intf) {
467 std::shared_ptr<SymbolTable> old = fSymbolTable;
468 AutoSymbolTable table(this);
469 Modifiers mods = this->convertModifiers(intf.fModifiers);
470 std::vector<Type::Field> fields;
471 for (size_t i = 0; i < intf.fDeclarations.size(); i++) {
472 std::unique_ptr<VarDeclaration> decl = this->convertVarDeclaration(
473 *intf.f Declarations[i],
474 Variabl e::kGlobal_Storage);
475 for (size_t j = 0; j < decl->fVars.size(); j++) {
476 fields.push_back(Type::Field(decl->fVars[j]->fModifiers, decl->fVars [j]->fName,
477 decl->fVars[j]->fType));
478 if (decl->fValues[j]) {
479 fErrors.error(decl->fPosition, "initializers are not permitted o n interface block "
480 "fields");
481 }
482 }
483 }
484 std::shared_ptr<Type> type = std::shared_ptr<Type>(new Type(intf.fInterfaceN ame, fields));
485 std::string name = intf.fValueName.length() > 0 ? intf.fValueName : intf.fIn terfaceName;
486 std::shared_ptr<Variable> var = std::shared_ptr<Variable>(new Variable(intf. fPosition, mods,
487 name, type,
488 Variable::kGloba l_Storage));
489 if (intf.fValueName.length()) {
490 old->add(intf.fValueName, var);
491
492 } else {
493 for (size_t i = 0; i < fields.size(); i++) {
494 std::shared_ptr<Field> field = std::shared_ptr<Field>(new Field(intf .fPosition, var,
495 (int ) i));
496 old->add(fields[i].fName, field);
497 }
498 }
499 return std::unique_ptr<InterfaceBlock>(new InterfaceBlock(intf.fPosition, va r));
500 }
501
502 std::shared_ptr<Type> IRGenerator::convertType(const ASTType& type) {
503 std::shared_ptr<Symbol> result = (*fSymbolTable)[type.fName];
504 if (result && result->fKind == Symbol::kType_Kind) {
505 return std::static_pointer_cast<Type>(result);
506 }
507 fErrors.error(type.fPosition, "unknown type '" + type.fName + "'");
508 return nullptr;
509 }
510
511 std::unique_ptr<Expression> IRGenerator::convertExpression(const ASTExpression& expr) {
512 switch (expr.fKind) {
513 case ASTExpression::kIdentifier_Kind:
514 return this->convertIdentifier((ASTIdentifier&) expr);
515 case ASTExpression::kBool_Kind:
516 return std::unique_ptr<Expression>(new BoolLiteral(expr.fPosition,
517 ((ASTBoolLiteral& ) expr).fValue));
518 case ASTExpression::kInt_Kind:
519 return std::unique_ptr<Expression>(new IntLiteral(expr.fPosition,
520 ((ASTIntLiteral&) expr).fValue));
521 case ASTExpression::kFloat_Kind:
522 return std::unique_ptr<Expression>(new FloatLiteral(expr.fPosition,
523 ((ASTFloatLitera l&) expr).fValue));
524 case ASTExpression::kBinary_Kind:
525 return this->convertBinaryExpression((ASTBinaryExpression&) expr);
526 case ASTExpression::kPrefix_Kind:
527 return this->convertPrefixExpression((ASTPrefixExpression&) expr);
528 case ASTExpression::kSuffix_Kind:
529 return this->convertSuffixExpression((ASTSuffixExpression&) expr);
530 case ASTExpression::kTernary_Kind:
531 return this->convertTernaryExpression((ASTTernaryExpression&) expr);
532 default:
533 ABORT("unsupported expression type: %d\n", expr.fKind);
534 }
535 }
536
537 std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier& identifier) {
538 std::shared_ptr<Symbol> result = (*fSymbolTable)[identifier.fText];
539 if (!result) {
540 fErrors.error(identifier.fPosition, "unknown identifier '" + identifier. fText + "'");
541 return nullptr;
542 }
543 switch (result->fKind) {
544 case Symbol::kFunctionDeclaration_Kind: {
545 std::vector<std::shared_ptr<FunctionDeclaration>> f = {
546 std::static_pointer_cast<FunctionDeclaration>(result)
547 };
548 return std::unique_ptr<FunctionReference>(new FunctionReference(iden tifier.fPosition,
549 std: :move(f)));
550 }
551 case Symbol::kUnresolvedFunction_Kind: {
552 auto f = std::static_pointer_cast<UnresolvedFunction>(result);
553 return std::unique_ptr<FunctionReference>(new FunctionReference(iden tifier.fPosition,
554 f->f Functions));
555 }
556 case Symbol::kVariable_Kind: {
557 std::shared_ptr<Variable> var = std::static_pointer_cast<Variable>(r esult);
558 this->markReadFrom(var);
559 return std::unique_ptr<VariableReference>(new VariableReference(iden tifier.fPosition,
560 std: :move(var)));
561 }
562 case Symbol::kField_Kind: {
563 std::shared_ptr<Field> field = std::static_pointer_cast<Field>(resul t);
564 VariableReference* base = new VariableReference(identifier.fPosition , field->fOwner);
565 return std::unique_ptr<Expression>(new FieldAccess(std::unique_ptr<E xpression>(base),
566 field->fFieldInde x));
567 }
568 case Symbol::kType_Kind: {
569 auto t = std::static_pointer_cast<Type>(result);
570 return std::unique_ptr<TypeReference>(new TypeReference(identifier.f Position,
571 std::move(t) ));
572 }
573 default:
574 ABORT("unsupported symbol type %d\n", result->fKind);
575 }
576
577 }
578
579 std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr ,
580 std::shared_ptr<Type> type) {
581 if (!expr) {
582 return nullptr;
583 }
584 if (*expr->fType == *type) {
585 return expr;
586 }
587 this->checkValid(*expr);
588 if (*expr->fType == *kInvalid_Type) {
dogben 2016/06/30 18:19:45 Isn't this unreachable due to the assertion in che
589 return nullptr;
590 }
591 if (!expr->fType->canCoerceTo(type)) {
592 fErrors.error(expr->fPosition, "expected '" + type->description() + "', but found '" +
593 expr->fType->description() + "'");
594 return nullptr;
595 }
596 if (type->kind() == Type::kScalar_Kind) {
597 std::vector<std::unique_ptr<Expression>> args;
598 args.push_back(std::move(expr));
599 ASTIdentifier id(Position(), type->description());
600 std::unique_ptr<Expression> ctor = this->convertIdentifier(id);
601 ASSERT(ctor);
602 return this->call(Position(), std::move(ctor), std::move(args));
603 }
604 ABORT("cannot coerce %s to %s", expr->fType->description().c_str(),
605 type->description().c_str());
606 }
607
608 /**
609 * Determines the operand and result types of a binary expression. Returns true if the expression is
610 * legal, false otherwise. If false, the values of the out parameters are undefi ned.
611 */
612 static bool determine_binary_type(Token::Kind op, std::shared_ptr<Type> left,
613 std::shared_ptr<Type> right,
614 std::shared_ptr<Type>* outLeftType,
615 std::shared_ptr<Type>* outRightType,
616 std::shared_ptr<Type>* outResultType,
617 bool tryFlipped) {
618 bool isLogical;
619 switch (op) {
620 case Token::EQEQ: // fall through
621 case Token::NEQ: // fall through
622 case Token::LT: // fall through
623 case Token::GT: // fall through
624 case Token::LTEQ: // fall through
625 case Token::GTEQ:
626 isLogical = true;
627 break;
628 case Token::LOGICALOR: // fall through
629 case Token::LOGICALAND: // fall through
630 case Token::LOGICALXOR: // fall through
631 case Token::LOGICALOREQ: // fall through
632 case Token::LOGICALANDEQ: // fall through
633 case Token::LOGICALXOREQ:
634 *outLeftType = kBool_Type;
635 *outRightType = kBool_Type;
636 *outResultType = kBool_Type;
637 return left->canCoerceTo(kBool_Type) && right->canCoerceTo(kBool_Typ e);
638 case Token::STAR: // fall through
639 case Token::STAREQ:
640 // FIXME need to handle non-square matrices
641 if (left->kind() == Type::kMatrix_Kind && right->kind() == Type::kVe ctor_Kind) {
642 *outLeftType = left;
643 *outRightType = right;
644 *outResultType = right;
645 return left->rows() == right->columns();
646 }
647 if (left->kind() == Type::kVector_Kind && right->kind() == Type::kMa trix_Kind) {
648 *outLeftType = left;
649 *outRightType = right;
650 *outResultType = left;
651 return left->columns() == right->columns();
652 }
653 // fall through
654 default:
655 isLogical = false;
656 }
657 // FIXME: need to disallow illegal operations like vec3 > vec3. Also do not currently have
658 // full support for numbers other than float.
659 if (left == right) {
660 *outLeftType = left;
661 *outRightType = left;
662 if (isLogical) {
663 *outResultType = kBool_Type;
664 } else {
665 *outResultType = left;
666 }
667 return true;
668 }
669 // FIXME: incorrect for shift operations
670 if (left->canCoerceTo(right)) {
671 *outLeftType = right;
672 *outRightType = right;
673 if (isLogical) {
674 *outResultType = kBool_Type;
675 } else {
676 *outResultType = right;
677 }
678 return true;
679 }
680 if ((left->kind() == Type::kVector_Kind || left->kind() == Type::kMatrix_Kin d) &&
681 (right->kind() == Type::kScalar_Kind)) {
682 if (determine_binary_type(op, left->componentType(), right, outLeftType, outRightType,
683 outResultType, false)) {
684 *outLeftType = (*outLeftType)->toCompound(left->columns(), left->row s());
685 if (!isLogical) {
686 *outResultType = (*outResultType)->toCompound(left->columns(), l eft->rows());
687 }
688 return true;
689 }
690 return false;
691 }
692 if (tryFlipped) {
693 return determine_binary_type(op, right, left, outRightType, outLeftType, outResultType,
694 false);
695 }
696 return false;
697 }
698
699 std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(
700 const ASTBinaryExpre ssion& expression) {
701 std::unique_ptr<Expression> left = this->convertExpression(*expression.fLeft );
702 if (!left) {
703 return nullptr;
704 }
705 std::unique_ptr<Expression> right = this->convertExpression(*expression.fRig ht);
706 if (!right) {
707 return nullptr;
708 }
709 std::shared_ptr<Type> leftType;
710 std::shared_ptr<Type> rightType;
711 std::shared_ptr<Type> resultType;
712 if (!determine_binary_type(expression.fOperator, left->fType, right->fType, &leftType,
713 &rightType, &resultType, true)) {
714 fErrors.error(expression.fPosition, "type mismatch: '" +
715 Token::OperatorName(expression.fOper ator) +
716 "' cannot operate on '" + left->fTyp e->fName +
717 "', '" + right->fType->fName + "'");
718 return nullptr;
719 }
720 switch (expression.fOperator) {
721 case Token::EQ: // fall through
722 case Token::PLUSEQ: // fall through
723 case Token::MINUSEQ: // fall through
724 case Token::STAREQ: // fall through
725 case Token::SLASHEQ: // fall through
726 case Token::PERCENTEQ: // fall through
727 case Token::SHLEQ: // fall through
728 case Token::SHREQ: // fall through
729 case Token::BITWISEOREQ: // fall through
730 case Token::BITWISEXOREQ: // fall through
731 case Token::BITWISEANDEQ: // fall through
732 case Token::LOGICALOREQ: // fall through
733 case Token::LOGICALXOREQ: // fall through
734 case Token::LOGICALANDEQ:
735 this->markWrittenTo(*left);
736 default:
737 break;
738 }
739 return std::unique_ptr<Expression>(new BinaryExpression(expression.fPosition ,
740 this->coerce(std::mo ve(left), leftType),
741 expression.fOperator ,
742 this->coerce(std::mo ve(right),
743 rightTy pe),
744 resultType));
745 }
746
747 std::unique_ptr<Expression> IRGenerator::convertTernaryExpression(
748 const ASTTernaryExpre ssion& expression) {
749 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*exp ression.fTest),
750 kBool_Type);
751 if (!test) {
752 return nullptr;
753 }
754 std::unique_ptr<Expression> ifTrue = this->convertExpression(*expression.fIf True);
755 if (!ifTrue) {
756 return nullptr;
757 }
758 std::unique_ptr<Expression> ifFalse = this->convertExpression(*expression.fI fFalse);
759 if (!ifFalse) {
760 return nullptr;
761 }
762 std::shared_ptr<Type> trueType;
763 std::shared_ptr<Type> falseType;
764 std::shared_ptr<Type> resultType;
765 if (!determine_binary_type(Token::EQEQ, ifTrue->fType, ifFalse->fType, &true Type,
766 &falseType, &resultType, true)) {
767 fErrors.error(expression.fPosition, "ternary operator result mismatch: ' " +
768 ifTrue->fType->fName + "', '" +
769 ifFalse->fType->fName + "'");
770 return nullptr;
771 }
772 ASSERT(trueType == falseType);
773 ifTrue = this->coerce(std::move(ifTrue), trueType);
774 ifFalse = this->coerce(std::move(ifFalse), falseType);
775 return std::unique_ptr<Expression>(new TernaryExpression(expression.fPositio n,
776 std::move(test),
777 std::move(ifTrue),
778 std::move(ifFalse)) );
779 }
780
781 std::unique_ptr<Expression> IRGenerator::call(
782 Position position,
783 std::shared_ptr<FunctionDeclaration> fu nction,
784 std::vector<std::unique_ptr<Expression> > arguments) {
785 if (function->fParameters.size() != arguments.size()) {
786 std::string msg = "call to '" + function->fName + "' expected " +
787 to_string(function->fParameters.size()) +
788 " argument";
789 if (function->fParameters.size() != 1) {
790 msg += "s";
791 }
792 msg += ", but found " + to_string(arguments.size());
793 fErrors.error(position, msg);
794 return nullptr;
795 }
796 for (size_t i = 0; i < arguments.size(); i++) {
797 arguments[i] = this->coerce(std::move(arguments[i]), function->fParamete rs[i]->fType);
798 if (arguments[i] && (function->fParameters[i]->fModifiers.fFlags & Modif iers::kOut_Flag)) {
799 this->markWrittenTo(*arguments[i]);
800 }
801 }
802 return std::unique_ptr<FunctionCall>(new FunctionCall(position, std::move(fu nction),
803 std::move(arguments))) ;
804 }
805
806 /**
807 * Determines the cost of coercing the arguments of a function to the required t ypes. Returns true
808 * if the cost could be computed, false if the call is not valid. Cost has no pa rticular meaning
809 * other than "lower costs are preferred".
810 */
811 bool IRGenerator::determineCallCost(std::shared_ptr<FunctionDeclaration> functio n,
812 const std::vector<std::unique_ptr<Expression >>& arguments,
813 int* outCost) {
814 if (function->fParameters.size() != arguments.size()) {
815 return false;
816 }
817 int total = 0;
818 for (size_t i = 0; i < arguments.size(); i++) {
819 int cost;
820 if (arguments[i]->fType->determineCoercionCost(function->fParameters[i]- >fType, &cost)) {
821 total += cost;
822 } else {
823 return false;
824 }
825 }
826 *outCost = total;
827 return true;
828 }
829
830 std::unique_ptr<Expression> IRGenerator::call(Position position,
831 std::unique_ptr<Expression> functi onValue,
832 std::vector<std::unique_ptr<Expres sion>> arguments) {
833 if (functionValue->fKind == Expression::kTypeReference_Kind) {
834 return this->convertConstructor(position,
835 ((TypeReference&) *functionValue).fValue ,
836 std::move(arguments));
837 }
838 if (functionValue->fKind != Expression::kFunctionReference_Kind) {
839 fErrors.error(position, "'" + functionValue->description() + "' is not a function");
840 return nullptr;
841 }
842 FunctionReference* ref = (FunctionReference*) functionValue.get();
843 int bestCost = INT_MAX;
844 std::shared_ptr<FunctionDeclaration> best;
845 if (ref->fFunctions.size() > 1) {
846 for (const auto& f : ref->fFunctions) {
847 int cost;
848 if (this->determineCallCost(f, arguments, &cost) && cost < bestCost) {
849 bestCost = cost;
850 best = f;
851 }
852 }
853 if (best) {
854 return this->call(position, std::move(best), std::move(arguments));
855 }
856 std::string msg = "no match for " + ref->fFunctions[0]->fName + "(";
857 std::string separator = "";
858 for (size_t i = 0; i < arguments.size(); i++) {
859 msg += separator;
860 separator = ", ";
861 msg += arguments[i]->fType->description();
862 }
863 msg += ")";
864 fErrors.error(position, msg);
865 return nullptr;
866 }
867 return this->call(position, ref->fFunctions[0], std::move(arguments));
868 }
869
870 std::unique_ptr<Expression> IRGenerator::convertConstructor(
871 Position position,
872 std::shared_ptr<Type> type,
873 std::vector<std::unique_ptr< Expression>> args) {
874 // FIXME: add support for structs and arrays
875 Type::Kind kind = type->kind();
876 if (!type->isNumber() && kind != Type::kVector_Kind && kind != Type::kMatrix _Kind) {
877 fErrors.error(position, "cannot construct '" + type->description() + "'" );
878 return nullptr;
879 }
880 if (type == kFloat_Type && args.size() == 1 &&
881 args[0]->fKind == Expression::kIntLiteral_Kind) {
882 int64_t value = ((IntLiteral&) *args[0]).fValue;
883 return std::unique_ptr<Expression>(new FloatLiteral(position, (double) v alue));
884 }
885 if (args.size() == 1 && args[0]->fType == type) {
886 // argument is already the right type, just return it
887 return std::move(args[0]);
888 }
889 if (type->isNumber()) {
890 if (args.size() != 1) {
891 fErrors.error(position, "invalid arguments to '" + type->description () +
892 "' constructor, (expected exactly 1 argument , but found " +
893 to_string(args.size()) + ")");
894 }
895 if (args[0]->fType == kBool_Type) {
896 std::unique_ptr<IntLiteral> zero(new IntLiteral(position, 0));
897 std::unique_ptr<IntLiteral> one(new IntLiteral(position, 1));
898 return std::unique_ptr<Expression>(
899 new TernaryExpression(position, std::mo ve(args[0]),
900 this->coerce(std: :move(one), type),
901 this->coerce(std: :move(zero),
902 type )));
903 } else if (!args[0]->fType->isNumber()) {
904 fErrors.error(position, "invalid argument to '" + type->description( ) +
905 "' constructor (expected a number or bool, b ut found '" +
906 args[0]->fType->description() + "')");
907 }
908 } else {
909 ASSERT(kind == Type::kVector_Kind || kind == Type::kMatrix_Kind);
910 int actual = 0;
911 for (size_t i = 0; i < args.size(); i++) {
912 if (args[i]->fType->kind() == Type::kVector_Kind ||
913 args[i]->fType->kind() == Type::kMatrix_Kind) {
914 int columns = args[i]->fType->columns();
915 int rows = args[i]->fType->rows();
916 args[i] = this->coerce(std::move(args[i]),
917 type->componentType()->toCompound(columns , rows));
918 actual += args[i]->fType->rows() * args[i]->fType->columns();
919 } else if (args[i]->fType->kind() == Type::kScalar_Kind) {
920 actual += 1;
921 if (type->kind() != Type::kScalar_Kind) {
922 args[i] = this->coerce(std::move(args[i]), type->componentTy pe());
923 }
924 } else {
925 fErrors.error(position, "'" + args[i]->fType->description() + "' is not a valid "
926 "parameter to '" + type->description() + "' constructor");
927 return nullptr;
928 }
929 }
930 int min = type->rows() * type->columns();
931 int max = type->columns() > 1 ? INT_MAX : min;
932 if ((actual < min || actual > max) &&
933 !((kind == Type::kVector_Kind || kind == Type::kMatrix_Kind) && (act ual == 1))) {
934 fErrors.error(position, "invalid arguments to '" + type->description () +
935 "' constructor (expected " + to_string(min) + " scalar" +
936 (min == 1 ? "" : "s") + ", but found " + to_ string(actual) +
937 ")");
938 return nullptr;
939 }
940 }
941 return std::unique_ptr<Expression>(new Constructor(position, std::move(type) , std::move(args)));
942 }
943
944 std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(
945 const ASTPrefixExpre ssion& expression) {
946 std::unique_ptr<Expression> base = this->convertExpression(*expression.fOper and);
947 if (!base) {
948 return nullptr;
949 }
950 switch (expression.fOperator) {
951 case Token::PLUS:
952 if (!base->fType->isNumber() && base->fType->kind() != Type::kVector _Kind) {
953 fErrors.error(expression.fPosition,
954 "'+' cannot operate on '" + base->fType->descripti on() + "'");
955 return nullptr;
956 }
957 return base;
958 case Token::MINUS:
959 if (!base->fType->isNumber() && base->fType->kind() != Type::kVector _Kind) {
960 fErrors.error(expression.fPosition,
961 "'-' cannot operate on '" + base->fType->descripti on() + "'");
962 return nullptr;
963 }
964 if (base->fKind == Expression::kIntLiteral_Kind) {
965 return std::unique_ptr<Expression>(new IntLiteral(base->fPositio n,
966 -((IntLiteral& ) *base).fValue));
967 }
968 if (base->fKind == Expression::kFloatLiteral_Kind) {
969 double value = -((FloatLiteral&) *base).fValue;
970 return std::unique_ptr<Expression>(new FloatLiteral(base->fPosit ion, value));
971 }
972 return std::unique_ptr<Expression>(new PrefixExpression(Token::MINUS , std::move(base)));
973 case Token::PLUSPLUS:
974 if (!base->fType->isNumber()) {
975 fErrors.error(expression.fPosition,
976 "'" + Token::OperatorName(expression.fOperator) +
977 "' cannot operate on '" + base->fType->description () + "'");
978 return nullptr;
979 }
980 this->markWrittenTo(*base);
981 break;
982 case Token::MINUSMINUS:
983 if (!base->fType->isNumber()) {
984 fErrors.error(expression.fPosition,
985 "'" + Token::OperatorName(expression.fOperator) +
986 "' cannot operate on '" + base->fType->description () + "'");
987 return nullptr;
988 }
989 this->markWrittenTo(*base);
990 break;
991 case Token::NOT:
992 if (base->fType != kBool_Type) {
993 fErrors.error(expression.fPosition,
994 "'" + Token::OperatorName(expression.fOperator) +
995 "' cannot operate on '" + base->fType->description () + "'");
996 return nullptr;
997 }
998 break;
999 default:
1000 ABORT("unsupported prefix operator\n");
1001 }
1002 return std::unique_ptr<Expression>(new PrefixExpression(expression.fOperator ,
1003 std::move(base)));
1004 }
1005
1006 std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression > base,
1007 const ASTExpression& index ) {
1008 if (base->fType->kind() != Type::kArray_Kind && base->fType->kind() != Type: :kMatrix_Kind &&
1009 base->fType->kind() != Type::kVector_Kind) {
1010 fErrors.error(base->fPosition, "expected array, but found '" + base->fTy pe->description() +
1011 "'");
1012 return nullptr;
1013 }
1014 std::unique_ptr<Expression> converted = this->convertExpression(index);
1015 if (!converted) {
1016 return nullptr;
1017 }
1018 converted = this->coerce(std::move(converted), kInt_Type);
1019 if (!converted) {
1020 return nullptr;
1021 }
1022 return std::unique_ptr<Expression>(new IndexExpression(std::move(base), std: :move(converted)));
1023 }
1024
1025 std::unique_ptr<Expression> IRGenerator::convertField(std::unique_ptr<Expression > base,
1026 const std::string& field) {
1027 auto fields = base->fType->fields();
1028 for (size_t i = 0; i < fields.size(); i++) {
1029 if (fields[i].fName == field) {
1030 return std::unique_ptr<Expression>(new FieldAccess(std::move(base), (int) i));
1031 }
1032 }
1033 fErrors.error(base->fPosition, "type '" + base->fType->description() + "' do es not have a "
1034 "field named '" + field + "");
1035 return nullptr;
1036 }
1037
1038 std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expressi on> base,
1039 const std::string& field s) {
1040 if (base->fType->kind() != Type::kVector_Kind) {
1041 fErrors.error(base->fPosition, "cannot swizzle type '" + base->fType->de scription() + "'");
1042 return nullptr;
1043 }
1044 std::vector<int> swizzleComponents;
1045 for (char c : fields) {
1046 switch (c) {
1047 case 'x': // fall through
1048 case 'r': // fall through
1049 case 's':
1050 swizzleComponents.push_back(0);
1051 break;
1052 case 'y': // fall through
1053 case 'g': // fall through
1054 case 't':
1055 if (base->fType->columns() >= 2) {
1056 swizzleComponents.push_back(1);
1057 break;
1058 }
1059 // fall through
1060 case 'z': // fall through
1061 case 'b': // fall through
1062 case 'p':
1063 if (base->fType->columns() >= 3) {
1064 swizzleComponents.push_back(2);
1065 break;
1066 }
1067 // fall through
1068 case 'w': // fall through
1069 case 'a': // fall through
1070 case 'q':
1071 if (base->fType->columns() >= 4) {
1072 swizzleComponents.push_back(3);
1073 break;
1074 }
1075 // fall through
1076 default:
1077 fErrors.error(base->fPosition, "invalid swizzle component '" + s td::string(1, c) +
1078 "'");
1079 return nullptr;
1080 }
1081 }
1082 ASSERT(swizzleComponents.size() > 0);
1083 if (swizzleComponents.size() > 4) {
1084 fErrors.error(base->fPosition, "too many components in swizzle mask '" + fields + "'");
1085 return nullptr;
1086 }
1087 return std::unique_ptr<Expression>(new Swizzle(std::move(base), swizzleCompo nents));
1088 }
1089
1090 std::unique_ptr<Expression> IRGenerator::convertSuffixExpression(
1091 const ASTSuffixExpre ssion& expression) {
1092 std::unique_ptr<Expression> base = this->convertExpression(*expression.fBase );
1093 if (!base) {
1094 return nullptr;
1095 }
1096 switch (expression.fSuffix->fKind) {
1097 case ASTSuffix::kIndex_Kind:
1098 return this->convertIndex(std::move(base),
1099 *((ASTIndexSuffix&) *expression.fSuffix).f Expression);
1100 case ASTSuffix::kCall_Kind: {
1101 auto rawArguments = &((ASTCallSuffix&) *expression.fSuffix).fArgumen ts;
1102 std::vector<std::unique_ptr<Expression>> arguments;
1103 for (size_t i = 0; i < rawArguments->size(); i++) {
1104 std::unique_ptr<Expression> converted =
1105 this->convertExpression(*(*rawArguments)[i]);
1106 if (!converted) {
1107 return nullptr;
1108 }
1109 arguments.push_back(std::move(converted));
1110 }
1111 return this->call(expression.fPosition, std::move(base), std::move(a rguments));
1112 }
1113 case ASTSuffix::kField_Kind: {
1114 switch (base->fType->kind()) {
1115 case Type::kVector_Kind:
1116 return this->convertSwizzle(std::move(base),
1117 ((ASTFieldSuffix&) *expression.f Suffix).fField);
1118 case Type::kStruct_Kind:
1119 return this->convertField(std::move(base),
1120 ((ASTFieldSuffix&) *expression.fSu ffix).fField);
1121 default:
1122 fErrors.error(base->fPosition, "cannot swizzle value of type '" +
1123 base->fType->description() + "'");
1124 return nullptr;
1125 }
1126 }
1127 case ASTSuffix::kPostIncrement_Kind:
1128 if (!base->fType->isNumber()) {
1129 fErrors.error(expression.fPosition,
1130 "'++' cannot operate on '" + base->fType->descript ion() + "'");
1131 return nullptr;
1132 }
1133 this->markWrittenTo(*base);
1134 return std::unique_ptr<Expression>(new PostfixExpression(std::move(b ase),
1135 Token::PLUS PLUS));
1136 case ASTSuffix::kPostDecrement_Kind:
1137 if (!base->fType->isNumber()) {
1138 fErrors.error(expression.fPosition,
1139 "'--' cannot operate on '" + base->fType->descript ion() + "'");
1140 return nullptr;
1141 }
1142 this->markWrittenTo(*base);
1143 return std::unique_ptr<Expression>(new PostfixExpression(std::move(b ase),
1144 Token::MINU SMINUS));
1145 default:
1146 ABORT("unsupported suffix operator");
1147 }
1148 }
1149
1150 void IRGenerator::checkValid(const Expression& expr) {
1151 switch (expr.fKind) {
1152 case Expression::kFunctionReference_Kind:
1153 fErrors.error(expr.fPosition, "expected '(' to begin function call") ;
1154 break;
1155 case Expression::kTypeReference_Kind:
1156 fErrors.error(expr.fPosition, "expected '(' to begin constructor inv ocation");
1157 break;
1158 default:
1159 ASSERT(expr.fType != kInvalid_Type);
1160 break;
1161 }
1162 }
1163
1164 void IRGenerator::markReadFrom(std::shared_ptr<Variable> var) {
1165 var->fIsReadFrom = true;
1166 }
1167
1168 static bool has_duplicates(const Swizzle& swizzle) {
1169 int bits = 0;
1170 for (int idx : swizzle.fComponents) {
1171 ASSERT(idx >= 0 && idx <= 3);
1172 int bit = 1 << idx;
1173 if (bits & bit) {
1174 return true;
1175 }
1176 bits |= bit;
1177 }
1178 return false;
1179 }
1180
1181 void IRGenerator::markWrittenTo(const Expression& expr) {
1182 switch (expr.fKind) {
1183 case Expression::kVariableReference_Kind: {
1184 const Variable& var = *((VariableReference&) expr).fVariable;
1185 if (var.fModifiers.fFlags & (Modifiers::kConst_Flag | Modifiers::kUn iform_Flag)) {
1186 fErrors.error(expr.fPosition,
1187 "cannot modify immutable variable '" + var.fName + "'");
1188 }
1189 var.fIsWrittenTo = true;
1190 break;
1191 }
1192 case Expression::kFieldAccess_Kind:
1193 this->markWrittenTo(*((FieldAccess&) expr).fBase);
dogben 2016/06/30 18:19:45 nit: Is it possible for an interface field to be c
ethannicholas 2016/06/30 19:16:41 Not legal. I've added a check to error if storage
1194 break;
1195 case Expression::kSwizzle_Kind:
1196 if (has_duplicates((Swizzle&) expr)) {
1197 fErrors.error(expr.fPosition,
1198 "cannot write to the same swizzle field more than once");
1199 }
1200 this->markWrittenTo(*((Swizzle&) expr).fBase);
1201 break;
1202 case Expression::kIndex_Kind:
1203 this->markWrittenTo(*((IndexExpression&) expr).fBase);
1204 break;
1205 default:
1206 fErrors.error(expr.fPosition, "cannot assign to '" + expr.descriptio n() + "'");
1207 break;
1208 }
1209 }
1210
1211 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698