SkSLCompiler.cpp revision 5af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64
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 */ 76ad9909fb7ccc973f35bbd222b0f424b8c3df0d2Mike Klein 8b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "SkSLCompiler.h" 9b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas#include "SkSLCFGGenerator.h" 11762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas#include "SkSLCPPCodeGenerator.h" 12941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas#include "SkSLGLSLCodeGenerator.h" 13762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas#include "SkSLHCodeGenerator.h" 14b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "SkSLIRGenerator.h" 15b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "SkSLSPIRVCodeGenerator.h" 16b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLExpression.h" 17cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas#include "ir/SkSLExpressionStatement.h" 18b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLIntLiteral.h" 195961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas#include "ir/SkSLModifiersDeclaration.h" 20cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas#include "ir/SkSLNop.h" 21b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLSymbolTable.h" 22cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas#include "ir/SkSLTernaryExpression.h" 23ddb37d67ba4db42fa5c6012b58d0f4985b454dc0ethannicholas#include "ir/SkSLUnresolvedFunction.h" 2422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas#include "ir/SkSLVarDeclarations.h" 25b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 26a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas#ifdef SK_ENABLE_SPIRV_VALIDATION 27a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas#include "spirv-tools/libspirv.hpp" 28a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas#endif 29a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas 30b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#define STRINGIFY(x) #x 31b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 32b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas// include the built-in shader symbols as static strings 33b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 345961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholasstatic const char* SKSL_INCLUDE = 35b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "sksl.include" 36b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas; 37b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 385961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholasstatic const char* SKSL_VERT_INCLUDE = 39b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "sksl_vert.include" 40b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas; 41b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 425961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholasstatic const char* SKSL_FRAG_INCLUDE = 43b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "sksl_frag.include" 44b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas; 45b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 4652cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholasstatic const char* SKSL_GEOM_INCLUDE = 4752cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas#include "sksl_geom.include" 4852cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas; 4952cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas 50762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholasstatic const char* SKSL_FP_INCLUDE = 51762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas#include "sksl_fp.include" 52762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas; 53762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas 54762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas 55b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasnamespace SkSL { 56b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 576e1cbc012b10e99d9caed19eef43939778d1d8ffEthan NicholasCompiler::Compiler(Flags flags) 586e1cbc012b10e99d9caed19eef43939778d1d8ffEthan Nicholas: fFlags(flags) 596e1cbc012b10e99d9caed19eef43939778d1d8ffEthan Nicholas, fErrorCount(0) { 608feeff929e57ea63914213f3b14d8f00b287a0adEthan Nicholas auto types = std::shared_ptr<SymbolTable>(new SymbolTable(this)); 618feeff929e57ea63914213f3b14d8f00b287a0adEthan Nicholas auto symbols = std::shared_ptr<SymbolTable>(new SymbolTable(types, this)); 62d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fIRGenerator = new IRGenerator(&fContext, symbols, *this); 63b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fTypes = types; 64d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas #define ADD_TYPE(t) types->addWithoutOwnership(fContext.f ## t ## _Type->fName, \ 65d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fContext.f ## t ## _Type.get()) 66b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Void); 67b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Float); 685af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Float2); 695af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Float3); 705af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Float4); 71b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Double); 725af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Double2); 735af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Double3); 745af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Double4); 75b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Int); 765af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Int2); 775af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Int3); 785af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Int4); 79b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(UInt); 805af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(UInt2); 815af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(UInt3); 825af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(UInt4); 83b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Bool); 845af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Bool2); 855af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Bool3); 865af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Bool4); 875af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Float2x2); 885af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Float2x3); 895af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Float2x4); 905af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Float3x2); 915af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Float3x3); 925af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Float3x4); 935af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Float4x2); 945af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Float4x3); 955af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Float4x4); 96b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GenType); 97b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GenDType); 98b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GenIType); 99b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GenUType); 100b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GenBType); 101b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Mat); 102b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Vec); 103b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GVec); 104b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GVec2); 105b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GVec3); 106b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GVec4); 107b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(DVec); 108b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(IVec); 109b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(UVec); 110b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(BVec); 111b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 112b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Sampler1D); 113b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Sampler2D); 114b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Sampler3D); 1155961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas ADD_TYPE(SamplerExternalOES); 116b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(SamplerCube); 117b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Sampler2DRect); 118b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Sampler1DArray); 119b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Sampler2DArray); 120b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(SamplerCubeArray); 121b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(SamplerBuffer); 122b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Sampler2DMS); 123b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Sampler2DMSArray); 124b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 125bf7b620b1e44985b164a8bd68031a7613fe0bb9bBrian Salomon ADD_TYPE(ISampler2D); 126bf7b620b1e44985b164a8bd68031a7613fe0bb9bBrian Salomon 1272a51de82ceb6790f329b9f4cc85e61f34fc2d0d4Brian Salomon ADD_TYPE(Image2D); 1282a51de82ceb6790f329b9f4cc85e61f34fc2d0d4Brian Salomon ADD_TYPE(IImage2D); 1292a51de82ceb6790f329b9f4cc85e61f34fc2d0d4Brian Salomon 13064773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel ADD_TYPE(SubpassInput); 13164773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel ADD_TYPE(SubpassInputMS); 13264773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel 133b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GSampler1D); 134b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GSampler2D); 135b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GSampler3D); 136b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GSamplerCube); 137b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GSampler2DRect); 138b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GSampler1DArray); 139b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GSampler2DArray); 140b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GSamplerCubeArray); 141b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GSamplerBuffer); 142b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GSampler2DMS); 143b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GSampler2DMSArray); 144b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 145b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Sampler1DShadow); 146b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Sampler2DShadow); 147b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(SamplerCubeShadow); 148b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Sampler2DRectShadow); 149b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Sampler1DArrayShadow); 150b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Sampler2DArrayShadow); 151b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(SamplerCubeArrayShadow); 152b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GSampler2DArrayShadow); 153b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GSamplerCubeArrayShadow); 154762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas ADD_TYPE(ColorSpaceXform); 155b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1560df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas String skCapsName("sk_Caps"); 1570df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas Variable* skCaps = new Variable(Position(), Modifiers(), skCapsName, 1583605ace7ddaf0b576bf6df1c7a550ab4f44d22a8Ethan Nicholas *fContext.fSkCaps_Type, Variable::kGlobal_Storage); 1593605ace7ddaf0b576bf6df1c7a550ab4f44d22a8Ethan Nicholas fIRGenerator->fSymbolTable->add(skCapsName, std::unique_ptr<Symbol>(skCaps)); 1603605ace7ddaf0b576bf6df1c7a550ab4f44d22a8Ethan Nicholas 161762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas String skArgsName("sk_Args"); 162762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas Variable* skArgs = new Variable(Position(), Modifiers(), skArgsName, 163762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas *fContext.fSkArgs_Type, Variable::kGlobal_Storage); 164762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas fIRGenerator->fSymbolTable->add(skArgsName, std::unique_ptr<Symbol>(skArgs)); 165762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas 1665961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas Modifiers::Flag ignored1; 1675961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas std::vector<std::unique_ptr<ProgramElement>> ignored2; 1687da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas fIRGenerator->convertProgram(String(SKSL_INCLUDE), *fTypes, &ignored1, &ignored2); 169ddb37d67ba4db42fa5c6012b58d0f4985b454dc0ethannicholas fIRGenerator->fSymbolTable->markAllFunctionsBuiltin(); 170b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(!fErrorCount); 171b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 172b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 173b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasCompiler::~Compiler() { 174b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas delete fIRGenerator; 175b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 176b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 17722f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas// add the definition created by assigning to the lvalue to the definition set 17886a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholasvoid Compiler::addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr, 17986a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas DefinitionMap* definitions) { 18022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas switch (lvalue->fKind) { 18122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas case Expression::kVariableReference_Kind: { 18222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas const Variable& var = ((VariableReference*) lvalue)->fVariable; 18322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas if (var.fStorage == Variable::kLocal_Storage) { 18422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas (*definitions)[&var] = expr; 18522f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 18622f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas break; 18722f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 18822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas case Expression::kSwizzle_Kind: 18922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas // We consider the variable written to as long as at least some of its components have 19022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas // been written to. This will lead to some false negatives (we won't catch it if you 19122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas // write to foo.x and then read foo.y), but being stricter could lead to false positives 1926ad9909fb7ccc973f35bbd222b0f424b8c3df0d2Mike Klein // (we write to foo.x, and then pass foo to a function which happens to only read foo.x, 1936ad9909fb7ccc973f35bbd222b0f424b8c3df0d2Mike Klein // but since we pass foo as a whole it is flagged as an error) unless we perform a much 19422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas // more complicated whole-program analysis. This is probably good enough. 1956ad9909fb7ccc973f35bbd222b0f424b8c3df0d2Mike Klein this->addDefinition(((Swizzle*) lvalue)->fBase.get(), 19686a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas (std::unique_ptr<Expression>*) &fContext.fDefined_Expression, 19722f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas definitions); 19822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas break; 19922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas case Expression::kIndex_Kind: 20022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas // see comments in Swizzle 2016ad9909fb7ccc973f35bbd222b0f424b8c3df0d2Mike Klein this->addDefinition(((IndexExpression*) lvalue)->fBase.get(), 20286a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas (std::unique_ptr<Expression>*) &fContext.fDefined_Expression, 20322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas definitions); 20422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas break; 20522f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas case Expression::kFieldAccess_Kind: 20622f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas // see comments in Swizzle 2076ad9909fb7ccc973f35bbd222b0f424b8c3df0d2Mike Klein this->addDefinition(((FieldAccess*) lvalue)->fBase.get(), 20886a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas (std::unique_ptr<Expression>*) &fContext.fDefined_Expression, 20922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas definitions); 21022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas break; 21122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas default: 21222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas // not an lvalue, can't happen 21322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas ASSERT(false); 21422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 21522f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas} 21622f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas 21722f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas// add local variables defined by this node to the set 2186ad9909fb7ccc973f35bbd222b0f424b8c3df0d2Mike Kleinvoid Compiler::addDefinitions(const BasicBlock::Node& node, 21986a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas DefinitionMap* definitions) { 22022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas switch (node.fKind) { 22122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas case BasicBlock::Node::kExpression_Kind: { 222cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas ASSERT(node.expression()); 223cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas const Expression* expr = (Expression*) node.expression()->get(); 22486a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas switch (expr->fKind) { 22586a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas case Expression::kBinary_Kind: { 22686a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas BinaryExpression* b = (BinaryExpression*) expr; 22786a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas if (b->fOperator == Token::EQ) { 22886a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas this->addDefinition(b->fLeft.get(), &b->fRight, definitions); 22986a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas } else if (Token::IsAssignment(b->fOperator)) { 23086a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas this->addDefinition( 23186a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas b->fLeft.get(), 23286a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas (std::unique_ptr<Expression>*) &fContext.fDefined_Expression, 23386a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas definitions); 23486a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas 23586a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas } 23686a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas break; 23786a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas } 23886a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas case Expression::kPrefix_Kind: { 23986a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas const PrefixExpression* p = (PrefixExpression*) expr; 24086a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas if (p->fOperator == Token::MINUSMINUS || p->fOperator == Token::PLUSPLUS) { 24186a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas this->addDefinition( 24286a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas p->fOperand.get(), 24386a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas (std::unique_ptr<Expression>*) &fContext.fDefined_Expression, 24486a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas definitions); 24586a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas } 24686a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas break; 24722f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 24886a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas case Expression::kPostfix_Kind: { 24986a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas const PostfixExpression* p = (PostfixExpression*) expr; 25086a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas if (p->fOperator == Token::MINUSMINUS || p->fOperator == Token::PLUSPLUS) { 25186a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas this->addDefinition( 25286a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas p->fOperand.get(), 25386a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas (std::unique_ptr<Expression>*) &fContext.fDefined_Expression, 25486a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas definitions); 25586a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas } 25686a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas break; 25786a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas } 258cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Expression::kVariableReference_Kind: { 259cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas const VariableReference* v = (VariableReference*) expr; 260cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (v->fRefKind != VariableReference::kRead_RefKind) { 261cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas this->addDefinition( 262cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas v, 263cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas (std::unique_ptr<Expression>*) &fContext.fDefined_Expression, 264cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas definitions); 265cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 266cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 26786a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas default: 26886a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas break; 26922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 27022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas break; 27122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 27222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas case BasicBlock::Node::kStatement_Kind: { 273cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas const Statement* stmt = (Statement*) node.statement()->get(); 274b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas if (stmt->fKind == Statement::kVarDeclaration_Kind) { 275b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas VarDeclaration& vd = (VarDeclaration&) *stmt; 276b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas if (vd.fValue) { 277b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas (*definitions)[vd.fVar] = &vd.fValue; 27822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 27922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 28022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas break; 28122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 28222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 28322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas} 28422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas 28522f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholasvoid Compiler::scanCFG(CFG* cfg, BlockId blockId, std::set<BlockId>* workList) { 28622f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas BasicBlock& block = cfg->fBlocks[blockId]; 28722f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas 28822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas // compute definitions after this block 28986a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas DefinitionMap after = block.fBefore; 29022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas for (const BasicBlock::Node& n : block.fNodes) { 29122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas this->addDefinitions(n, &after); 29222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 29322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas 29422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas // propagate definitions to exits 29522f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas for (BlockId exitId : block.fExits) { 29622f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas BasicBlock& exit = cfg->fBlocks[exitId]; 29722f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas for (const auto& pair : after) { 29886a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas std::unique_ptr<Expression>* e1 = pair.second; 29986a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas auto found = exit.fBefore.find(pair.first); 30086a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas if (found == exit.fBefore.end()) { 30186a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas // exit has no definition for it, just copy it 30286a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas workList->insert(exitId); 30322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas exit.fBefore[pair.first] = e1; 30422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } else { 30586a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas // exit has a (possibly different) value already defined 30686a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas std::unique_ptr<Expression>* e2 = exit.fBefore[pair.first]; 30722f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas if (e1 != e2) { 30822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas // definition has changed, merge and add exit block to worklist 30922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas workList->insert(exitId); 310af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas if (e1 && e2) { 311af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas exit.fBefore[pair.first] = 31286a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas (std::unique_ptr<Expression>*) &fContext.fDefined_Expression; 313af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas } else { 314af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas exit.fBefore[pair.first] = nullptr; 315af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas } 31622f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 31722f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 31822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 31922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 32022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas} 32122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas 32222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas// returns a map which maps all local variables in the function to null, indicating that their value 32322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas// is initially unknown 32486a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholasstatic DefinitionMap compute_start_state(const CFG& cfg) { 32586a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas DefinitionMap result; 3266ad9909fb7ccc973f35bbd222b0f424b8c3df0d2Mike Klein for (const auto& block : cfg.fBlocks) { 3276ad9909fb7ccc973f35bbd222b0f424b8c3df0d2Mike Klein for (const auto& node : block.fNodes) { 32822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas if (node.fKind == BasicBlock::Node::kStatement_Kind) { 329cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas ASSERT(node.statement()); 330cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas const Statement* s = node.statement()->get(); 33122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas if (s->fKind == Statement::kVarDeclarations_Kind) { 33222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas const VarDeclarationsStatement* vd = (const VarDeclarationsStatement*) s; 333cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas for (const auto& decl : vd->fDeclaration->fVars) { 33491a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas if (decl->fKind == Statement::kVarDeclaration_Kind) { 33591a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas result[((VarDeclaration&) *decl).fVar] = nullptr; 33691a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas } 3376ad9909fb7ccc973f35bbd222b0f424b8c3df0d2Mike Klein } 33822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 33922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 34022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 34122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 34222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas return result; 34322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas} 34422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas 345cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas/** 346cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas * Returns true if assigning to this lvalue has no effect. 347cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas */ 348cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholasstatic bool is_dead(const Expression& lvalue) { 349cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas switch (lvalue.fKind) { 350cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Expression::kVariableReference_Kind: 351cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas return ((VariableReference&) lvalue).fVariable.dead(); 352cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Expression::kSwizzle_Kind: 353cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas return is_dead(*((Swizzle&) lvalue).fBase); 354cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Expression::kFieldAccess_Kind: 355cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas return is_dead(*((FieldAccess&) lvalue).fBase); 356cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Expression::kIndex_Kind: { 357cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas const IndexExpression& idx = (IndexExpression&) lvalue; 358cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas return is_dead(*idx.fBase) && !idx.fIndex->hasSideEffects(); 359cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 360cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas default: 361cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas ABORT("invalid lvalue: %s\n", lvalue.description().c_str()); 362cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 363cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas} 364cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas 365cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas/** 366cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas * Returns true if this is an assignment which can be collapsed down to just the right hand side due 367cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas * to a dead target and lack of side effects on the left hand side. 368cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas */ 369cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholasstatic bool dead_assignment(const BinaryExpression& b) { 370cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (!Token::IsAssignment(b.fOperator)) { 371cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas return false; 372cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 373cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas return is_dead(*b.fLeft); 374cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas} 37522f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas 376cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholasvoid Compiler::computeDataFlow(CFG* cfg) { 377cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas cfg->fBlocks[cfg->fStart].fBefore = compute_start_state(*cfg); 37822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas std::set<BlockId> workList; 379cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas for (BlockId i = 0; i < cfg->fBlocks.size(); i++) { 38022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas workList.insert(i); 38122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 38222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas while (workList.size()) { 38322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas BlockId next = *workList.begin(); 38422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas workList.erase(workList.begin()); 385cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas this->scanCFG(cfg, next, &workList); 386cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 387cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas} 388cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas 389cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas/** 390cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas * Attempts to replace the expression pointed to by iter with a new one (in both the CFG and the 391cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas * IR). If the expression can be cleanly removed, returns true and updates the iterator to point to 392cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas * the newly-inserted element. Otherwise updates only the IR and returns false (and the CFG will 393cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas * need to be regenerated). 394cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas */ 395cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholasbool try_replace_expression(BasicBlock* b, 396cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas std::vector<BasicBlock::Node>::iterator* iter, 397cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas std::unique_ptr<Expression>* newExpression) { 398cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas std::unique_ptr<Expression>* target = (*iter)->expression(); 399cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (!b->tryRemoveExpression(iter)) { 400cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *target = std::move(*newExpression); 401cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas return false; 402cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 403cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *target = std::move(*newExpression); 404cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas return b->tryInsertExpression(iter, target); 405cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas} 406cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas 407cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas/** 408fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas * Returns true if the expression is a constant numeric literal with the specified value, or a 409fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas * constant vector with all elements equal to the specified value. 410cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas */ 411fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholasbool is_constant(const Expression& expr, double value) { 412cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas switch (expr.fKind) { 413cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Expression::kIntLiteral_Kind: 414cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas return ((IntLiteral&) expr).fValue == value; 415cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Expression::kFloatLiteral_Kind: 416cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas return ((FloatLiteral&) expr).fValue == value; 417fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas case Expression::kConstructor_Kind: { 418fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas Constructor& c = (Constructor&) expr; 419fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (c.fType.kind() == Type::kVector_Kind && c.isConstant()) { 420fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas for (int i = 0; i < c.fType.columns(); ++i) { 421fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (!is_constant(c.getVecComponent(i), value)) { 422fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas return false; 423fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 424fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 425fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas return true; 426fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 427fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas return false; 428fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 429cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas default: 430cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas return false; 431cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 432cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas} 433cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas 434cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas/** 435cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas * Collapses the binary expression pointed to by iter down to just the right side (in both the IR 436cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas * and CFG structures). 437cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas */ 438cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholasvoid delete_left(BasicBlock* b, 439cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas std::vector<BasicBlock::Node>::iterator* iter, 440cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas bool* outUpdated, 441cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas bool* outNeedsRescan) { 442cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *outUpdated = true; 443c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas std::unique_ptr<Expression>* target = (*iter)->expression(); 444c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas ASSERT((*target)->fKind == Expression::kBinary_Kind); 445c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas BinaryExpression& bin = (BinaryExpression&) **target; 446c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas bool result; 447c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas if (bin.fOperator == Token::EQ) { 4484b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas result = b->tryRemoveLValueBefore(iter, bin.fLeft.get()); 449c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas } else { 4504b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas result = b->tryRemoveExpressionBefore(iter, bin.fLeft.get()); 451c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas } 4524b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas *target = std::move(bin.fRight); 453c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas if (!result) { 4544b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas *outNeedsRescan = true; 4554b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas return; 4564b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas } 4574b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas if (*iter == b->fNodes.begin()) { 458cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *outNeedsRescan = true; 459c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas return; 460cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 461c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas --(*iter); 4624b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas if ((*iter)->fKind != BasicBlock::Node::kExpression_Kind || 4634b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas (*iter)->expression() != &bin.fRight) { 4644b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas *outNeedsRescan = true; 4654b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas return; 4664b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas } 467c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas *iter = b->fNodes.erase(*iter); 468c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas ASSERT((*iter)->expression() == target); 469cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas} 470cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas 471cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas/** 472cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas * Collapses the binary expression pointed to by iter down to just the left side (in both the IR and 473cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas * CFG structures). 474cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas */ 475cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholasvoid delete_right(BasicBlock* b, 476cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas std::vector<BasicBlock::Node>::iterator* iter, 477cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas bool* outUpdated, 478cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas bool* outNeedsRescan) { 479cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *outUpdated = true; 480c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas std::unique_ptr<Expression>* target = (*iter)->expression(); 481c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas ASSERT((*target)->fKind == Expression::kBinary_Kind); 482c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas BinaryExpression& bin = (BinaryExpression&) **target; 483c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas if (!b->tryRemoveExpressionBefore(iter, bin.fRight.get())) { 484c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas *target = std::move(bin.fLeft); 485cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *outNeedsRescan = true; 486c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas return; 487cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 4884b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas *target = std::move(bin.fLeft); 4894b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas if (*iter == b->fNodes.begin()) { 4904b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas *outNeedsRescan = true; 4914b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas return; 4924b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas } 493c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas --(*iter); 4944b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas if (((*iter)->fKind != BasicBlock::Node::kExpression_Kind || 4954b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas (*iter)->expression() != &bin.fLeft)) { 4964b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas *outNeedsRescan = true; 4974b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas return; 4984b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas } 499c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas *iter = b->fNodes.erase(*iter); 500c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas ASSERT((*iter)->expression() == target); 501cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas} 502cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas 503fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas/** 504fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas * Constructs the specified type using a single argument. 505fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas */ 506fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholasstatic std::unique_ptr<Expression> construct(const Type& type, std::unique_ptr<Expression> v) { 507fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas std::vector<std::unique_ptr<Expression>> args; 508fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas args.push_back(std::move(v)); 509fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas auto result = std::unique_ptr<Expression>(new Constructor(Position(), type, std::move(args))); 510fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas return result; 511fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas} 512fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas 513fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas/** 514fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas * Used in the implementations of vectorize_left and vectorize_right. Given a vector type and an 515fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas * expression x, deletes the expression pointed to by iter and replaces it with <type>(x). 516fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas */ 517fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholasstatic void vectorize(BasicBlock* b, 518fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas std::vector<BasicBlock::Node>::iterator* iter, 519fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas const Type& type, 520fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas std::unique_ptr<Expression>* otherExpression, 521fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bool* outUpdated, 522fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bool* outNeedsRescan) { 523fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas ASSERT((*(*iter)->expression())->fKind == Expression::kBinary_Kind); 524fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas ASSERT(type.kind() == Type::kVector_Kind); 525fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas ASSERT((*otherExpression)->fType.kind() == Type::kScalar_Kind); 526fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas *outUpdated = true; 527fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas std::unique_ptr<Expression>* target = (*iter)->expression(); 528fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (!b->tryRemoveExpression(iter)) { 529fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas *target = construct(type, std::move(*otherExpression)); 530fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas *outNeedsRescan = true; 531fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } else { 532fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas *target = construct(type, std::move(*otherExpression)); 533fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (!b->tryInsertExpression(iter, target)) { 534fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas *outNeedsRescan = true; 535fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 536fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 537fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas} 538fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas 539fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas/** 540fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas * Given a binary expression of the form x <op> vec<n>(y), deletes the right side and vectorizes the 541fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas * left to yield vec<n>(x). 542fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas */ 543fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholasstatic void vectorize_left(BasicBlock* b, 544fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas std::vector<BasicBlock::Node>::iterator* iter, 545fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bool* outUpdated, 546fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bool* outNeedsRescan) { 547fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas BinaryExpression& bin = (BinaryExpression&) **(*iter)->expression(); 548fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas vectorize(b, iter, bin.fRight->fType, &bin.fLeft, outUpdated, outNeedsRescan); 549fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas} 550fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas 551fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas/** 552fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas * Given a binary expression of the form vec<n>(x) <op> y, deletes the left side and vectorizes the 553fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas * right to yield vec<n>(y). 554fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas */ 555fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholasstatic void vectorize_right(BasicBlock* b, 556fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas std::vector<BasicBlock::Node>::iterator* iter, 557fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bool* outUpdated, 558fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bool* outNeedsRescan) { 559fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas BinaryExpression& bin = (BinaryExpression&) **(*iter)->expression(); 560fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas vectorize(b, iter, bin.fLeft->fType, &bin.fRight, outUpdated, outNeedsRescan); 561fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas} 562fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas 563fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas// Mark that an expression which we were writing to is no longer being written to 564fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholasvoid clear_write(const Expression& expr) { 565fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas switch (expr.fKind) { 566fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas case Expression::kVariableReference_Kind: { 567fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas ((VariableReference&) expr).setRefKind(VariableReference::kRead_RefKind); 568fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas break; 569fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 570fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas case Expression::kFieldAccess_Kind: 571fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas clear_write(*((FieldAccess&) expr).fBase); 572fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas break; 573fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas case Expression::kSwizzle_Kind: 574fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas clear_write(*((Swizzle&) expr).fBase); 575fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas break; 576fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas case Expression::kIndex_Kind: 577fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas clear_write(*((IndexExpression&) expr).fBase); 578fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas break; 579fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas default: 580fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas ABORT("shouldn't be writing to this kind of expression\n"); 581fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas break; 582fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 583fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas} 584fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas 585cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholasvoid Compiler::simplifyExpression(DefinitionMap& definitions, 586cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas BasicBlock& b, 587cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas std::vector<BasicBlock::Node>::iterator* iter, 588cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas std::unordered_set<const Variable*>* undefinedVariables, 589cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas bool* outUpdated, 590cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas bool* outNeedsRescan) { 591cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas Expression* expr = (*iter)->expression()->get(); 592cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas ASSERT(expr); 593cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if ((*iter)->fConstantPropagation) { 594cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas std::unique_ptr<Expression> optimized = expr->constantPropagate(*fIRGenerator, definitions); 595cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (optimized) { 5964b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas *outUpdated = true; 597cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (!try_replace_expression(&b, iter, &optimized)) { 598cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *outNeedsRescan = true; 5994b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas return; 600cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 601cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas ASSERT((*iter)->fKind == BasicBlock::Node::kExpression_Kind); 602cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas expr = (*iter)->expression()->get(); 603cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 604cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 605cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas switch (expr->fKind) { 606cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Expression::kVariableReference_Kind: { 607cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas const Variable& var = ((VariableReference*) expr)->fVariable; 608cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (var.fStorage == Variable::kLocal_Storage && !definitions[&var] && 609cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas (*undefinedVariables).find(&var) == (*undefinedVariables).end()) { 610cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas (*undefinedVariables).insert(&var); 611cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas this->error(expr->fPosition, 612cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas "'" + var.fName + "' has not been assigned"); 613cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 614cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas break; 615cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 616cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Expression::kTernary_Kind: { 617cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas TernaryExpression* t = (TernaryExpression*) expr; 618cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (t->fTest->fKind == Expression::kBoolLiteral_Kind) { 619cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas // ternary has a constant test, replace it with either the true or 620cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas // false branch 621cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (((BoolLiteral&) *t->fTest).fValue) { 622cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas (*iter)->setExpression(std::move(t->fIfTrue)); 623cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } else { 624cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas (*iter)->setExpression(std::move(t->fIfFalse)); 625cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 626cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *outUpdated = true; 627cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *outNeedsRescan = true; 628cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 629cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas break; 630cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 631cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Expression::kBinary_Kind: { 632cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas BinaryExpression* bin = (BinaryExpression*) expr; 633c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas if (dead_assignment(*bin)) { 634c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas delete_left(&b, iter, outUpdated, outNeedsRescan); 635c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas break; 636c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas } 637c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas // collapse useless expressions like x * 1 or x + 0 638fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (((bin->fLeft->fType.kind() != Type::kScalar_Kind) && 639fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas (bin->fLeft->fType.kind() != Type::kVector_Kind)) || 640fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas ((bin->fRight->fType.kind() != Type::kScalar_Kind) && 641fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas (bin->fRight->fType.kind() != Type::kVector_Kind))) { 642fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas break; 643fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 644cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas switch (bin->fOperator) { 645cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Token::STAR: 646cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (is_constant(*bin->fLeft, 1)) { 647fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (bin->fLeft->fType.kind() == Type::kVector_Kind && 648fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bin->fRight->fType.kind() == Type::kScalar_Kind) { 6495af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(1) * x -> float4(x) 650fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas vectorize_right(&b, iter, outUpdated, outNeedsRescan); 651fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } else { 652fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas // 1 * x -> x 6535af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // 1 * float4(x) -> float4(x) 6545af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(1) * float4(x) -> float4(x) 655fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas delete_left(&b, iter, outUpdated, outNeedsRescan); 656fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 657fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 658fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas else if (is_constant(*bin->fLeft, 0)) { 659fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (bin->fLeft->fType.kind() == Type::kScalar_Kind && 660fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bin->fRight->fType.kind() == Type::kVector_Kind) { 6615af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // 0 * float4(x) -> float4(0) 662fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas vectorize_left(&b, iter, outUpdated, outNeedsRescan); 663fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } else { 664fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas // 0 * x -> 0 6655af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(0) * x -> float4(0) 6665af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(0) * float4(x) -> float4(0) 667fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas delete_right(&b, iter, outUpdated, outNeedsRescan); 668fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 669cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 670cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas else if (is_constant(*bin->fRight, 1)) { 671fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (bin->fLeft->fType.kind() == Type::kScalar_Kind && 672fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bin->fRight->fType.kind() == Type::kVector_Kind) { 6735af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // x * float4(1) -> float4(x) 674fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas vectorize_left(&b, iter, outUpdated, outNeedsRescan); 675fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } else { 676fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas // x * 1 -> x 6775af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(x) * 1 -> float4(x) 6785af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(x) * float4(1) -> float4(x) 679fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas delete_right(&b, iter, outUpdated, outNeedsRescan); 680fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 681fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 682fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas else if (is_constant(*bin->fRight, 0)) { 683fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (bin->fLeft->fType.kind() == Type::kVector_Kind && 684fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bin->fRight->fType.kind() == Type::kScalar_Kind) { 6855af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(x) * 0 -> float4(0) 686fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas vectorize_right(&b, iter, outUpdated, outNeedsRescan); 687fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } else { 688fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas // x * 0 -> 0 6895af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // x * float4(0) -> float4(0) 6905af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(x) * float4(0) -> float4(0) 691fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas delete_left(&b, iter, outUpdated, outNeedsRescan); 692fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 693cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 694cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas break; 69556e42714d351f8ecb662136076166904b9934b71Ethan Nicholas case Token::PLUS: 696cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (is_constant(*bin->fLeft, 0)) { 697fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (bin->fLeft->fType.kind() == Type::kVector_Kind && 698fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bin->fRight->fType.kind() == Type::kScalar_Kind) { 6995af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(0) + x -> float4(x) 700fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas vectorize_right(&b, iter, outUpdated, outNeedsRescan); 701fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } else { 702fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas // 0 + x -> x 7035af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // 0 + float4(x) -> float4(x) 7045af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(0) + float4(x) -> float4(x) 705fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas delete_left(&b, iter, outUpdated, outNeedsRescan); 706fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 707fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } else if (is_constant(*bin->fRight, 0)) { 708fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (bin->fLeft->fType.kind() == Type::kScalar_Kind && 709fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bin->fRight->fType.kind() == Type::kVector_Kind) { 7105af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // x + float4(0) -> float4(x) 711fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas vectorize_left(&b, iter, outUpdated, outNeedsRescan); 712fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } else { 713fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas // x + 0 -> x 7145af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(x) + 0 -> float4(x) 7155af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(x) + float4(0) -> float4(x) 716fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas delete_right(&b, iter, outUpdated, outNeedsRescan); 717fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 718cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 719fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas break; 720fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas case Token::MINUS: 72156e42714d351f8ecb662136076166904b9934b71Ethan Nicholas if (is_constant(*bin->fRight, 0)) { 722fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (bin->fLeft->fType.kind() == Type::kScalar_Kind && 723fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bin->fRight->fType.kind() == Type::kVector_Kind) { 7245af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // x - float4(0) -> float4(x) 725fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas vectorize_left(&b, iter, outUpdated, outNeedsRescan); 726fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } else { 727fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas // x - 0 -> x 7285af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(x) - 0 -> float4(x) 7295af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(x) - float4(0) -> float4(x) 730fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas delete_right(&b, iter, outUpdated, outNeedsRescan); 731fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 732fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 733fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas break; 734fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas case Token::SLASH: 735fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (is_constant(*bin->fRight, 1)) { 736fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (bin->fLeft->fType.kind() == Type::kScalar_Kind && 737fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bin->fRight->fType.kind() == Type::kVector_Kind) { 7385af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // x / float4(1) -> float4(x) 739fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas vectorize_left(&b, iter, outUpdated, outNeedsRescan); 740fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } else { 741fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas // x / 1 -> x 7425af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(x) / 1 -> float4(x) 7435af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(x) / float4(1) -> float4(x) 744fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas delete_right(&b, iter, outUpdated, outNeedsRescan); 745fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 746fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } else if (is_constant(*bin->fLeft, 0)) { 747fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (bin->fLeft->fType.kind() == Type::kScalar_Kind && 748fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bin->fRight->fType.kind() == Type::kVector_Kind) { 7495af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // 0 / float4(x) -> float4(0) 750fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas vectorize_left(&b, iter, outUpdated, outNeedsRescan); 751fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } else { 752fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas // 0 / x -> 0 7535af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(0) / x -> float4(0) 7545af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(0) / float4(x) -> float4(0) 755fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas delete_right(&b, iter, outUpdated, outNeedsRescan); 756fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 757fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 758fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas break; 759fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas case Token::PLUSEQ: 760fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (is_constant(*bin->fRight, 0)) { 761fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas clear_write(*bin->fLeft); 76256e42714d351f8ecb662136076166904b9934b71Ethan Nicholas delete_right(&b, iter, outUpdated, outNeedsRescan); 76356e42714d351f8ecb662136076166904b9934b71Ethan Nicholas } 76456e42714d351f8ecb662136076166904b9934b71Ethan Nicholas break; 765fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas case Token::MINUSEQ: 76656e42714d351f8ecb662136076166904b9934b71Ethan Nicholas if (is_constant(*bin->fRight, 0)) { 767fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas clear_write(*bin->fLeft); 768cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas delete_right(&b, iter, outUpdated, outNeedsRescan); 769cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 770cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas break; 771fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas case Token::STAREQ: 772fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (is_constant(*bin->fRight, 1)) { 773fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas clear_write(*bin->fLeft); 774fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas delete_right(&b, iter, outUpdated, outNeedsRescan); 775fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 776fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas break; 777fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas case Token::SLASHEQ: 778cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (is_constant(*bin->fRight, 1)) { 779fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas clear_write(*bin->fLeft); 780cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas delete_right(&b, iter, outUpdated, outNeedsRescan); 781cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 782cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas break; 783cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas default: 784cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas break; 785cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 786cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 787cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas default: 788cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas break; 78922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 790cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas} 791cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas 7925ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas// returns true if this statement could potentially execute a break at the current level (we ignore 7935ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas// nested loops and switches, since any breaks inside of them will merely break the loop / switch) 7945ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholasstatic bool contains_break(Statement& s) { 7955ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas switch (s.fKind) { 7965ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas case Statement::kBlock_Kind: 7975ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas for (const auto& sub : ((Block&) s).fStatements) { 7985ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (contains_break(*sub)) { 7995ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas return true; 8005ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 8015ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 8025ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas return false; 8035ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas case Statement::kBreak_Kind: 8045ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas return true; 8055ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas case Statement::kIf_Kind: { 8065ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas const IfStatement& i = (IfStatement&) s; 8075ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas return contains_break(*i.fIfTrue) || (i.fIfFalse && contains_break(*i.fIfFalse)); 8085ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 8095ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas default: 8105ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas return false; 8115ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 8125ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas} 8135ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas 8145ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas// Returns a block containing all of the statements that will be run if the given case matches 8155ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas// (which, owing to the statements being owned by unique_ptrs, means the switch itself will be 8165ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas// broken by this call and must then be discarded). 8175ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas// Returns null (and leaves the switch unmodified) if no such simple reduction is possible, such as 8185ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas// when break statements appear inside conditionals. 8195ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholasstatic std::unique_ptr<Statement> block_for_case(SwitchStatement* s, SwitchCase* c) { 8205ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas bool capturing = false; 8215ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas std::vector<std::unique_ptr<Statement>*> statementPtrs; 8225ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas for (const auto& current : s->fCases) { 8235ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (current.get() == c) { 8245ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas capturing = true; 8255ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 8265ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (capturing) { 8275ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas for (auto& stmt : current->fStatements) { 8285ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (stmt->fKind == Statement::kBreak_Kind) { 8295ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas capturing = false; 8305ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas break; 8315ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 8325ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (contains_break(*stmt)) { 8335ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas return nullptr; 8345ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 8355ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas statementPtrs.push_back(&stmt); 8365ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 8375ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (!capturing) { 8385ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas break; 8395ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 8405ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 8415ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 8425ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas std::vector<std::unique_ptr<Statement>> statements; 8435ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas for (const auto& s : statementPtrs) { 8445ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas statements.push_back(std::move(*s)); 8455ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 846c432b0ca8a5022d86f0ccf2efd1064ed9fce2e53Ethan Nicholas return std::unique_ptr<Statement>(new Block(Position(), std::move(statements), s->fSymbols)); 8475ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas} 8485ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas 849cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholasvoid Compiler::simplifyStatement(DefinitionMap& definitions, 8505ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas BasicBlock& b, 8515ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas std::vector<BasicBlock::Node>::iterator* iter, 8525ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas std::unordered_set<const Variable*>* undefinedVariables, 8535ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas bool* outUpdated, 8545ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas bool* outNeedsRescan) { 855cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas Statement* stmt = (*iter)->statement()->get(); 856cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas switch (stmt->fKind) { 857b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas case Statement::kVarDeclaration_Kind: { 858b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas const auto& varDecl = (VarDeclaration&) *stmt; 859b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas if (varDecl.fVar->dead() && 860b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas (!varDecl.fValue || 861b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas !varDecl.fValue->hasSideEffects())) { 862b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas if (varDecl.fValue) { 863b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas ASSERT((*iter)->statement()->get() == stmt); 864b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas if (!b.tryRemoveExpressionBefore(iter, varDecl.fValue.get())) { 865b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas *outNeedsRescan = true; 866cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 867cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 868cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas (*iter)->setStatement(std::unique_ptr<Statement>(new Nop())); 869b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas *outUpdated = true; 870cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 871cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas break; 872cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 873cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Statement::kIf_Kind: { 874cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas IfStatement& i = (IfStatement&) *stmt; 8755ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (i.fTest->fKind == Expression::kBoolLiteral_Kind) { 8765ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas // constant if, collapse down to a single branch 8775ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (((BoolLiteral&) *i.fTest).fValue) { 8785ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas ASSERT(i.fIfTrue); 8795ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas (*iter)->setStatement(std::move(i.fIfTrue)); 8805ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } else { 8815ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (i.fIfFalse) { 8825ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas (*iter)->setStatement(std::move(i.fIfFalse)); 8835ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } else { 8845ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas (*iter)->setStatement(std::unique_ptr<Statement>(new Nop())); 8855ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 8865ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 8875ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas *outUpdated = true; 8885ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas *outNeedsRescan = true; 8895ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas break; 8905ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 891cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (i.fIfFalse && i.fIfFalse->isEmpty()) { 892cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas // else block doesn't do anything, remove it 893cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas i.fIfFalse.reset(); 894cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *outUpdated = true; 895cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *outNeedsRescan = true; 896cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 897cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (!i.fIfFalse && i.fIfTrue->isEmpty()) { 898cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas // if block doesn't do anything, no else block 899cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (i.fTest->hasSideEffects()) { 900cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas // test has side effects, keep it 901cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas (*iter)->setStatement(std::unique_ptr<Statement>( 902cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas new ExpressionStatement(std::move(i.fTest)))); 903cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } else { 904cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas // no if, no else, no test side effects, kill the whole if 905cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas // statement 906cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas (*iter)->setStatement(std::unique_ptr<Statement>(new Nop())); 907cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 908cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *outUpdated = true; 909cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *outNeedsRescan = true; 910cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 911cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas break; 912cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 9135ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas case Statement::kSwitch_Kind: { 9145ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas SwitchStatement& s = (SwitchStatement&) *stmt; 9155ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (s.fValue->isConstant()) { 9165ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas // switch is constant, replace it with the case that matches 9175ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas bool found = false; 9185ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas SwitchCase* defaultCase = nullptr; 9195ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas for (const auto& c : s.fCases) { 9205ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (!c->fValue) { 9215ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas defaultCase = c.get(); 9225ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas continue; 9235ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 9245ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas ASSERT(c->fValue->fKind == s.fValue->fKind); 9255ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas found = c->fValue->compareConstant(fContext, *s.fValue); 9265ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (found) { 9275ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas std::unique_ptr<Statement> newBlock = block_for_case(&s, c.get()); 9285ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (newBlock) { 9295ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas (*iter)->setStatement(std::move(newBlock)); 9305ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas break; 9315ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } else { 9326e1cbc012b10e99d9caed19eef43939778d1d8ffEthan Nicholas if (s.fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) { 9335ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas this->error(s.fPosition, 9345ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas "static switch contains non-static conditional break"); 9355ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas s.fIsStatic = false; 9365ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 9375ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas return; // can't simplify 9385ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 9395ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 9405ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 9415ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (!found) { 9425ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas // no matching case. use default if it exists, or kill the whole thing 9435ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (defaultCase) { 9445ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas std::unique_ptr<Statement> newBlock = block_for_case(&s, defaultCase); 9455ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (newBlock) { 9465ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas (*iter)->setStatement(std::move(newBlock)); 9475ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } else { 9486e1cbc012b10e99d9caed19eef43939778d1d8ffEthan Nicholas if (s.fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) { 9495ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas this->error(s.fPosition, 9505ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas "static switch contains non-static conditional break"); 9515ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas s.fIsStatic = false; 9525ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 9535ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas return; // can't simplify 9545ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 9555ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } else { 9565ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas (*iter)->setStatement(std::unique_ptr<Statement>(new Nop())); 9575ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 9585ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 9595ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas *outUpdated = true; 9605ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas *outNeedsRescan = true; 9615ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 9625ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas break; 9635ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 964cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Statement::kExpression_Kind: { 965cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas ExpressionStatement& e = (ExpressionStatement&) *stmt; 966cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas ASSERT((*iter)->statement()->get() == &e); 967cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (!e.fExpression->hasSideEffects()) { 968cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas // Expression statement with no side effects, kill it 969cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (!b.tryRemoveExpressionBefore(iter, e.fExpression.get())) { 970cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *outNeedsRescan = true; 971cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 972cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas ASSERT((*iter)->statement()->get() == stmt); 973cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas (*iter)->setStatement(std::unique_ptr<Statement>(new Nop())); 974cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *outUpdated = true; 975cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 976cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas break; 977cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 978cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas default: 979cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas break; 980cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 981cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas} 982cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas 983cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholasvoid Compiler::scanCFG(FunctionDefinition& f) { 984cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas CFG cfg = CFGGenerator().getCFG(f); 985cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas this->computeDataFlow(&cfg); 98622f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas 98722f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas // check for unreachable code 98822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas for (size_t i = 0; i < cfg.fBlocks.size(); i++) { 9896ad9909fb7ccc973f35bbd222b0f424b8c3df0d2Mike Klein if (i != cfg.fStart && !cfg.fBlocks[i].fEntrances.size() && 99022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas cfg.fBlocks[i].fNodes.size()) { 99186a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas Position p; 99286a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas switch (cfg.fBlocks[i].fNodes[0].fKind) { 99386a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas case BasicBlock::Node::kStatement_Kind: 994cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas p = (*cfg.fBlocks[i].fNodes[0].statement())->fPosition; 99586a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas break; 99686a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas case BasicBlock::Node::kExpression_Kind: 997cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas p = (*cfg.fBlocks[i].fNodes[0].expression())->fPosition; 99886a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas break; 99986a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas } 10000df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas this->error(p, String("unreachable")); 100122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 100222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 100322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas if (fErrorCount) { 100422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas return; 100522f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 100622f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas 1007cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas // check for dead code & undefined variables, perform constant propagation 1008cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas std::unordered_set<const Variable*> undefinedVariables; 1009cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas bool updated; 1010cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas bool needsRescan = false; 1011cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas do { 1012cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (needsRescan) { 1013cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas cfg = CFGGenerator().getCFG(f); 1014cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas this->computeDataFlow(&cfg); 1015cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas needsRescan = false; 1016cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 1017cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas 1018cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas updated = false; 1019cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas for (BasicBlock& b : cfg.fBlocks) { 1020cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas DefinitionMap definitions = b.fBefore; 1021cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas 1022cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas for (auto iter = b.fNodes.begin(); iter != b.fNodes.end() && !needsRescan; ++iter) { 1023cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (iter->fKind == BasicBlock::Node::kExpression_Kind) { 1024cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas this->simplifyExpression(definitions, b, &iter, &undefinedVariables, &updated, 1025cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas &needsRescan); 1026cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } else { 1027cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas this->simplifyStatement(definitions, b, &iter, &undefinedVariables, &updated, 1028cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas &needsRescan); 102922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 10304b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas if (needsRescan) { 10314b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas break; 10324b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas } 1033cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas this->addDefinitions(*iter, &definitions); 103422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 103522f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 1036cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } while (updated); 1037cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas ASSERT(!needsRescan); 103822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas 103991a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas // verify static ifs & switches, clean up dead variable decls 10405ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas for (BasicBlock& b : cfg.fBlocks) { 10415ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas DefinitionMap definitions = b.fBefore; 10425ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas 104391a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas for (auto iter = b.fNodes.begin(); iter != b.fNodes.end() && !needsRescan;) { 10445ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (iter->fKind == BasicBlock::Node::kStatement_Kind) { 10455ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas const Statement& s = **iter->statement(); 10465ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas switch (s.fKind) { 10475ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas case Statement::kIf_Kind: 10486e1cbc012b10e99d9caed19eef43939778d1d8ffEthan Nicholas if (((const IfStatement&) s).fIsStatic && 10496e1cbc012b10e99d9caed19eef43939778d1d8ffEthan Nicholas !(fFlags & kPermitInvalidStaticTests_Flag)) { 10505ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas this->error(s.fPosition, "static if has non-static test"); 10515ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 105291a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas ++iter; 10535ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas break; 10545ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas case Statement::kSwitch_Kind: 10556e1cbc012b10e99d9caed19eef43939778d1d8ffEthan Nicholas if (((const SwitchStatement&) s).fIsStatic && 10566e1cbc012b10e99d9caed19eef43939778d1d8ffEthan Nicholas !(fFlags & kPermitInvalidStaticTests_Flag)) { 10575ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas this->error(s.fPosition, "static switch has non-static test"); 10585ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 105991a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas ++iter; 106091a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas break; 106191a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas case Statement::kVarDeclarations_Kind: { 106291a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas VarDeclarations& decls = *((VarDeclarationsStatement&) s).fDeclaration; 106391a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas for (auto varIter = decls.fVars.begin(); varIter != decls.fVars.end();) { 106491a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas if ((*varIter)->fKind == Statement::kNop_Kind) { 106591a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas varIter = decls.fVars.erase(varIter); 106691a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas } else { 106791a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas ++varIter; 106891a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas } 106991a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas } 107091a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas if (!decls.fVars.size()) { 107191a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas iter = b.fNodes.erase(iter); 107291a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas } else { 107391a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas ++iter; 107491a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas } 10755ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas break; 107691a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas } 10775ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas default: 107891a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas ++iter; 10795ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas break; 10805ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 108191a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas } else { 108291a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas ++iter; 10835ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 10845ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 10855ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 10865ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas 108722f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas // check for missing return 108822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas if (f.fDeclaration.fReturnType != *fContext.fVoid_Type) { 108922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas if (cfg.fBlocks[cfg.fExit].fEntrances.size()) { 10900df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas this->error(f.fPosition, String("function can exit without returning a value")); 109122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 109222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 109322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas} 109422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas 10950df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholasstd::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String text, 1096941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas const Program::Settings& settings) { 1097b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrorText = ""; 1098b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrorCount = 0; 1099941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fIRGenerator->start(&settings); 1100d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas std::vector<std::unique_ptr<ProgramElement>> elements; 11015961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas Modifiers::Flag ignored; 1102b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (kind) { 1103b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Program::kVertex_Kind: 11047da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas fIRGenerator->convertProgram(String(SKSL_VERT_INCLUDE), *fTypes, &ignored, &elements); 1105b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 1106b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Program::kFragment_Kind: 11077da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas fIRGenerator->convertProgram(String(SKSL_FRAG_INCLUDE), *fTypes, &ignored, &elements); 1108b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 110952cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas case Program::kGeometry_Kind: 11107da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas fIRGenerator->convertProgram(String(SKSL_GEOM_INCLUDE), *fTypes, &ignored, &elements); 111152cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas break; 1112762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas case Program::kFragmentProcessor_Kind: 1113762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas fIRGenerator->convertProgram(String(SKSL_FP_INCLUDE), *fTypes, &ignored, &elements); 1114762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas break; 1115b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1116ddb37d67ba4db42fa5c6012b58d0f4985b454dc0ethannicholas fIRGenerator->fSymbolTable->markAllFunctionsBuiltin(); 11175961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas Modifiers::Flag defaultPrecision; 11187da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas fIRGenerator->convertProgram(text, *fTypes, &defaultPrecision, &elements); 11197da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas if (!fErrorCount) { 11207da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas for (auto& element : elements) { 11217da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas if (element->fKind == ProgramElement::kFunction_Kind) { 11227da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas this->scanCFG((FunctionDefinition&) *element); 11237da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas } 11247da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas } 11257da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas } 1126941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas auto result = std::unique_ptr<Program>(new Program(kind, settings, defaultPrecision, &fContext, 1127941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas std::move(elements), 1128941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fIRGenerator->fSymbolTable, 1129941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fIRGenerator->fInputs)); 11303605ace7ddaf0b576bf6df1c7a550ab4f44d22a8Ethan Nicholas fIRGenerator->finish(); 1131b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeErrorCount(); 1132941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (fErrorCount) { 1133941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas return nullptr; 1134941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas } 1135d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return result; 1136b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1137b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 11380df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholasbool Compiler::toSPIRV(const Program& program, OutputStream& out) { 1139a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas#ifdef SK_ENABLE_SPIRV_VALIDATION 11400df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas StringStream buffer; 1141a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas SPIRVCodeGenerator cg(&fContext, &program, this, &buffer); 1142a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas bool result = cg.generateCode(); 1143a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas if (result) { 1144a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0); 1145762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas const String& data = buffer.str(); 1146762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas ASSERT(0 == data.size() % 4); 1147a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas auto dumpmsg = [](spv_message_level_t, const char*, const spv_position_t&, const char* m) { 1148a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas SkDebugf("SPIR-V validation error: %s\n", m); 1149a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas }; 1150a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas tools.SetMessageConsumer(dumpmsg); 1151a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas // Verify that the SPIR-V we produced is valid. If this assert fails, check the logs prior 1152a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas // to the failure to see the validation errors. 1153762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas ASSERT_RESULT(tools.Validate((const uint32_t*) data.c_str(), data.size() / 4)); 1154762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas out.write(data.c_str(), data.size()); 1155a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas } 1156a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas#else 1157941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas SPIRVCodeGenerator cg(&fContext, &program, this, &out); 1158941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas bool result = cg.generateCode(); 1159a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas#endif 1160941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeErrorCount(); 1161b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 1162b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1163b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 11640df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholasbool Compiler::toSPIRV(const Program& program, String* out) { 11650df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas StringStream buffer; 1166941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas bool result = this->toSPIRV(program, buffer); 1167941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (result) { 1168762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas *out = buffer.str(); 1169b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1170941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas return result; 1171b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1172b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 11730df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholasbool Compiler::toGLSL(const Program& program, OutputStream& out) { 1174941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas GLSLCodeGenerator cg(&fContext, &program, this, &out); 1175941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas bool result = cg.generateCode(); 1176941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeErrorCount(); 1177941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas return result; 1178b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1179b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 11800df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholasbool Compiler::toGLSL(const Program& program, String* out) { 11810df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas StringStream buffer; 1182941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas bool result = this->toGLSL(program, buffer); 1183b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (result) { 1184762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas *out = buffer.str(); 1185b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1186f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas return result; 1187f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 1188f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 1189762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholasbool Compiler::toCPP(const Program& program, String name, OutputStream& out) { 1190762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas CPPCodeGenerator cg(&fContext, &program, this, name, &out); 1191762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas bool result = cg.generateCode(); 1192762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas this->writeErrorCount(); 1193762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas return result; 1194762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas} 1195762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas 1196762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholasbool Compiler::toH(const Program& program, String name, OutputStream& out) { 1197762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas HCodeGenerator cg(&program, this, name, &out); 1198762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas bool result = cg.generateCode(); 1199762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas this->writeErrorCount(); 1200762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas return result; 1201762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas} 1202941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas 12030df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholasvoid Compiler::error(Position position, String msg) { 1204941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fErrorCount++; 1205941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fErrorText += "error: " + position.description() + ": " + msg.c_str() + "\n"; 12063605ace7ddaf0b576bf6df1c7a550ab4f44d22a8Ethan Nicholas} 12073605ace7ddaf0b576bf6df1c7a550ab4f44d22a8Ethan Nicholas 12080df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan NicholasString Compiler::errorText() { 12090df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas String result = fErrorText; 1210941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas return result; 1211b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1212b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1213941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholasvoid Compiler::writeErrorCount() { 1214941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (fErrorCount) { 1215941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fErrorText += to_string(fErrorCount) + " error"; 1216941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (fErrorCount > 1) { 1217941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fErrorText += "s"; 1218941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas } 1219941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fErrorText += "\n"; 1220f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 1221f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 1222f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 1223b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} // namespace 1224