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" 15cc3057784b89cdde367fd1d645f1cf69d0eee5f7Ethan Nicholas#include "SkSLMetalCodeGenerator.h" 16b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "SkSLSPIRVCodeGenerator.h" 17aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas#include "ir/SkSLEnum.h" 18b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLExpression.h" 19cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas#include "ir/SkSLExpressionStatement.h" 20b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLIntLiteral.h" 215961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas#include "ir/SkSLModifiersDeclaration.h" 22cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas#include "ir/SkSLNop.h" 23b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLSymbolTable.h" 24cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas#include "ir/SkSLTernaryExpression.h" 25ddb37d67ba4db42fa5c6012b58d0f4985b454dc0ethannicholas#include "ir/SkSLUnresolvedFunction.h" 2622f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas#include "ir/SkSLVarDeclarations.h" 27b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 28a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas#ifdef SK_ENABLE_SPIRV_VALIDATION 29a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas#include "spirv-tools/libspirv.hpp" 30a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas#endif 31a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas 32b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas// include the built-in shader symbols as static strings 33b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 347970765f7db5919ef5c6ad04b1a1bfe6505355c6Ethan Nicholas#define STRINGIFY(x) #x 357970765f7db5919ef5c6ad04b1a1bfe6505355c6Ethan Nicholas 365961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholasstatic const char* SKSL_INCLUDE = 37a56c4d267a877d208311a5326d134824ec987db3Ben Wagner#include "sksl.inc" 38b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas; 39b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 405961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholasstatic const char* SKSL_VERT_INCLUDE = 41a56c4d267a877d208311a5326d134824ec987db3Ben Wagner#include "sksl_vert.inc" 42b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas; 43b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 445961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholasstatic const char* SKSL_FRAG_INCLUDE = 45a56c4d267a877d208311a5326d134824ec987db3Ben Wagner#include "sksl_frag.inc" 46b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas; 47b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 4852cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholasstatic const char* SKSL_GEOM_INCLUDE = 49a56c4d267a877d208311a5326d134824ec987db3Ben Wagner#include "sksl_geom.inc" 5052cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas; 5152cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas 52762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholasstatic const char* SKSL_FP_INCLUDE = 53a56c4d267a877d208311a5326d134824ec987db3Ben Wagner#include "sksl_enums.inc" 54a56c4d267a877d208311a5326d134824ec987db3Ben Wagner#include "sksl_fp.inc" 55762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas; 56762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas 57b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasnamespace SkSL { 58b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 596e1cbc012b10e99d9caed19eef43939778d1d8ffEthan NicholasCompiler::Compiler(Flags flags) 606e1cbc012b10e99d9caed19eef43939778d1d8ffEthan Nicholas: fFlags(flags) 616e1cbc012b10e99d9caed19eef43939778d1d8ffEthan Nicholas, fErrorCount(0) { 628feeff929e57ea63914213f3b14d8f00b287a0adEthan Nicholas auto types = std::shared_ptr<SymbolTable>(new SymbolTable(this)); 638feeff929e57ea63914213f3b14d8f00b287a0adEthan Nicholas auto symbols = std::shared_ptr<SymbolTable>(new SymbolTable(types, this)); 64d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fIRGenerator = new IRGenerator(&fContext, symbols, *this); 65b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fTypes = types; 66d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas #define ADD_TYPE(t) types->addWithoutOwnership(fContext.f ## t ## _Type->fName, \ 67d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fContext.f ## t ## _Type.get()) 68b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Void); 69b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Float); 705af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Float2); 715af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Float3); 725af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Float4); 73dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(Half); 74dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(Half2); 75dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(Half3); 76dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(Half4); 77b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Double); 785af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Double2); 795af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Double3); 805af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Double4); 81b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Int); 825af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Int2); 835af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Int3); 845af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Int4); 85b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(UInt); 865af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(UInt2); 875af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(UInt3); 885af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(UInt4); 89dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(Short); 90dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(Short2); 91dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(Short3); 92dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(Short4); 93dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(UShort); 94dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(UShort2); 95dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(UShort3); 96dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(UShort4); 97b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Bool); 985af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Bool2); 995af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Bool3); 1005af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Bool4); 1015af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Float2x2); 1025af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Float2x3); 1035af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Float2x4); 1045af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Float3x2); 1055af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Float3x3); 1065af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Float3x4); 1075af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Float4x2); 1085af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Float4x3); 1095af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas ADD_TYPE(Float4x4); 110dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(Half2x2); 111dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(Half2x3); 112dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(Half2x4); 113dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(Half3x2); 114dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(Half3x3); 115dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(Half3x4); 116dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(Half4x2); 117dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(Half4x3); 118dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(Half4x4); 119dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(Double2x2); 120dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(Double2x3); 121dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(Double2x4); 122dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(Double3x2); 123dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(Double3x3); 124dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(Double3x4); 125dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(Double4x2); 126dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(Double4x3); 127dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(Double4x4); 128b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GenType); 129dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(GenHType); 130b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GenDType); 131b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GenIType); 132b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GenUType); 133b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GenBType); 134b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Mat); 135b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Vec); 136b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GVec); 137b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GVec2); 138b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GVec3); 139b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GVec4); 140dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(HVec); 141b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(DVec); 142b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(IVec); 143b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(UVec); 144dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(SVec); 145dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas ADD_TYPE(USVec); 146b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(BVec); 147b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 148b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Sampler1D); 149b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Sampler2D); 150b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Sampler3D); 1515961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas ADD_TYPE(SamplerExternalOES); 152b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(SamplerCube); 153b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Sampler2DRect); 154b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Sampler1DArray); 155b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Sampler2DArray); 156b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(SamplerCubeArray); 157b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(SamplerBuffer); 158b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Sampler2DMS); 159b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Sampler2DMSArray); 160b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 161bf7b620b1e44985b164a8bd68031a7613fe0bb9bBrian Salomon ADD_TYPE(ISampler2D); 162bf7b620b1e44985b164a8bd68031a7613fe0bb9bBrian Salomon 1632a51de82ceb6790f329b9f4cc85e61f34fc2d0d4Brian Salomon ADD_TYPE(Image2D); 1642a51de82ceb6790f329b9f4cc85e61f34fc2d0d4Brian Salomon ADD_TYPE(IImage2D); 1652a51de82ceb6790f329b9f4cc85e61f34fc2d0d4Brian Salomon 16664773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel ADD_TYPE(SubpassInput); 16764773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel ADD_TYPE(SubpassInputMS); 16864773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel 169b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GSampler1D); 170b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GSampler2D); 171b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GSampler3D); 172b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GSamplerCube); 173b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GSampler2DRect); 174b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GSampler1DArray); 175b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GSampler2DArray); 176b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GSamplerCubeArray); 177b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GSamplerBuffer); 178b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GSampler2DMS); 179b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GSampler2DMSArray); 180b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 181b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Sampler1DShadow); 182b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Sampler2DShadow); 183b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(SamplerCubeShadow); 184b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Sampler2DRectShadow); 185b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Sampler1DArrayShadow); 186b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(Sampler2DArrayShadow); 187b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(SamplerCubeArrayShadow); 188b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GSampler2DArrayShadow); 189b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ADD_TYPE(GSamplerCubeArrayShadow); 190c9472af8585be3c12691b968b667cde3ca83cae4Ethan Nicholas ADD_TYPE(FragmentProcessor); 191b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1925b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas StringFragment skCapsName("sk_Caps"); 1935b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas Variable* skCaps = new Variable(-1, Modifiers(), skCapsName, 19482a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas *fContext.fSkCaps_Type, Variable::kGlobal_Storage); 1953605ace7ddaf0b576bf6df1c7a550ab4f44d22a8Ethan Nicholas fIRGenerator->fSymbolTable->add(skCapsName, std::unique_ptr<Symbol>(skCaps)); 1963605ace7ddaf0b576bf6df1c7a550ab4f44d22a8Ethan Nicholas 1975b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas StringFragment skArgsName("sk_Args"); 1985b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas Variable* skArgs = new Variable(-1, Modifiers(), skArgsName, 19982a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas *fContext.fSkArgs_Type, Variable::kGlobal_Storage); 200762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas fIRGenerator->fSymbolTable->add(skArgsName, std::unique_ptr<Symbol>(skArgs)); 201762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas 202f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas std::vector<std::unique_ptr<ProgramElement>> ignored; 203fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips fIRGenerator->convertProgram(Program::kFragment_Kind, SKSL_INCLUDE, strlen(SKSL_INCLUDE), 204fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips *fTypes, &ignored); 205ddb37d67ba4db42fa5c6012b58d0f4985b454dc0ethannicholas fIRGenerator->fSymbolTable->markAllFunctionsBuiltin(); 2065b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas if (fErrorCount) { 2075b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas printf("Unexpected errors: %s\n", fErrorText.c_str()); 2085b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas } 209b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(!fErrorCount); 210b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 211b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 212b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasCompiler::~Compiler() { 213b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas delete fIRGenerator; 214b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 215b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 21622f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas// add the definition created by assigning to the lvalue to the definition set 21786a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholasvoid Compiler::addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr, 21886a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas DefinitionMap* definitions) { 21922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas switch (lvalue->fKind) { 22022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas case Expression::kVariableReference_Kind: { 22122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas const Variable& var = ((VariableReference*) lvalue)->fVariable; 22222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas if (var.fStorage == Variable::kLocal_Storage) { 22322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas (*definitions)[&var] = expr; 22422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 22522f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas break; 22622f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 22722f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas case Expression::kSwizzle_Kind: 22822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas // We consider the variable written to as long as at least some of its components have 22922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas // been written to. This will lead to some false negatives (we won't catch it if you 23022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas // write to foo.x and then read foo.y), but being stricter could lead to false positives 2316ad9909fb7ccc973f35bbd222b0f424b8c3df0d2Mike Klein // (we write to foo.x, and then pass foo to a function which happens to only read foo.x, 2326ad9909fb7ccc973f35bbd222b0f424b8c3df0d2Mike Klein // but since we pass foo as a whole it is flagged as an error) unless we perform a much 23322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas // more complicated whole-program analysis. This is probably good enough. 2346ad9909fb7ccc973f35bbd222b0f424b8c3df0d2Mike Klein this->addDefinition(((Swizzle*) lvalue)->fBase.get(), 23586a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas (std::unique_ptr<Expression>*) &fContext.fDefined_Expression, 23622f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas definitions); 23722f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas break; 23822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas case Expression::kIndex_Kind: 23922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas // see comments in Swizzle 2406ad9909fb7ccc973f35bbd222b0f424b8c3df0d2Mike Klein this->addDefinition(((IndexExpression*) lvalue)->fBase.get(), 24186a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas (std::unique_ptr<Expression>*) &fContext.fDefined_Expression, 24222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas definitions); 24322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas break; 24422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas case Expression::kFieldAccess_Kind: 24522f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas // see comments in Swizzle 2466ad9909fb7ccc973f35bbd222b0f424b8c3df0d2Mike Klein this->addDefinition(((FieldAccess*) lvalue)->fBase.get(), 24786a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas (std::unique_ptr<Expression>*) &fContext.fDefined_Expression, 24822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas definitions); 24922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas break; 250a583b813b9f1e2904d6f9f6cb487b9e477d2bde4Ethan Nicholas case Expression::kTernary_Kind: 251a583b813b9f1e2904d6f9f6cb487b9e477d2bde4Ethan Nicholas // To simplify analysis, we just pretend that we write to both sides of the ternary. 252a583b813b9f1e2904d6f9f6cb487b9e477d2bde4Ethan Nicholas // This allows for false positives (meaning we fail to detect that a variable might not 253a583b813b9f1e2904d6f9f6cb487b9e477d2bde4Ethan Nicholas // have been assigned), but is preferable to false negatives. 254a583b813b9f1e2904d6f9f6cb487b9e477d2bde4Ethan Nicholas this->addDefinition(((TernaryExpression*) lvalue)->fIfTrue.get(), 255a583b813b9f1e2904d6f9f6cb487b9e477d2bde4Ethan Nicholas (std::unique_ptr<Expression>*) &fContext.fDefined_Expression, 256a583b813b9f1e2904d6f9f6cb487b9e477d2bde4Ethan Nicholas definitions); 257a583b813b9f1e2904d6f9f6cb487b9e477d2bde4Ethan Nicholas this->addDefinition(((TernaryExpression*) lvalue)->fIfFalse.get(), 258a583b813b9f1e2904d6f9f6cb487b9e477d2bde4Ethan Nicholas (std::unique_ptr<Expression>*) &fContext.fDefined_Expression, 259a583b813b9f1e2904d6f9f6cb487b9e477d2bde4Ethan Nicholas definitions); 260a583b813b9f1e2904d6f9f6cb487b9e477d2bde4Ethan Nicholas break; 26122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas default: 26222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas // not an lvalue, can't happen 26322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas ASSERT(false); 26422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 26522f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas} 26622f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas 26722f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas// add local variables defined by this node to the set 2686ad9909fb7ccc973f35bbd222b0f424b8c3df0d2Mike Kleinvoid Compiler::addDefinitions(const BasicBlock::Node& node, 26986a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas DefinitionMap* definitions) { 27022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas switch (node.fKind) { 27122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas case BasicBlock::Node::kExpression_Kind: { 272cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas ASSERT(node.expression()); 273cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas const Expression* expr = (Expression*) node.expression()->get(); 27486a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas switch (expr->fKind) { 27586a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas case Expression::kBinary_Kind: { 27686a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas BinaryExpression* b = (BinaryExpression*) expr; 27786a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas if (b->fOperator == Token::EQ) { 27886a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas this->addDefinition(b->fLeft.get(), &b->fRight, definitions); 2795b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas } else if (Compiler::IsAssignment(b->fOperator)) { 28086a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas this->addDefinition( 28186a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas b->fLeft.get(), 28286a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas (std::unique_ptr<Expression>*) &fContext.fDefined_Expression, 28386a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas definitions); 28486a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas 28586a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas } 28686a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas break; 28786a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas } 28886a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas case Expression::kPrefix_Kind: { 28986a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas const PrefixExpression* p = (PrefixExpression*) expr; 29086a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas if (p->fOperator == Token::MINUSMINUS || p->fOperator == Token::PLUSPLUS) { 29186a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas this->addDefinition( 29286a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas p->fOperand.get(), 29386a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas (std::unique_ptr<Expression>*) &fContext.fDefined_Expression, 29486a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas definitions); 29586a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas } 29686a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas break; 29722f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 29886a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas case Expression::kPostfix_Kind: { 29986a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas const PostfixExpression* p = (PostfixExpression*) expr; 30086a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas if (p->fOperator == Token::MINUSMINUS || p->fOperator == Token::PLUSPLUS) { 30186a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas this->addDefinition( 30286a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas p->fOperand.get(), 30386a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas (std::unique_ptr<Expression>*) &fContext.fDefined_Expression, 30486a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas definitions); 30586a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas } 30686a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas break; 30786a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas } 308cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Expression::kVariableReference_Kind: { 309cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas const VariableReference* v = (VariableReference*) expr; 310cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (v->fRefKind != VariableReference::kRead_RefKind) { 311cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas this->addDefinition( 312cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas v, 313cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas (std::unique_ptr<Expression>*) &fContext.fDefined_Expression, 314cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas definitions); 315cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 316cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 31786a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas default: 31886a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas break; 31922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 32022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas break; 32122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 32222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas case BasicBlock::Node::kStatement_Kind: { 323cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas const Statement* stmt = (Statement*) node.statement()->get(); 32482a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas if (stmt->fKind == Statement::kVarDeclaration_Kind) { 32582a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas VarDeclaration& vd = (VarDeclaration&) *stmt; 32682a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas if (vd.fValue) { 32782a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas (*definitions)[vd.fVar] = &vd.fValue; 32822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 32922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 33022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas break; 33122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 33222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 33322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas} 33422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas 33522f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholasvoid Compiler::scanCFG(CFG* cfg, BlockId blockId, std::set<BlockId>* workList) { 33622f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas BasicBlock& block = cfg->fBlocks[blockId]; 33722f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas 33822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas // compute definitions after this block 33986a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas DefinitionMap after = block.fBefore; 34022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas for (const BasicBlock::Node& n : block.fNodes) { 34122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas this->addDefinitions(n, &after); 34222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 34322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas 34422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas // propagate definitions to exits 34522f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas for (BlockId exitId : block.fExits) { 34622f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas BasicBlock& exit = cfg->fBlocks[exitId]; 34722f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas for (const auto& pair : after) { 34886a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas std::unique_ptr<Expression>* e1 = pair.second; 34986a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas auto found = exit.fBefore.find(pair.first); 35086a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas if (found == exit.fBefore.end()) { 35186a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas // exit has no definition for it, just copy it 35286a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas workList->insert(exitId); 35322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas exit.fBefore[pair.first] = e1; 35422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } else { 35586a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas // exit has a (possibly different) value already defined 35686a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas std::unique_ptr<Expression>* e2 = exit.fBefore[pair.first]; 35722f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas if (e1 != e2) { 35822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas // definition has changed, merge and add exit block to worklist 35922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas workList->insert(exitId); 360af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas if (e1 && e2) { 361af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas exit.fBefore[pair.first] = 36286a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas (std::unique_ptr<Expression>*) &fContext.fDefined_Expression; 363af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas } else { 364af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas exit.fBefore[pair.first] = nullptr; 365af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas } 36622f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 36722f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 36822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 36922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 37022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas} 37122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas 37222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas// returns a map which maps all local variables in the function to null, indicating that their value 37322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas// is initially unknown 37486a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholasstatic DefinitionMap compute_start_state(const CFG& cfg) { 37586a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas DefinitionMap result; 3766ad9909fb7ccc973f35bbd222b0f424b8c3df0d2Mike Klein for (const auto& block : cfg.fBlocks) { 3776ad9909fb7ccc973f35bbd222b0f424b8c3df0d2Mike Klein for (const auto& node : block.fNodes) { 37822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas if (node.fKind == BasicBlock::Node::kStatement_Kind) { 379cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas ASSERT(node.statement()); 380cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas const Statement* s = node.statement()->get(); 38122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas if (s->fKind == Statement::kVarDeclarations_Kind) { 38222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas const VarDeclarationsStatement* vd = (const VarDeclarationsStatement*) s; 38382a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas for (const auto& decl : vd->fDeclaration->fVars) { 38482a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas if (decl->fKind == Statement::kVarDeclaration_Kind) { 38582a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas result[((VarDeclaration&) *decl).fVar] = nullptr; 38682a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas } 3876ad9909fb7ccc973f35bbd222b0f424b8c3df0d2Mike Klein } 38822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 38922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 39022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 39122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 39222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas return result; 39322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas} 39422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas 395cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas/** 396cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas * Returns true if assigning to this lvalue has no effect. 397cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas */ 398cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholasstatic bool is_dead(const Expression& lvalue) { 399cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas switch (lvalue.fKind) { 400cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Expression::kVariableReference_Kind: 401cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas return ((VariableReference&) lvalue).fVariable.dead(); 402cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Expression::kSwizzle_Kind: 403cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas return is_dead(*((Swizzle&) lvalue).fBase); 404cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Expression::kFieldAccess_Kind: 405cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas return is_dead(*((FieldAccess&) lvalue).fBase); 406cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Expression::kIndex_Kind: { 407cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas const IndexExpression& idx = (IndexExpression&) lvalue; 408cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas return is_dead(*idx.fBase) && !idx.fIndex->hasSideEffects(); 409cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 410a583b813b9f1e2904d6f9f6cb487b9e477d2bde4Ethan Nicholas case Expression::kTernary_Kind: { 411a583b813b9f1e2904d6f9f6cb487b9e477d2bde4Ethan Nicholas const TernaryExpression& t = (TernaryExpression&) lvalue; 412a583b813b9f1e2904d6f9f6cb487b9e477d2bde4Ethan Nicholas return !t.fTest->hasSideEffects() && is_dead(*t.fIfTrue) && is_dead(*t.fIfFalse); 413a583b813b9f1e2904d6f9f6cb487b9e477d2bde4Ethan Nicholas } 414cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas default: 415cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas ABORT("invalid lvalue: %s\n", lvalue.description().c_str()); 416cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 417cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas} 418cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas 419cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas/** 420cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas * Returns true if this is an assignment which can be collapsed down to just the right hand side due 421cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas * to a dead target and lack of side effects on the left hand side. 422cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas */ 423cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholasstatic bool dead_assignment(const BinaryExpression& b) { 4245b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas if (!Compiler::IsAssignment(b.fOperator)) { 425cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas return false; 426cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 427cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas return is_dead(*b.fLeft); 428cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas} 42922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas 430cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholasvoid Compiler::computeDataFlow(CFG* cfg) { 431cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas cfg->fBlocks[cfg->fStart].fBefore = compute_start_state(*cfg); 43222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas std::set<BlockId> workList; 433cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas for (BlockId i = 0; i < cfg->fBlocks.size(); i++) { 43422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas workList.insert(i); 43522f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 43622f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas while (workList.size()) { 43722f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas BlockId next = *workList.begin(); 43822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas workList.erase(workList.begin()); 439cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas this->scanCFG(cfg, next, &workList); 440cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 441cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas} 442cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas 443cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas/** 444cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas * Attempts to replace the expression pointed to by iter with a new one (in both the CFG and the 445cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas * IR). If the expression can be cleanly removed, returns true and updates the iterator to point to 446cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas * the newly-inserted element. Otherwise updates only the IR and returns false (and the CFG will 447cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas * need to be regenerated). 448cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas */ 449cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholasbool try_replace_expression(BasicBlock* b, 450cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas std::vector<BasicBlock::Node>::iterator* iter, 451cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas std::unique_ptr<Expression>* newExpression) { 452cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas std::unique_ptr<Expression>* target = (*iter)->expression(); 453cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (!b->tryRemoveExpression(iter)) { 454cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *target = std::move(*newExpression); 455cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas return false; 456cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 457cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *target = std::move(*newExpression); 458cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas return b->tryInsertExpression(iter, target); 459cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas} 460cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas 461cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas/** 462fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas * Returns true if the expression is a constant numeric literal with the specified value, or a 463fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas * constant vector with all elements equal to the specified value. 464cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas */ 465fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholasbool is_constant(const Expression& expr, double value) { 466cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas switch (expr.fKind) { 467cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Expression::kIntLiteral_Kind: 468cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas return ((IntLiteral&) expr).fValue == value; 469cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Expression::kFloatLiteral_Kind: 470cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas return ((FloatLiteral&) expr).fValue == value; 471fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas case Expression::kConstructor_Kind: { 472fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas Constructor& c = (Constructor&) expr; 473fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (c.fType.kind() == Type::kVector_Kind && c.isConstant()) { 474fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas for (int i = 0; i < c.fType.columns(); ++i) { 475fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (!is_constant(c.getVecComponent(i), value)) { 476fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas return false; 477fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 478fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 479fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas return true; 480fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 481fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas return false; 482fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 483cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas default: 484cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas return false; 485cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 486cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas} 487cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas 488cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas/** 489cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas * Collapses the binary expression pointed to by iter down to just the right side (in both the IR 490cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas * and CFG structures). 491cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas */ 492cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholasvoid delete_left(BasicBlock* b, 493cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas std::vector<BasicBlock::Node>::iterator* iter, 494cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas bool* outUpdated, 495cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas bool* outNeedsRescan) { 496cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *outUpdated = true; 497c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas std::unique_ptr<Expression>* target = (*iter)->expression(); 498c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas ASSERT((*target)->fKind == Expression::kBinary_Kind); 499c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas BinaryExpression& bin = (BinaryExpression&) **target; 50051493ee8488e29499a1a0a678a50aeca44ebf718Ethan Nicholas ASSERT(!bin.fLeft->hasSideEffects()); 501c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas bool result; 502c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas if (bin.fOperator == Token::EQ) { 5034b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas result = b->tryRemoveLValueBefore(iter, bin.fLeft.get()); 504c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas } else { 5054b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas result = b->tryRemoveExpressionBefore(iter, bin.fLeft.get()); 506c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas } 5074b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas *target = std::move(bin.fRight); 508c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas if (!result) { 5094b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas *outNeedsRescan = true; 5104b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas return; 5114b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas } 5124b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas if (*iter == b->fNodes.begin()) { 513cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *outNeedsRescan = true; 514c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas return; 515cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 516c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas --(*iter); 5174b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas if ((*iter)->fKind != BasicBlock::Node::kExpression_Kind || 5184b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas (*iter)->expression() != &bin.fRight) { 5194b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas *outNeedsRescan = true; 5204b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas return; 5214b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas } 522c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas *iter = b->fNodes.erase(*iter); 523c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas ASSERT((*iter)->expression() == target); 524cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas} 525cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas 526cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas/** 527cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas * Collapses the binary expression pointed to by iter down to just the left side (in both the IR and 528cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas * CFG structures). 529cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas */ 530cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholasvoid delete_right(BasicBlock* b, 531cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas std::vector<BasicBlock::Node>::iterator* iter, 532cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas bool* outUpdated, 533cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas bool* outNeedsRescan) { 534cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *outUpdated = true; 535c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas std::unique_ptr<Expression>* target = (*iter)->expression(); 536c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas ASSERT((*target)->fKind == Expression::kBinary_Kind); 537c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas BinaryExpression& bin = (BinaryExpression&) **target; 53851493ee8488e29499a1a0a678a50aeca44ebf718Ethan Nicholas ASSERT(!bin.fRight->hasSideEffects()); 539c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas if (!b->tryRemoveExpressionBefore(iter, bin.fRight.get())) { 540c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas *target = std::move(bin.fLeft); 541cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *outNeedsRescan = true; 542c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas return; 543cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 5444b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas *target = std::move(bin.fLeft); 5454b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas if (*iter == b->fNodes.begin()) { 5464b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas *outNeedsRescan = true; 5474b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas return; 5484b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas } 549c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas --(*iter); 5504b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas if (((*iter)->fKind != BasicBlock::Node::kExpression_Kind || 5514b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas (*iter)->expression() != &bin.fLeft)) { 5524b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas *outNeedsRescan = true; 5534b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas return; 5544b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas } 555c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas *iter = b->fNodes.erase(*iter); 556c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas ASSERT((*iter)->expression() == target); 557cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas} 558cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas 559fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas/** 560fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas * Constructs the specified type using a single argument. 561fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas */ 562fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholasstatic std::unique_ptr<Expression> construct(const Type& type, std::unique_ptr<Expression> v) { 563fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas std::vector<std::unique_ptr<Expression>> args; 564fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas args.push_back(std::move(v)); 5655b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas auto result = std::unique_ptr<Expression>(new Constructor(-1, type, std::move(args))); 566fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas return result; 567fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas} 568fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas 569fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas/** 570fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas * Used in the implementations of vectorize_left and vectorize_right. Given a vector type and an 571fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas * expression x, deletes the expression pointed to by iter and replaces it with <type>(x). 572fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas */ 573fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholasstatic void vectorize(BasicBlock* b, 574fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas std::vector<BasicBlock::Node>::iterator* iter, 575fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas const Type& type, 576fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas std::unique_ptr<Expression>* otherExpression, 577fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bool* outUpdated, 578fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bool* outNeedsRescan) { 579fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas ASSERT((*(*iter)->expression())->fKind == Expression::kBinary_Kind); 580fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas ASSERT(type.kind() == Type::kVector_Kind); 581fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas ASSERT((*otherExpression)->fType.kind() == Type::kScalar_Kind); 582fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas *outUpdated = true; 583fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas std::unique_ptr<Expression>* target = (*iter)->expression(); 584fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (!b->tryRemoveExpression(iter)) { 585fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas *target = construct(type, std::move(*otherExpression)); 586fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas *outNeedsRescan = true; 587fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } else { 588fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas *target = construct(type, std::move(*otherExpression)); 589fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (!b->tryInsertExpression(iter, target)) { 590fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas *outNeedsRescan = true; 591fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 592fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 593fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas} 594fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas 595fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas/** 596fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas * Given a binary expression of the form x <op> vec<n>(y), deletes the right side and vectorizes the 597fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas * left to yield vec<n>(x). 598fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas */ 599fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholasstatic void vectorize_left(BasicBlock* b, 600fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas std::vector<BasicBlock::Node>::iterator* iter, 601fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bool* outUpdated, 602fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bool* outNeedsRescan) { 603fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas BinaryExpression& bin = (BinaryExpression&) **(*iter)->expression(); 604fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas vectorize(b, iter, bin.fRight->fType, &bin.fLeft, outUpdated, outNeedsRescan); 605fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas} 606fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas 607fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas/** 608fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas * Given a binary expression of the form vec<n>(x) <op> y, deletes the left side and vectorizes the 609fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas * right to yield vec<n>(y). 610fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas */ 611fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholasstatic void vectorize_right(BasicBlock* b, 612fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas std::vector<BasicBlock::Node>::iterator* iter, 613fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bool* outUpdated, 614fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bool* outNeedsRescan) { 615fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas BinaryExpression& bin = (BinaryExpression&) **(*iter)->expression(); 616fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas vectorize(b, iter, bin.fLeft->fType, &bin.fRight, outUpdated, outNeedsRescan); 617fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas} 618fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas 619fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas// Mark that an expression which we were writing to is no longer being written to 620fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholasvoid clear_write(const Expression& expr) { 621fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas switch (expr.fKind) { 622fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas case Expression::kVariableReference_Kind: { 623fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas ((VariableReference&) expr).setRefKind(VariableReference::kRead_RefKind); 624fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas break; 625fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 626fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas case Expression::kFieldAccess_Kind: 627fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas clear_write(*((FieldAccess&) expr).fBase); 628fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas break; 629fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas case Expression::kSwizzle_Kind: 630fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas clear_write(*((Swizzle&) expr).fBase); 631fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas break; 632fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas case Expression::kIndex_Kind: 633fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas clear_write(*((IndexExpression&) expr).fBase); 634fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas break; 635fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas default: 636fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas ABORT("shouldn't be writing to this kind of expression\n"); 637fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas break; 638fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 639fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas} 640fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas 641cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholasvoid Compiler::simplifyExpression(DefinitionMap& definitions, 642cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas BasicBlock& b, 643cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas std::vector<BasicBlock::Node>::iterator* iter, 644cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas std::unordered_set<const Variable*>* undefinedVariables, 645cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas bool* outUpdated, 646cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas bool* outNeedsRescan) { 647cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas Expression* expr = (*iter)->expression()->get(); 648cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas ASSERT(expr); 649cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if ((*iter)->fConstantPropagation) { 650cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas std::unique_ptr<Expression> optimized = expr->constantPropagate(*fIRGenerator, definitions); 651cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (optimized) { 6524b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas *outUpdated = true; 653cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (!try_replace_expression(&b, iter, &optimized)) { 654cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *outNeedsRescan = true; 6554b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas return; 656cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 657cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas ASSERT((*iter)->fKind == BasicBlock::Node::kExpression_Kind); 658cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas expr = (*iter)->expression()->get(); 659cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 660cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 661cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas switch (expr->fKind) { 662cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Expression::kVariableReference_Kind: { 663cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas const Variable& var = ((VariableReference*) expr)->fVariable; 664cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (var.fStorage == Variable::kLocal_Storage && !definitions[&var] && 665cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas (*undefinedVariables).find(&var) == (*undefinedVariables).end()) { 666cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas (*undefinedVariables).insert(&var); 66782a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas this->error(expr->fOffset, 66882a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas "'" + var.fName + "' has not been assigned"); 669cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 670cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas break; 671cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 672cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Expression::kTernary_Kind: { 673cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas TernaryExpression* t = (TernaryExpression*) expr; 674cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (t->fTest->fKind == Expression::kBoolLiteral_Kind) { 675cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas // ternary has a constant test, replace it with either the true or 676cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas // false branch 677cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (((BoolLiteral&) *t->fTest).fValue) { 678cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas (*iter)->setExpression(std::move(t->fIfTrue)); 679cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } else { 680cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas (*iter)->setExpression(std::move(t->fIfFalse)); 681cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 682cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *outUpdated = true; 683cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *outNeedsRescan = true; 684cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 685cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas break; 686cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 687cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Expression::kBinary_Kind: { 688cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas BinaryExpression* bin = (BinaryExpression*) expr; 689c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas if (dead_assignment(*bin)) { 690c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas delete_left(&b, iter, outUpdated, outNeedsRescan); 691c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas break; 692c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas } 693c2371a4e325fd123f2d47a9b85d3c8405e8d5e29Ethan Nicholas // collapse useless expressions like x * 1 or x + 0 694fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (((bin->fLeft->fType.kind() != Type::kScalar_Kind) && 695fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas (bin->fLeft->fType.kind() != Type::kVector_Kind)) || 696fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas ((bin->fRight->fType.kind() != Type::kScalar_Kind) && 697fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas (bin->fRight->fType.kind() != Type::kVector_Kind))) { 698fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas break; 699fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 700cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas switch (bin->fOperator) { 701cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Token::STAR: 702cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (is_constant(*bin->fLeft, 1)) { 703fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (bin->fLeft->fType.kind() == Type::kVector_Kind && 704fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bin->fRight->fType.kind() == Type::kScalar_Kind) { 7055af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(1) * x -> float4(x) 706fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas vectorize_right(&b, iter, outUpdated, outNeedsRescan); 707fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } else { 708fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas // 1 * x -> x 7095af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // 1 * float4(x) -> float4(x) 7105af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(1) * float4(x) -> float4(x) 711fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas delete_left(&b, iter, outUpdated, outNeedsRescan); 712fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 713fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 714fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas else if (is_constant(*bin->fLeft, 0)) { 715fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (bin->fLeft->fType.kind() == Type::kScalar_Kind && 71608dae924f63cd00153ec365074ad498dbb8ab5abEthan Nicholas bin->fRight->fType.kind() == Type::kVector_Kind && 71708dae924f63cd00153ec365074ad498dbb8ab5abEthan Nicholas !bin->fRight->hasSideEffects()) { 7185af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // 0 * float4(x) -> float4(0) 719fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas vectorize_left(&b, iter, outUpdated, outNeedsRescan); 720fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } else { 721fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas // 0 * x -> 0 7225af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(0) * x -> float4(0) 7235af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(0) * float4(x) -> float4(0) 72451493ee8488e29499a1a0a678a50aeca44ebf718Ethan Nicholas if (!bin->fRight->hasSideEffects()) { 72551493ee8488e29499a1a0a678a50aeca44ebf718Ethan Nicholas delete_right(&b, iter, outUpdated, outNeedsRescan); 72651493ee8488e29499a1a0a678a50aeca44ebf718Ethan Nicholas } 727fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 728cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 729cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas else if (is_constant(*bin->fRight, 1)) { 730fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (bin->fLeft->fType.kind() == Type::kScalar_Kind && 731fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bin->fRight->fType.kind() == Type::kVector_Kind) { 7325af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // x * float4(1) -> float4(x) 733fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas vectorize_left(&b, iter, outUpdated, outNeedsRescan); 734fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } else { 735fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas // x * 1 -> x 7365af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(x) * 1 -> float4(x) 7375af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(x) * float4(1) -> float4(x) 738fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas delete_right(&b, iter, outUpdated, outNeedsRescan); 739fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 740fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 741fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas else if (is_constant(*bin->fRight, 0)) { 742fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (bin->fLeft->fType.kind() == Type::kVector_Kind && 74308dae924f63cd00153ec365074ad498dbb8ab5abEthan Nicholas bin->fRight->fType.kind() == Type::kScalar_Kind && 74408dae924f63cd00153ec365074ad498dbb8ab5abEthan Nicholas !bin->fLeft->hasSideEffects()) { 7455af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(x) * 0 -> float4(0) 746fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas vectorize_right(&b, iter, outUpdated, outNeedsRescan); 747fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } else { 748fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas // x * 0 -> 0 7495af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // x * float4(0) -> float4(0) 7505af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(x) * float4(0) -> float4(0) 75151493ee8488e29499a1a0a678a50aeca44ebf718Ethan Nicholas if (!bin->fLeft->hasSideEffects()) { 75251493ee8488e29499a1a0a678a50aeca44ebf718Ethan Nicholas delete_left(&b, iter, outUpdated, outNeedsRescan); 75351493ee8488e29499a1a0a678a50aeca44ebf718Ethan Nicholas } 754fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 755cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 756cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas break; 75756e42714d351f8ecb662136076166904b9934b71Ethan Nicholas case Token::PLUS: 758cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (is_constant(*bin->fLeft, 0)) { 759fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (bin->fLeft->fType.kind() == Type::kVector_Kind && 760fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bin->fRight->fType.kind() == Type::kScalar_Kind) { 7615af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(0) + x -> float4(x) 762fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas vectorize_right(&b, iter, outUpdated, outNeedsRescan); 763fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } else { 764fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas // 0 + x -> x 7655af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // 0 + float4(x) -> float4(x) 7665af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(0) + float4(x) -> float4(x) 767fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas delete_left(&b, iter, outUpdated, outNeedsRescan); 768fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 769fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } else if (is_constant(*bin->fRight, 0)) { 770fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (bin->fLeft->fType.kind() == Type::kScalar_Kind && 771fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bin->fRight->fType.kind() == Type::kVector_Kind) { 7725af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // x + float4(0) -> float4(x) 773fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas vectorize_left(&b, iter, outUpdated, outNeedsRescan); 774fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } else { 775fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas // x + 0 -> x 7765af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(x) + 0 -> float4(x) 7775af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(x) + float4(0) -> float4(x) 778fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas delete_right(&b, iter, outUpdated, outNeedsRescan); 779fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 780cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 781fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas break; 782fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas case Token::MINUS: 78356e42714d351f8ecb662136076166904b9934b71Ethan Nicholas if (is_constant(*bin->fRight, 0)) { 784fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (bin->fLeft->fType.kind() == Type::kScalar_Kind && 785fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bin->fRight->fType.kind() == Type::kVector_Kind) { 7865af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // x - float4(0) -> float4(x) 787fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas vectorize_left(&b, iter, outUpdated, outNeedsRescan); 788fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } else { 789fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas // x - 0 -> x 7905af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(x) - 0 -> float4(x) 7915af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(x) - float4(0) -> float4(x) 792fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas delete_right(&b, iter, outUpdated, outNeedsRescan); 793fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 794fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 795fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas break; 796fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas case Token::SLASH: 797fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (is_constant(*bin->fRight, 1)) { 798fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (bin->fLeft->fType.kind() == Type::kScalar_Kind && 799fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas bin->fRight->fType.kind() == Type::kVector_Kind) { 8005af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // x / float4(1) -> float4(x) 801fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas vectorize_left(&b, iter, outUpdated, outNeedsRescan); 802fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } else { 803fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas // x / 1 -> x 8045af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(x) / 1 -> float4(x) 8055af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(x) / float4(1) -> float4(x) 806fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas delete_right(&b, iter, outUpdated, outNeedsRescan); 807fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 808fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } else if (is_constant(*bin->fLeft, 0)) { 809fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (bin->fLeft->fType.kind() == Type::kScalar_Kind && 81008dae924f63cd00153ec365074ad498dbb8ab5abEthan Nicholas bin->fRight->fType.kind() == Type::kVector_Kind && 81108dae924f63cd00153ec365074ad498dbb8ab5abEthan Nicholas !bin->fRight->hasSideEffects()) { 8125af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // 0 / float4(x) -> float4(0) 813fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas vectorize_left(&b, iter, outUpdated, outNeedsRescan); 814fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } else { 815fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas // 0 / x -> 0 8165af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(0) / x -> float4(0) 8175af9ea399d5e0344cc4b7da4e97b5dc5b3c74f64Ethan Nicholas // float4(0) / float4(x) -> float4(0) 81851493ee8488e29499a1a0a678a50aeca44ebf718Ethan Nicholas if (!bin->fRight->hasSideEffects()) { 81951493ee8488e29499a1a0a678a50aeca44ebf718Ethan Nicholas delete_right(&b, iter, outUpdated, outNeedsRescan); 82051493ee8488e29499a1a0a678a50aeca44ebf718Ethan Nicholas } 821fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 822fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 823fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas break; 824fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas case Token::PLUSEQ: 825fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (is_constant(*bin->fRight, 0)) { 826fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas clear_write(*bin->fLeft); 82756e42714d351f8ecb662136076166904b9934b71Ethan Nicholas delete_right(&b, iter, outUpdated, outNeedsRescan); 82856e42714d351f8ecb662136076166904b9934b71Ethan Nicholas } 82956e42714d351f8ecb662136076166904b9934b71Ethan Nicholas break; 830fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas case Token::MINUSEQ: 83156e42714d351f8ecb662136076166904b9934b71Ethan Nicholas if (is_constant(*bin->fRight, 0)) { 832fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas clear_write(*bin->fLeft); 833cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas delete_right(&b, iter, outUpdated, outNeedsRescan); 834cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 835cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas break; 836fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas case Token::STAREQ: 837fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas if (is_constant(*bin->fRight, 1)) { 838fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas clear_write(*bin->fLeft); 839fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas delete_right(&b, iter, outUpdated, outNeedsRescan); 840fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas } 841fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas break; 842fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas case Token::SLASHEQ: 843cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (is_constant(*bin->fRight, 1)) { 844fe53e5828fd31326cdc4594ca06435eb0af50afeEthan Nicholas clear_write(*bin->fLeft); 845cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas delete_right(&b, iter, outUpdated, outNeedsRescan); 846cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 847cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas break; 848cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas default: 849cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas break; 850cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 851cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 852cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas default: 853cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas break; 85422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 855cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas} 856cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas 8575ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas// returns true if this statement could potentially execute a break at the current level (we ignore 8585ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas// nested loops and switches, since any breaks inside of them will merely break the loop / switch) 8595ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholasstatic bool contains_break(Statement& s) { 8605ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas switch (s.fKind) { 8615ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas case Statement::kBlock_Kind: 8625ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas for (const auto& sub : ((Block&) s).fStatements) { 8635ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (contains_break(*sub)) { 8645ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas return true; 8655ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 8665ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 8675ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas return false; 8685ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas case Statement::kBreak_Kind: 8695ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas return true; 8705ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas case Statement::kIf_Kind: { 8715ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas const IfStatement& i = (IfStatement&) s; 8725ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas return contains_break(*i.fIfTrue) || (i.fIfFalse && contains_break(*i.fIfFalse)); 8735ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 8745ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas default: 8755ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas return false; 8765ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 8775ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas} 8785ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas 8795ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas// Returns a block containing all of the statements that will be run if the given case matches 8805ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas// (which, owing to the statements being owned by unique_ptrs, means the switch itself will be 8815ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas// broken by this call and must then be discarded). 8825ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas// Returns null (and leaves the switch unmodified) if no such simple reduction is possible, such as 8835ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas// when break statements appear inside conditionals. 8845ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholasstatic std::unique_ptr<Statement> block_for_case(SwitchStatement* s, SwitchCase* c) { 8855ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas bool capturing = false; 8865ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas std::vector<std::unique_ptr<Statement>*> statementPtrs; 8875ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas for (const auto& current : s->fCases) { 8885ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (current.get() == c) { 8895ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas capturing = true; 8905ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 8915ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (capturing) { 8925ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas for (auto& stmt : current->fStatements) { 8935ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (stmt->fKind == Statement::kBreak_Kind) { 8945ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas capturing = false; 8955ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas break; 8965ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 8975ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (contains_break(*stmt)) { 8985ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas return nullptr; 8995ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 9005ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas statementPtrs.push_back(&stmt); 9015ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 9025ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (!capturing) { 9035ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas break; 9045ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 9055ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 9065ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 9075ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas std::vector<std::unique_ptr<Statement>> statements; 9085ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas for (const auto& s : statementPtrs) { 9095ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas statements.push_back(std::move(*s)); 9105ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 9115b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas return std::unique_ptr<Statement>(new Block(-1, std::move(statements), s->fSymbols)); 9125ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas} 9135ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas 914cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholasvoid Compiler::simplifyStatement(DefinitionMap& definitions, 9155ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas BasicBlock& b, 9165ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas std::vector<BasicBlock::Node>::iterator* iter, 9175ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas std::unordered_set<const Variable*>* undefinedVariables, 9185ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas bool* outUpdated, 9195ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas bool* outNeedsRescan) { 920cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas Statement* stmt = (*iter)->statement()->get(); 921cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas switch (stmt->fKind) { 92282a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas case Statement::kVarDeclaration_Kind: { 92382a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas const auto& varDecl = (VarDeclaration&) *stmt; 92482a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas if (varDecl.fVar->dead() && 92582a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas (!varDecl.fValue || 92682a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas !varDecl.fValue->hasSideEffects())) { 92782a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas if (varDecl.fValue) { 92882a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas ASSERT((*iter)->statement()->get() == stmt); 92982a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas if (!b.tryRemoveExpressionBefore(iter, varDecl.fValue.get())) { 93082a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas *outNeedsRescan = true; 931cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 932cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 933cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas (*iter)->setStatement(std::unique_ptr<Statement>(new Nop())); 93482a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas *outUpdated = true; 935cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 936cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas break; 937cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 938cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Statement::kIf_Kind: { 939cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas IfStatement& i = (IfStatement&) *stmt; 9405ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (i.fTest->fKind == Expression::kBoolLiteral_Kind) { 9415ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas // constant if, collapse down to a single branch 9425ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (((BoolLiteral&) *i.fTest).fValue) { 9435ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas ASSERT(i.fIfTrue); 9445ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas (*iter)->setStatement(std::move(i.fIfTrue)); 9455ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } else { 9465ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (i.fIfFalse) { 9475ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas (*iter)->setStatement(std::move(i.fIfFalse)); 9485ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } else { 9495ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas (*iter)->setStatement(std::unique_ptr<Statement>(new Nop())); 9505ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 9515ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 9525ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas *outUpdated = true; 9535ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas *outNeedsRescan = true; 9545ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas break; 9555ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 956cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (i.fIfFalse && i.fIfFalse->isEmpty()) { 957cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas // else block doesn't do anything, remove it 958cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas i.fIfFalse.reset(); 959cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *outUpdated = true; 960cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *outNeedsRescan = true; 961cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 962cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (!i.fIfFalse && i.fIfTrue->isEmpty()) { 963cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas // if block doesn't do anything, no else block 964cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (i.fTest->hasSideEffects()) { 965cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas // test has side effects, keep it 966cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas (*iter)->setStatement(std::unique_ptr<Statement>( 967cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas new ExpressionStatement(std::move(i.fTest)))); 968cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } else { 969cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas // no if, no else, no test side effects, kill the whole if 970cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas // statement 971cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas (*iter)->setStatement(std::unique_ptr<Statement>(new Nop())); 972cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 973cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *outUpdated = true; 974cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *outNeedsRescan = true; 975cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 976cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas break; 977cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 9785ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas case Statement::kSwitch_Kind: { 9795ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas SwitchStatement& s = (SwitchStatement&) *stmt; 9805ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (s.fValue->isConstant()) { 9815ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas // switch is constant, replace it with the case that matches 9825ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas bool found = false; 9835ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas SwitchCase* defaultCase = nullptr; 9845ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas for (const auto& c : s.fCases) { 9855ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (!c->fValue) { 9865ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas defaultCase = c.get(); 9875ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas continue; 9885ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 9895ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas ASSERT(c->fValue->fKind == s.fValue->fKind); 9905ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas found = c->fValue->compareConstant(fContext, *s.fValue); 9915ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (found) { 9925ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas std::unique_ptr<Statement> newBlock = block_for_case(&s, c.get()); 9935ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (newBlock) { 9945ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas (*iter)->setStatement(std::move(newBlock)); 9955ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas break; 9965ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } else { 9976e1cbc012b10e99d9caed19eef43939778d1d8ffEthan Nicholas if (s.fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) { 9985b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas this->error(s.fOffset, 9995ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas "static switch contains non-static conditional break"); 10005ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas s.fIsStatic = false; 10015ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 10025ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas return; // can't simplify 10035ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 10045ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 10055ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 10065ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (!found) { 10075ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas // no matching case. use default if it exists, or kill the whole thing 10085ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (defaultCase) { 10095ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas std::unique_ptr<Statement> newBlock = block_for_case(&s, defaultCase); 10105ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (newBlock) { 10115ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas (*iter)->setStatement(std::move(newBlock)); 10125ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } else { 10136e1cbc012b10e99d9caed19eef43939778d1d8ffEthan Nicholas if (s.fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) { 10145b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas this->error(s.fOffset, 10155ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas "static switch contains non-static conditional break"); 10165ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas s.fIsStatic = false; 10175ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 10185ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas return; // can't simplify 10195ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 10205ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } else { 10215ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas (*iter)->setStatement(std::unique_ptr<Statement>(new Nop())); 10225ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 10235ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 10245ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas *outUpdated = true; 10255ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas *outNeedsRescan = true; 10265ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 10275ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas break; 10285ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 1029cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Statement::kExpression_Kind: { 1030cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas ExpressionStatement& e = (ExpressionStatement&) *stmt; 1031cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas ASSERT((*iter)->statement()->get() == &e); 1032cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (!e.fExpression->hasSideEffects()) { 1033cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas // Expression statement with no side effects, kill it 1034cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (!b.tryRemoveExpressionBefore(iter, e.fExpression.get())) { 1035cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *outNeedsRescan = true; 1036cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 1037cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas ASSERT((*iter)->statement()->get() == stmt); 1038cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas (*iter)->setStatement(std::unique_ptr<Statement>(new Nop())); 1039cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas *outUpdated = true; 1040cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 1041cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas break; 1042cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 1043cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas default: 1044cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas break; 1045cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 1046cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas} 1047cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas 1048cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholasvoid Compiler::scanCFG(FunctionDefinition& f) { 1049cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas CFG cfg = CFGGenerator().getCFG(f); 1050cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas this->computeDataFlow(&cfg); 105122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas 105222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas // check for unreachable code 105322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas for (size_t i = 0; i < cfg.fBlocks.size(); i++) { 10546ad9909fb7ccc973f35bbd222b0f424b8c3df0d2Mike Klein if (i != cfg.fStart && !cfg.fBlocks[i].fEntrances.size() && 105522f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas cfg.fBlocks[i].fNodes.size()) { 10565b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas int offset; 105786a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas switch (cfg.fBlocks[i].fNodes[0].fKind) { 105886a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas case BasicBlock::Node::kStatement_Kind: 10595b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas offset = (*cfg.fBlocks[i].fNodes[0].statement())->fOffset; 106086a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas break; 106186a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas case BasicBlock::Node::kExpression_Kind: 10625b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas offset = (*cfg.fBlocks[i].fNodes[0].expression())->fOffset; 106386a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas break; 106486a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas } 10655b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas this->error(offset, String("unreachable")); 106622f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 106722f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 106822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas if (fErrorCount) { 106922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas return; 107022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 107122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas 1072cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas // check for dead code & undefined variables, perform constant propagation 1073cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas std::unordered_set<const Variable*> undefinedVariables; 1074cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas bool updated; 1075cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas bool needsRescan = false; 1076cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas do { 1077cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (needsRescan) { 1078cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas cfg = CFGGenerator().getCFG(f); 1079cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas this->computeDataFlow(&cfg); 1080cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas needsRescan = false; 1081cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 1082cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas 1083cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas updated = false; 1084cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas for (BasicBlock& b : cfg.fBlocks) { 1085cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas DefinitionMap definitions = b.fBefore; 1086cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas 1087cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas for (auto iter = b.fNodes.begin(); iter != b.fNodes.end() && !needsRescan; ++iter) { 1088cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (iter->fKind == BasicBlock::Node::kExpression_Kind) { 1089cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas this->simplifyExpression(definitions, b, &iter, &undefinedVariables, &updated, 1090cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas &needsRescan); 1091cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } else { 1092cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas this->simplifyStatement(definitions, b, &iter, &undefinedVariables, &updated, 1093cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas &needsRescan); 109422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 10954b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas if (needsRescan) { 10964b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas break; 10974b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas } 1098cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas this->addDefinitions(*iter, &definitions); 109922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 110022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 1101cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } while (updated); 1102cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas ASSERT(!needsRescan); 110322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas 110491a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas // verify static ifs & switches, clean up dead variable decls 11055ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas for (BasicBlock& b : cfg.fBlocks) { 11065ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas DefinitionMap definitions = b.fBefore; 11075ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas 110891a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas for (auto iter = b.fNodes.begin(); iter != b.fNodes.end() && !needsRescan;) { 11095ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas if (iter->fKind == BasicBlock::Node::kStatement_Kind) { 11105ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas const Statement& s = **iter->statement(); 11115ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas switch (s.fKind) { 11125ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas case Statement::kIf_Kind: 11136e1cbc012b10e99d9caed19eef43939778d1d8ffEthan Nicholas if (((const IfStatement&) s).fIsStatic && 11146e1cbc012b10e99d9caed19eef43939778d1d8ffEthan Nicholas !(fFlags & kPermitInvalidStaticTests_Flag)) { 11155b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas this->error(s.fOffset, "static if has non-static test"); 11165ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 111791a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas ++iter; 11185ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas break; 11195ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas case Statement::kSwitch_Kind: 11206e1cbc012b10e99d9caed19eef43939778d1d8ffEthan Nicholas if (((const SwitchStatement&) s).fIsStatic && 11216e1cbc012b10e99d9caed19eef43939778d1d8ffEthan Nicholas !(fFlags & kPermitInvalidStaticTests_Flag)) { 11225b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas this->error(s.fOffset, "static switch has non-static test"); 11235ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 112491a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas ++iter; 112591a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas break; 112682a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas case Statement::kVarDeclarations_Kind: { 112782a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas VarDeclarations& decls = *((VarDeclarationsStatement&) s).fDeclaration; 112882a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas for (auto varIter = decls.fVars.begin(); varIter != decls.fVars.end();) { 112982a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas if ((*varIter)->fKind == Statement::kNop_Kind) { 113082a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas varIter = decls.fVars.erase(varIter); 113182a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas } else { 113282a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas ++varIter; 113382a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas } 113482a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas } 113582a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas if (!decls.fVars.size()) { 113682a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas iter = b.fNodes.erase(iter); 113782a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas } else { 113882a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas ++iter; 113982a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas } 114082a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas break; 114182a62d2d4ef55e53730a4f194a82d4e5da0c4a64Ethan Nicholas } 11425ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas default: 114391a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas ++iter; 11445ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas break; 11455ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 114691a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas } else { 114791a1053f2d4f7be31d7f3a14f718d0e457e49710Ethan Nicholas ++iter; 11485ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 11495ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 11505ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas } 11515ac13c23628c6ee8c3f6056f38527706b403e502Ethan Nicholas 115222f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas // check for missing return 115322f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas if (f.fDeclaration.fReturnType != *fContext.fVoid_Type) { 115422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas if (cfg.fBlocks[cfg.fExit].fEntrances.size()) { 11555b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas this->error(f.fOffset, String("function can exit without returning a value")); 115622f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 115722f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 115822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas} 115922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas 11600df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholasstd::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String text, 1161941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas const Program::Settings& settings) { 1162b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrorText = ""; 1163b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fErrorCount = 0; 1164941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fIRGenerator->start(&settings); 1165d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas std::vector<std::unique_ptr<ProgramElement>> elements; 1166b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (kind) { 1167b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Program::kVertex_Kind: 1168fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips fIRGenerator->convertProgram(kind, SKSL_VERT_INCLUDE, strlen(SKSL_VERT_INCLUDE), 1169fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips *fTypes, &elements); 1170b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 1171b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Program::kFragment_Kind: 1172fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips fIRGenerator->convertProgram(kind, SKSL_FRAG_INCLUDE, strlen(SKSL_FRAG_INCLUDE), 1173fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips *fTypes, &elements); 1174b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 117552cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas case Program::kGeometry_Kind: 1176fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips fIRGenerator->convertProgram(kind, SKSL_GEOM_INCLUDE, strlen(SKSL_GEOM_INCLUDE), 1177fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips *fTypes, &elements); 117852cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas break; 1179762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas case Program::kFragmentProcessor_Kind: 1180fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips fIRGenerator->convertProgram(kind, SKSL_FP_INCLUDE, strlen(SKSL_FP_INCLUDE), *fTypes, 1181f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas &elements); 1182762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas break; 1183b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1184ddb37d67ba4db42fa5c6012b58d0f4985b454dc0ethannicholas fIRGenerator->fSymbolTable->markAllFunctionsBuiltin(); 1185aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas for (auto& element : elements) { 1186aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas if (element->fKind == ProgramElement::kEnum_Kind) { 1187aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas ((Enum&) *element).fBuiltin = true; 1188aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas } 1189aae47c878b83ab6d9742d92a6fa47e762f6b9204Ethan Nicholas } 11905b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas std::unique_ptr<String> textPtr(new String(std::move(text))); 11915b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas fSource = textPtr.get(); 1192fe8da17f5333a0134a01b9fe4d7f67e3df949c61Robert Phillips fIRGenerator->convertProgram(kind, textPtr->c_str(), textPtr->size(), *fTypes, &elements); 11937da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas if (!fErrorCount) { 11947da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas for (auto& element : elements) { 11957da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas if (element->fKind == ProgramElement::kFunction_Kind) { 11967da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas this->scanCFG((FunctionDefinition&) *element); 11977da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas } 11987da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas } 11997da6dfabc44891c51dedcb4754477b662d8c8a0aEthan Nicholas } 1200f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas auto result = std::unique_ptr<Program>(new Program(kind, 1201f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas std::move(textPtr), 1202f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas settings, 1203f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas &fContext, 1204941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas std::move(elements), 1205941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fIRGenerator->fSymbolTable, 1206941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fIRGenerator->fInputs)); 12073605ace7ddaf0b576bf6df1c7a550ab4f44d22a8Ethan Nicholas fIRGenerator->finish(); 12085b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas fSource = nullptr; 1209b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeErrorCount(); 1210941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (fErrorCount) { 1211941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas return nullptr; 1212941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas } 1213d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return result; 1214b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1215b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 12160df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholasbool Compiler::toSPIRV(const Program& program, OutputStream& out) { 1217a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas#ifdef SK_ENABLE_SPIRV_VALIDATION 12180df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas StringStream buffer; 12195b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas fSource = program.fSource.get(); 1220a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas SPIRVCodeGenerator cg(&fContext, &program, this, &buffer); 1221a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas bool result = cg.generateCode(); 12225b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas fSource = nullptr; 1223a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas if (result) { 1224a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0); 1225762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas const String& data = buffer.str(); 1226762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas ASSERT(0 == data.size() % 4); 1227a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas auto dumpmsg = [](spv_message_level_t, const char*, const spv_position_t&, const char* m) { 1228a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas SkDebugf("SPIR-V validation error: %s\n", m); 1229a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas }; 1230a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas tools.SetMessageConsumer(dumpmsg); 1231a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas // Verify that the SPIR-V we produced is valid. If this assert fails, check the logs prior 1232a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas // to the failure to see the validation errors. 1233762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas ASSERT_RESULT(tools.Validate((const uint32_t*) data.c_str(), data.size() / 4)); 1234762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas out.write(data.c_str(), data.size()); 1235a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas } 1236a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas#else 12375b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas fSource = program.fSource.get(); 1238941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas SPIRVCodeGenerator cg(&fContext, &program, this, &out); 1239941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas bool result = cg.generateCode(); 12405b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas fSource = nullptr; 1241a6ae1f7cda072ff814a838e2d9013a017552cc35Ethan Nicholas#endif 1242941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeErrorCount(); 1243b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 1244b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1245b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 12460df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholasbool Compiler::toSPIRV(const Program& program, String* out) { 12470df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas StringStream buffer; 1248941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas bool result = this->toSPIRV(program, buffer); 1249941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (result) { 1250762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas *out = buffer.str(); 1251b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1252941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas return result; 1253b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1254b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 12550df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholasbool Compiler::toGLSL(const Program& program, OutputStream& out) { 12565b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas fSource = program.fSource.get(); 1257941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas GLSLCodeGenerator cg(&fContext, &program, this, &out); 1258941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas bool result = cg.generateCode(); 12595b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas fSource = nullptr; 1260941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeErrorCount(); 1261941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas return result; 1262b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1263b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 12640df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholasbool Compiler::toGLSL(const Program& program, String* out) { 12650df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas StringStream buffer; 1266941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas bool result = this->toGLSL(program, buffer); 1267b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (result) { 1268762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas *out = buffer.str(); 1269b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1270f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas return result; 1271f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 1272f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 1273cc3057784b89cdde367fd1d645f1cf69d0eee5f7Ethan Nicholasbool Compiler::toMetal(const Program& program, OutputStream& out) { 1274cc3057784b89cdde367fd1d645f1cf69d0eee5f7Ethan Nicholas MetalCodeGenerator cg(&fContext, &program, this, &out); 1275cc3057784b89cdde367fd1d645f1cf69d0eee5f7Ethan Nicholas bool result = cg.generateCode(); 1276cc3057784b89cdde367fd1d645f1cf69d0eee5f7Ethan Nicholas this->writeErrorCount(); 1277cc3057784b89cdde367fd1d645f1cf69d0eee5f7Ethan Nicholas return result; 1278cc3057784b89cdde367fd1d645f1cf69d0eee5f7Ethan Nicholas} 1279cc3057784b89cdde367fd1d645f1cf69d0eee5f7Ethan Nicholas 1280762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholasbool Compiler::toCPP(const Program& program, String name, OutputStream& out) { 12815b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas fSource = program.fSource.get(); 1282762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas CPPCodeGenerator cg(&fContext, &program, this, name, &out); 1283762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas bool result = cg.generateCode(); 12845b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas fSource = nullptr; 1285762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas this->writeErrorCount(); 1286762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas return result; 1287762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas} 1288762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas 1289762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholasbool Compiler::toH(const Program& program, String name, OutputStream& out) { 12905b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas fSource = program.fSource.get(); 1291c9472af8585be3c12691b968b667cde3ca83cae4Ethan Nicholas HCodeGenerator cg(&fContext, &program, this, name, &out); 1292762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas bool result = cg.generateCode(); 12935b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas fSource = nullptr; 1294762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas this->writeErrorCount(); 1295762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas return result; 1296762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas} 1297941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas 12985b5f096a038259b8d9084834f877588a0db80250Ethan Nicholasconst char* Compiler::OperatorName(Token::Kind kind) { 12995b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas switch (kind) { 13005b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::PLUS: return "+"; 13015b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::MINUS: return "-"; 13025b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::STAR: return "*"; 13035b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::SLASH: return "/"; 13045b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::PERCENT: return "%"; 13055b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::SHL: return "<<"; 13065b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::SHR: return ">>"; 13075b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::LOGICALNOT: return "!"; 13085b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::LOGICALAND: return "&&"; 13095b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::LOGICALOR: return "||"; 13105b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::LOGICALXOR: return "^^"; 13115b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::BITWISENOT: return "~"; 13125b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::BITWISEAND: return "&"; 13135b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::BITWISEOR: return "|"; 13145b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::BITWISEXOR: return "^"; 13155b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::EQ: return "="; 13165b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::EQEQ: return "=="; 13175b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::NEQ: return "!="; 13185b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::LT: return "<"; 13195b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::GT: return ">"; 13205b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::LTEQ: return "<="; 13215b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::GTEQ: return ">="; 13225b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::PLUSEQ: return "+="; 13235b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::MINUSEQ: return "-="; 13245b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::STAREQ: return "*="; 13255b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::SLASHEQ: return "/="; 13265b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::PERCENTEQ: return "%="; 13275b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::SHLEQ: return "<<="; 13285b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::SHREQ: return ">>="; 13295b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::LOGICALANDEQ: return "&&="; 13305b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::LOGICALOREQ: return "||="; 13315b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::LOGICALXOREQ: return "^^="; 13325b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::BITWISEANDEQ: return "&="; 13335b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::BITWISEOREQ: return "|="; 13345b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::BITWISEXOREQ: return "^="; 13355b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::PLUSPLUS: return "++"; 13365b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::MINUSMINUS: return "--"; 13375b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::COMMA: return ","; 13385b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas default: 13395b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas ABORT("unsupported operator: %d\n", kind); 13405b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas } 13415b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas} 13425b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas 13435b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas 13445b5f096a038259b8d9084834f877588a0db80250Ethan Nicholasbool Compiler::IsAssignment(Token::Kind op) { 13455b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas switch (op) { 13465b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::EQ: // fall through 13475b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::PLUSEQ: // fall through 13485b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::MINUSEQ: // fall through 13495b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::STAREQ: // fall through 13505b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::SLASHEQ: // fall through 13515b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::PERCENTEQ: // fall through 13525b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::SHLEQ: // fall through 13535b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::SHREQ: // fall through 13545b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::BITWISEOREQ: // fall through 13555b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::BITWISEXOREQ: // fall through 13565b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::BITWISEANDEQ: // fall through 13575b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::LOGICALOREQ: // fall through 13585b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::LOGICALXOREQ: // fall through 13595b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas case Token::LOGICALANDEQ: 13605b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas return true; 13615b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas default: 13625b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas return false; 13635b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas } 13645b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas} 13655b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas 13665b5f096a038259b8d9084834f877588a0db80250Ethan NicholasPosition Compiler::position(int offset) { 13675b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas ASSERT(fSource); 13685b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas int line = 1; 13695b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas int column = 1; 13705b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas for (int i = 0; i < offset; i++) { 13715b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas if ((*fSource)[i] == '\n') { 13725b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas ++line; 13735b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas column = 1; 13745b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas } 13755b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas else { 13765b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas ++column; 13775b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas } 13785b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas } 13795b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas return Position(line, column); 13805b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas} 13815b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas 13825b5f096a038259b8d9084834f877588a0db80250Ethan Nicholasvoid Compiler::error(int offset, String msg) { 1383941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fErrorCount++; 13845b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas Position pos = this->position(offset); 13855b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas fErrorText += "error: " + to_string(pos.fLine) + ": " + msg.c_str() + "\n"; 13863605ace7ddaf0b576bf6df1c7a550ab4f44d22a8Ethan Nicholas} 13873605ace7ddaf0b576bf6df1c7a550ab4f44d22a8Ethan Nicholas 13880df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan NicholasString Compiler::errorText() { 13890df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas String result = fErrorText; 1390941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas return result; 1391b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1392b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1393941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholasvoid Compiler::writeErrorCount() { 1394941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (fErrorCount) { 1395941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fErrorText += to_string(fErrorCount) + " error"; 1396941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (fErrorCount > 1) { 1397941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fErrorText += "s"; 1398941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas } 1399941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fErrorText += "\n"; 1400f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 1401f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 1402f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 1403b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} // namespace 1404