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