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, ¤tValue); 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