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 */
711d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas
8b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "SkSLIRGenerator.h"
9b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
10b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "limits.h"
11af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas#include <unordered_set>
12b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
13941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas#include "SkSLCompiler.h"
147da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas#include "SkSLParser.h"
15b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ast/SkSLASTBoolLiteral.h"
16b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ast/SkSLASTFieldSuffix.h"
17b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ast/SkSLASTFloatLiteral.h"
18b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ast/SkSLASTIndexSuffix.h"
19b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ast/SkSLASTIntLiteral.h"
20b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLBinaryExpression.h"
21b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLBoolLiteral.h"
22b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLBreakStatement.h"
23b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLConstructor.h"
24b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLContinueStatement.h"
25b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLDiscardStatement.h"
26b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLDoStatement.h"
27aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas#include "ir/SkSLEnum.h"
28b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLExpressionStatement.h"
29b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLField.h"
30b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLFieldAccess.h"
31b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLFloatLiteral.h"
32b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLForStatement.h"
33b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLFunctionCall.h"
34b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLFunctionDeclaration.h"
35b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLFunctionDefinition.h"
36b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLFunctionReference.h"
37b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLIfStatement.h"
38b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLIndexExpression.h"
39b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLInterfaceBlock.h"
40b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLIntLiteral.h"
41b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLLayout.h"
42b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLPostfixExpression.h"
43b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLPrefixExpression.h"
44b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLReturnStatement.h"
45762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas#include "ir/SkSLSetting.h"
46af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas#include "ir/SkSLSwitchCase.h"
47af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas#include "ir/SkSLSwitchStatement.h"
48b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLSwizzle.h"
49b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLTernaryExpression.h"
50b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLUnresolvedFunction.h"
51b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLVariable.h"
5222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas#include "ir/SkSLVarDeclarations.h"
5322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas#include "ir/SkSLVarDeclarationsStatement.h"
54b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLVariableReference.h"
55b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLWhileStatement.h"
56b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
57b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasnamespace SkSL {
58b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
59b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasclass AutoSymbolTable {
60b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholaspublic:
6111d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas    AutoSymbolTable(IRGenerator* ir)
62b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    : fIR(ir)
63b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    , fPrevious(fIR->fSymbolTable) {
64b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        fIR->pushSymbolTable();
65b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
66b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
67b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    ~AutoSymbolTable() {
68b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        fIR->popSymbolTable();
69b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        ASSERT(fPrevious == fIR->fSymbolTable);
70b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
71b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
72b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    IRGenerator* fIR;
73b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    std::shared_ptr<SymbolTable> fPrevious;
74b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas};
75b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
7622f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholasclass AutoLoopLevel {
7722f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholaspublic:
7811d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas    AutoLoopLevel(IRGenerator* ir)
7922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas    : fIR(ir) {
8022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas        fIR->fLoopLevel++;
8122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas    }
8222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas
8322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas    ~AutoLoopLevel() {
8422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas        fIR->fLoopLevel--;
8522f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas    }
8622f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas
8722f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas    IRGenerator* fIR;
8822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas};
8922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas
90af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholasclass AutoSwitchLevel {
91af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholaspublic:
92af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas    AutoSwitchLevel(IRGenerator* ir)
93af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas    : fIR(ir) {
94af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas        fIR->fSwitchLevel++;
95af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas    }
96af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas
97af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas    ~AutoSwitchLevel() {
98af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas        fIR->fSwitchLevel--;
99af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas    }
100af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas
101af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas    IRGenerator* fIR;
102af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas};
103af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas
10411d53974317fa29cc516075382e658ddd45fc151Ethan NicholasIRGenerator::IRGenerator(const Context* context, std::shared_ptr<SymbolTable> symbolTable,
105b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                         ErrorReporter& errorReporter)
106d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas: fContext(*context)
107d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas, fCurrentFunction(nullptr)
108762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas, fRootSymbolTable(symbolTable)
109762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas, fSymbolTable(symbolTable)
11022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas, fLoopLevel(0)
111af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas, fSwitchLevel(0)
112762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas, fTmpCount(0)
113d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas, fErrors(errorReporter) {}
114b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
115b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasvoid IRGenerator::pushSymbolTable() {
1168feeff929e57ea63914213f3b14d8f00b287a0adEthan Nicholas    fSymbolTable.reset(new SymbolTable(std::move(fSymbolTable), &fErrors));
117b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
118b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
119b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasvoid IRGenerator::popSymbolTable() {
120b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    fSymbolTable = fSymbolTable->fParent;
121b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
122b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
123762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholasstatic void fill_caps(const SKSL_CAPS_CLASS& caps,
124762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas                      std::unordered_map<String, Program::Settings::Value>* capsMap) {
125762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas#define CAP(name) capsMap->insert(std::make_pair(String(#name), \
126762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas                                  Program::Settings::Value(caps.name())));
127941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas    CAP(fbFetchSupport);
128941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas    CAP(fbFetchNeedsCustomOutput);
129941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas    CAP(dropsTileOnZeroDivide);
130941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas    CAP(flatInterpolationSupport);
131941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas    CAP(noperspectiveInterpolationSupport);
132941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas    CAP(externalTextureSupport);
133941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas    CAP(texelFetchSupport);
134941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas    CAP(imageLoadStoreSupport);
135941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas    CAP(mustEnableAdvBlendEqs);
136941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas    CAP(mustEnableSpecificAdvBlendEqs);
137941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas    CAP(mustDeclareFragmentShaderOutput);
138941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas    CAP(canUseAnyFunctionInShader);
13947c8ed3c064f5176750f370b88119735163c0e8aChris Dalton    CAP(floatIs32Bits);
14007990de8179e98a4ba06d7e66f40b8ec5465badeEthan Nicholas    CAP(integerSupport);
141941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas#undef CAP
142941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas}
143941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas
144941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholasvoid IRGenerator::start(const Program::Settings* settings) {
145941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas    fSettings = settings;
146941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas    fCapsMap.clear();
147941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas    if (settings->fCaps) {
148941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas        fill_caps(*settings->fCaps, &fCapsMap);
149941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas    }
1503605ace7ddaf0b576bf6df1c7a550ab4f44d22a8Ethan Nicholas    this->pushSymbolTable();
1517da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    fInvocations = -1;
152941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas    fInputs.reset();
153fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    fSkPerVertex = nullptr;
154fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    fRTAdjust = nullptr;
155fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    fRTAdjustInterfaceBlock = nullptr;
1563605ace7ddaf0b576bf6df1c7a550ab4f44d22a8Ethan Nicholas}
1573605ace7ddaf0b576bf6df1c7a550ab4f44d22a8Ethan Nicholas
1583605ace7ddaf0b576bf6df1c7a550ab4f44d22a8Ethan Nicholasvoid IRGenerator::finish() {
1593605ace7ddaf0b576bf6df1c7a550ab4f44d22a8Ethan Nicholas    this->popSymbolTable();
160941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas    fSettings = nullptr;
1613605ace7ddaf0b576bf6df1c7a550ab4f44d22a8Ethan Nicholas}
1623605ace7ddaf0b576bf6df1c7a550ab4f44d22a8Ethan Nicholas
163b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Extension> IRGenerator::convertExtension(const ASTExtension& extension) {
1645b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    return std::unique_ptr<Extension>(new Extension(extension.fOffset, extension.fName));
165b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
166b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
167b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Statement> IRGenerator::convertStatement(const ASTStatement& statement) {
168b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    switch (statement.fKind) {
169b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case ASTStatement::kBlock_Kind:
170b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            return this->convertBlock((ASTBlock&) statement);
171b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case ASTStatement::kVarDeclaration_Kind:
172b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            return this->convertVarDeclarationStatement((ASTVarDeclarationStatement&) statement);
173fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips        case ASTStatement::kExpression_Kind: {
174fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips            std::unique_ptr<Statement> result =
175fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                              this->convertExpressionStatement((ASTExpressionStatement&) statement);
176fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips            if (fRTAdjust && Program::kGeometry_Kind == fKind) {
177fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                ASSERT(result->fKind == Statement::kExpression_Kind);
178fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                Expression& expr = *((ExpressionStatement&) *result).fExpression;
179fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                if (expr.fKind == Expression::kFunctionCall_Kind) {
180fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                    FunctionCall& fc = (FunctionCall&) expr;
181fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                    if (fc.fFunction.fBuiltin && fc.fFunction.fName == "EmitVertex") {
182fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                        std::vector<std::unique_ptr<Statement>> statements;
183fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                        statements.push_back(getNormalizeSkPositionCode());
184fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                        statements.push_back(std::move(result));
185fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                        return std::unique_ptr<Block>(new Block(statement.fOffset,
186fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                                                                std::move(statements),
187fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                                                                fSymbolTable));
188fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                    }
189fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                }
190fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips            }
191fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips            return result;
192fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips        }
193b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case ASTStatement::kIf_Kind:
194b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            return this->convertIf((ASTIfStatement&) statement);
195b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case ASTStatement::kFor_Kind:
196b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            return this->convertFor((ASTForStatement&) statement);
197b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case ASTStatement::kWhile_Kind:
198b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            return this->convertWhile((ASTWhileStatement&) statement);
199b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case ASTStatement::kDo_Kind:
200b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            return this->convertDo((ASTDoStatement&) statement);
201af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas        case ASTStatement::kSwitch_Kind:
202af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas            return this->convertSwitch((ASTSwitchStatement&) statement);
203b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case ASTStatement::kReturn_Kind:
204b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            return this->convertReturn((ASTReturnStatement&) statement);
205b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case ASTStatement::kBreak_Kind:
206b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            return this->convertBreak((ASTBreakStatement&) statement);
207b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case ASTStatement::kContinue_Kind:
208b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            return this->convertContinue((ASTContinueStatement&) statement);
209b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case ASTStatement::kDiscard_Kind:
210b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            return this->convertDiscard((ASTDiscardStatement&) statement);
211b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        default:
212b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            ABORT("unsupported statement type: %d\n", statement.fKind);
213b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
214b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
215b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
216b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Block> IRGenerator::convertBlock(const ASTBlock& block) {
217b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    AutoSymbolTable table(this);
218b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    std::vector<std::unique_ptr<Statement>> statements;
219b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    for (size_t i = 0; i < block.fStatements.size(); i++) {
220b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        std::unique_ptr<Statement> statement = this->convertStatement(*block.fStatements[i]);
221b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        if (!statement) {
222b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            return nullptr;
223b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
224b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        statements.push_back(std::move(statement));
225b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
2265b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    return std::unique_ptr<Block>(new Block(block.fOffset, std::move(statements), fSymbolTable));
227b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
228b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
229b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Statement> IRGenerator::convertVarDeclarationStatement(
230b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                                              const ASTVarDeclarationStatement& s) {
23114fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas    auto decl = this->convertVarDeclarations(*s.fDeclarations, Variable::kLocal_Storage);
232b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (!decl) {
233b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
234b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
23514fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas    return std::unique_ptr<Statement>(new VarDeclarationsStatement(std::move(decl)));
236b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
237b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
23814fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholasstd::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVarDeclarations& decl,
23914fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas                                                                     Variable::Storage storage) {
24082a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas    std::vector<std::unique_ptr<VarDeclaration>> variables;
241d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    const Type* baseType = this->convertType(*decl.fType);
242b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (!baseType) {
243b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
244b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
24514fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas    for (const auto& varDecl : decl.fVars) {
246d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas        const Type* type = baseType;
24714fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas        std::vector<std::unique_ptr<Expression>> sizes;
24814fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas        for (const auto& rawSize : varDecl.fSizes) {
24914fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas            if (rawSize) {
25014fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas                auto size = this->coerce(this->convertExpression(*rawSize), *fContext.fInt_Type);
251b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                if (!size) {
252b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                    return nullptr;
253b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                }
2545b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                String name(type->fName);
25550afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas                int64_t count;
256b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                if (size->fKind == Expression::kIntLiteral_Kind) {
257b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                    count = ((IntLiteral&) *size).fValue;
258b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                    if (count <= 0) {
2595b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                        fErrors.error(size->fOffset, "array size must be positive");
260b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                    }
261b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                    name += "[" + to_string(count) + "]";
262b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                } else {
263b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                    count = -1;
264b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                    name += "[]";
265b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                }
266d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                type = new Type(name, Type::kArray_Kind, *type, (int) count);
267d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                fSymbolTable->takeOwnership((Type*) type);
26814fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas                sizes.push_back(std::move(size));
269b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            } else {
2705b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                type = new Type(type->name() + "[]", Type::kArray_Kind, *type, -1);
271d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                fSymbolTable->takeOwnership((Type*) type);
27214fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas                sizes.push_back(nullptr);
273b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            }
274b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
27582a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas        auto var = std::unique_ptr<Variable>(new Variable(decl.fOffset, decl.fModifiers,
27682a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas                                                          varDecl.fName, *type, storage));
277fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips        if (var->fName == Compiler::RTADJUST_NAME) {
278fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips            ASSERT(!fRTAdjust);
279fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips            ASSERT(var->fType == *fContext.fFloat4_Type);
280fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips            fRTAdjust = var.get();
281fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips        }
282b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        std::unique_ptr<Expression> value;
28314fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas        if (varDecl.fValue) {
28414fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas            value = this->convertExpression(*varDecl.fValue);
285b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            if (!value) {
286b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                return nullptr;
287b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            }
288d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            value = this->coerce(std::move(value), *type);
28968dd2c1fa051019354d0c441c78b3885d8e72a7aEthan Nicholas            if (!value) {
29068dd2c1fa051019354d0c441c78b3885d8e72a7aEthan Nicholas                return nullptr;
29168dd2c1fa051019354d0c441c78b3885d8e72a7aEthan Nicholas            }
292cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas            var->fWriteCount = 1;
2938f6c2aba638c9397e9987fca7cbd8d0ff4b23e8fEthan Nicholas            var->fInitialValue = value.get();
294b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
2955b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        if (storage == Variable::kGlobal_Storage && varDecl.fName == "sk_FragColor" &&
296ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas            (*fSymbolTable)[varDecl.fName]) {
2975961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas            // already defined, ignore
298ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas        } else if (storage == Variable::kGlobal_Storage && (*fSymbolTable)[varDecl.fName] &&
299ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas                   (*fSymbolTable)[varDecl.fName]->fKind == Symbol::kVariable_Kind &&
3005961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas                   ((Variable*) (*fSymbolTable)[varDecl.fName])->fModifiers.fLayout.fBuiltin >= 0) {
301f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas            // already defined, just update the modifiers
30214fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas            Variable* old = (Variable*) (*fSymbolTable)[varDecl.fName];
303f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas            old->fModifiers = var->fModifiers;
304f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas        } else {
30582a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas            variables.emplace_back(new VarDeclaration(var.get(), std::move(sizes),
30682a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas                                                      std::move(value)));
30714fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas            fSymbolTable->add(varDecl.fName, std::move(var));
308f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas        }
309b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
3105b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    return std::unique_ptr<VarDeclarations>(new VarDeclarations(decl.fOffset,
31114fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas                                                                baseType,
31214fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas                                                                std::move(variables)));
313b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
314b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
3155961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholasstd::unique_ptr<ModifiersDeclaration> IRGenerator::convertModifiersDeclaration(
3165961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas                                                                 const ASTModifiersDeclaration& m) {
3177da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    Modifiers modifiers = m.fModifiers;
3187da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    if (modifiers.fLayout.fInvocations != -1) {
3197da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas        fInvocations = modifiers.fLayout.fInvocations;
320f1b47bb299e72456d70cf3eae8086a5e01766c67Chris Dalton        if (fSettings->fCaps && !fSettings->fCaps->gsInvocationsSupport()) {
3217da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas            modifiers.fLayout.fInvocations = -1;
3227da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas            Variable* invocationId = (Variable*) (*fSymbolTable)["sk_InvocationID"];
3237da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas            ASSERT(invocationId);
3247da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas            invocationId->fModifiers.fLayout.fBuiltin = -1;
3257da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas            if (modifiers.fLayout.description() == "") {
3267da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                return nullptr;
3277da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas            }
3287da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas        }
3297da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    }
3307da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    if (modifiers.fLayout.fMaxVertices != -1 && fInvocations > 0 && fSettings->fCaps &&
331f1b47bb299e72456d70cf3eae8086a5e01766c67Chris Dalton        !fSettings->fCaps->gsInvocationsSupport()) {
3327da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas        modifiers.fLayout.fMaxVertices *= fInvocations;
3337da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    }
3347da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    return std::unique_ptr<ModifiersDeclaration>(new ModifiersDeclaration(modifiers));
3355961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas}
3365961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas
337b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Statement> IRGenerator::convertIf(const ASTIfStatement& s) {
33811d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas    std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*s.fTest),
339d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                                                    *fContext.fBool_Type);
340b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (!test) {
341b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
342b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
343b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    std::unique_ptr<Statement> ifTrue = this->convertStatement(*s.fIfTrue);
344b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (!ifTrue) {
345b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
346b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
347b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    std::unique_ptr<Statement> ifFalse;
348b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (s.fIfFalse) {
349b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        ifFalse = this->convertStatement(*s.fIfFalse);
350b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        if (!ifFalse) {
351b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            return nullptr;
352b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
353b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
35408a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas    if (test->fKind == Expression::kBoolLiteral_Kind) {
35508a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas        // static boolean value, fold down to a single branch
35608a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas        if (((BoolLiteral&) *test).fValue) {
35708a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            return ifTrue;
35808a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas        } else if (s.fIfFalse) {
35908a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            return ifFalse;
36008a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas        } else {
36108a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            // False & no else clause. Not an error, so don't return null!
36208a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            std::vector<std::unique_ptr<Statement>> empty;
3635b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas            return std::unique_ptr<Statement>(new Block(s.fOffset, std::move(empty),
36408a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas                                                        fSymbolTable));
36508a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas        }
36608a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas    }
3675b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    return std::unique_ptr<Statement>(new IfStatement(s.fOffset, s.fIsStatic, std::move(test),
368b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                                      std::move(ifTrue), std::move(ifFalse)));
369b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
370b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
371b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Statement> IRGenerator::convertFor(const ASTForStatement& f) {
37222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas    AutoLoopLevel level(this);
373b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    AutoSymbolTable table(this);
37422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas    std::unique_ptr<Statement> initializer;
37522f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas    if (f.fInitializer) {
37622f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas        initializer = this->convertStatement(*f.fInitializer);
37722f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas        if (!initializer) {
37822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas            return nullptr;
37922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas        }
380b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
38122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas    std::unique_ptr<Expression> test;
38222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas    if (f.fTest) {
38322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas        test = this->coerce(this->convertExpression(*f.fTest), *fContext.fBool_Type);
38422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas        if (!test) {
38522f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas            return nullptr;
38622f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas        }
387b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
38822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas    std::unique_ptr<Expression> next;
38922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas    if (f.fNext) {
39022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas        next = this->convertExpression(*f.fNext);
39122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas        if (!next) {
39222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas            return nullptr;
39322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas        }
39422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas        this->checkValid(*next);
395b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
396b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    std::unique_ptr<Statement> statement = this->convertStatement(*f.fStatement);
397b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (!statement) {
398b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
399b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
4005b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    return std::unique_ptr<Statement>(new ForStatement(f.fOffset, std::move(initializer),
401b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                                       std::move(test), std::move(next),
402d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                                                       std::move(statement), fSymbolTable));
403b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
404b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
405b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Statement> IRGenerator::convertWhile(const ASTWhileStatement& w) {
40622f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas    AutoLoopLevel level(this);
40711d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas    std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*w.fTest),
408d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                                                    *fContext.fBool_Type);
409b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (!test) {
410b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
411b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
412b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    std::unique_ptr<Statement> statement = this->convertStatement(*w.fStatement);
413b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (!statement) {
414b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
415b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
4165b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    return std::unique_ptr<Statement>(new WhileStatement(w.fOffset, std::move(test),
417b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                                         std::move(statement)));
418b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
419b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
420b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Statement> IRGenerator::convertDo(const ASTDoStatement& d) {
42122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas    AutoLoopLevel level(this);
422d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*d.fTest),
423d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                                                    *fContext.fBool_Type);
424b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (!test) {
425b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
426b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
427b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    std::unique_ptr<Statement> statement = this->convertStatement(*d.fStatement);
428b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (!statement) {
429b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
430b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
4315b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    return std::unique_ptr<Statement>(new DoStatement(d.fOffset, std::move(statement),
432b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                                      std::move(test)));
433b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
434b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
435af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholasstd::unique_ptr<Statement> IRGenerator::convertSwitch(const ASTSwitchStatement& s) {
436af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas    AutoSwitchLevel level(this);
437af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas    std::unique_ptr<Expression> value = this->convertExpression(*s.fValue);
438af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas    if (!value) {
439af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas        return nullptr;
440af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas    }
441aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas    if (value->fType != *fContext.fUInt_Type && value->fType.kind() != Type::kEnum_Kind) {
442af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas        value = this->coerce(std::move(value), *fContext.fInt_Type);
443af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas        if (!value) {
444af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas            return nullptr;
445af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas        }
446af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas    }
447af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas    AutoSymbolTable table(this);
448af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas    std::unordered_set<int> caseValues;
449af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas    std::vector<std::unique_ptr<SwitchCase>> cases;
450af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas    for (const auto& c : s.fCases) {
451af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas        std::unique_ptr<Expression> caseValue;
452af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas        if (c->fValue) {
453af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas            caseValue = this->convertExpression(*c->fValue);
454af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas            if (!caseValue) {
455af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas                return nullptr;
456af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas            }
457aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            caseValue = this->coerce(std::move(caseValue), value->fType);
458aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            if (!caseValue) {
459aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                return nullptr;
460af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas            }
461af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas            if (!caseValue->isConstant()) {
4625b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                fErrors.error(caseValue->fOffset, "case value must be a constant");
463af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas                return nullptr;
464af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas            }
465aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            int64_t v;
466aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            this->getConstantInt(*caseValue, &v);
467af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas            if (caseValues.find(v) != caseValues.end()) {
4685b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                fErrors.error(caseValue->fOffset, "duplicate case value");
469af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas            }
470af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas            caseValues.insert(v);
471af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas        }
472af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas        std::vector<std::unique_ptr<Statement>> statements;
473af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas        for (const auto& s : c->fStatements) {
474af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas            std::unique_ptr<Statement> converted = this->convertStatement(*s);
475af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas            if (!converted) {
476af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas                return nullptr;
477af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas            }
478af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas            statements.push_back(std::move(converted));
479af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas        }
4805b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        cases.emplace_back(new SwitchCase(c->fOffset, std::move(caseValue),
481af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas                                          std::move(statements)));
482af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas    }
4835b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    return std::unique_ptr<Statement>(new SwitchStatement(s.fOffset, s.fIsStatic,
484c432b0ca8a5022d86f0ccf2efd1064ed9fce2e53Ethan Nicholas                                                          std::move(value), std::move(cases),
485c432b0ca8a5022d86f0ccf2efd1064ed9fce2e53Ethan Nicholas                                                          fSymbolTable));
486af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas}
487af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas
488b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Statement> IRGenerator::convertExpressionStatement(
489b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                                                  const ASTExpressionStatement& s) {
490b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    std::unique_ptr<Expression> e = this->convertExpression(*s.fExpression);
491b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (!e) {
492b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
493b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
494b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    this->checkValid(*e);
495b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    return std::unique_ptr<Statement>(new ExpressionStatement(std::move(e)));
496b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
497b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
498b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Statement> IRGenerator::convertReturn(const ASTReturnStatement& r) {
499b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    ASSERT(fCurrentFunction);
500fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    // early returns from a vertex main function will bypass the sk_Position normalization, so
501fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    // assert that we aren't doing that. It is of course possible to fix this by adding a
502fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    // normalization before each return, but it will probably never actually be necessary.
503fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    ASSERT(Program::kVertex_Kind != fKind || !fRTAdjust || "main" != fCurrentFunction->fName);
504b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (r.fExpression) {
505b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        std::unique_ptr<Expression> result = this->convertExpression(*r.fExpression);
506b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        if (!result) {
507b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            return nullptr;
508b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
509d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas        if (fCurrentFunction->fReturnType == *fContext.fVoid_Type) {
5105b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas            fErrors.error(result->fOffset, "may not return a value from a void function");
511b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        } else {
512b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            result = this->coerce(std::move(result), fCurrentFunction->fReturnType);
513b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            if (!result) {
514b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                return nullptr;
515b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            }
516b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
517b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return std::unique_ptr<Statement>(new ReturnStatement(std::move(result)));
518b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    } else {
519d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas        if (fCurrentFunction->fReturnType != *fContext.fVoid_Type) {
5205b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas            fErrors.error(r.fOffset, "expected function to return '" +
5215b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                     fCurrentFunction->fReturnType.description() + "'");
522b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
5235b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        return std::unique_ptr<Statement>(new ReturnStatement(r.fOffset));
524b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
525b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
526b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
527b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Statement> IRGenerator::convertBreak(const ASTBreakStatement& b) {
528af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas    if (fLoopLevel > 0 || fSwitchLevel > 0) {
5295b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        return std::unique_ptr<Statement>(new BreakStatement(b.fOffset));
53022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas    } else {
5315b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        fErrors.error(b.fOffset, "break statement must be inside a loop or switch");
53222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas        return nullptr;
53322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas    }
534b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
535b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
536b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Statement> IRGenerator::convertContinue(const ASTContinueStatement& c) {
53722f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas    if (fLoopLevel > 0) {
5385b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        return std::unique_ptr<Statement>(new ContinueStatement(c.fOffset));
53922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas    } else {
5405b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        fErrors.error(c.fOffset, "continue statement must be inside a loop");
54122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas        return nullptr;
54222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas    }
543b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
544b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
545b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Statement> IRGenerator::convertDiscard(const ASTDiscardStatement& d) {
5465b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    return std::unique_ptr<Statement>(new DiscardStatement(d.fOffset));
547b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
548b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
549aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholasstd::unique_ptr<Block> IRGenerator::applyInvocationIDWorkaround(std::unique_ptr<Block> main) {
5507da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    Layout invokeLayout;
5517da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    Modifiers invokeModifiers(invokeLayout, Modifiers::kHasSideEffects_Flag);
5525b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    FunctionDeclaration* invokeDecl = new FunctionDeclaration(-1,
5537da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                                                              invokeModifiers,
5547da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                                                              "_invoke",
5557da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                                                              std::vector<const Variable*>(),
5567da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                                                              *fContext.fVoid_Type);
557aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas    fProgramElements->push_back(std::unique_ptr<ProgramElement>(
558aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                                         new FunctionDefinition(-1, *invokeDecl, std::move(main))));
5597da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    fSymbolTable->add(invokeDecl->fName, std::unique_ptr<FunctionDeclaration>(invokeDecl));
5607da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas
56182a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas    std::vector<std::unique_ptr<VarDeclaration>> variables;
5627da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    Variable* loopIdx = (Variable*) (*fSymbolTable)["sk_InvocationID"];
5637da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    ASSERT(loopIdx);
5645b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    std::unique_ptr<Expression> test(new BinaryExpression(-1,
5655b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                    std::unique_ptr<Expression>(new VariableReference(-1, *loopIdx)),
5667da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                    Token::LT,
5675b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                    std::unique_ptr<IntLiteral>(new IntLiteral(fContext, -1, fInvocations)),
5687da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                    *fContext.fBool_Type));
5697da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    std::unique_ptr<Expression> next(new PostfixExpression(
5707da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                std::unique_ptr<Expression>(
5715b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                      new VariableReference(-1,
5727da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                                                            *loopIdx,
5737da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                                                            VariableReference::kReadWrite_RefKind)),
5747da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                Token::PLUSPLUS));
5755b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    ASTIdentifier endPrimitiveID = ASTIdentifier(-1, "EndPrimitive");
5767da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    std::unique_ptr<Expression> endPrimitive = this->convertExpression(endPrimitiveID);
5777da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    ASSERT(endPrimitive);
5787da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas
5797da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    std::vector<std::unique_ptr<Statement>> loopBody;
5807da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    std::vector<std::unique_ptr<Expression>> invokeArgs;
5817da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    loopBody.push_back(std::unique_ptr<Statement>(new ExpressionStatement(
5825b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                          this->call(-1,
5837da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                                                     *invokeDecl,
5847da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                                                     std::vector<std::unique_ptr<Expression>>()))));
5857da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    loopBody.push_back(std::unique_ptr<Statement>(new ExpressionStatement(
5865b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                          this->call(-1,
5877da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                                                     std::move(endPrimitive),
5887da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                                                     std::vector<std::unique_ptr<Expression>>()))));
5895b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    std::unique_ptr<Expression> assignment(new BinaryExpression(-1,
5905b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                    std::unique_ptr<Expression>(new VariableReference(-1, *loopIdx)),
5917da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                    Token::EQ,
5925b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                    std::unique_ptr<IntLiteral>(new IntLiteral(fContext, -1, 0)),
5937da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                    *fContext.fInt_Type));
5947da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    std::unique_ptr<Statement> initializer(new ExpressionStatement(std::move(assignment)));
5957da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    std::unique_ptr<Statement> loop = std::unique_ptr<Statement>(
5965b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                new ForStatement(-1,
5977da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                                 std::move(initializer),
5987da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                                 std::move(test),
5997da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                                 std::move(next),
6005b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                 std::unique_ptr<Block>(new Block(-1, std::move(loopBody))),
6017da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                                 fSymbolTable));
6027da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    std::vector<std::unique_ptr<Statement>> children;
6037da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    children.push_back(std::move(loop));
6045b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    return std::unique_ptr<Block>(new Block(-1, std::move(children)));
6057da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas}
6067da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas
607fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillipsstd::unique_ptr<Statement> IRGenerator::getNormalizeSkPositionCode() {
608fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    // sk_Position = float4(sk_Position.x * rtAdjust.x + sk_Position.w * rtAdjust.y,
609fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    //                      sk_Position.y * rtAdjust.z + sk_Position.w * rtAdjust.w,
610fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    //                      0,
611fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    //                      sk_Position.w);
612fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    ASSERT(fSkPerVertex && fRTAdjust);
613fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    #define REF(var) std::unique_ptr<Expression>(\
614fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                                  new VariableReference(-1, *var, VariableReference::kRead_RefKind))
615fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    #define FIELD(var, idx) std::unique_ptr<Expression>(\
616fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                    new FieldAccess(REF(var), idx, FieldAccess::kAnonymousInterfaceBlock_OwnerKind))
617fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    #define POS std::unique_ptr<Expression>(new FieldAccess(REF(fSkPerVertex), 0, \
618fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                                                   FieldAccess::kAnonymousInterfaceBlock_OwnerKind))
619fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    #define ADJUST (fRTAdjustInterfaceBlock ? \
620fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                    FIELD(fRTAdjustInterfaceBlock, fRTAdjustFieldIndex) : \
621fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                    REF(fRTAdjust))
622fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    #define SWIZZLE(expr, field) std::unique_ptr<Expression>(new Swizzle(fContext, expr, { field }))
623fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    #define OP(left, op, right) std::unique_ptr<Expression>(\
624fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                                   new BinaryExpression(-1, left, op, right, *fContext.fFloat_Type))
625fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    std::vector<std::unique_ptr<Expression>> children;
626fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    children.push_back(OP(OP(SWIZZLE(POS, 0), Token::STAR, SWIZZLE(ADJUST, 0)),
627fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                          Token::PLUS,
628fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                          OP(SWIZZLE(POS, 3), Token::STAR, SWIZZLE(ADJUST, 1))));
629fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    children.push_back(OP(OP(SWIZZLE(POS, 1), Token::STAR, SWIZZLE(ADJUST, 2)),
630fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                          Token::PLUS,
631fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                          OP(SWIZZLE(POS, 3), Token::STAR, SWIZZLE(ADJUST, 3))));
632fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    children.push_back(std::unique_ptr<Expression>(new FloatLiteral(fContext, -1, 0.0)));
633fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    children.push_back(SWIZZLE(POS, 3));
634fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    std::unique_ptr<Expression> result = OP(POS, Token::EQ,
635fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                                 std::unique_ptr<Expression>(new Constructor(-1,
636fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                                                                             *fContext.fFloat4_Type,
637fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                                                                             std::move(children))));
638fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    return std::unique_ptr<Statement>(new ExpressionStatement(std::move(result)));
639fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips}
640fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips
641aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholasvoid IRGenerator::convertFunction(const ASTFunction& f) {
642d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    const Type* returnType = this->convertType(*f.fReturnType);
643b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (!returnType) {
6447da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas        return;
645b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
646d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    std::vector<const Variable*> parameters;
647b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    for (const auto& param : f.fParameters) {
648d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas        const Type* type = this->convertType(*param->fType);
649b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        if (!type) {
6507da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas            return;
651b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
652b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        for (int j = (int) param->fSizes.size() - 1; j >= 0; j--) {
653b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            int size = param->fSizes[j];
6540df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas            String name = type->name() + "[" + to_string(size) + "]";
655d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            Type* newType = new Type(std::move(name), Type::kArray_Kind, *type, size);
656d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            fSymbolTable->takeOwnership(newType);
657d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            type = newType;
658b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
6595b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        StringFragment name = param->fName;
6605b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        Variable* var = new Variable(param->fOffset, param->fModifiers, name, *type,
66182a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas                                     Variable::kParameter_Storage);
662d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas        fSymbolTable->takeOwnership(var);
663d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas        parameters.push_back(var);
664b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
665b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
666b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    // find existing declaration
667d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    const FunctionDeclaration* decl = nullptr;
668d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    auto entry = (*fSymbolTable)[f.fName];
669b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (entry) {
670d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas        std::vector<const FunctionDeclaration*> functions;
671b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        switch (entry->fKind) {
672b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            case Symbol::kUnresolvedFunction_Kind:
673d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                functions = ((UnresolvedFunction*) entry)->fFunctions;
674b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                break;
675b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            case Symbol::kFunctionDeclaration_Kind:
676d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                functions.push_back((FunctionDeclaration*) entry);
677b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                break;
678b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            default:
6795b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                fErrors.error(f.fOffset, "symbol '" + f.fName + "' was already defined");
6807da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                return;
681b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
682b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        for (const auto& other : functions) {
683b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            ASSERT(other->fName == f.fName);
684b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            if (parameters.size() == other->fParameters.size()) {
685b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                bool match = true;
686b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                for (size_t i = 0; i < parameters.size(); i++) {
687b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                    if (parameters[i]->fType != other->fParameters[i]->fType) {
688b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                        match = false;
689b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                        break;
690b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                    }
691b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                }
692b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                if (match) {
693d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                    if (*returnType != other->fReturnType) {
6945b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                        FunctionDeclaration newDecl(f.fOffset, f.fModifiers, f.fName, parameters,
695cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas                                                    *returnType);
6965b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                        fErrors.error(f.fOffset, "functions '" + newDecl.description() +
6975b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                                 "' and '" + other->description() +
6985b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                                 "' differ only in return type");
6997da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                        return;
700b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                    }
701b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                    decl = other;
702b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                    for (size_t i = 0; i < parameters.size(); i++) {
703b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                        if (parameters[i]->fModifiers != other->fParameters[i]->fModifiers) {
7045b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                            fErrors.error(f.fOffset, "modifiers on parameter " +
7055b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                                     to_string((uint64_t) i + 1) +
7065b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                                     " differ between declaration and "
7075b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                                     "definition");
7087da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                            return;
709b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                        }
710b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                    }
711b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                    if (other->fDefined) {
7125b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                        fErrors.error(f.fOffset, "duplicate definition of " +
7135b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                                 other->description());
714b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                    }
715b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                    break;
716b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                }
717b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            }
718b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
719b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
720b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (!decl) {
721b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        // couldn't find an existing declaration
7225b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        auto newDecl = std::unique_ptr<FunctionDeclaration>(new FunctionDeclaration(f.fOffset,
723cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas                                                                                    f.fModifiers,
724471e89405b71f04e07ae2887bde061185e262c81ethannicholas                                                                                    f.fName,
725471e89405b71f04e07ae2887bde061185e262c81ethannicholas                                                                                    parameters,
726471e89405b71f04e07ae2887bde061185e262c81ethannicholas                                                                                    *returnType));
727471e89405b71f04e07ae2887bde061185e262c81ethannicholas        decl = newDecl.get();
728471e89405b71f04e07ae2887bde061185e262c81ethannicholas        fSymbolTable->add(decl->fName, std::move(newDecl));
729b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
730d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    if (f.fBody) {
731d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas        ASSERT(!fCurrentFunction);
732d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas        fCurrentFunction = decl;
733d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas        decl->fDefined = true;
734d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas        std::shared_ptr<SymbolTable> old = fSymbolTable;
735d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas        AutoSymbolTable table(this);
736d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas        for (size_t i = 0; i < parameters.size(); i++) {
737d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            fSymbolTable->addWithoutOwnership(parameters[i]->fName, decl->fParameters[i]);
738d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas        }
739f1b47bb299e72456d70cf3eae8086a5e01766c67Chris Dalton        bool needInvocationIDWorkaround = fInvocations != -1 && f.fName == "main" &&
740f1b47bb299e72456d70cf3eae8086a5e01766c67Chris Dalton                                          fSettings->fCaps &&
741f1b47bb299e72456d70cf3eae8086a5e01766c67Chris Dalton                                          !fSettings->fCaps->gsInvocationsSupport();
742762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas        ASSERT(!fExtraVars.size());
743d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas        std::unique_ptr<Block> body = this->convertBlock(*f.fBody);
744762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas        for (auto& v : fExtraVars) {
745762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas            body->fStatements.insert(body->fStatements.begin(), std::move(v));
746762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas        }
747762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas        fExtraVars.clear();
748d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas        fCurrentFunction = nullptr;
749d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas        if (!body) {
7507da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas            return;
7517da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas        }
7527da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas        if (needInvocationIDWorkaround) {
753aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            body = this->applyInvocationIDWorkaround(std::move(body));
754b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
755cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas        // conservatively assume all user-defined functions have side effects
756cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas        ((Modifiers&) decl->fModifiers).fFlags |= Modifiers::kHasSideEffects_Flag;
757fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips        if (Program::kVertex_Kind == fKind && f.fName == "main" && fRTAdjust) {
758fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips            body->fStatements.insert(body->fStatements.end(), this->getNormalizeSkPositionCode());
759fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips        }
760aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas        fProgramElements->push_back(std::unique_ptr<FunctionDefinition>(
761aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                                        new FunctionDefinition(f.fOffset, *decl, std::move(body))));
762b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
763b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
764b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
765b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInterfaceBlock& intf) {
766b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    std::shared_ptr<SymbolTable> old = fSymbolTable;
76768dd2c1fa051019354d0c441c78b3885d8e72a7aEthan Nicholas    this->pushSymbolTable();
76868dd2c1fa051019354d0c441c78b3885d8e72a7aEthan Nicholas    std::shared_ptr<SymbolTable> symbols = fSymbolTable;
769b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    std::vector<Type::Field> fields;
7700dd30d99282c48cb3b5d50939a4b200ace6b8c71Ethan Nicholas    bool haveRuntimeArray = false;
771fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    bool foundRTAdjust = false;
772b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    for (size_t i = 0; i < intf.fDeclarations.size(); i++) {
77314fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas        std::unique_ptr<VarDeclarations> decl = this->convertVarDeclarations(
77411d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas                                                                         *intf.fDeclarations[i],
775b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                                                         Variable::kGlobal_Storage);
7767effa7a29a04fb417c5e4abbe6aabf576a2aede0ethannicholas        if (!decl) {
7777effa7a29a04fb417c5e4abbe6aabf576a2aede0ethannicholas            return nullptr;
7787effa7a29a04fb417c5e4abbe6aabf576a2aede0ethannicholas        }
77982a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas        for (const auto& stmt : decl->fVars) {
78082a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas            VarDeclaration& vd = (VarDeclaration&) *stmt;
7810dd30d99282c48cb3b5d50939a4b200ace6b8c71Ethan Nicholas            if (haveRuntimeArray) {
78282a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas                fErrors.error(decl->fOffset,
7830dd30d99282c48cb3b5d50939a4b200ace6b8c71Ethan Nicholas                              "only the last entry in an interface block may be a runtime-sized "
7840dd30d99282c48cb3b5d50939a4b200ace6b8c71Ethan Nicholas                              "array");
7850dd30d99282c48cb3b5d50939a4b200ace6b8c71Ethan Nicholas            }
786fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips            if (vd.fVar == fRTAdjust) {
787fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                foundRTAdjust = true;
788fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                ASSERT(vd.fVar->fType == *fContext.fFloat4_Type);
789fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                fRTAdjustFieldIndex = fields.size();
790fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips            }
79182a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas            fields.push_back(Type::Field(vd.fVar->fModifiers, vd.fVar->fName,
79282a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas                                         &vd.fVar->fType));
79382a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas            if (vd.fValue) {
7945b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                fErrors.error(decl->fOffset,
795b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                              "initializers are not permitted on interface block fields");
796b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            }
79782a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas            if (vd.fVar->fModifiers.fFlags & (Modifiers::kIn_Flag |
79882a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas                                                Modifiers::kOut_Flag |
79982a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas                                                Modifiers::kUniform_Flag |
80082a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas                                                Modifiers::kBuffer_Flag |
80182a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas                                                Modifiers::kConst_Flag)) {
8025b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                fErrors.error(decl->fOffset,
803b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                              "interface block fields may not have storage qualifiers");
804b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            }
80582a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas            if (vd.fVar->fType.kind() == Type::kArray_Kind &&
80682a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas                vd.fVar->fType.columns() == -1) {
8070dd30d99282c48cb3b5d50939a4b200ace6b8c71Ethan Nicholas                haveRuntimeArray = true;
8080dd30d99282c48cb3b5d50939a4b200ace6b8c71Ethan Nicholas            }
80911d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas        }
810b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
81168dd2c1fa051019354d0c441c78b3885d8e72a7aEthan Nicholas    this->popSymbolTable();
8125b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    Type* type = new Type(intf.fOffset, intf.fTypeName, fields);
81386a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas    old->takeOwnership(type);
81450afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas    std::vector<std::unique_ptr<Expression>> sizes;
81550afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas    for (const auto& size : intf.fSizes) {
81650afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas        if (size) {
81750afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas            std::unique_ptr<Expression> converted = this->convertExpression(*size);
81850afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas            if (!converted) {
81950afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas                return nullptr;
82050afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas            }
8210df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas            String name = type->fName;
82250afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas            int64_t count;
82350afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas            if (converted->fKind == Expression::kIntLiteral_Kind) {
82450afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas                count = ((IntLiteral&) *converted).fValue;
82550afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas                if (count <= 0) {
8265b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                    fErrors.error(converted->fOffset, "array size must be positive");
82750afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas                }
82850afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas                name += "[" + to_string(count) + "]";
82950afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas            } else {
83050afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas                count = -1;
83150afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas                name += "[]";
83250afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas            }
83350afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas            type = new Type(name, Type::kArray_Kind, *type, (int) count);
83468dd2c1fa051019354d0c441c78b3885d8e72a7aEthan Nicholas            symbols->takeOwnership((Type*) type);
83550afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas            sizes.push_back(std::move(converted));
83650afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas        } else {
8375b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas            type = new Type(type->name() + "[]", Type::kArray_Kind, *type, -1);
83868dd2c1fa051019354d0c441c78b3885d8e72a7aEthan Nicholas            symbols->takeOwnership((Type*) type);
83950afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas            sizes.push_back(nullptr);
84050afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas        }
84150afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas    }
8425b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    Variable* var = new Variable(intf.fOffset, intf.fModifiers,
8435b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                 intf.fInstanceName.fLength ? intf.fInstanceName : intf.fTypeName,
84482a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas                                 *type, Variable::kGlobal_Storage);
845fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    if (foundRTAdjust) {
846fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips        fRTAdjustInterfaceBlock = var;
847fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    }
84886a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas    old->takeOwnership(var);
8495b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    if (intf.fInstanceName.fLength) {
85050afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas        old->addWithoutOwnership(intf.fInstanceName, var);
851b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    } else {
852b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        for (size_t i = 0; i < fields.size(); i++) {
8535b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas            old->add(fields[i].fName, std::unique_ptr<Field>(new Field(intf.fOffset, *var,
854d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                                                                       (int) i)));
855b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
856b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
857fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    if (var->fName == Compiler::PERVERTEX_NAME) {
858fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips        ASSERT(!fSkPerVertex);
859fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips        fSkPerVertex = var;
860fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    }
8615b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    return std::unique_ptr<InterfaceBlock>(new InterfaceBlock(intf.fOffset,
8628feeff929e57ea63914213f3b14d8f00b287a0adEthan Nicholas                                                              var,
86350afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas                                                              intf.fTypeName,
86450afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas                                                              intf.fInstanceName,
86550afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas                                                              std::move(sizes),
86668dd2c1fa051019354d0c441c78b3885d8e72a7aEthan Nicholas                                                              symbols));
867b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
868b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
869aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholasvoid IRGenerator::getConstantInt(const Expression& value, int64_t* out) {
870aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas    switch (value.fKind) {
871aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas        case Expression::kIntLiteral_Kind:
872aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            *out = ((const IntLiteral&) value).fValue;
873aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            break;
874aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas        case Expression::kVariableReference_Kind: {
875aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            const Variable& var = ((VariableReference&) value).fVariable;
876aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            if ((var.fModifiers.fFlags & Modifiers::kConst_Flag) &&
877aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                var.fInitialValue) {
878aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                this->getConstantInt(*var.fInitialValue, out);
879aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            }
880aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            break;
881aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas        }
882aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas        default:
883aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            fErrors.error(value.fOffset, "expected a constant int");
884aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas    }
885aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas}
886aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas
887aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholasvoid IRGenerator::convertEnum(const ASTEnum& e) {
888aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas    std::vector<Variable*> variables;
889aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas    int64_t currentValue = 0;
890aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas    Layout layout;
891aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas    ASTType enumType(e.fOffset, e.fTypeName, ASTType::kIdentifier_Kind, {});
892aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas    const Type* type = this->convertType(enumType);
893aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas    Modifiers modifiers(layout, Modifiers::kConst_Flag);
894aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas    std::shared_ptr<SymbolTable> symbols(new SymbolTable(fSymbolTable, &fErrors));
895aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas    fSymbolTable = symbols;
896aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas    for (size_t i = 0; i < e.fNames.size(); i++) {
897aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas        std::unique_ptr<Expression> value;
898aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas        if (e.fValues[i]) {
899aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            value = this->convertExpression(*e.fValues[i]);
900aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            if (!value) {
901aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                fSymbolTable = symbols->fParent;
902aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                return;
903aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            }
904aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            this->getConstantInt(*value, &currentValue);
905aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas        }
906aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas        value = std::unique_ptr<Expression>(new IntLiteral(fContext, e.fOffset, currentValue));
907aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas        ++currentValue;
908aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas        auto var = std::unique_ptr<Variable>(new Variable(e.fOffset, modifiers, e.fNames[i],
909aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                                                          *type, Variable::kGlobal_Storage,
910aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                                                          value.get()));
911aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas        variables.push_back(var.get());
912aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas        symbols->add(e.fNames[i], std::move(var));
913aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas        symbols->takeOwnership(value.release());
914aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas    }
915aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas    fProgramElements->push_back(std::unique_ptr<ProgramElement>(new Enum(e.fOffset, e.fTypeName,
916aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                                                                         symbols)));
917aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas    fSymbolTable = symbols->fParent;
918aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas}
919aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas
920d598f7981f34811e6f2a949207dc13638852f3f7ethannicholasconst Type* IRGenerator::convertType(const ASTType& type) {
921d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    const Symbol* result = (*fSymbolTable)[type.fName];
922b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (result && result->fKind == Symbol::kType_Kind) {
92350afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas        for (int size : type.fSizes) {
9245b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas            String name(result->fName);
9255b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas            name += "[";
92650afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas            if (size != -1) {
92750afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas                name += to_string(size);
92850afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas            }
92950afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas            name += "]";
93050afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas            result = new Type(name, Type::kArray_Kind, (const Type&) *result, size);
93150afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas            fSymbolTable->takeOwnership((Type*) result);
93250afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas        }
933d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas        return (const Type*) result;
934b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
9355b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    fErrors.error(type.fOffset, "unknown type '" + type.fName + "'");
936b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    return nullptr;
937b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
938b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
939b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Expression> IRGenerator::convertExpression(const ASTExpression& expr) {
940b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    switch (expr.fKind) {
941b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case ASTExpression::kIdentifier_Kind:
942b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            return this->convertIdentifier((ASTIdentifier&) expr);
943b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case ASTExpression::kBool_Kind:
9445b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas            return std::unique_ptr<Expression>(new BoolLiteral(fContext, expr.fOffset,
945b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                                               ((ASTBoolLiteral&) expr).fValue));
946b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case ASTExpression::kInt_Kind:
9475b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas            return std::unique_ptr<Expression>(new IntLiteral(fContext, expr.fOffset,
948b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                                              ((ASTIntLiteral&) expr).fValue));
949b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case ASTExpression::kFloat_Kind:
9505b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas            return std::unique_ptr<Expression>(new FloatLiteral(fContext, expr.fOffset,
951b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                                                ((ASTFloatLiteral&) expr).fValue));
952b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case ASTExpression::kBinary_Kind:
953b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            return this->convertBinaryExpression((ASTBinaryExpression&) expr);
954b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case ASTExpression::kPrefix_Kind:
955b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            return this->convertPrefixExpression((ASTPrefixExpression&) expr);
956b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case ASTExpression::kSuffix_Kind:
957b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            return this->convertSuffixExpression((ASTSuffixExpression&) expr);
958b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case ASTExpression::kTernary_Kind:
959b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            return this->convertTernaryExpression((ASTTernaryExpression&) expr);
960b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        default:
961b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            ABORT("unsupported expression type: %d\n", expr.fKind);
962b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
963b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
964b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
965b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier& identifier) {
966d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    const Symbol* result = (*fSymbolTable)[identifier.fText];
967b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (!result) {
9685b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        fErrors.error(identifier.fOffset, "unknown identifier '" + identifier.fText + "'");
969b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
970b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
971b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    switch (result->fKind) {
972b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case Symbol::kFunctionDeclaration_Kind: {
973d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            std::vector<const FunctionDeclaration*> f = {
974d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                (const FunctionDeclaration*) result
975b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            };
976d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            return std::unique_ptr<FunctionReference>(new FunctionReference(fContext,
9775b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                                                            identifier.fOffset,
978d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                                                                            f));
979b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
980b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case Symbol::kUnresolvedFunction_Kind: {
981d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            const UnresolvedFunction* f = (const UnresolvedFunction*) result;
982d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            return std::unique_ptr<FunctionReference>(new FunctionReference(fContext,
9835b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                                                            identifier.fOffset,
984b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                                                            f->fFunctions));
985b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
986b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case Symbol::kVariable_Kind: {
9873865711259e25a90a1d72480f848863ada202067Ethan Nicholas            const Variable* var = (const Variable*) result;
988762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas#ifndef SKSL_STANDALONE
9893865711259e25a90a1d72480f848863ada202067Ethan Nicholas            if (var->fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN) {
9903865711259e25a90a1d72480f848863ada202067Ethan Nicholas                fInputs.fFlipY = true;
9913865711259e25a90a1d72480f848863ada202067Ethan Nicholas                if (fSettings->fFlipY &&
9923865711259e25a90a1d72480f848863ada202067Ethan Nicholas                    (!fSettings->fCaps ||
9933865711259e25a90a1d72480f848863ada202067Ethan Nicholas                     !fSettings->fCaps->fragCoordConventionsExtensionString())) {
9943865711259e25a90a1d72480f848863ada202067Ethan Nicholas                    fInputs.fRTHeight = true;
9953865711259e25a90a1d72480f848863ada202067Ethan Nicholas                }
996941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas            }
997762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas#endif
99886a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas            // default to kRead_RefKind; this will be corrected later if the variable is written to
99986a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas            return std::unique_ptr<VariableReference>(new VariableReference(
10005b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                                                 identifier.fOffset,
100186a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas                                                                 *var,
100286a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas                                                                 VariableReference::kRead_RefKind));
1003b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
1004b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case Symbol::kField_Kind: {
1005d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            const Field* field = (const Field*) result;
10065b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas            VariableReference* base = new VariableReference(identifier.fOffset, field->fOwner,
100786a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas                                                            VariableReference::kRead_RefKind);
1008f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas            return std::unique_ptr<Expression>(new FieldAccess(
1009f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                                                  std::unique_ptr<Expression>(base),
1010f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                                                  field->fFieldIndex,
1011f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                                                  FieldAccess::kAnonymousInterfaceBlock_OwnerKind));
1012b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
1013b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case Symbol::kType_Kind: {
1014d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            const Type* t = (const Type*) result;
10155b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas            return std::unique_ptr<TypeReference>(new TypeReference(fContext, identifier.fOffset,
1016d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                                                                    *t));
1017b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
1018b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        default:
1019b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            ABORT("unsupported symbol type %d\n", result->fKind);
1020b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
1021762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas}
1022b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
1023762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholasstd::unique_ptr<Section> IRGenerator::convertSection(const ASTSection& s) {
10245b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    return std::unique_ptr<Section>(new Section(s.fOffset, s.fName, s.fArgument, s.fText));
1025b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
1026b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
1027762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas
102811d53974317fa29cc516075382e658ddd45fc151Ethan Nicholasstd::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr,
1029d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                                                const Type& type) {
1030b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (!expr) {
1031b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
1032b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
1033d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    if (expr->fType == type) {
1034b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return expr;
1035b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
1036b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    this->checkValid(*expr);
1037d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    if (expr->fType == *fContext.fInvalid_Type) {
1038b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
1039b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
1040dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas    if (expr->coercionCost(type) == INT_MAX) {
10415b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        fErrors.error(expr->fOffset, "expected '" + type.description() + "', but found '" +
1042d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                                        expr->fType.description() + "'");
1043b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
1044b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
1045d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    if (type.kind() == Type::kScalar_Kind) {
1046b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        std::vector<std::unique_ptr<Expression>> args;
1047b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        args.push_back(std::move(expr));
10485b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        ASTIdentifier id(-1, type.fName);
1049b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        std::unique_ptr<Expression> ctor = this->convertIdentifier(id);
1050b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        ASSERT(ctor);
10515b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        return this->call(-1, std::move(ctor), std::move(args));
1052b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
10535961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas    std::vector<std::unique_ptr<Expression>> args;
10545961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas    args.push_back(std::move(expr));
10555b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    return std::unique_ptr<Expression>(new Constructor(-1, type, std::move(args)));
1056b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
1057b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
1058f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasstatic bool is_matrix_multiply(const Type& left, const Type& right) {
1059f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas    if (left.kind() == Type::kMatrix_Kind) {
1060f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas        return right.kind() == Type::kMatrix_Kind || right.kind() == Type::kVector_Kind;
1061f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas    }
1062f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas    return left.kind() == Type::kVector_Kind && right.kind() == Type::kMatrix_Kind;
1063f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas}
1064ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas
1065b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas/**
1066b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas * Determines the operand and result types of a binary expression. Returns true if the expression is
1067b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas * legal, false otherwise. If false, the values of the out parameters are undefined.
1068b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas */
106911d53974317fa29cc516075382e658ddd45fc151Ethan Nicholasstatic bool determine_binary_type(const Context& context,
107011d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas                                  Token::Kind op,
107111d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas                                  const Type& left,
107211d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas                                  const Type& right,
1073d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                                  const Type** outLeftType,
1074d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                                  const Type** outRightType,
1075d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                                  const Type** outResultType,
1076b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                  bool tryFlipped) {
1077b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    bool isLogical;
1078ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas    bool validMatrixOrVectorOp;
1079b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    switch (op) {
1080ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas        case Token::EQ:
1081ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas            *outLeftType = &left;
1082ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas            *outRightType = &left;
1083ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas            *outResultType = &left;
1084ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas            return right.canCoerceTo(left);
1085b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case Token::EQEQ: // fall through
1086ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas        case Token::NEQ:
1087aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            if (left == right) {
1088aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                *outLeftType = &left;
1089aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                *outRightType = &right;
1090aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                *outResultType = context.fBool_Type.get();
1091aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                return true;
1092aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            }
1093ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas            isLogical = true;
1094ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas            validMatrixOrVectorOp = true;
1095ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas            break;
1096b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case Token::LT:   // fall through
1097b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case Token::GT:   // fall through
1098b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case Token::LTEQ: // fall through
1099b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case Token::GTEQ:
1100b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            isLogical = true;
1101ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas            validMatrixOrVectorOp = false;
1102b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            break;
1103b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case Token::LOGICALOR: // fall through
1104b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case Token::LOGICALAND: // fall through
1105b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case Token::LOGICALXOR: // fall through
1106b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case Token::LOGICALOREQ: // fall through
1107b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case Token::LOGICALANDEQ: // fall through
1108b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case Token::LOGICALXOREQ:
1109d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            *outLeftType = context.fBool_Type.get();
1110d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            *outRightType = context.fBool_Type.get();
1111d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            *outResultType = context.fBool_Type.get();
111211d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas            return left.canCoerceTo(*context.fBool_Type) &&
1113d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                   right.canCoerceTo(*context.fBool_Type);
111411d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas        case Token::STAREQ:
1115f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas            if (left.kind() == Type::kScalar_Kind) {
1116f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas                *outLeftType = &left;
1117f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas                *outRightType = &left;
1118f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas                *outResultType = &left;
1119f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas                return right.canCoerceTo(left);
1120f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas            }
1121f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas            // fall through
1122f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        case Token::STAR:
1123f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas            if (is_matrix_multiply(left, right)) {
1124f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                // determine final component type
1125f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                if (determine_binary_type(context, Token::STAR, left.componentType(),
1126f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                                          right.componentType(), outLeftType, outRightType,
1127f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                                          outResultType, false)) {
112811d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas                    *outLeftType = &(*outResultType)->toCompound(context, left.columns(),
1129f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                                                                 left.rows());;
113011d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas                    *outRightType = &(*outResultType)->toCompound(context, right.columns(),
1131f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                                                                  right.rows());;
1132f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                    int leftColumns = left.columns();
1133f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                    int leftRows = left.rows();
1134f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                    int rightColumns;
1135f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                    int rightRows;
1136f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                    if (right.kind() == Type::kVector_Kind) {
1137f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                        // matrix * vector treats the vector as a column vector, so we need to
1138f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                        // transpose it
1139f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                        rightColumns = right.rows();
1140f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                        rightRows = right.columns();
1141f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                        ASSERT(rightColumns == 1);
1142f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                    } else {
1143f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                        rightColumns = right.columns();
1144f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                        rightRows = right.rows();
1145f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                    }
1146f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                    if (rightColumns > 1) {
1147f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                        *outResultType = &(*outResultType)->toCompound(context, rightColumns,
1148f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                                                                       leftRows);
1149f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                    } else {
1150f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                        // result was a column vector, transpose it back to a row
1151f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                        *outResultType = &(*outResultType)->toCompound(context, leftRows,
1152f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                                                                       rightColumns);
1153f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                    }
1154f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                    return leftColumns == rightRows;
1155f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                } else {
1156f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                    return false;
1157f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas                }
1158b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            }
1159ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas            isLogical = false;
1160ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas            validMatrixOrVectorOp = true;
1161ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas            break;
1162f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        case Token::PLUSEQ:
1163f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        case Token::MINUSEQ:
1164f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        case Token::SLASHEQ:
1165f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        case Token::PERCENTEQ:
1166f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        case Token::SHLEQ:
1167f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        case Token::SHREQ:
1168f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas            if (left.kind() == Type::kScalar_Kind) {
1169f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas                *outLeftType = &left;
1170f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas                *outRightType = &left;
1171f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas                *outResultType = &left;
1172f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas                return right.canCoerceTo(left);
1173f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas            }
1174f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas            // fall through
1175ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas        case Token::PLUS:    // fall through
1176ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas        case Token::MINUS:   // fall through
1177ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas        case Token::SLASH:   // fall through
1178ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas            isLogical = false;
1179ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas            validMatrixOrVectorOp = true;
1180ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas            break;
11814b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas        case Token::COMMA:
11824b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas            *outLeftType = &left;
11834b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas            *outRightType = &right;
11844b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas            *outResultType = &right;
11854b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas            return true;
1186b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        default:
1187b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            isLogical = false;
1188ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas            validMatrixOrVectorOp = false;
1189b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
1190ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas    bool isVectorOrMatrix = left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind;
1191f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    if (left.kind() == Type::kScalar_Kind && right.kind() == Type::kScalar_Kind &&
1192f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas            right.canCoerceTo(left)) {
1193f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        if (left.priority() > right.priority()) {
1194f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas            *outLeftType = &left;
1195f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas            *outRightType = &left;
1196f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        } else {
1197f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas            *outLeftType = &right;
1198f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas            *outRightType = &right;
1199f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        }
1200f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        if (isLogical) {
1201f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas            *outResultType = context.fBool_Type.get();
1202f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        } else {
1203f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas            *outResultType = &left;
1204f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        }
1205f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        return true;
1206f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    }
1207f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    if (right.canCoerceTo(left) && isVectorOrMatrix && validMatrixOrVectorOp) {
1208d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas        *outLeftType = &left;
1209d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas        *outRightType = &left;
1210b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        if (isLogical) {
1211d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            *outResultType = context.fBool_Type.get();
1212b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        } else {
1213d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            *outResultType = &left;
1214b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
1215b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return true;
1216b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
121711d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas    if ((left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind) &&
1218d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas        (right.kind() == Type::kScalar_Kind)) {
121911d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas        if (determine_binary_type(context, op, left.componentType(), right, outLeftType,
1220d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                                  outRightType, outResultType, false)) {
1221d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            *outLeftType = &(*outLeftType)->toCompound(context, left.columns(), left.rows());
1222b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            if (!isLogical) {
122311d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas                *outResultType = &(*outResultType)->toCompound(context, left.columns(),
1224d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                                                               left.rows());
1225b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            }
1226b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            return true;
1227b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
1228b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return false;
1229b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
1230b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (tryFlipped) {
123111d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas        return determine_binary_type(context, op, right, left, outRightType, outLeftType,
1232d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                                     outResultType, false);
1233b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
1234b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    return false;
1235b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
1236b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
123708a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholasstd::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
123808a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas                                                      Token::Kind op,
123986a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas                                                      const Expression& right) const {
1240cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas    if (!left.isConstant() || !right.isConstant()) {
1241cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas        return nullptr;
1242cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas    }
124308a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas    // Note that we expressly do not worry about precision and overflow here -- we use the maximum
124408a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas    // precision to calculate the results and hope the result makes sense. The plan is to move the
124508a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas    // Skia caps into SkSL, so we have access to all of them including the precisions of the various
124608a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas    // types, which will let us be more intelligent about this.
124711d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas    if (left.fKind == Expression::kBoolLiteral_Kind &&
124808a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas        right.fKind == Expression::kBoolLiteral_Kind) {
124908a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas        bool leftVal  = ((BoolLiteral&) left).fValue;
125008a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas        bool rightVal = ((BoolLiteral&) right).fValue;
125108a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas        bool result;
125208a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas        switch (op) {
125308a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            case Token::LOGICALAND: result = leftVal && rightVal; break;
125408a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            case Token::LOGICALOR:  result = leftVal || rightVal; break;
125508a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            case Token::LOGICALXOR: result = leftVal ^  rightVal; break;
125608a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            default: return nullptr;
125708a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas        }
12585b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        return std::unique_ptr<Expression>(new BoolLiteral(fContext, left.fOffset, result));
125908a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas    }
12605b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    #define RESULT(t, op) std::unique_ptr<Expression>(new t ## Literal(fContext, left.fOffset, \
126108a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas                                                                       leftVal op rightVal))
126208a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas    if (left.fKind == Expression::kIntLiteral_Kind && right.fKind == Expression::kIntLiteral_Kind) {
126308a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas        int64_t leftVal  = ((IntLiteral&) left).fValue;
126408a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas        int64_t rightVal = ((IntLiteral&) right).fValue;
126508a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas        switch (op) {
1266cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas            case Token::PLUS:       return RESULT(Int, +);
1267cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas            case Token::MINUS:      return RESULT(Int, -);
1268cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas            case Token::STAR:       return RESULT(Int, *);
12699a5610e35d1a54161c1d4b15bd49145fd5ab49caEthan Nicholas            case Token::SLASH:
12709a5610e35d1a54161c1d4b15bd49145fd5ab49caEthan Nicholas                if (rightVal) {
12719a5610e35d1a54161c1d4b15bd49145fd5ab49caEthan Nicholas                    return RESULT(Int, /);
12729a5610e35d1a54161c1d4b15bd49145fd5ab49caEthan Nicholas                }
12735b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                fErrors.error(right.fOffset, "division by zero");
12749a5610e35d1a54161c1d4b15bd49145fd5ab49caEthan Nicholas                return nullptr;
12752503ab6e92cb9893788d75a4062f1a8d7e6738d0Ethan Nicholas            case Token::PERCENT:
12762503ab6e92cb9893788d75a4062f1a8d7e6738d0Ethan Nicholas                if (rightVal) {
12772503ab6e92cb9893788d75a4062f1a8d7e6738d0Ethan Nicholas                    return RESULT(Int, %);
12782503ab6e92cb9893788d75a4062f1a8d7e6738d0Ethan Nicholas                }
12795b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                fErrors.error(right.fOffset, "division by zero");
12802503ab6e92cb9893788d75a4062f1a8d7e6738d0Ethan Nicholas                return nullptr;
128108a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            case Token::BITWISEAND: return RESULT(Int,  &);
128208a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            case Token::BITWISEOR:  return RESULT(Int,  |);
128308a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            case Token::BITWISEXOR: return RESULT(Int,  ^);
128408a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            case Token::SHL:        return RESULT(Int,  <<);
128508a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            case Token::SHR:        return RESULT(Int,  >>);
128608a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            case Token::EQEQ:       return RESULT(Bool, ==);
128708a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            case Token::NEQ:        return RESULT(Bool, !=);
128808a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            case Token::GT:         return RESULT(Bool, >);
128908a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            case Token::GTEQ:       return RESULT(Bool, >=);
129008a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            case Token::LT:         return RESULT(Bool, <);
129108a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            case Token::LTEQ:       return RESULT(Bool, <=);
129208a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            default:                return nullptr;
129308a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas        }
129408a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas    }
129511d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas    if (left.fKind == Expression::kFloatLiteral_Kind &&
129608a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas        right.fKind == Expression::kFloatLiteral_Kind) {
129708a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas        double leftVal  = ((FloatLiteral&) left).fValue;
129808a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas        double rightVal = ((FloatLiteral&) right).fValue;
129908a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas        switch (op) {
130008a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            case Token::PLUS:       return RESULT(Float, +);
130108a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            case Token::MINUS:      return RESULT(Float, -);
130208a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            case Token::STAR:       return RESULT(Float, *);
13039a5610e35d1a54161c1d4b15bd49145fd5ab49caEthan Nicholas            case Token::SLASH:
13049a5610e35d1a54161c1d4b15bd49145fd5ab49caEthan Nicholas                if (rightVal) {
13059a5610e35d1a54161c1d4b15bd49145fd5ab49caEthan Nicholas                    return RESULT(Float, /);
13069a5610e35d1a54161c1d4b15bd49145fd5ab49caEthan Nicholas                }
13075b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                fErrors.error(right.fOffset, "division by zero");
13089a5610e35d1a54161c1d4b15bd49145fd5ab49caEthan Nicholas                return nullptr;
1309cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas            case Token::EQEQ:       return RESULT(Bool, ==);
1310cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas            case Token::NEQ:        return RESULT(Bool, !=);
1311cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas            case Token::GT:         return RESULT(Bool, >);
1312cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas            case Token::GTEQ:       return RESULT(Bool, >=);
1313cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas            case Token::LT:         return RESULT(Bool, <);
1314cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas            case Token::LTEQ:       return RESULT(Bool, <=);
131508a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            default:                return nullptr;
131608a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas        }
131708a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas    }
1318cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas    if (left.fType.kind() == Type::kVector_Kind &&
1319cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas        left.fType.componentType() == *fContext.fFloat_Type &&
1320cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas        left.fType == right.fType) {
1321cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas        ASSERT(left.fKind  == Expression::kConstructor_Kind);
1322cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas        ASSERT(right.fKind == Expression::kConstructor_Kind);
1323cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas        std::vector<std::unique_ptr<Expression>> args;
1324cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas        #define RETURN_VEC_COMPONENTWISE_RESULT(op)                                    \
1325cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas            for (int i = 0; i < left.fType.columns(); i++) {                           \
1326cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas                float value = ((Constructor&) left).getFVecComponent(i) op             \
1327cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas                              ((Constructor&) right).getFVecComponent(i);              \
13285b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                args.emplace_back(new FloatLiteral(fContext, -1, value));              \
1329cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas            }                                                                          \
13305b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas            return std::unique_ptr<Expression>(new Constructor(-1, left.fType,         \
1331cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas                                                               std::move(args)));
1332cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas        switch (op) {
13333deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas            case Token::EQEQ:
13345b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
13353deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas                                                            left.compareConstant(fContext, right)));
13363deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas            case Token::NEQ:
13375b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
13383deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas                                                           !left.compareConstant(fContext, right)));
1339cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas            case Token::PLUS:  RETURN_VEC_COMPONENTWISE_RESULT(+);
1340cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas            case Token::MINUS: RETURN_VEC_COMPONENTWISE_RESULT(-);
1341cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas            case Token::STAR:  RETURN_VEC_COMPONENTWISE_RESULT(*);
1342cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas            case Token::SLASH: RETURN_VEC_COMPONENTWISE_RESULT(/);
1343cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas            default:           return nullptr;
1344cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas        }
1345cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas    }
13463deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas    if (left.fType.kind() == Type::kMatrix_Kind &&
13473deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas        right.fType.kind() == Type::kMatrix_Kind &&
13483deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas        left.fKind == right.fKind) {
13493deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas        switch (op) {
13503deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas            case Token::EQEQ:
13515b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
13523deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas                                                            left.compareConstant(fContext, right)));
13533deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas            case Token::NEQ:
13545b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
13553deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas                                                           !left.compareConstant(fContext, right)));
13563deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas            default:
13573deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas                return nullptr;
13583deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas        }
13593deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas    }
136008a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas    #undef RESULT
136108a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas    return nullptr;
136208a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas}
136308a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas
1364b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Expression> IRGenerator::convertBinaryExpression(
1365b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                                            const ASTBinaryExpression& expression) {
1366b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    std::unique_ptr<Expression> left = this->convertExpression(*expression.fLeft);
1367b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (!left) {
1368b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
1369b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
1370b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    std::unique_ptr<Expression> right = this->convertExpression(*expression.fRight);
1371b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (!right) {
1372b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
1373b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
1374d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    const Type* leftType;
1375d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    const Type* rightType;
1376d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    const Type* resultType;
1377dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas    const Type* rawLeftType;
1378dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas    if (left->fKind == Expression::kIntLiteral_Kind && right->fType.isInteger()) {
1379dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas        rawLeftType = &right->fType;
1380dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas    } else {
1381dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas        rawLeftType = &left->fType;
1382dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas    }
1383dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas    const Type* rawRightType;
1384dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas    if (right->fKind == Expression::kIntLiteral_Kind && left->fType.isInteger()) {
1385dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas        rawRightType = &left->fType;
1386dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas    } else {
1387dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas        rawRightType = &right->fType;
1388dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas    }
1389dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas    if (!determine_binary_type(fContext, expression.fOperator, *rawLeftType, *rawRightType,
1390dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas                               &leftType, &rightType, &resultType,
13915b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                               !Compiler::IsAssignment(expression.fOperator))) {
13925b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        fErrors.error(expression.fOffset, String("type mismatch: '") +
13935b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                          Compiler::OperatorName(expression.fOperator) +
13945b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                          "' cannot operate on '" + left->fType.fName +
13955b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                          "', '" + right->fType.fName + "'");
1396b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
1397b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
13985b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    if (Compiler::IsAssignment(expression.fOperator)) {
139986a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas        this->markWrittenTo(*left, expression.fOperator != Token::EQ);
1400ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas    }
1401ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas    left = this->coerce(std::move(left), *leftType);
1402ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas    right = this->coerce(std::move(right), *rightType);
1403ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas    if (!left || !right) {
1404ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas        return nullptr;
1405b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
140611d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas    std::unique_ptr<Expression> result = this->constantFold(*left.get(), expression.fOperator,
140708a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas                                                            *right.get());
140808a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas    if (!result) {
14095b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        result = std::unique_ptr<Expression>(new BinaryExpression(expression.fOffset,
141008a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas                                                                  std::move(left),
141108a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas                                                                  expression.fOperator,
141208a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas                                                                  std::move(right),
141308a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas                                                                  *resultType));
141408a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas    }
141508a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas    return result;
1416b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
1417b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
141811d53974317fa29cc516075382e658ddd45fc151Ethan Nicholasstd::unique_ptr<Expression> IRGenerator::convertTernaryExpression(
1419b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                                           const ASTTernaryExpression& expression) {
142011d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas    std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*expression.fTest),
1421d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                                                    *fContext.fBool_Type);
1422b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (!test) {
1423b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
1424b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
1425b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    std::unique_ptr<Expression> ifTrue = this->convertExpression(*expression.fIfTrue);
1426b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (!ifTrue) {
1427b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
1428b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
1429b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    std::unique_ptr<Expression> ifFalse = this->convertExpression(*expression.fIfFalse);
1430b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (!ifFalse) {
1431b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
1432b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
1433d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    const Type* trueType;
1434d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    const Type* falseType;
1435d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    const Type* resultType;
1436d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    if (!determine_binary_type(fContext, Token::EQEQ, ifTrue->fType, ifFalse->fType, &trueType,
14372be687af58ec1f445c6380457d136562ef27155eEthan Nicholas                               &falseType, &resultType, true) || trueType != falseType) {
14385b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        fErrors.error(expression.fOffset, "ternary operator result mismatch: '" +
14395b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                          ifTrue->fType.fName + "', '" +
14405b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                          ifFalse->fType.fName + "'");
1441b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
1442b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
1443d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    ifTrue = this->coerce(std::move(ifTrue), *trueType);
14442be687af58ec1f445c6380457d136562ef27155eEthan Nicholas    if (!ifTrue) {
14452be687af58ec1f445c6380457d136562ef27155eEthan Nicholas        return nullptr;
14462be687af58ec1f445c6380457d136562ef27155eEthan Nicholas    }
1447d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    ifFalse = this->coerce(std::move(ifFalse), *falseType);
14482be687af58ec1f445c6380457d136562ef27155eEthan Nicholas    if (!ifFalse) {
14492be687af58ec1f445c6380457d136562ef27155eEthan Nicholas        return nullptr;
14502be687af58ec1f445c6380457d136562ef27155eEthan Nicholas    }
145108a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas    if (test->fKind == Expression::kBoolLiteral_Kind) {
145208a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas        // static boolean test, just return one of the branches
145308a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas        if (((BoolLiteral&) *test).fValue) {
145408a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            return ifTrue;
145508a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas        } else {
145608a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            return ifFalse;
145708a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas        }
145808a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas    }
14595b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    return std::unique_ptr<Expression>(new TernaryExpression(expression.fOffset,
1460b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                                             std::move(test),
146111d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas                                                             std::move(ifTrue),
1462b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                                             std::move(ifFalse)));
1463b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
1464b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
14655338f99a8a75d0e7622a37c5d1c05fcce49f55f5Ethan Nicholas// scales the texture coordinates by the texture size for sampling rectangle textures.
14665af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas// For float2coordinates, implements the transformation:
14675338f99a8a75d0e7622a37c5d1c05fcce49f55f5Ethan Nicholas//     texture(sampler, coord) -> texture(sampler, textureSize(sampler) * coord)
14685af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas// For float3coordinates, implements the transformation:
14695af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas//     texture(sampler, coord) -> texture(sampler, float3textureSize(sampler), 1.0) * coord))
14705338f99a8a75d0e7622a37c5d1c05fcce49f55f5Ethan Nicholasvoid IRGenerator::fixRectSampling(std::vector<std::unique_ptr<Expression>>& arguments) {
14715338f99a8a75d0e7622a37c5d1c05fcce49f55f5Ethan Nicholas    ASSERT(arguments.size() == 2);
14725338f99a8a75d0e7622a37c5d1c05fcce49f55f5Ethan Nicholas    ASSERT(arguments[0]->fType == *fContext.fSampler2DRect_Type);
14735338f99a8a75d0e7622a37c5d1c05fcce49f55f5Ethan Nicholas    ASSERT(arguments[0]->fKind == Expression::kVariableReference_Kind);
14745338f99a8a75d0e7622a37c5d1c05fcce49f55f5Ethan Nicholas    const Variable& sampler = ((VariableReference&) *arguments[0]).fVariable;
14755338f99a8a75d0e7622a37c5d1c05fcce49f55f5Ethan Nicholas    const Symbol* textureSizeSymbol = (*fSymbolTable)["textureSize"];
14765338f99a8a75d0e7622a37c5d1c05fcce49f55f5Ethan Nicholas    ASSERT(textureSizeSymbol->fKind == Symbol::kFunctionDeclaration_Kind);
14775338f99a8a75d0e7622a37c5d1c05fcce49f55f5Ethan Nicholas    const FunctionDeclaration& textureSize = (FunctionDeclaration&) *textureSizeSymbol;
14785338f99a8a75d0e7622a37c5d1c05fcce49f55f5Ethan Nicholas    std::vector<std::unique_ptr<Expression>> sizeArguments;
14795b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    sizeArguments.emplace_back(new VariableReference(-1, sampler));
14805b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    std::unique_ptr<Expression> float2ize = call(-1, textureSize, std::move(sizeArguments));
14815338f99a8a75d0e7622a37c5d1c05fcce49f55f5Ethan Nicholas    const Type& type = arguments[1]->fType;
14825338f99a8a75d0e7622a37c5d1c05fcce49f55f5Ethan Nicholas    std::unique_ptr<Expression> scale;
14835af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas    if (type == *fContext.fFloat2_Type) {
14845af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas        scale = std::move(float2ize);
14855338f99a8a75d0e7622a37c5d1c05fcce49f55f5Ethan Nicholas    } else {
14865af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas        ASSERT(type == *fContext.fFloat3_Type);
14875af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas        std::vector<std::unique_ptr<Expression>> float3rguments;
14885af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas        float3rguments.push_back(std::move(float2ize));
14895b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        float3rguments.emplace_back(new FloatLiteral(fContext, -1, 1.0));
14905b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        scale.reset(new Constructor(-1, *fContext.fFloat3_Type, std::move(float3rguments)));
14915338f99a8a75d0e7622a37c5d1c05fcce49f55f5Ethan Nicholas    }
14925b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    arguments[1].reset(new BinaryExpression(-1, std::move(scale), Token::STAR,
14935338f99a8a75d0e7622a37c5d1c05fcce49f55f5Ethan Nicholas                                            std::move(arguments[1]), type));
14945338f99a8a75d0e7622a37c5d1c05fcce49f55f5Ethan Nicholas}
14955338f99a8a75d0e7622a37c5d1c05fcce49f55f5Ethan Nicholas
14965b5f096a038259b8d9084834f877588a0db80250Ethan Nicholasstd::unique_ptr<Expression> IRGenerator::call(int offset,
149711d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas                                              const FunctionDeclaration& function,
1498d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                                              std::vector<std::unique_ptr<Expression>> arguments) {
1499d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    if (function.fParameters.size() != arguments.size()) {
15000df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas        String msg = "call to '" + function.fName + "' expected " +
150111d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas                                 to_string((uint64_t) function.fParameters.size()) +
1502b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                 " argument";
1503d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas        if (function.fParameters.size() != 1) {
1504b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            msg += "s";
1505b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
15065961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas        msg += ", but found " + to_string((uint64_t) arguments.size());
15075b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        fErrors.error(offset, msg);
1508b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
1509b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
1510471e89405b71f04e07ae2887bde061185e262c81ethannicholas    std::vector<const Type*> types;
1511471e89405b71f04e07ae2887bde061185e262c81ethannicholas    const Type* returnType;
1512471e89405b71f04e07ae2887bde061185e262c81ethannicholas    if (!function.determineFinalTypes(arguments, &types, &returnType)) {
15130df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas        String msg = "no match for " + function.fName + "(";
15140df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas        String separator;
1515471e89405b71f04e07ae2887bde061185e262c81ethannicholas        for (size_t i = 0; i < arguments.size(); i++) {
1516471e89405b71f04e07ae2887bde061185e262c81ethannicholas            msg += separator;
1517471e89405b71f04e07ae2887bde061185e262c81ethannicholas            separator = ", ";
1518471e89405b71f04e07ae2887bde061185e262c81ethannicholas            msg += arguments[i]->fType.description();
1519471e89405b71f04e07ae2887bde061185e262c81ethannicholas        }
1520471e89405b71f04e07ae2887bde061185e262c81ethannicholas        msg += ")";
15215b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        fErrors.error(offset, msg);
1522471e89405b71f04e07ae2887bde061185e262c81ethannicholas        return nullptr;
1523471e89405b71f04e07ae2887bde061185e262c81ethannicholas    }
1524b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    for (size_t i = 0; i < arguments.size(); i++) {
1525471e89405b71f04e07ae2887bde061185e262c81ethannicholas        arguments[i] = this->coerce(std::move(arguments[i]), *types[i]);
1526ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas        if (!arguments[i]) {
1527ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas            return nullptr;
1528ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas        }
1529d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas        if (arguments[i] && (function.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag)) {
1530762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas            this->markWrittenTo(*arguments[i],
1531cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas                                function.fParameters[i]->fModifiers.fFlags & Modifiers::kIn_Flag);
1532b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
1533b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
15345338f99a8a75d0e7622a37c5d1c05fcce49f55f5Ethan Nicholas    if (function.fBuiltin && function.fName == "texture" &&
15355338f99a8a75d0e7622a37c5d1c05fcce49f55f5Ethan Nicholas        arguments[0]->fType == *fContext.fSampler2DRect_Type) {
15365338f99a8a75d0e7622a37c5d1c05fcce49f55f5Ethan Nicholas        this->fixRectSampling(arguments);
15375338f99a8a75d0e7622a37c5d1c05fcce49f55f5Ethan Nicholas    }
15385b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    return std::unique_ptr<FunctionCall>(new FunctionCall(offset, *returnType, function,
1539b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                                          std::move(arguments)));
1540b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
1541b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
1542b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas/**
1543dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas * Determines the cost of coercing the arguments of a function to the required types. Cost has no
1544dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas * particular meaning other than "lower costs are preferred". Returns INT_MAX if the call is not
1545dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas * valid.
1546b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas */
1547dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholasint IRGenerator::callCost(const FunctionDeclaration& function,
1548dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas             const std::vector<std::unique_ptr<Expression>>& arguments) {
1549d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    if (function.fParameters.size() != arguments.size()) {
1550dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas        return INT_MAX;
1551b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
1552b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    int total = 0;
1553471e89405b71f04e07ae2887bde061185e262c81ethannicholas    std::vector<const Type*> types;
1554471e89405b71f04e07ae2887bde061185e262c81ethannicholas    const Type* ignored;
1555471e89405b71f04e07ae2887bde061185e262c81ethannicholas    if (!function.determineFinalTypes(arguments, &types, &ignored)) {
1556dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas        return INT_MAX;
1557471e89405b71f04e07ae2887bde061185e262c81ethannicholas    }
1558b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    for (size_t i = 0; i < arguments.size(); i++) {
1559dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas        int cost = arguments[i]->coercionCost(*types[i]);
1560dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas        if (cost != INT_MAX) {
1561b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            total += cost;
1562b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        } else {
1563dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas            return INT_MAX;
1564b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
1565b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
1566dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas    return total;
1567b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
1568b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
15695b5f096a038259b8d9084834f877588a0db80250Ethan Nicholasstd::unique_ptr<Expression> IRGenerator::call(int offset,
157011d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas                                              std::unique_ptr<Expression> functionValue,
1571b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                              std::vector<std::unique_ptr<Expression>> arguments) {
1572b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (functionValue->fKind == Expression::kTypeReference_Kind) {
15735b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        return this->convertConstructor(offset,
157411d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas                                        ((TypeReference&) *functionValue).fValue,
1575b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                        std::move(arguments));
1576b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
1577b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (functionValue->fKind != Expression::kFunctionReference_Kind) {
15785b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        fErrors.error(offset, "'" + functionValue->description() + "' is not a function");
1579b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
1580b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
1581b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    FunctionReference* ref = (FunctionReference*) functionValue.get();
1582b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    int bestCost = INT_MAX;
1583d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    const FunctionDeclaration* best = nullptr;
1584b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (ref->fFunctions.size() > 1) {
1585b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        for (const auto& f : ref->fFunctions) {
1586dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas            int cost = this->callCost(*f, arguments);
1587dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas            if (cost < bestCost) {
1588b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                bestCost = cost;
1589b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                best = f;
1590b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            }
1591b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
1592b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        if (best) {
15935b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas            return this->call(offset, *best, std::move(arguments));
1594b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
15950df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas        String msg = "no match for " + ref->fFunctions[0]->fName + "(";
15960df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas        String separator;
1597b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        for (size_t i = 0; i < arguments.size(); i++) {
1598b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            msg += separator;
1599b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            separator = ", ";
1600d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            msg += arguments[i]->fType.description();
1601b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
1602b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        msg += ")";
16035b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        fErrors.error(offset, msg);
1604b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
1605b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
16065b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    return this->call(offset, *ref->fFunctions[0], std::move(arguments));
1607b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
1608b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
160984645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholasstd::unique_ptr<Expression> IRGenerator::convertNumberConstructor(
16105b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                                    int offset,
161111d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas                                                    const Type& type,
1612b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                                    std::vector<std::unique_ptr<Expression>> args) {
161384645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas    ASSERT(type.isNumber());
161484645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas    if (args.size() != 1) {
16155b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        fErrors.error(offset, "invalid arguments to '" + type.description() +
16165b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                              "' constructor, (expected exactly 1 argument, but found " +
16175b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                              to_string((uint64_t) args.size()) + ")");
1618b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
1619b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
1620f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    if (type == args[0]->fType) {
1621dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas        return std::move(args[0]);
1622dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas    }
1623f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    if (type.isFloat() && args.size() == 1 && args[0]->fKind == Expression::kFloatLiteral_Kind) {
1624f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        double value = ((FloatLiteral&) *args[0]).fValue;
1625f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        return std::unique_ptr<Expression>(new FloatLiteral(fContext, offset, value, &type));
1626dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas    }
1627dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas    if (type.isFloat() && args.size() == 1 && args[0]->fKind == Expression::kIntLiteral_Kind) {
1628b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        int64_t value = ((IntLiteral&) *args[0]).fValue;
1629f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        return std::unique_ptr<Expression>(new FloatLiteral(fContext, offset, (double) value,
1630f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas                                                            &type));
1631b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
163284645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas    if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext.fInt_Type ||
163384645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas        type == *fContext.fUInt_Type)) {
163484645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas        return std::unique_ptr<Expression>(new IntLiteral(fContext,
16355b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                                          offset,
163684645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas                                                          ((IntLiteral&) *args[0]).fValue,
163784645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas                                                          &type));
163884645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas    }
163984645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas    if (args[0]->fType == *fContext.fBool_Type) {
16405b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, offset, 0));
16415b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        std::unique_ptr<IntLiteral> one(new IntLiteral(fContext, offset, 1));
164284645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas        return std::unique_ptr<Expression>(
16435b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                     new TernaryExpression(offset, std::move(args[0]),
164484645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas                                                           this->coerce(std::move(one), type),
164584645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas                                                           this->coerce(std::move(zero),
164684645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas                                                                        type)));
164784645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas    }
164884645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas    if (!args[0]->fType.isNumber()) {
16495b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        fErrors.error(offset, "invalid argument to '" + type.description() +
16505b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                              "' constructor (expected a number or bool, but found '" +
16515b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                              args[0]->fType.description() + "')");
165284645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas        return nullptr;
1653b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
16545b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
165584645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas}
165684645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas
165784645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholasint component_count(const Type& type) {
165884645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas    switch (type.kind()) {
165984645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas        case Type::kVector_Kind:
166084645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas            return type.columns();
166184645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas        case Type::kMatrix_Kind:
166284645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas            return type.columns() * type.rows();
166384645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas        default:
166484645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas            return 1;
166584645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas    }
166684645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas}
166784645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas
166884645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholasstd::unique_ptr<Expression> IRGenerator::convertCompoundConstructor(
16695b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                                    int offset,
167084645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas                                                    const Type& type,
167184645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas                                                    std::vector<std::unique_ptr<Expression>> args) {
167284645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas    ASSERT(type.kind() == Type::kVector_Kind || type.kind() == Type::kMatrix_Kind);
167384645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas    if (type.kind() == Type::kMatrix_Kind && args.size() == 1 &&
167484645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas        args[0]->fType.kind() == Type::kMatrix_Kind) {
167584645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas        // matrix from matrix is always legal
16765b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
167784645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas    }
167884645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas    int actual = 0;
167984645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas    int expected = type.rows() * type.columns();
168084645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas    if (args.size() != 1 || expected != component_count(args[0]->fType) ||
168184645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas        type.componentType().isNumber() != args[0]->fType.componentType().isNumber()) {
168249a36ba6234168ef3b591f55810c22bf0fe1c2e4Ethan Nicholas        for (size_t i = 0; i < args.size(); i++) {
168384645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas            if (args[i]->fType.kind() == Type::kVector_Kind) {
168449a36ba6234168ef3b591f55810c22bf0fe1c2e4Ethan Nicholas                if (type.componentType().isNumber() !=
168549a36ba6234168ef3b591f55810c22bf0fe1c2e4Ethan Nicholas                    args[i]->fType.componentType().isNumber()) {
16865b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                    fErrors.error(offset, "'" + args[i]->fType.description() + "' is not a valid "
16875b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                          "parameter to '" + type.description() +
16885b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                          "' constructor");
168949a36ba6234168ef3b591f55810c22bf0fe1c2e4Ethan Nicholas                    return nullptr;
169049a36ba6234168ef3b591f55810c22bf0fe1c2e4Ethan Nicholas                }
169184645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas                actual += args[i]->fType.columns();
169249a36ba6234168ef3b591f55810c22bf0fe1c2e4Ethan Nicholas            } else if (args[i]->fType.kind() == Type::kScalar_Kind) {
169349a36ba6234168ef3b591f55810c22bf0fe1c2e4Ethan Nicholas                actual += 1;
169449a36ba6234168ef3b591f55810c22bf0fe1c2e4Ethan Nicholas                if (type.kind() != Type::kScalar_Kind) {
169549a36ba6234168ef3b591f55810c22bf0fe1c2e4Ethan Nicholas                    args[i] = this->coerce(std::move(args[i]), type.componentType());
169649a36ba6234168ef3b591f55810c22bf0fe1c2e4Ethan Nicholas                    if (!args[i]) {
169749a36ba6234168ef3b591f55810c22bf0fe1c2e4Ethan Nicholas                        return nullptr;
169849a36ba6234168ef3b591f55810c22bf0fe1c2e4Ethan Nicholas                    }
169949a36ba6234168ef3b591f55810c22bf0fe1c2e4Ethan Nicholas                }
170049a36ba6234168ef3b591f55810c22bf0fe1c2e4Ethan Nicholas            } else {
17015b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                fErrors.error(offset, "'" + args[i]->fType.description() + "' is not a valid "
17025b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                      "parameter to '" + type.description() + "' constructor");
170349a36ba6234168ef3b591f55810c22bf0fe1c2e4Ethan Nicholas                return nullptr;
170449a36ba6234168ef3b591f55810c22bf0fe1c2e4Ethan Nicholas            }
170549a36ba6234168ef3b591f55810c22bf0fe1c2e4Ethan Nicholas        }
170684645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas        if (actual != 1 && actual != expected) {
17075b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas            fErrors.error(offset, "invalid arguments to '" + type.description() +
17085b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                  "' constructor (expected " + to_string(expected) +
17095b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                  " scalars, but found " + to_string(actual) + ")");
171049a36ba6234168ef3b591f55810c22bf0fe1c2e4Ethan Nicholas            return nullptr;
171149a36ba6234168ef3b591f55810c22bf0fe1c2e4Ethan Nicholas        }
1712b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
17135b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
1714b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
1715b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
171684645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholasstd::unique_ptr<Expression> IRGenerator::convertConstructor(
17175b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                                    int offset,
171884645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas                                                    const Type& type,
171984645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas                                                    std::vector<std::unique_ptr<Expression>> args) {
172084645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas    // FIXME: add support for structs
172184645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas    Type::Kind kind = type.kind();
172284645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas    if (args.size() == 1 && args[0]->fType == type) {
172384645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas        // argument is already the right type, just return it
172484645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas        return std::move(args[0]);
172584645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas    }
172684645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas    if (type.isNumber()) {
17275b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        return this->convertNumberConstructor(offset, type, std::move(args));
172884645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas    } else if (kind == Type::kArray_Kind) {
172984645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas        const Type& base = type.componentType();
173084645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas        for (size_t i = 0; i < args.size(); i++) {
173184645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas            args[i] = this->coerce(std::move(args[i]), base);
173284645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas            if (!args[i]) {
173384645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas                return nullptr;
173484645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas            }
173584645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas        }
17365b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
173784645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas    } else if (kind == Type::kVector_Kind || kind == Type::kMatrix_Kind) {
17385b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        return this->convertCompoundConstructor(offset, type, std::move(args));
173984645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas    } else {
17405b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        fErrors.error(offset, "cannot construct '" + type.description() + "'");
174184645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas        return nullptr;
174284645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas    }
174384645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas}
174484645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas
1745b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Expression> IRGenerator::convertPrefixExpression(
1746b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                                            const ASTPrefixExpression& expression) {
1747b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    std::unique_ptr<Expression> base = this->convertExpression(*expression.fOperand);
1748b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (!base) {
1749b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
1750b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
1751b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    switch (expression.fOperator) {
1752b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case Token::PLUS:
1753d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) {
17545b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                fErrors.error(expression.fOffset,
1755d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                              "'+' cannot operate on '" + base->fType.description() + "'");
1756b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                return nullptr;
1757b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            }
1758b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            return base;
1759b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case Token::MINUS:
1760d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) {
17615b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                fErrors.error(expression.fOffset,
1762d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                              "'-' cannot operate on '" + base->fType.description() + "'");
1763b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                return nullptr;
1764b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            }
1765b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            if (base->fKind == Expression::kIntLiteral_Kind) {
17665b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                return std::unique_ptr<Expression>(new IntLiteral(fContext, base->fOffset,
1767b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                                                  -((IntLiteral&) *base).fValue));
1768b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            }
1769b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            if (base->fKind == Expression::kFloatLiteral_Kind) {
1770b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                double value = -((FloatLiteral&) *base).fValue;
17715b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                return std::unique_ptr<Expression>(new FloatLiteral(fContext, base->fOffset,
1772d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                                                                    value));
1773b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            }
1774b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            return std::unique_ptr<Expression>(new PrefixExpression(Token::MINUS, std::move(base)));
1775b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case Token::PLUSPLUS:
1776d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            if (!base->fType.isNumber()) {
17775b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                fErrors.error(expression.fOffset,
17785b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                              String("'") + Compiler::OperatorName(expression.fOperator) +
1779d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                              "' cannot operate on '" + base->fType.description() + "'");
1780b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                return nullptr;
1781b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            }
178286a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas            this->markWrittenTo(*base, true);
1783b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            break;
178411d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas        case Token::MINUSMINUS:
1785d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            if (!base->fType.isNumber()) {
17865b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                fErrors.error(expression.fOffset,
17875b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                              String("'") + Compiler::OperatorName(expression.fOperator) +
1788d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                              "' cannot operate on '" + base->fType.description() + "'");
1789b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                return nullptr;
1790b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            }
179186a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas            this->markWrittenTo(*base, true);
1792b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            break;
17935961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas        case Token::LOGICALNOT:
1794d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            if (base->fType != *fContext.fBool_Type) {
17955b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                fErrors.error(expression.fOffset,
17965b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                              String("'") + Compiler::OperatorName(expression.fOperator) +
1797d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                              "' cannot operate on '" + base->fType.description() + "'");
1798b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                return nullptr;
1799b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            }
180008a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            if (base->fKind == Expression::kBoolLiteral_Kind) {
18015b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                return std::unique_ptr<Expression>(new BoolLiteral(fContext, base->fOffset,
180208a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas                                                                   !((BoolLiteral&) *base).fValue));
180308a9211a8492a84e1f4a6899759f8f37ed5aec3eethannicholas            }
1804b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            break;
18055961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas        case Token::BITWISENOT:
18065961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas            if (base->fType != *fContext.fInt_Type) {
18075b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                fErrors.error(expression.fOffset,
18085b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                              String("'") + Compiler::OperatorName(expression.fOperator) +
18095961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas                              "' cannot operate on '" + base->fType.description() + "'");
18105961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas                return nullptr;
18115961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas            }
18125961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas            break;
181311d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas        default:
1814b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            ABORT("unsupported prefix operator\n");
1815b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
181611d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas    return std::unique_ptr<Expression>(new PrefixExpression(expression.fOperator,
1817b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                                            std::move(base)));
1818b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
1819b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
1820b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression> base,
1821b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                                      const ASTExpression& index) {
182250afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas    if (base->fKind == Expression::kTypeReference_Kind) {
182350afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas        if (index.fKind == ASTExpression::kInt_Kind) {
182450afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas            const Type& oldType = ((TypeReference&) *base).fValue;
182550afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas            int64_t size = ((const ASTIntLiteral&) index).fValue;
182650afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas            Type* newType = new Type(oldType.name() + "[" + to_string(size) + "]",
182750afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas                                     Type::kArray_Kind, oldType, size);
182850afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas            fSymbolTable->takeOwnership(newType);
18295b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas            return std::unique_ptr<Expression>(new TypeReference(fContext, base->fOffset,
183050afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas                                                                 *newType));
183150afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas
183250afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas        } else {
18335b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas            fErrors.error(base->fOffset, "array size must be a constant");
183450afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas            return nullptr;
183550afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas        }
183650afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas    }
18375961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas    if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::kMatrix_Kind &&
18385961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas            base->fType.kind() != Type::kVector_Kind) {
18395b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        fErrors.error(base->fOffset, "expected array, but found '" + base->fType.description() +
18405b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                     "'");
1841b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
1842b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
1843b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    std::unique_ptr<Expression> converted = this->convertExpression(index);
1844b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (!converted) {
1845b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
1846b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
18475961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas    if (converted->fType != *fContext.fUInt_Type) {
18485961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas        converted = this->coerce(std::move(converted), *fContext.fInt_Type);
18495961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas        if (!converted) {
18505961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas            return nullptr;
18515961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas        }
1852b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
185311d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas    return std::unique_ptr<Expression>(new IndexExpression(fContext, std::move(base),
1854d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                                                           std::move(converted)));
1855b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
1856b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
1857b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Expression> IRGenerator::convertField(std::unique_ptr<Expression> base,
18585b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                                      StringFragment field) {
1859d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    auto fields = base->fType.fields();
1860b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    for (size_t i = 0; i < fields.size(); i++) {
1861b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        if (fields[i].fName == field) {
1862b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            return std::unique_ptr<Expression>(new FieldAccess(std::move(base), (int) i));
1863b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
1864b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
18655b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    fErrors.error(base->fOffset, "type '" + base->fType.description() + "' does not have a "
18665b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                 "field named '" + field + "");
1867b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    return nullptr;
1868b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
1869b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
1870b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expression> base,
18715b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                                        StringFragment fields) {
1872d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    if (base->fType.kind() != Type::kVector_Kind) {
18735b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        fErrors.error(base->fOffset, "cannot swizzle type '" + base->fType.description() + "'");
1874b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
1875b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
1876b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    std::vector<int> swizzleComponents;
18775b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    for (size_t i = 0; i < fields.fLength; i++) {
18789e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas        switch (fields[i]) {
1879b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            case 'x': // fall through
1880b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            case 'r': // fall through
188111d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas            case 's':
1882b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                swizzleComponents.push_back(0);
1883b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                break;
1884b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            case 'y': // fall through
1885b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            case 'g': // fall through
1886b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            case 't':
1887d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                if (base->fType.columns() >= 2) {
1888b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                    swizzleComponents.push_back(1);
1889b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                    break;
1890b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                }
1891b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                // fall through
1892b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            case 'z': // fall through
1893b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            case 'b': // fall through
189411d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas            case 'p':
1895d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                if (base->fType.columns() >= 3) {
1896b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                    swizzleComponents.push_back(2);
1897b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                    break;
1898b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                }
1899b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                // fall through
1900b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            case 'w': // fall through
1901b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            case 'a': // fall through
1902b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            case 'q':
1903d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                if (base->fType.columns() >= 4) {
1904b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                    swizzleComponents.push_back(3);
1905b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                    break;
1906b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                }
1907b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                // fall through
1908b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            default:
19095b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                fErrors.error(base->fOffset, String::printf("invalid swizzle component '%c'",
19105b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                                            fields[i]));
1911b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                return nullptr;
1912b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
1913b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
1914b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    ASSERT(swizzleComponents.size() > 0);
1915b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (swizzleComponents.size() > 4) {
19165b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        fErrors.error(base->fOffset, "too many components in swizzle mask '" + fields + "'");
1917b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
1918b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
1919d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    return std::unique_ptr<Expression>(new Swizzle(fContext, std::move(base), swizzleComponents));
1920b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
1921b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
19225b5f096a038259b8d9084834f877588a0db80250Ethan Nicholasstd::unique_ptr<Expression> IRGenerator::getCap(int offset, String name) {
1923941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas    auto found = fCapsMap.find(name);
1924941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas    if (found == fCapsMap.end()) {
19255b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        fErrors.error(offset, "unknown capability flag '" + name + "'");
19263605ace7ddaf0b576bf6df1c7a550ab4f44d22a8Ethan Nicholas        return nullptr;
19273605ace7ddaf0b576bf6df1c7a550ab4f44d22a8Ethan Nicholas    }
1928762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas    String fullName = "sk_Caps." + name;
19295b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    return std::unique_ptr<Expression>(new Setting(offset, fullName,
19305b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                                   found->second.literal(fContext, offset)));
1931762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas}
1932762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas
19335b5f096a038259b8d9084834f877588a0db80250Ethan Nicholasstd::unique_ptr<Expression> IRGenerator::getArg(int offset, String name) {
1934762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas    auto found = fSettings->fArgs.find(name);
1935762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas    if (found == fSettings->fArgs.end()) {
19365b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas        fErrors.error(offset, "unknown argument '" + name + "'");
1937762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas        return nullptr;
19383605ace7ddaf0b576bf6df1c7a550ab4f44d22a8Ethan Nicholas    }
1939762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas    String fullName = "sk_Args." + name;
19405b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    return std::unique_ptr<Expression>(new Setting(offset,
1941762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas                                                   fullName,
19425b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                                   found->second.literal(fContext, offset)));
19433605ace7ddaf0b576bf6df1c7a550ab4f44d22a8Ethan Nicholas}
19443605ace7ddaf0b576bf6df1c7a550ab4f44d22a8Ethan Nicholas
1945aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholasstd::unique_ptr<Expression> IRGenerator::convertTypeField(int offset, const Type& type,
1946aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                                                          StringFragment field) {
1947aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas    std::unique_ptr<Expression> result;
1948aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas    for (const auto& e : *fProgramElements) {
1949aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas        if (e->fKind == ProgramElement::kEnum_Kind && type.name() == ((Enum&) *e).fTypeName) {
1950aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            std::shared_ptr<SymbolTable> old = fSymbolTable;
1951aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            fSymbolTable = ((Enum&) *e).fSymbols;
1952aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            result = convertIdentifier(ASTIdentifier(offset, field));
1953aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            fSymbolTable = old;
1954aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas        }
1955aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas    }
1956aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas    if (!result) {
1957aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas        fErrors.error(offset, "type '" + type.fName + "' does not have a field named '" + field +
1958aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                              "'");
1959aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas    }
1960aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas    return result;
1961aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas}
1962aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas
1963b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstd::unique_ptr<Expression> IRGenerator::convertSuffixExpression(
1964b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                                            const ASTSuffixExpression& expression) {
1965b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    std::unique_ptr<Expression> base = this->convertExpression(*expression.fBase);
1966b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    if (!base) {
1967b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return nullptr;
1968b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
1969b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    switch (expression.fSuffix->fKind) {
19705961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas        case ASTSuffix::kIndex_Kind: {
19715961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas            const ASTExpression* expr = ((ASTIndexSuffix&) *expression.fSuffix).fExpression.get();
19725961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas            if (expr) {
19735961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas                return this->convertIndex(std::move(base), *expr);
19745961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas            } else if (base->fKind == Expression::kTypeReference_Kind) {
19755961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas                const Type& oldType = ((TypeReference&) *base).fValue;
197611d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas                Type* newType = new Type(oldType.name() + "[]", Type::kArray_Kind, oldType,
19775961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas                                         -1);
19785961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas                fSymbolTable->takeOwnership(newType);
19795b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                return std::unique_ptr<Expression>(new TypeReference(fContext, base->fOffset,
19805961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas                                                                     *newType));
19815961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas            } else {
19825b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                fErrors.error(expression.fOffset, "'[]' must follow a type name");
1983a54401da547def2e6e058df3ee2a03a843fb40aeethannicholas                return nullptr;
19845961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas            }
19855961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas        }
1986b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case ASTSuffix::kCall_Kind: {
1987b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            auto rawArguments = &((ASTCallSuffix&) *expression.fSuffix).fArguments;
1988b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            std::vector<std::unique_ptr<Expression>> arguments;
1989b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            for (size_t i = 0; i < rawArguments->size(); i++) {
199011d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas                std::unique_ptr<Expression> converted =
1991b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                        this->convertExpression(*(*rawArguments)[i]);
1992b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                if (!converted) {
1993b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                    return nullptr;
1994b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                }
1995b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                arguments.push_back(std::move(converted));
1996b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            }
19975b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas            return this->call(expression.fOffset, std::move(base), std::move(arguments));
1998b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
1999b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case ASTSuffix::kField_Kind: {
2000aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            StringFragment field = ((ASTFieldSuffix&) *expression.fSuffix).fField;
20013605ace7ddaf0b576bf6df1c7a550ab4f44d22a8Ethan Nicholas            if (base->fType == *fContext.fSkCaps_Type) {
2002aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                return this->getCap(expression.fOffset, field);
20033605ace7ddaf0b576bf6df1c7a550ab4f44d22a8Ethan Nicholas            }
2004762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas            if (base->fType == *fContext.fSkArgs_Type) {
2005aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                return this->getArg(expression.fOffset, field);
2006aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            }
2007aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            if (base->fKind == Expression::kTypeReference_Kind) {
2008aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                return this->convertTypeField(base->fOffset, ((TypeReference&) *base).fValue,
2009aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                                              field);
2010762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas            }
2011d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            switch (base->fType.kind()) {
2012b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                case Type::kVector_Kind:
2013aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                    return this->convertSwizzle(std::move(base), field);
2014b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                case Type::kStruct_Kind:
2015aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                    return this->convertField(std::move(base), field);
2016b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                default:
20175b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                    fErrors.error(base->fOffset, "cannot swizzle value of type '" +
20185b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                                 base->fType.description() + "'");
2019b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                    return nullptr;
2020b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            }
2021b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
2022b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case ASTSuffix::kPostIncrement_Kind:
2023d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            if (!base->fType.isNumber()) {
20245b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                fErrors.error(expression.fOffset,
2025d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                              "'++' cannot operate on '" + base->fType.description() + "'");
2026b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                return nullptr;
2027b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            }
202886a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas            this->markWrittenTo(*base, true);
202911d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas            return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
2030b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                                                     Token::PLUSPLUS));
2031b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case ASTSuffix::kPostDecrement_Kind:
2032d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            if (!base->fType.isNumber()) {
20335b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                fErrors.error(expression.fOffset,
2034d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas                              "'--' cannot operate on '" + base->fType.description() + "'");
2035b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                return nullptr;
2036b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            }
203786a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas            this->markWrittenTo(*base, true);
203811d53974317fa29cc516075382e658ddd45fc151Ethan Nicholas            return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
2039b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                                                                     Token::MINUSMINUS));
2040b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        default:
2041b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            ABORT("unsupported suffix operator");
2042b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
2043b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
2044b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
2045b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasvoid IRGenerator::checkValid(const Expression& expr) {
2046b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    switch (expr.fKind) {
2047b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case Expression::kFunctionReference_Kind:
20485b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas            fErrors.error(expr.fOffset, "expected '(' to begin function call");
2049b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            break;
2050b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case Expression::kTypeReference_Kind:
20515b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas            fErrors.error(expr.fOffset, "expected '(' to begin constructor invocation");
2052b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            break;
2053b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        default:
2054ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas            if (expr.fType == *fContext.fInvalid_Type) {
20555b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                fErrors.error(expr.fOffset, "invalid expression");
2056ea4567c1b080361b43eb0f52bb63e33f858baf94ethannicholas            }
2057b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
2058b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
2059b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
2060b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstatic bool has_duplicates(const Swizzle& swizzle) {
2061b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    int bits = 0;
2062b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    for (int idx : swizzle.fComponents) {
2063b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        ASSERT(idx >= 0 && idx <= 3);
2064b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        int bit = 1 << idx;
2065b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        if (bits & bit) {
2066b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            return true;
2067b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
2068b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        bits |= bit;
2069b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
2070b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    return false;
2071b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
2072b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
207386a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholasvoid IRGenerator::markWrittenTo(const Expression& expr, bool readWrite) {
2074b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    switch (expr.fKind) {
2075b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case Expression::kVariableReference_Kind: {
2076d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas            const Variable& var = ((VariableReference&) expr).fVariable;
2077b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            if (var.fModifiers.fFlags & (Modifiers::kConst_Flag | Modifiers::kUniform_Flag)) {
20785b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                fErrors.error(expr.fOffset,
2079b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                              "cannot modify immutable variable '" + var.fName + "'");
2080b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            }
208186a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas            ((VariableReference&) expr).setRefKind(readWrite ? VariableReference::kReadWrite_RefKind
208286a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas                                                             : VariableReference::kWrite_RefKind);
2083b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            break;
2084b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        }
2085b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case Expression::kFieldAccess_Kind:
208686a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas            this->markWrittenTo(*((FieldAccess&) expr).fBase, readWrite);
2087b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            break;
2088b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case Expression::kSwizzle_Kind:
2089b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            if (has_duplicates((Swizzle&) expr)) {
20905b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                fErrors.error(expr.fOffset,
2091b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas                              "cannot write to the same swizzle field more than once");
2092b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            }
209386a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas            this->markWrittenTo(*((Swizzle&) expr).fBase, readWrite);
2094b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            break;
2095b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        case Expression::kIndex_Kind:
209686a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas            this->markWrittenTo(*((IndexExpression&) expr).fBase, readWrite);
2097b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            break;
2098a583b813b9f1e2904d6f9f6cb487b9e477d2bde4Ethan Nicholas        case Expression::kTernary_Kind: {
2099a583b813b9f1e2904d6f9f6cb487b9e477d2bde4Ethan Nicholas            TernaryExpression& t = (TernaryExpression&) expr;
2100a583b813b9f1e2904d6f9f6cb487b9e477d2bde4Ethan Nicholas            this->markWrittenTo(*t.fIfTrue, readWrite);
2101a583b813b9f1e2904d6f9f6cb487b9e477d2bde4Ethan Nicholas            this->markWrittenTo(*t.fIfFalse, readWrite);
2102a583b813b9f1e2904d6f9f6cb487b9e477d2bde4Ethan Nicholas            break;
2103a583b813b9f1e2904d6f9f6cb487b9e477d2bde4Ethan Nicholas        }
2104b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        default:
21055b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas            fErrors.error(expr.fOffset, "cannot assign to '" + expr.description() + "'");
2106b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas            break;
2107b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
2108b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
2109b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
2110fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillipsvoid IRGenerator::convertProgram(Program::Kind kind,
2111fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips                                 const char* text,
21125b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas                                 size_t length,
21137da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                                 SymbolTable& types,
21147da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                                 std::vector<std::unique_ptr<ProgramElement>>* out) {
2115fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips    fKind = kind;
2116aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas    fProgramElements = out;
21175b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    Parser parser(text, length, types, fErrors);
21187da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    std::vector<std::unique_ptr<ASTDeclaration>> parsed = parser.file();
21197da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    if (fErrors.errorCount()) {
21207da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas        return;
21217da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    }
21227da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    for (size_t i = 0; i < parsed.size(); i++) {
21237da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas        ASTDeclaration& decl = *parsed[i];
21247da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas        switch (decl.fKind) {
21257da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas            case ASTDeclaration::kVar_Kind: {
21267da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                std::unique_ptr<VarDeclarations> s = this->convertVarDeclarations(
21277da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                                                                         (ASTVarDeclarations&) decl,
21287da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                                                                         Variable::kGlobal_Storage);
21297da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                if (s) {
2130aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                    fProgramElements->push_back(std::move(s));
21317da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                }
21327da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                break;
21337da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas            }
2134aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            case ASTDeclaration::kEnum_Kind: {
2135aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                this->convertEnum((ASTEnum&) decl);
2136aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                break;
2137aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas            }
21387da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas            case ASTDeclaration::kFunction_Kind: {
2139aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                this->convertFunction((ASTFunction&) decl);
21407da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                break;
21417da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas            }
21427da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas            case ASTDeclaration::kModifiers_Kind: {
21437da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                std::unique_ptr<ModifiersDeclaration> f = this->convertModifiersDeclaration(
21447da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                                                                   (ASTModifiersDeclaration&) decl);
21457da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                if (f) {
2146aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                    fProgramElements->push_back(std::move(f));
21477da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                }
21487da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                break;
21497da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas            }
21507da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas            case ASTDeclaration::kInterfaceBlock_Kind: {
21517da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                std::unique_ptr<InterfaceBlock> i = this->convertInterfaceBlock(
21527da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                                                                         (ASTInterfaceBlock&) decl);
21537da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                if (i) {
2154aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                    fProgramElements->push_back(std::move(i));
21557da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                }
21567da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                break;
21577da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas            }
21587da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas            case ASTDeclaration::kExtension_Kind: {
21597da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                std::unique_ptr<Extension> e = this->convertExtension((ASTExtension&) decl);
21607da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                if (e) {
2161aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                    fProgramElements->push_back(std::move(e));
21627da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                }
21637da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                break;
21647da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas            }
2165762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas            case ASTDeclaration::kSection_Kind: {
2166762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas                std::unique_ptr<Section> s = this->convertSection((ASTSection&) decl);
2167762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas                if (s) {
2168aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas                    fProgramElements->push_back(std::move(s));
2169762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas                }
2170762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas                break;
2171762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas            }
21727da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas            default:
21737da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas                ABORT("unsupported declaration: %s\n", decl.description().c_str());
21747da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas        }
21757da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas    }
21767da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas}
21777da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas
21787da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas
2179b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}
2180