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