SkSLIRGenerator.cpp revision 5961bc9278a00e56dacdd9408d0744b5a0a3b493
1b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas/* 2b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas * Copyright 2016 Google Inc. 3b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas * 4b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas * Use of this source code is governed by a BSD-style license that can be 5b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas * found in the LICENSE file. 6b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas */ 7b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 8b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "SkSLIRGenerator.h" 9b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 10b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "limits.h" 11b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 12b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ast/SkSLASTBoolLiteral.h" 13b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ast/SkSLASTFieldSuffix.h" 14b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ast/SkSLASTFloatLiteral.h" 15b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ast/SkSLASTIndexSuffix.h" 16b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ast/SkSLASTIntLiteral.h" 17b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLBinaryExpression.h" 18b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLBoolLiteral.h" 19b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLBreakStatement.h" 20b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLConstructor.h" 21b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLContinueStatement.h" 22b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLDiscardStatement.h" 23b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLDoStatement.h" 24b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLExpressionStatement.h" 25b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLField.h" 26b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLFieldAccess.h" 27b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLFloatLiteral.h" 28b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLForStatement.h" 29b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLFunctionCall.h" 30b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLFunctionDeclaration.h" 31b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLFunctionDefinition.h" 32b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLFunctionReference.h" 33b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLIfStatement.h" 34b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLIndexExpression.h" 35b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLInterfaceBlock.h" 36b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLIntLiteral.h" 37b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLLayout.h" 38b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLPostfixExpression.h" 39b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLPrefixExpression.h" 40b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLReturnStatement.h" 41b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLSwizzle.h" 42b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLTernaryExpression.h" 43b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLUnresolvedFunction.h" 44b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLVariable.h" 45b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLVarDeclaration.h" 46b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLVarDeclarationStatement.h" 47b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLVariableReference.h" 48b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLWhileStatement.h" 49b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 50b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasnamespace SkSL { 51b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 52b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasclass AutoSymbolTable { 53b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholaspublic: 54b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas AutoSymbolTable(IRGenerator* ir) 55b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas : fIR(ir) 56b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas , fPrevious(fIR->fSymbolTable) { 57b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fIR->pushSymbolTable(); 58b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 59b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 60b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ~AutoSymbolTable() { 61b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fIR->popSymbolTable(); 62b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(fPrevious == fIR->fSymbolTable); 63b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 64b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 65b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas IRGenerator* fIR; 66b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::shared_ptr<SymbolTable> fPrevious; 67b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}; 68b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 69d598f7981f34811e6f2a949207dc13638852f3f7ethannicholasIRGenerator::IRGenerator(const Context* context, std::shared_ptr<SymbolTable> symbolTable, 70b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ErrorReporter& errorReporter) 71d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas: fContext(*context) 72d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas, fCurrentFunction(nullptr) 73d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas, fSymbolTable(std::move(symbolTable)) 74d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas, fErrors(errorReporter) {} 75b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 76b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasvoid IRGenerator::pushSymbolTable() { 77b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fSymbolTable.reset(new SymbolTable(std::move(fSymbolTable), fErrors)); 78b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 79b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 80b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasvoid IRGenerator::popSymbolTable() { 81b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fSymbolTable = fSymbolTable->fParent; 82b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 83b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 84b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Extension> IRGenerator::convertExtension(const ASTExtension& extension) { 85b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::unique_ptr<Extension>(new Extension(extension.fPosition, extension.fName)); 86b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 87b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 88b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Statement> IRGenerator::convertStatement(const ASTStatement& statement) { 89b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (statement.fKind) { 90b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case ASTStatement::kBlock_Kind: 91b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->convertBlock((ASTBlock&) statement); 92b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case ASTStatement::kVarDeclaration_Kind: 93b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->convertVarDeclarationStatement((ASTVarDeclarationStatement&) statement); 94b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case ASTStatement::kExpression_Kind: 95b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->convertExpressionStatement((ASTExpressionStatement&) statement); 96b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case ASTStatement::kIf_Kind: 97b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->convertIf((ASTIfStatement&) statement); 98b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case ASTStatement::kFor_Kind: 99b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->convertFor((ASTForStatement&) statement); 100b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case ASTStatement::kWhile_Kind: 101b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->convertWhile((ASTWhileStatement&) statement); 102b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case ASTStatement::kDo_Kind: 103b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->convertDo((ASTDoStatement&) statement); 104b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case ASTStatement::kReturn_Kind: 105b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->convertReturn((ASTReturnStatement&) statement); 106b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case ASTStatement::kBreak_Kind: 107b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->convertBreak((ASTBreakStatement&) statement); 108b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case ASTStatement::kContinue_Kind: 109b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->convertContinue((ASTContinueStatement&) statement); 110b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case ASTStatement::kDiscard_Kind: 111b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->convertDiscard((ASTDiscardStatement&) statement); 112b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 113b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ABORT("unsupported statement type: %d\n", statement.fKind); 114b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 115b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 116b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 117b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Block> IRGenerator::convertBlock(const ASTBlock& block) { 118b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas AutoSymbolTable table(this); 119b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::vector<std::unique_ptr<Statement>> statements; 120b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t i = 0; i < block.fStatements.size(); i++) { 121b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<Statement> statement = this->convertStatement(*block.fStatements[i]); 122b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!statement) { 123b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 124b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 125b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas statements.push_back(std::move(statement)); 126b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 127d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return std::unique_ptr<Block>(new Block(block.fPosition, std::move(statements), fSymbolTable)); 128b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 129b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 130b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Statement> IRGenerator::convertVarDeclarationStatement( 131b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas const ASTVarDeclarationStatement& s) { 13214fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas auto decl = this->convertVarDeclarations(*s.fDeclarations, Variable::kLocal_Storage); 133b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!decl) { 134b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 135b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 13614fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas return std::unique_ptr<Statement>(new VarDeclarationsStatement(std::move(decl))); 137b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 138b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 139b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasModifiers IRGenerator::convertModifiers(const ASTModifiers& modifiers) { 140b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return Modifiers(modifiers); 141b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 142b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 14314fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholasstd::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVarDeclarations& decl, 14414fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas Variable::Storage storage) { 14514fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas std::vector<VarDeclaration> variables; 146d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Type* baseType = this->convertType(*decl.fType); 147b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!baseType) { 148b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 149b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 15014fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas for (const auto& varDecl : decl.fVars) { 151b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas Modifiers modifiers = this->convertModifiers(decl.fModifiers); 152d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Type* type = baseType; 153b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(type->kind() != Type::kArray_Kind); 15414fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas std::vector<std::unique_ptr<Expression>> sizes; 15514fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas for (const auto& rawSize : varDecl.fSizes) { 15614fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas if (rawSize) { 15714fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas auto size = this->coerce(this->convertExpression(*rawSize), *fContext.fInt_Type); 158b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!size) { 159b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 160b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 161b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::string name = type->fName; 162b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas uint64_t count; 163b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (size->fKind == Expression::kIntLiteral_Kind) { 164b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas count = ((IntLiteral&) *size).fValue; 165b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (count <= 0) { 166b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(size->fPosition, "array size must be positive"); 167b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 168b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas name += "[" + to_string(count) + "]"; 169b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 170b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas count = -1; 171b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas name += "[]"; 172b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 173d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas type = new Type(name, Type::kArray_Kind, *type, (int) count); 174d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fSymbolTable->takeOwnership((Type*) type); 17514fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas sizes.push_back(std::move(size)); 176b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 177d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas type = new Type(type->fName + "[]", Type::kArray_Kind, *type, -1); 178d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fSymbolTable->takeOwnership((Type*) type); 17914fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas sizes.push_back(nullptr); 180b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 181b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 18214fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas auto var = std::unique_ptr<Variable>(new Variable(decl.fPosition, modifiers, varDecl.fName, 183d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas *type, storage)); 184b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<Expression> value; 18514fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas if (varDecl.fValue) { 18614fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas value = this->convertExpression(*varDecl.fValue); 187b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!value) { 188b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 189b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 190d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas value = this->coerce(std::move(value), *type); 191b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1925961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if ("sk_FragColor" == varDecl.fName && (*fSymbolTable)[varDecl.fName]) { 1935961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas // already defined, ignore 1945961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } else if ((*fSymbolTable)[varDecl.fName] && 1955961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas (*fSymbolTable)[varDecl.fName]->fKind == Symbol::kVariable_Kind && 1965961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas ((Variable*) (*fSymbolTable)[varDecl.fName])->fModifiers.fLayout.fBuiltin >= 0) { 197f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas // already defined, just update the modifiers 19814fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas Variable* old = (Variable*) (*fSymbolTable)[varDecl.fName]; 199f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas old->fModifiers = var->fModifiers; 200f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } else { 20114fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas variables.emplace_back(var.get(), std::move(sizes), std::move(value)); 20214fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas fSymbolTable->add(varDecl.fName, std::move(var)); 203f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 204b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 20514fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas return std::unique_ptr<VarDeclarations>(new VarDeclarations(decl.fPosition, 20614fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas baseType, 20714fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas std::move(variables))); 208b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 209b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 2105961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholasstd::unique_ptr<ModifiersDeclaration> IRGenerator::convertModifiersDeclaration( 2115961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas const ASTModifiersDeclaration& m) { 2125961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas Modifiers modifiers = this->convertModifiers(m.fModifiers); 2135961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas return std::unique_ptr<ModifiersDeclaration>(new ModifiersDeclaration(modifiers)); 2145961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas} 2155961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas 216b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Statement> IRGenerator::convertIf(const ASTIfStatement& s) { 217d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*s.fTest), 218d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas *fContext.fBool_Type); 219b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!test) { 220b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 221b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 222b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<Statement> ifTrue = this->convertStatement(*s.fIfTrue); 223b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!ifTrue) { 224b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 225b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 226b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<Statement> ifFalse; 227b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (s.fIfFalse) { 228b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ifFalse = this->convertStatement(*s.fIfFalse); 229b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!ifFalse) { 230b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 231b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 232b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 233b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::unique_ptr<Statement>(new IfStatement(s.fPosition, std::move(test), 234b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::move(ifTrue), std::move(ifFalse))); 235b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 236b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 237b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Statement> IRGenerator::convertFor(const ASTForStatement& f) { 238b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas AutoSymbolTable table(this); 239b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<Statement> initializer = this->convertStatement(*f.fInitializer); 240b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!initializer) { 241b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 242b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 243d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*f.fTest), 244d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas *fContext.fBool_Type); 245b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!test) { 246b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 247b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 248b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<Expression> next = this->convertExpression(*f.fNext); 249b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!next) { 250b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 251b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 252b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->checkValid(*next); 253b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<Statement> statement = this->convertStatement(*f.fStatement); 254b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!statement) { 255b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 256b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 257b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::unique_ptr<Statement>(new ForStatement(f.fPosition, std::move(initializer), 258b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::move(test), std::move(next), 259d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas std::move(statement), fSymbolTable)); 260b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 261b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 262b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Statement> IRGenerator::convertWhile(const ASTWhileStatement& w) { 263d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*w.fTest), 264d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas *fContext.fBool_Type); 265b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!test) { 266b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 267b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 268b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<Statement> statement = this->convertStatement(*w.fStatement); 269b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!statement) { 270b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 271b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 272b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::unique_ptr<Statement>(new WhileStatement(w.fPosition, std::move(test), 273b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::move(statement))); 274b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 275b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 276b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Statement> IRGenerator::convertDo(const ASTDoStatement& d) { 277d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*d.fTest), 278d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas *fContext.fBool_Type); 279b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!test) { 280b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 281b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 282b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<Statement> statement = this->convertStatement(*d.fStatement); 283b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!statement) { 284b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 285b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 286b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::unique_ptr<Statement>(new DoStatement(d.fPosition, std::move(statement), 287b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::move(test))); 288b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 289b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 290b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Statement> IRGenerator::convertExpressionStatement( 291b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas const ASTExpressionStatement& s) { 292b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<Expression> e = this->convertExpression(*s.fExpression); 293b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!e) { 294b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 295b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 296b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->checkValid(*e); 297b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::unique_ptr<Statement>(new ExpressionStatement(std::move(e))); 298b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 299b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 300b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Statement> IRGenerator::convertReturn(const ASTReturnStatement& r) { 301b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(fCurrentFunction); 302b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (r.fExpression) { 303b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<Expression> result = this->convertExpression(*r.fExpression); 304b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!result) { 305b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 306b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 307d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (fCurrentFunction->fReturnType == *fContext.fVoid_Type) { 308b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(result->fPosition, "may not return a value from a void function"); 309b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 310b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas result = this->coerce(std::move(result), fCurrentFunction->fReturnType); 311b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!result) { 312b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 313b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 314b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 315b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::unique_ptr<Statement>(new ReturnStatement(std::move(result))); 316b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 317d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (fCurrentFunction->fReturnType != *fContext.fVoid_Type) { 318b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(r.fPosition, "expected function to return '" + 319d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fCurrentFunction->fReturnType.description() + "'"); 320b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 321b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::unique_ptr<Statement>(new ReturnStatement(r.fPosition)); 322b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 323b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 324b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 325b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Statement> IRGenerator::convertBreak(const ASTBreakStatement& b) { 326b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::unique_ptr<Statement>(new BreakStatement(b.fPosition)); 327b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 328b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 329b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Statement> IRGenerator::convertContinue(const ASTContinueStatement& c) { 330b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::unique_ptr<Statement>(new ContinueStatement(c.fPosition)); 331b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 332b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 333b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Statement> IRGenerator::convertDiscard(const ASTDiscardStatement& d) { 334b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::unique_ptr<Statement>(new DiscardStatement(d.fPosition)); 335b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 336b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 337d598f7981f34811e6f2a949207dc13638852f3f7ethannicholasstatic const Type& expand_generics(const Type& type, int i) { 338d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (type.kind() == Type::kGeneric_Kind) { 339d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return *type.coercibleTypes()[i]; 340b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 341b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return type; 342b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 343b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 344d598f7981f34811e6f2a949207dc13638852f3f7ethannicholasstatic void expand_generics(const FunctionDeclaration& decl, 345d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas std::shared_ptr<SymbolTable> symbolTable) { 346b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (int i = 0; i < 4; i++) { 347d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Type& returnType = expand_generics(decl.fReturnType, i); 348d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas std::vector<const Variable*> parameters; 349b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (const auto& p : decl.fParameters) { 350d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas Variable* var = new Variable(p->fPosition, Modifiers(p->fModifiers), p->fName, 351d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas expand_generics(p->fType, i), 352d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas Variable::kParameter_Storage); 353d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas symbolTable->takeOwnership(var); 354d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas parameters.push_back(var); 355b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 356d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas symbolTable->add(decl.fName, std::unique_ptr<FunctionDeclaration>(new FunctionDeclaration( 357d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas decl.fPosition, 358d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas decl.fName, 359d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas std::move(parameters), 360d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas std::move(returnType)))); 361b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 362b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 363b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 364b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<FunctionDefinition> IRGenerator::convertFunction(const ASTFunction& f) { 365b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas bool isGeneric; 366d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Type* returnType = this->convertType(*f.fReturnType); 367b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!returnType) { 368b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 369b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 370b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas isGeneric = returnType->kind() == Type::kGeneric_Kind; 371d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas std::vector<const Variable*> parameters; 372b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (const auto& param : f.fParameters) { 373d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Type* type = this->convertType(*param->fType); 374b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!type) { 375b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 376b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 377b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (int j = (int) param->fSizes.size() - 1; j >= 0; j--) { 378b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas int size = param->fSizes[j]; 379b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::string name = type->name() + "[" + to_string(size) + "]"; 380d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas Type* newType = new Type(std::move(name), Type::kArray_Kind, *type, size); 381d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fSymbolTable->takeOwnership(newType); 382d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas type = newType; 383b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 384b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::string name = param->fName; 385b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas Modifiers modifiers = this->convertModifiers(param->fModifiers); 386b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas Position pos = param->fPosition; 387d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas Variable* var = new Variable(pos, modifiers, std::move(name), *type, 388d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas Variable::kParameter_Storage); 389d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fSymbolTable->takeOwnership(var); 390d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas parameters.push_back(var); 391b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas isGeneric |= type->kind() == Type::kGeneric_Kind; 392b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 393b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 394b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // find existing declaration 395d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const FunctionDeclaration* decl = nullptr; 396d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas auto entry = (*fSymbolTable)[f.fName]; 397b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (entry) { 398d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas std::vector<const FunctionDeclaration*> functions; 399b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (entry->fKind) { 400b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Symbol::kUnresolvedFunction_Kind: 401d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas functions = ((UnresolvedFunction*) entry)->fFunctions; 402b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 403b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Symbol::kFunctionDeclaration_Kind: 404d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas functions.push_back((FunctionDeclaration*) entry); 405b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 406b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 407b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(f.fPosition, "symbol '" + f.fName + "' was already defined"); 408b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 409b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 410b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (const auto& other : functions) { 411b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(other->fName == f.fName); 412b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (parameters.size() == other->fParameters.size()) { 413b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas bool match = true; 414b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t i = 0; i < parameters.size(); i++) { 415b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (parameters[i]->fType != other->fParameters[i]->fType) { 416b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas match = false; 417b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 418b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 419b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 420b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (match) { 421d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (*returnType != other->fReturnType) { 422d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas FunctionDeclaration newDecl(f.fPosition, f.fName, parameters, *returnType); 423b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(f.fPosition, "functions '" + newDecl.description() + 424b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas "' and '" + other->description() + 425b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas "' differ only in return type"); 426b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 427b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 428b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas decl = other; 429b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t i = 0; i < parameters.size(); i++) { 430b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (parameters[i]->fModifiers != other->fParameters[i]->fModifiers) { 431b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(f.fPosition, "modifiers on parameter " + 4325961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas to_string((uint64_t) i + 1) + 4335961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas " differ between declaration and " 4345961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas "definition"); 435b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 436b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 437b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 438b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (other->fDefined) { 439b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(f.fPosition, "duplicate definition of " + 440b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas other->description()); 441b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 442b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 443b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 444b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 445b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 446b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 447b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!decl) { 448b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // couldn't find an existing declaration 449d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (isGeneric) { 450d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ASSERT(!f.fBody); 451d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas expand_generics(FunctionDeclaration(f.fPosition, f.fName, parameters, *returnType), 452d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fSymbolTable); 453d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas } else { 454d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas auto newDecl = std::unique_ptr<FunctionDeclaration>(new FunctionDeclaration( 455d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas f.fPosition, 456d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas f.fName, 457d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas parameters, 458d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas *returnType)); 459d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas decl = newDecl.get(); 460d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fSymbolTable->add(decl->fName, std::move(newDecl)); 461b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 462b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 463d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (f.fBody) { 464d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ASSERT(!fCurrentFunction); 465d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fCurrentFunction = decl; 466d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas decl->fDefined = true; 467d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas std::shared_ptr<SymbolTable> old = fSymbolTable; 468d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas AutoSymbolTable table(this); 469d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas for (size_t i = 0; i < parameters.size(); i++) { 470d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fSymbolTable->addWithoutOwnership(parameters[i]->fName, decl->fParameters[i]); 471d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas } 472d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas std::unique_ptr<Block> body = this->convertBlock(*f.fBody); 473d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fCurrentFunction = nullptr; 474d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (!body) { 475d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return nullptr; 476b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 477d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return std::unique_ptr<FunctionDefinition>(new FunctionDefinition(f.fPosition, *decl, 478d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas std::move(body))); 479b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 480b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 481b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 482b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 483b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInterfaceBlock& intf) { 484b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::shared_ptr<SymbolTable> old = fSymbolTable; 485b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas AutoSymbolTable table(this); 486b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas Modifiers mods = this->convertModifiers(intf.fModifiers); 487b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::vector<Type::Field> fields; 488b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t i = 0; i < intf.fDeclarations.size(); i++) { 48914fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas std::unique_ptr<VarDeclarations> decl = this->convertVarDeclarations( 490b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas *intf.fDeclarations[i], 491b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas Variable::kGlobal_Storage); 49214fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas for (const auto& var : decl->fVars) { 49314fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas fields.push_back(Type::Field(var.fVar->fModifiers, var.fVar->fName, 49414fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas &var.fVar->fType)); 49514fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas if (var.fValue) { 496b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(decl->fPosition, 497b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas "initializers are not permitted on interface block fields"); 498b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 49914fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas if (var.fVar->fModifiers.fFlags & (Modifiers::kIn_Flag | 50014fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas Modifiers::kOut_Flag | 50114fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas Modifiers::kUniform_Flag | 50214fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas Modifiers::kConst_Flag)) { 50314fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas fErrors.error(decl->fPosition, 504b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas "interface block fields may not have storage qualifiers"); 505b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 506b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 507b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 508d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas Type* type = new Type(intf.fInterfaceName, fields); 509d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fSymbolTable->takeOwnership(type); 510b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::string name = intf.fValueName.length() > 0 ? intf.fValueName : intf.fInterfaceName; 511d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas Variable* var = new Variable(intf.fPosition, mods, name, *type, Variable::kGlobal_Storage); 512d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fSymbolTable->takeOwnership(var); 513b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (intf.fValueName.length()) { 514d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas old->addWithoutOwnership(intf.fValueName, var); 515b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 516b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t i = 0; i < fields.size(); i++) { 517d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas old->add(fields[i].fName, std::unique_ptr<Field>(new Field(intf.fPosition, *var, 518d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas (int) i))); 519b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 520b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 521d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return std::unique_ptr<InterfaceBlock>(new InterfaceBlock(intf.fPosition, *var, fSymbolTable)); 522b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 523b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 524d598f7981f34811e6f2a949207dc13638852f3f7ethannicholasconst Type* IRGenerator::convertType(const ASTType& type) { 525d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Symbol* result = (*fSymbolTable)[type.fName]; 526b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (result && result->fKind == Symbol::kType_Kind) { 527d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return (const Type*) result; 528b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 529b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(type.fPosition, "unknown type '" + type.fName + "'"); 530b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 531b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 532b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 533b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Expression> IRGenerator::convertExpression(const ASTExpression& expr) { 534b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (expr.fKind) { 535b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case ASTExpression::kIdentifier_Kind: 536b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->convertIdentifier((ASTIdentifier&) expr); 537b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case ASTExpression::kBool_Kind: 538d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return std::unique_ptr<Expression>(new BoolLiteral(fContext, expr.fPosition, 539b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ((ASTBoolLiteral&) expr).fValue)); 540b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case ASTExpression::kInt_Kind: 541d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return std::unique_ptr<Expression>(new IntLiteral(fContext, expr.fPosition, 542b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ((ASTIntLiteral&) expr).fValue)); 543b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case ASTExpression::kFloat_Kind: 544d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return std::unique_ptr<Expression>(new FloatLiteral(fContext, expr.fPosition, 545b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ((ASTFloatLiteral&) expr).fValue)); 546b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case ASTExpression::kBinary_Kind: 547b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->convertBinaryExpression((ASTBinaryExpression&) expr); 548b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case ASTExpression::kPrefix_Kind: 549b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->convertPrefixExpression((ASTPrefixExpression&) expr); 550b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case ASTExpression::kSuffix_Kind: 551b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->convertSuffixExpression((ASTSuffixExpression&) expr); 552b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case ASTExpression::kTernary_Kind: 553b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->convertTernaryExpression((ASTTernaryExpression&) expr); 554b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 555b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ABORT("unsupported expression type: %d\n", expr.fKind); 556b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 557b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 558b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 559b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier& identifier) { 560d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Symbol* result = (*fSymbolTable)[identifier.fText]; 561b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!result) { 562b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(identifier.fPosition, "unknown identifier '" + identifier.fText + "'"); 563b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 564b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 565b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (result->fKind) { 566b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Symbol::kFunctionDeclaration_Kind: { 567d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas std::vector<const FunctionDeclaration*> f = { 568d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas (const FunctionDeclaration*) result 569b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas }; 570d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return std::unique_ptr<FunctionReference>(new FunctionReference(fContext, 571d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas identifier.fPosition, 572d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas f)); 573b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 574b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Symbol::kUnresolvedFunction_Kind: { 575d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const UnresolvedFunction* f = (const UnresolvedFunction*) result; 576d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return std::unique_ptr<FunctionReference>(new FunctionReference(fContext, 577d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas identifier.fPosition, 578b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas f->fFunctions)); 579b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 580b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Symbol::kVariable_Kind: { 581d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Variable* var = (const Variable*) result; 582d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->markReadFrom(*var); 583b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::unique_ptr<VariableReference>(new VariableReference(identifier.fPosition, 584d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas *var)); 585b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 586b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Symbol::kField_Kind: { 587d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Field* field = (const Field*) result; 588b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas VariableReference* base = new VariableReference(identifier.fPosition, field->fOwner); 589f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas return std::unique_ptr<Expression>(new FieldAccess( 590f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas std::unique_ptr<Expression>(base), 591f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas field->fFieldIndex, 592f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas FieldAccess::kAnonymousInterfaceBlock_OwnerKind)); 593b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 594b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Symbol::kType_Kind: { 595d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Type* t = (const Type*) result; 596d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return std::unique_ptr<TypeReference>(new TypeReference(fContext, identifier.fPosition, 597d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas *t)); 598b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 599b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 600b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ABORT("unsupported symbol type %d\n", result->fKind); 601b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 602b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 603b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 604b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 605b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr, 606d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Type& type) { 607b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!expr) { 608b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 609b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 610d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (expr->fType == type) { 611b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return expr; 612b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 613b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->checkValid(*expr); 614d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (expr->fType == *fContext.fInvalid_Type) { 615b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 616b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 617d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (!expr->fType.canCoerceTo(type)) { 618d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fErrors.error(expr->fPosition, "expected '" + type.description() + "', but found '" + 619d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas expr->fType.description() + "'"); 620b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 621b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 622d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (type.kind() == Type::kScalar_Kind) { 623b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::vector<std::unique_ptr<Expression>> args; 624b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas args.push_back(std::move(expr)); 625d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ASTIdentifier id(Position(), type.description()); 626b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<Expression> ctor = this->convertIdentifier(id); 627b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(ctor); 628b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->call(Position(), std::move(ctor), std::move(args)); 629b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 6305961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas std::vector<std::unique_ptr<Expression>> args; 6315961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas args.push_back(std::move(expr)); 6325961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas return std::unique_ptr<Expression>(new Constructor(Position(), type, std::move(args))); 633b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 634b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 635f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasstatic bool is_matrix_multiply(const Type& left, const Type& right) { 636f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (left.kind() == Type::kMatrix_Kind) { 637f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas return right.kind() == Type::kMatrix_Kind || right.kind() == Type::kVector_Kind; 638f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 639f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas return left.kind() == Type::kVector_Kind && right.kind() == Type::kMatrix_Kind; 640f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 641b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas/** 642b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas * Determines the operand and result types of a binary expression. Returns true if the expression is 643b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas * legal, false otherwise. If false, the values of the out parameters are undefined. 644b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas */ 645d598f7981f34811e6f2a949207dc13638852f3f7ethannicholasstatic bool determine_binary_type(const Context& context, 646d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas Token::Kind op, 647d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Type& left, 648d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Type& right, 649d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Type** outLeftType, 650d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Type** outRightType, 651d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Type** outResultType, 652b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas bool tryFlipped) { 653b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas bool isLogical; 654b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (op) { 655b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::EQEQ: // fall through 656b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::NEQ: // fall through 657b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::LT: // fall through 658b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::GT: // fall through 659b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::LTEQ: // fall through 660b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::GTEQ: 661b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas isLogical = true; 662b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 663b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::LOGICALOR: // fall through 664b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::LOGICALAND: // fall through 665b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::LOGICALXOR: // fall through 666b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::LOGICALOREQ: // fall through 667b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::LOGICALANDEQ: // fall through 668b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::LOGICALXOREQ: 669d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas *outLeftType = context.fBool_Type.get(); 670d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas *outRightType = context.fBool_Type.get(); 671d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas *outResultType = context.fBool_Type.get(); 672d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return left.canCoerceTo(*context.fBool_Type) && 673d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas right.canCoerceTo(*context.fBool_Type); 674b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::STAR: // fall through 675b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::STAREQ: 676f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (is_matrix_multiply(left, right)) { 677f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas // determine final component type 678f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (determine_binary_type(context, Token::STAR, left.componentType(), 679f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas right.componentType(), outLeftType, outRightType, 680f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas outResultType, false)) { 681f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas *outLeftType = &(*outResultType)->toCompound(context, left.columns(), 682f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas left.rows());; 683f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas *outRightType = &(*outResultType)->toCompound(context, right.columns(), 684f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas right.rows());; 685f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas int leftColumns = left.columns(); 686f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas int leftRows = left.rows(); 687f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas int rightColumns; 688f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas int rightRows; 689f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (right.kind() == Type::kVector_Kind) { 690f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas // matrix * vector treats the vector as a column vector, so we need to 691f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas // transpose it 692f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas rightColumns = right.rows(); 693f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas rightRows = right.columns(); 694f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas ASSERT(rightColumns == 1); 695f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } else { 696f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas rightColumns = right.columns(); 697f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas rightRows = right.rows(); 698f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 699f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (rightColumns > 1) { 700f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas *outResultType = &(*outResultType)->toCompound(context, rightColumns, 701f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas leftRows); 702f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } else { 703f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas // result was a column vector, transpose it back to a row 704f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas *outResultType = &(*outResultType)->toCompound(context, leftRows, 705f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas rightColumns); 706f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 707f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas return leftColumns == rightRows; 708f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } else { 709f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas return false; 710f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 711b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 712b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // fall through 713b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 714b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas isLogical = false; 715b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 716b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // FIXME: need to disallow illegal operations like vec3 > vec3. Also do not currently have 717b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // full support for numbers other than float. 718b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (left == right) { 719d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas *outLeftType = &left; 720d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas *outRightType = &left; 721b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (isLogical) { 722d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas *outResultType = context.fBool_Type.get(); 723b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 724d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas *outResultType = &left; 725b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 726b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return true; 727b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 728b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // FIXME: incorrect for shift operations 729d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (left.canCoerceTo(right)) { 730d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas *outLeftType = &right; 731d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas *outRightType = &right; 732b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (isLogical) { 733d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas *outResultType = context.fBool_Type.get(); 734b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 735d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas *outResultType = &right; 736b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 737b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return true; 738b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 739d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if ((left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind) && 740d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas (right.kind() == Type::kScalar_Kind)) { 741d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (determine_binary_type(context, op, left.componentType(), right, outLeftType, 742d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas outRightType, outResultType, false)) { 743d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas *outLeftType = &(*outLeftType)->toCompound(context, left.columns(), left.rows()); 744b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!isLogical) { 745d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas *outResultType = &(*outResultType)->toCompound(context, left.columns(), 746d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas left.rows()); 747b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 748b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return true; 749b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 750b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return false; 751b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 752b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (tryFlipped) { 753d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return determine_binary_type(context, op, right, left, outRightType, outLeftType, 754d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas outResultType, false); 755b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 756b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return false; 757b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 758b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 759b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Expression> IRGenerator::convertBinaryExpression( 760b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas const ASTBinaryExpression& expression) { 761b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<Expression> left = this->convertExpression(*expression.fLeft); 762b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!left) { 763b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 764b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 765b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<Expression> right = this->convertExpression(*expression.fRight); 766b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!right) { 767b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 768b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 769d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Type* leftType; 770d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Type* rightType; 771d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Type* resultType; 772d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (!determine_binary_type(fContext, expression.fOperator, left->fType, right->fType, &leftType, 773b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas &rightType, &resultType, true)) { 774b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(expression.fPosition, "type mismatch: '" + 775b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas Token::OperatorName(expression.fOperator) + 776d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas "' cannot operate on '" + left->fType.fName + 777d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas "', '" + right->fType.fName + "'"); 778b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 779b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 780b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (expression.fOperator) { 781b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::EQ: // fall through 782b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::PLUSEQ: // fall through 783b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::MINUSEQ: // fall through 784b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::STAREQ: // fall through 785b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::SLASHEQ: // fall through 786b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::PERCENTEQ: // fall through 787b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::SHLEQ: // fall through 788b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::SHREQ: // fall through 789b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::BITWISEOREQ: // fall through 790b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::BITWISEXOREQ: // fall through 791b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::BITWISEANDEQ: // fall through 792b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::LOGICALOREQ: // fall through 793b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::LOGICALXOREQ: // fall through 794b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::LOGICALANDEQ: 795b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->markWrittenTo(*left); 796b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 797b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 798b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 799b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::unique_ptr<Expression>(new BinaryExpression(expression.fPosition, 800d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->coerce(std::move(left), 801d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas *leftType), 802b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas expression.fOperator, 803b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->coerce(std::move(right), 804d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas *rightType), 805d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas *resultType)); 806b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 807b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 808b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Expression> IRGenerator::convertTernaryExpression( 809b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas const ASTTernaryExpression& expression) { 810b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*expression.fTest), 811d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas *fContext.fBool_Type); 812b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!test) { 813b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 814b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 815b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<Expression> ifTrue = this->convertExpression(*expression.fIfTrue); 816b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!ifTrue) { 817b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 818b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 819b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<Expression> ifFalse = this->convertExpression(*expression.fIfFalse); 820b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!ifFalse) { 821b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 822b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 823d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Type* trueType; 824d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Type* falseType; 825d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Type* resultType; 826d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (!determine_binary_type(fContext, Token::EQEQ, ifTrue->fType, ifFalse->fType, &trueType, 827b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas &falseType, &resultType, true)) { 828b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(expression.fPosition, "ternary operator result mismatch: '" + 829d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ifTrue->fType.fName + "', '" + 830d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ifFalse->fType.fName + "'"); 831b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 832b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 833b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(trueType == falseType); 834d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ifTrue = this->coerce(std::move(ifTrue), *trueType); 835d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ifFalse = this->coerce(std::move(ifFalse), *falseType); 836b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::unique_ptr<Expression>(new TernaryExpression(expression.fPosition, 837b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::move(test), 838b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::move(ifTrue), 839b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::move(ifFalse))); 840b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 841b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 842d598f7981f34811e6f2a949207dc13638852f3f7ethannicholasstd::unique_ptr<Expression> IRGenerator::call(Position position, 843d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const FunctionDeclaration& function, 844d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas std::vector<std::unique_ptr<Expression>> arguments) { 845d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (function.fParameters.size() != arguments.size()) { 846d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas std::string msg = "call to '" + function.fName + "' expected " + 8475961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas to_string((uint64_t) function.fParameters.size()) + 848b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas " argument"; 849d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (function.fParameters.size() != 1) { 850b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas msg += "s"; 851b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 8525961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas msg += ", but found " + to_string((uint64_t) arguments.size()); 853b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(position, msg); 854b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 855b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 856b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t i = 0; i < arguments.size(); i++) { 857d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas arguments[i] = this->coerce(std::move(arguments[i]), function.fParameters[i]->fType); 858d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (arguments[i] && (function.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag)) { 859b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->markWrittenTo(*arguments[i]); 860b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 861b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 862d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return std::unique_ptr<FunctionCall>(new FunctionCall(position, function, 863b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::move(arguments))); 864b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 865b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 866b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas/** 867b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas * Determines the cost of coercing the arguments of a function to the required types. Returns true 868b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas * if the cost could be computed, false if the call is not valid. Cost has no particular meaning 869b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas * other than "lower costs are preferred". 870b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas */ 871d598f7981f34811e6f2a949207dc13638852f3f7ethannicholasbool IRGenerator::determineCallCost(const FunctionDeclaration& function, 872b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas const std::vector<std::unique_ptr<Expression>>& arguments, 873b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas int* outCost) { 874d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (function.fParameters.size() != arguments.size()) { 875b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return false; 876b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 877b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas int total = 0; 878b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t i = 0; i < arguments.size(); i++) { 879b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas int cost; 880d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (arguments[i]->fType.determineCoercionCost(function.fParameters[i]->fType, &cost)) { 881b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas total += cost; 882b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 883b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return false; 884b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 885b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 886b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas *outCost = total; 887b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return true; 888b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 889b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 890b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Expression> IRGenerator::call(Position position, 891b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<Expression> functionValue, 892b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::vector<std::unique_ptr<Expression>> arguments) { 893b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (functionValue->fKind == Expression::kTypeReference_Kind) { 894b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->convertConstructor(position, 895b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ((TypeReference&) *functionValue).fValue, 896b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::move(arguments)); 897b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 898b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (functionValue->fKind != Expression::kFunctionReference_Kind) { 899b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(position, "'" + functionValue->description() + "' is not a function"); 900b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 901b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 902b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas FunctionReference* ref = (FunctionReference*) functionValue.get(); 903b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas int bestCost = INT_MAX; 904d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const FunctionDeclaration* best = nullptr; 905b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (ref->fFunctions.size() > 1) { 906b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (const auto& f : ref->fFunctions) { 907b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas int cost; 908d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (this->determineCallCost(*f, arguments, &cost) && cost < bestCost) { 909b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas bestCost = cost; 910b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas best = f; 911b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 912b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 913b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (best) { 914d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return this->call(position, *best, std::move(arguments)); 915b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 916b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::string msg = "no match for " + ref->fFunctions[0]->fName + "("; 917b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::string separator = ""; 918b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t i = 0; i < arguments.size(); i++) { 919b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas msg += separator; 920b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas separator = ", "; 921d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas msg += arguments[i]->fType.description(); 922b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 923b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas msg += ")"; 924b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(position, msg); 925b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 926b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 927d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return this->call(position, *ref->fFunctions[0], std::move(arguments)); 928b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 929b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 930b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Expression> IRGenerator::convertConstructor( 931b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas Position position, 932d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Type& type, 933b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::vector<std::unique_ptr<Expression>> args) { 934b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // FIXME: add support for structs and arrays 935d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas Type::Kind kind = type.kind(); 9365961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (!type.isNumber() && kind != Type::kVector_Kind && kind != Type::kMatrix_Kind && 9375961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas kind != Type::kArray_Kind) { 938d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fErrors.error(position, "cannot construct '" + type.description() + "'"); 939b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 940b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 941d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (type == *fContext.fFloat_Type && args.size() == 1 && 942b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas args[0]->fKind == Expression::kIntLiteral_Kind) { 943b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas int64_t value = ((IntLiteral&) *args[0]).fValue; 944d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return std::unique_ptr<Expression>(new FloatLiteral(fContext, position, (double) value)); 945b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 946b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (args.size() == 1 && args[0]->fType == type) { 947b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // argument is already the right type, just return it 948b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::move(args[0]); 949b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 950d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (type.isNumber()) { 951b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (args.size() != 1) { 952d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fErrors.error(position, "invalid arguments to '" + type.description() + 953b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas "' constructor, (expected exactly 1 argument, but found " + 9545961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas to_string((uint64_t) args.size()) + ")"); 955b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 956d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (args[0]->fType == *fContext.fBool_Type) { 957d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, position, 0)); 958d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas std::unique_ptr<IntLiteral> one(new IntLiteral(fContext, position, 1)); 959b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::unique_ptr<Expression>( 960b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas new TernaryExpression(position, std::move(args[0]), 961b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->coerce(std::move(one), type), 962b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->coerce(std::move(zero), 963b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas type))); 964d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas } else if (!args[0]->fType.isNumber()) { 965d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fErrors.error(position, "invalid argument to '" + type.description() + 966b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas "' constructor (expected a number or bool, but found '" + 967d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas args[0]->fType.description() + "')"); 968b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 9695961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext.fInt_Type || 9705961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas type == *fContext.fUInt_Type)) { 9715961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas return std::unique_ptr<Expression>(new IntLiteral(fContext, 9725961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas position, 9735961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas ((IntLiteral&) *args[0]).fValue, 9745961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas &type)); 9755961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 9765961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } else if (kind == Type::kArray_Kind) { 9775961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas const Type& base = type.componentType(); 9785961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas for (size_t i = 0; i < args.size(); i++) { 9795961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas args[i] = this->coerce(std::move(args[i]), base); 9805961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 981b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 982b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(kind == Type::kVector_Kind || kind == Type::kMatrix_Kind); 983b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas int actual = 0; 984b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t i = 0; i < args.size(); i++) { 985d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (args[i]->fType.kind() == Type::kVector_Kind || 986d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas args[i]->fType.kind() == Type::kMatrix_Kind) { 987d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas int columns = args[i]->fType.columns(); 988d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas int rows = args[i]->fType.rows(); 989b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas args[i] = this->coerce(std::move(args[i]), 990d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas type.componentType().toCompound(fContext, columns, rows)); 991d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas actual += args[i]->fType.rows() * args[i]->fType.columns(); 992d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas } else if (args[i]->fType.kind() == Type::kScalar_Kind) { 993b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas actual += 1; 994d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (type.kind() != Type::kScalar_Kind) { 995d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas args[i] = this->coerce(std::move(args[i]), type.componentType()); 996b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 997b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 998d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fErrors.error(position, "'" + args[i]->fType.description() + "' is not a valid " 999d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas "parameter to '" + type.description() + "' constructor"); 1000b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 1001b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1002b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1003d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas int min = type.rows() * type.columns(); 1004d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas int max = type.columns() > 1 ? INT_MAX : min; 1005b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if ((actual < min || actual > max) && 1006b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas !((kind == Type::kVector_Kind || kind == Type::kMatrix_Kind) && (actual == 1))) { 1007d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fErrors.error(position, "invalid arguments to '" + type.description() + 1008b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas "' constructor (expected " + to_string(min) + " scalar" + 1009b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas (min == 1 ? "" : "s") + ", but found " + to_string(actual) + 1010b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ")"); 1011b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 1012b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1013b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1014b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::unique_ptr<Expression>(new Constructor(position, std::move(type), std::move(args))); 1015b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1016b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1017b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Expression> IRGenerator::convertPrefixExpression( 1018b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas const ASTPrefixExpression& expression) { 1019b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<Expression> base = this->convertExpression(*expression.fOperand); 1020b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!base) { 1021b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 1022b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1023b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (expression.fOperator) { 1024b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::PLUS: 1025d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) { 1026b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(expression.fPosition, 1027d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas "'+' cannot operate on '" + base->fType.description() + "'"); 1028b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 1029b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1030b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return base; 1031b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::MINUS: 1032d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) { 1033b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(expression.fPosition, 1034d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas "'-' cannot operate on '" + base->fType.description() + "'"); 1035b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 1036b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1037b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (base->fKind == Expression::kIntLiteral_Kind) { 1038d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return std::unique_ptr<Expression>(new IntLiteral(fContext, base->fPosition, 1039b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas -((IntLiteral&) *base).fValue)); 1040b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1041b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (base->fKind == Expression::kFloatLiteral_Kind) { 1042b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas double value = -((FloatLiteral&) *base).fValue; 1043d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return std::unique_ptr<Expression>(new FloatLiteral(fContext, base->fPosition, 1044d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas value)); 1045b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1046b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::unique_ptr<Expression>(new PrefixExpression(Token::MINUS, std::move(base))); 1047b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::PLUSPLUS: 1048d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (!base->fType.isNumber()) { 1049b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(expression.fPosition, 1050b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas "'" + Token::OperatorName(expression.fOperator) + 1051d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas "' cannot operate on '" + base->fType.description() + "'"); 1052b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 1053b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1054b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->markWrittenTo(*base); 1055b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 1056b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::MINUSMINUS: 1057d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (!base->fType.isNumber()) { 1058b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(expression.fPosition, 1059b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas "'" + Token::OperatorName(expression.fOperator) + 1060d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas "' cannot operate on '" + base->fType.description() + "'"); 1061b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 1062b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1063b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->markWrittenTo(*base); 1064b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 10655961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas case Token::LOGICALNOT: 1066d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (base->fType != *fContext.fBool_Type) { 1067b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(expression.fPosition, 1068b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas "'" + Token::OperatorName(expression.fOperator) + 1069d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas "' cannot operate on '" + base->fType.description() + "'"); 1070b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 1071b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1072b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 10735961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas case Token::BITWISENOT: 10745961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (base->fType != *fContext.fInt_Type) { 10755961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas fErrors.error(expression.fPosition, 10765961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas "'" + Token::OperatorName(expression.fOperator) + 10775961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas "' cannot operate on '" + base->fType.description() + "'"); 10785961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas return nullptr; 10795961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 10805961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas break; 1081b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 1082b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ABORT("unsupported prefix operator\n"); 1083b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1084b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::unique_ptr<Expression>(new PrefixExpression(expression.fOperator, 1085b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::move(base))); 1086b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1087b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1088b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression> base, 1089b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas const ASTExpression& index) { 10905961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::kMatrix_Kind && 10915961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas base->fType.kind() != Type::kVector_Kind) { 1092d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fErrors.error(base->fPosition, "expected array, but found '" + base->fType.description() + 1093b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas "'"); 1094b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 1095b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1096b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<Expression> converted = this->convertExpression(index); 1097b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!converted) { 1098b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 1099b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 11005961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (converted->fType != *fContext.fUInt_Type) { 11015961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas converted = this->coerce(std::move(converted), *fContext.fInt_Type); 11025961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (!converted) { 11035961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas return nullptr; 11045961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 1105b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1106d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return std::unique_ptr<Expression>(new IndexExpression(fContext, std::move(base), 1107d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas std::move(converted))); 1108b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1109b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1110b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Expression> IRGenerator::convertField(std::unique_ptr<Expression> base, 1111b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas const std::string& field) { 1112d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas auto fields = base->fType.fields(); 1113b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t i = 0; i < fields.size(); i++) { 1114b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (fields[i].fName == field) { 1115b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::unique_ptr<Expression>(new FieldAccess(std::move(base), (int) i)); 1116b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1117b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1118d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fErrors.error(base->fPosition, "type '" + base->fType.description() + "' does not have a " 1119b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas "field named '" + field + ""); 1120b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 1121b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1122b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1123b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expression> base, 1124b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas const std::string& fields) { 1125d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (base->fType.kind() != Type::kVector_Kind) { 1126d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fErrors.error(base->fPosition, "cannot swizzle type '" + base->fType.description() + "'"); 1127b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 1128b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1129b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::vector<int> swizzleComponents; 1130b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (char c : fields) { 1131b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (c) { 1132b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case 'x': // fall through 1133b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case 'r': // fall through 1134b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case 's': 1135b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas swizzleComponents.push_back(0); 1136b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 1137b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case 'y': // fall through 1138b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case 'g': // fall through 1139b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case 't': 1140d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (base->fType.columns() >= 2) { 1141b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas swizzleComponents.push_back(1); 1142b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 1143b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1144b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // fall through 1145b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case 'z': // fall through 1146b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case 'b': // fall through 1147b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case 'p': 1148d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (base->fType.columns() >= 3) { 1149b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas swizzleComponents.push_back(2); 1150b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 1151b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1152b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // fall through 1153b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case 'w': // fall through 1154b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case 'a': // fall through 1155b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case 'q': 1156d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (base->fType.columns() >= 4) { 1157b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas swizzleComponents.push_back(3); 1158b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 1159b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1160b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // fall through 1161b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 1162b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(base->fPosition, "invalid swizzle component '" + std::string(1, c) + 1163b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas "'"); 1164b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 1165b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1166b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1167b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(swizzleComponents.size() > 0); 1168b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (swizzleComponents.size() > 4) { 1169b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(base->fPosition, "too many components in swizzle mask '" + fields + "'"); 1170b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 1171b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1172d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return std::unique_ptr<Expression>(new Swizzle(fContext, std::move(base), swizzleComponents)); 1173b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1174b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1175b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Expression> IRGenerator::convertSuffixExpression( 1176b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas const ASTSuffixExpression& expression) { 1177b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<Expression> base = this->convertExpression(*expression.fBase); 1178b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!base) { 1179b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 1180b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1181b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (expression.fSuffix->fKind) { 11825961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas case ASTSuffix::kIndex_Kind: { 11835961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas const ASTExpression* expr = ((ASTIndexSuffix&) *expression.fSuffix).fExpression.get(); 11845961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (expr) { 11855961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas return this->convertIndex(std::move(base), *expr); 11865961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } else if (base->fKind == Expression::kTypeReference_Kind) { 11875961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas const Type& oldType = ((TypeReference&) *base).fValue; 11885961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas Type* newType = new Type(oldType.name() + "[]", Type::kArray_Kind, oldType, 11895961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas -1); 11905961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas fSymbolTable->takeOwnership(newType); 11915961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas return std::unique_ptr<Expression>(new TypeReference(fContext, base->fPosition, 11925961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas *newType)); 11935961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } else { 11945961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas fErrors.error(expression.fPosition, "'[]' must follow a type name"); 11955961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 11965961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 1197b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case ASTSuffix::kCall_Kind: { 1198b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas auto rawArguments = &((ASTCallSuffix&) *expression.fSuffix).fArguments; 1199b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::vector<std::unique_ptr<Expression>> arguments; 1200b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t i = 0; i < rawArguments->size(); i++) { 1201b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<Expression> converted = 1202b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->convertExpression(*(*rawArguments)[i]); 1203b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (!converted) { 1204b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 1205b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1206b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas arguments.push_back(std::move(converted)); 1207b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1208b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->call(expression.fPosition, std::move(base), std::move(arguments)); 1209b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1210b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case ASTSuffix::kField_Kind: { 1211d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas switch (base->fType.kind()) { 1212b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Type::kVector_Kind: 1213b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->convertSwizzle(std::move(base), 1214b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ((ASTFieldSuffix&) *expression.fSuffix).fField); 1215b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Type::kStruct_Kind: 1216b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->convertField(std::move(base), 1217b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ((ASTFieldSuffix&) *expression.fSuffix).fField); 1218b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 1219b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(base->fPosition, "cannot swizzle value of type '" + 1220d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas base->fType.description() + "'"); 1221b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 1222b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1223b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1224b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case ASTSuffix::kPostIncrement_Kind: 1225d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (!base->fType.isNumber()) { 1226b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(expression.fPosition, 1227d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas "'++' cannot operate on '" + base->fType.description() + "'"); 1228b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 1229b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1230b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->markWrittenTo(*base); 1231b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::unique_ptr<Expression>(new PostfixExpression(std::move(base), 1232b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas Token::PLUSPLUS)); 1233b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case ASTSuffix::kPostDecrement_Kind: 1234d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (!base->fType.isNumber()) { 1235b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(expression.fPosition, 1236d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas "'--' cannot operate on '" + base->fType.description() + "'"); 1237b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return nullptr; 1238b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1239b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->markWrittenTo(*base); 1240b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::unique_ptr<Expression>(new PostfixExpression(std::move(base), 1241b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas Token::MINUSMINUS)); 1242b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 1243b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ABORT("unsupported suffix operator"); 1244b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1245b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1246b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1247b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasvoid IRGenerator::checkValid(const Expression& expr) { 1248b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (expr.fKind) { 1249b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kFunctionReference_Kind: 1250b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(expr.fPosition, "expected '(' to begin function call"); 1251b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 1252b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kTypeReference_Kind: 1253b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(expr.fPosition, "expected '(' to begin constructor invocation"); 1254b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 1255b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 1256d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ASSERT(expr.fType != *fContext.fInvalid_Type); 1257b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 1258b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1259b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1260b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1261d598f7981f34811e6f2a949207dc13638852f3f7ethannicholasvoid IRGenerator::markReadFrom(const Variable& var) { 1262d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas var.fIsReadFrom = true; 1263b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1264b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1265b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstatic bool has_duplicates(const Swizzle& swizzle) { 1266b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas int bits = 0; 1267b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (int idx : swizzle.fComponents) { 1268b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(idx >= 0 && idx <= 3); 1269b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas int bit = 1 << idx; 1270b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (bits & bit) { 1271b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return true; 1272b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1273b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas bits |= bit; 1274b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1275b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return false; 1276b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1277b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1278b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasvoid IRGenerator::markWrittenTo(const Expression& expr) { 1279b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (expr.fKind) { 1280b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kVariableReference_Kind: { 1281d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Variable& var = ((VariableReference&) expr).fVariable; 1282b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (var.fModifiers.fFlags & (Modifiers::kConst_Flag | Modifiers::kUniform_Flag)) { 1283b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(expr.fPosition, 1284b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas "cannot modify immutable variable '" + var.fName + "'"); 1285b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1286b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas var.fIsWrittenTo = true; 1287b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 1288b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1289b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kFieldAccess_Kind: 1290b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->markWrittenTo(*((FieldAccess&) expr).fBase); 1291b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 1292b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kSwizzle_Kind: 1293b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (has_duplicates((Swizzle&) expr)) { 1294b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(expr.fPosition, 1295b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas "cannot write to the same swizzle field more than once"); 1296b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1297b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->markWrittenTo(*((Swizzle&) expr).fBase); 1298b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 1299b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kIndex_Kind: 1300b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->markWrittenTo(*((IndexExpression&) expr).fBase); 1301b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 1302b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 1303b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrors.error(expr.fPosition, "cannot assign to '" + expr.description() + "'"); 1304b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 1305b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1306b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1307b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1308b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1309