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