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