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