blob: 41ff5cc8f6a7cb09a9b6a7a05109af9df72ad5ca [file] [log] [blame]
ethannicholasb3058bd2016-07-01 08:22:01 -07001/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
Mike Klein6ad99092016-10-26 10:35:22 -04007
ethannicholasb3058bd2016-07-01 08:22:01 -07008#include "SkSLCompiler.h"
9
ethannicholas22f939e2016-10-13 13:25:34 -070010#include "SkSLCFGGenerator.h"
Ethan Nicholas762466e2017-06-29 10:03:38 -040011#include "SkSLCPPCodeGenerator.h"
Ethan Nicholas941e7e22016-12-12 15:33:30 -050012#include "SkSLGLSLCodeGenerator.h"
Ethan Nicholas762466e2017-06-29 10:03:38 -040013#include "SkSLHCodeGenerator.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070014#include "SkSLIRGenerator.h"
Ethan Nicholascc305772017-10-13 16:17:45 -040015#include "SkSLMetalCodeGenerator.h"
Ethan Nicholas00543112018-07-31 09:44:36 -040016#include "SkSLPipelineStageCodeGenerator.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070017#include "SkSLSPIRVCodeGenerator.h"
Ethan Nicholasaae47c82017-11-10 15:34:03 -050018#include "ir/SkSLEnum.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070019#include "ir/SkSLExpression.h"
Ethan Nicholascb670962017-04-20 19:31:52 -040020#include "ir/SkSLExpressionStatement.h"
Ethan Nicholasc6a19f12018-03-29 16:46:56 -040021#include "ir/SkSLFunctionCall.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070022#include "ir/SkSLIntLiteral.h"
ethannicholas5961bc92016-10-12 06:39:56 -070023#include "ir/SkSLModifiersDeclaration.h"
Ethan Nicholascb670962017-04-20 19:31:52 -040024#include "ir/SkSLNop.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070025#include "ir/SkSLSymbolTable.h"
Ethan Nicholascb670962017-04-20 19:31:52 -040026#include "ir/SkSLTernaryExpression.h"
ethannicholasddb37d62016-10-20 09:54:00 -070027#include "ir/SkSLUnresolvedFunction.h"
ethannicholas22f939e2016-10-13 13:25:34 -070028#include "ir/SkSLVarDeclarations.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070029
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -040030#ifdef SK_ENABLE_SPIRV_VALIDATION
31#include "spirv-tools/libspirv.hpp"
32#endif
33
ethannicholasb3058bd2016-07-01 08:22:01 -070034// include the built-in shader symbols as static strings
35
Ethan Nicholas79707652017-11-16 11:20:11 -050036#define STRINGIFY(x) #x
37
ethannicholas5961bc92016-10-12 06:39:56 -070038static const char* SKSL_INCLUDE =
Ben Wagnera56c4d22018-01-24 17:32:17 -050039#include "sksl.inc"
ethannicholasb3058bd2016-07-01 08:22:01 -070040;
41
ethannicholas5961bc92016-10-12 06:39:56 -070042static const char* SKSL_VERT_INCLUDE =
Ben Wagnera56c4d22018-01-24 17:32:17 -050043#include "sksl_vert.inc"
ethannicholasb3058bd2016-07-01 08:22:01 -070044;
45
ethannicholas5961bc92016-10-12 06:39:56 -070046static const char* SKSL_FRAG_INCLUDE =
Ben Wagnera56c4d22018-01-24 17:32:17 -050047#include "sksl_frag.inc"
ethannicholasb3058bd2016-07-01 08:22:01 -070048;
49
Ethan Nicholas52cad152017-02-16 16:37:32 -050050static const char* SKSL_GEOM_INCLUDE =
Ben Wagnera56c4d22018-01-24 17:32:17 -050051#include "sksl_geom.inc"
Ethan Nicholas52cad152017-02-16 16:37:32 -050052;
53
Ethan Nicholas762466e2017-06-29 10:03:38 -040054static const char* SKSL_FP_INCLUDE =
Ben Wagnera56c4d22018-01-24 17:32:17 -050055#include "sksl_enums.inc"
56#include "sksl_fp.inc"
Ethan Nicholas762466e2017-06-29 10:03:38 -040057;
58
Ethan Nicholas00543112018-07-31 09:44:36 -040059static const char* SKSL_PIPELINE_STAGE_INCLUDE =
60#include "sksl_pipeline.inc"
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040061;
62
ethannicholasb3058bd2016-07-01 08:22:01 -070063namespace SkSL {
64
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -040065Compiler::Compiler(Flags flags)
66: fFlags(flags)
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040067, fContext(new Context())
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -040068, fErrorCount(0) {
Ethan Nicholas8feeff92017-03-30 14:11:58 -040069 auto types = std::shared_ptr<SymbolTable>(new SymbolTable(this));
70 auto symbols = std::shared_ptr<SymbolTable>(new SymbolTable(types, this));
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040071 fIRGenerator = new IRGenerator(fContext.get(), symbols, *this);
ethannicholasb3058bd2016-07-01 08:22:01 -070072 fTypes = types;
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040073 #define ADD_TYPE(t) types->addWithoutOwnership(fContext->f ## t ## _Type->fName, \
74 fContext->f ## t ## _Type.get())
ethannicholasb3058bd2016-07-01 08:22:01 -070075 ADD_TYPE(Void);
76 ADD_TYPE(Float);
Ethan Nicholas5af9ea32017-07-28 15:19:46 -040077 ADD_TYPE(Float2);
78 ADD_TYPE(Float3);
79 ADD_TYPE(Float4);
Ethan Nicholasdcba08e2017-08-02 10:52:54 -040080 ADD_TYPE(Half);
81 ADD_TYPE(Half2);
82 ADD_TYPE(Half3);
83 ADD_TYPE(Half4);
ethannicholasb3058bd2016-07-01 08:22:01 -070084 ADD_TYPE(Double);
Ethan Nicholas5af9ea32017-07-28 15:19:46 -040085 ADD_TYPE(Double2);
86 ADD_TYPE(Double3);
87 ADD_TYPE(Double4);
ethannicholasb3058bd2016-07-01 08:22:01 -070088 ADD_TYPE(Int);
Ethan Nicholas5af9ea32017-07-28 15:19:46 -040089 ADD_TYPE(Int2);
90 ADD_TYPE(Int3);
91 ADD_TYPE(Int4);
ethannicholasb3058bd2016-07-01 08:22:01 -070092 ADD_TYPE(UInt);
Ethan Nicholas5af9ea32017-07-28 15:19:46 -040093 ADD_TYPE(UInt2);
94 ADD_TYPE(UInt3);
95 ADD_TYPE(UInt4);
Ethan Nicholasdcba08e2017-08-02 10:52:54 -040096 ADD_TYPE(Short);
97 ADD_TYPE(Short2);
98 ADD_TYPE(Short3);
99 ADD_TYPE(Short4);
100 ADD_TYPE(UShort);
101 ADD_TYPE(UShort2);
102 ADD_TYPE(UShort3);
103 ADD_TYPE(UShort4);
Ruiqi Maob609e6d2018-07-17 10:19:38 -0400104 ADD_TYPE(Byte);
105 ADD_TYPE(Byte2);
106 ADD_TYPE(Byte3);
107 ADD_TYPE(Byte4);
108 ADD_TYPE(UByte);
109 ADD_TYPE(UByte2);
110 ADD_TYPE(UByte3);
111 ADD_TYPE(UByte4);
ethannicholasb3058bd2016-07-01 08:22:01 -0700112 ADD_TYPE(Bool);
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400113 ADD_TYPE(Bool2);
114 ADD_TYPE(Bool3);
115 ADD_TYPE(Bool4);
116 ADD_TYPE(Float2x2);
117 ADD_TYPE(Float2x3);
118 ADD_TYPE(Float2x4);
119 ADD_TYPE(Float3x2);
120 ADD_TYPE(Float3x3);
121 ADD_TYPE(Float3x4);
122 ADD_TYPE(Float4x2);
123 ADD_TYPE(Float4x3);
124 ADD_TYPE(Float4x4);
Ethan Nicholasdcba08e2017-08-02 10:52:54 -0400125 ADD_TYPE(Half2x2);
126 ADD_TYPE(Half2x3);
127 ADD_TYPE(Half2x4);
128 ADD_TYPE(Half3x2);
129 ADD_TYPE(Half3x3);
130 ADD_TYPE(Half3x4);
131 ADD_TYPE(Half4x2);
132 ADD_TYPE(Half4x3);
133 ADD_TYPE(Half4x4);
134 ADD_TYPE(Double2x2);
135 ADD_TYPE(Double2x3);
136 ADD_TYPE(Double2x4);
137 ADD_TYPE(Double3x2);
138 ADD_TYPE(Double3x3);
139 ADD_TYPE(Double3x4);
140 ADD_TYPE(Double4x2);
141 ADD_TYPE(Double4x3);
142 ADD_TYPE(Double4x4);
ethannicholasb3058bd2016-07-01 08:22:01 -0700143 ADD_TYPE(GenType);
Ethan Nicholasdcba08e2017-08-02 10:52:54 -0400144 ADD_TYPE(GenHType);
ethannicholasb3058bd2016-07-01 08:22:01 -0700145 ADD_TYPE(GenDType);
146 ADD_TYPE(GenIType);
147 ADD_TYPE(GenUType);
148 ADD_TYPE(GenBType);
149 ADD_TYPE(Mat);
150 ADD_TYPE(Vec);
151 ADD_TYPE(GVec);
152 ADD_TYPE(GVec2);
153 ADD_TYPE(GVec3);
154 ADD_TYPE(GVec4);
Ethan Nicholasdcba08e2017-08-02 10:52:54 -0400155 ADD_TYPE(HVec);
ethannicholasb3058bd2016-07-01 08:22:01 -0700156 ADD_TYPE(DVec);
157 ADD_TYPE(IVec);
158 ADD_TYPE(UVec);
Ethan Nicholasdcba08e2017-08-02 10:52:54 -0400159 ADD_TYPE(SVec);
160 ADD_TYPE(USVec);
Ruiqi Maob609e6d2018-07-17 10:19:38 -0400161 ADD_TYPE(ByteVec);
162 ADD_TYPE(UByteVec);
ethannicholasb3058bd2016-07-01 08:22:01 -0700163 ADD_TYPE(BVec);
164
165 ADD_TYPE(Sampler1D);
166 ADD_TYPE(Sampler2D);
167 ADD_TYPE(Sampler3D);
ethannicholas5961bc92016-10-12 06:39:56 -0700168 ADD_TYPE(SamplerExternalOES);
ethannicholasb3058bd2016-07-01 08:22:01 -0700169 ADD_TYPE(SamplerCube);
170 ADD_TYPE(Sampler2DRect);
171 ADD_TYPE(Sampler1DArray);
172 ADD_TYPE(Sampler2DArray);
173 ADD_TYPE(SamplerCubeArray);
174 ADD_TYPE(SamplerBuffer);
175 ADD_TYPE(Sampler2DMS);
176 ADD_TYPE(Sampler2DMSArray);
177
Brian Salomonbf7b6202016-11-11 16:08:03 -0500178 ADD_TYPE(ISampler2D);
179
Brian Salomon2a51de82016-11-16 12:06:01 -0500180 ADD_TYPE(Image2D);
181 ADD_TYPE(IImage2D);
182
Greg Daniel64773e62016-11-22 09:44:03 -0500183 ADD_TYPE(SubpassInput);
184 ADD_TYPE(SubpassInputMS);
185
ethannicholasb3058bd2016-07-01 08:22:01 -0700186 ADD_TYPE(GSampler1D);
187 ADD_TYPE(GSampler2D);
188 ADD_TYPE(GSampler3D);
189 ADD_TYPE(GSamplerCube);
190 ADD_TYPE(GSampler2DRect);
191 ADD_TYPE(GSampler1DArray);
192 ADD_TYPE(GSampler2DArray);
193 ADD_TYPE(GSamplerCubeArray);
194 ADD_TYPE(GSamplerBuffer);
195 ADD_TYPE(GSampler2DMS);
196 ADD_TYPE(GSampler2DMSArray);
197
198 ADD_TYPE(Sampler1DShadow);
199 ADD_TYPE(Sampler2DShadow);
200 ADD_TYPE(SamplerCubeShadow);
201 ADD_TYPE(Sampler2DRectShadow);
202 ADD_TYPE(Sampler1DArrayShadow);
203 ADD_TYPE(Sampler2DArrayShadow);
204 ADD_TYPE(SamplerCubeArrayShadow);
205 ADD_TYPE(GSampler2DArrayShadow);
206 ADD_TYPE(GSamplerCubeArrayShadow);
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400207 ADD_TYPE(FragmentProcessor);
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400208 ADD_TYPE(SkRasterPipeline);
ethannicholasb3058bd2016-07-01 08:22:01 -0700209
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700210 StringFragment skCapsName("sk_Caps");
211 Variable* skCaps = new Variable(-1, Modifiers(), skCapsName,
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400212 *fContext->fSkCaps_Type, Variable::kGlobal_Storage);
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500213 fIRGenerator->fSymbolTable->add(skCapsName, std::unique_ptr<Symbol>(skCaps));
214
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700215 StringFragment skArgsName("sk_Args");
216 Variable* skArgs = new Variable(-1, Modifiers(), skArgsName,
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400217 *fContext->fSkArgs_Type, Variable::kGlobal_Storage);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400218 fIRGenerator->fSymbolTable->add(skArgsName, std::unique_ptr<Symbol>(skArgs));
219
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400220 std::vector<std::unique_ptr<ProgramElement>> ignored;
Robert Phillipsfe8da172018-01-24 14:52:02 +0000221 fIRGenerator->convertProgram(Program::kFragment_Kind, SKSL_INCLUDE, strlen(SKSL_INCLUDE),
222 *fTypes, &ignored);
ethannicholasddb37d62016-10-20 09:54:00 -0700223 fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700224 if (fErrorCount) {
225 printf("Unexpected errors: %s\n", fErrorText.c_str());
226 }
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400227 SkASSERT(!fErrorCount);
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400228
229 Program::Settings settings;
230 fIRGenerator->start(&settings, nullptr);
231 fIRGenerator->convertProgram(Program::kFragment_Kind, SKSL_VERT_INCLUDE,
232 strlen(SKSL_VERT_INCLUDE), *fTypes, &fVertexInclude);
233 fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
234 fVertexSymbolTable = fIRGenerator->fSymbolTable;
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400235
236 fIRGenerator->start(&settings, nullptr);
237 fIRGenerator->convertProgram(Program::kVertex_Kind, SKSL_FRAG_INCLUDE,
238 strlen(SKSL_FRAG_INCLUDE), *fTypes, &fFragmentInclude);
239 fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
240 fFragmentSymbolTable = fIRGenerator->fSymbolTable;
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400241
242 fIRGenerator->start(&settings, nullptr);
243 fIRGenerator->convertProgram(Program::kGeometry_Kind, SKSL_GEOM_INCLUDE,
244 strlen(SKSL_GEOM_INCLUDE), *fTypes, &fGeometryInclude);
245 fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
246 fGeometrySymbolTable = fIRGenerator->fSymbolTable;
ethannicholasb3058bd2016-07-01 08:22:01 -0700247}
248
249Compiler::~Compiler() {
250 delete fIRGenerator;
251}
252
ethannicholas22f939e2016-10-13 13:25:34 -0700253// add the definition created by assigning to the lvalue to the definition set
Ethan Nicholas86a43402017-01-19 13:32:00 -0500254void Compiler::addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr,
255 DefinitionMap* definitions) {
ethannicholas22f939e2016-10-13 13:25:34 -0700256 switch (lvalue->fKind) {
257 case Expression::kVariableReference_Kind: {
258 const Variable& var = ((VariableReference*) lvalue)->fVariable;
259 if (var.fStorage == Variable::kLocal_Storage) {
260 (*definitions)[&var] = expr;
261 }
262 break;
263 }
264 case Expression::kSwizzle_Kind:
265 // We consider the variable written to as long as at least some of its components have
266 // been written to. This will lead to some false negatives (we won't catch it if you
267 // write to foo.x and then read foo.y), but being stricter could lead to false positives
Mike Klein6ad99092016-10-26 10:35:22 -0400268 // (we write to foo.x, and then pass foo to a function which happens to only read foo.x,
269 // but since we pass foo as a whole it is flagged as an error) unless we perform a much
ethannicholas22f939e2016-10-13 13:25:34 -0700270 // more complicated whole-program analysis. This is probably good enough.
Mike Klein6ad99092016-10-26 10:35:22 -0400271 this->addDefinition(((Swizzle*) lvalue)->fBase.get(),
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400272 (std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
ethannicholas22f939e2016-10-13 13:25:34 -0700273 definitions);
274 break;
275 case Expression::kIndex_Kind:
276 // see comments in Swizzle
Mike Klein6ad99092016-10-26 10:35:22 -0400277 this->addDefinition(((IndexExpression*) lvalue)->fBase.get(),
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400278 (std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
ethannicholas22f939e2016-10-13 13:25:34 -0700279 definitions);
280 break;
281 case Expression::kFieldAccess_Kind:
282 // see comments in Swizzle
Mike Klein6ad99092016-10-26 10:35:22 -0400283 this->addDefinition(((FieldAccess*) lvalue)->fBase.get(),
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400284 (std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
ethannicholas22f939e2016-10-13 13:25:34 -0700285 definitions);
286 break;
Ethan Nicholasa583b812018-01-18 13:32:11 -0500287 case Expression::kTernary_Kind:
288 // To simplify analysis, we just pretend that we write to both sides of the ternary.
289 // This allows for false positives (meaning we fail to detect that a variable might not
290 // have been assigned), but is preferable to false negatives.
291 this->addDefinition(((TernaryExpression*) lvalue)->fIfTrue.get(),
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400292 (std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
Ethan Nicholasa583b812018-01-18 13:32:11 -0500293 definitions);
294 this->addDefinition(((TernaryExpression*) lvalue)->fIfFalse.get(),
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400295 (std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
Ethan Nicholasa583b812018-01-18 13:32:11 -0500296 definitions);
297 break;
ethannicholas22f939e2016-10-13 13:25:34 -0700298 default:
299 // not an lvalue, can't happen
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400300 SkASSERT(false);
ethannicholas22f939e2016-10-13 13:25:34 -0700301 }
302}
303
304// add local variables defined by this node to the set
Mike Klein6ad99092016-10-26 10:35:22 -0400305void Compiler::addDefinitions(const BasicBlock::Node& node,
Ethan Nicholas86a43402017-01-19 13:32:00 -0500306 DefinitionMap* definitions) {
ethannicholas22f939e2016-10-13 13:25:34 -0700307 switch (node.fKind) {
308 case BasicBlock::Node::kExpression_Kind: {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400309 SkASSERT(node.expression());
Ethan Nicholascb670962017-04-20 19:31:52 -0400310 const Expression* expr = (Expression*) node.expression()->get();
Ethan Nicholas86a43402017-01-19 13:32:00 -0500311 switch (expr->fKind) {
312 case Expression::kBinary_Kind: {
313 BinaryExpression* b = (BinaryExpression*) expr;
314 if (b->fOperator == Token::EQ) {
315 this->addDefinition(b->fLeft.get(), &b->fRight, definitions);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700316 } else if (Compiler::IsAssignment(b->fOperator)) {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500317 this->addDefinition(
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400318 b->fLeft.get(),
319 (std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
320 definitions);
Ethan Nicholas86a43402017-01-19 13:32:00 -0500321
322 }
323 break;
ethannicholas22f939e2016-10-13 13:25:34 -0700324 }
Ethan Nicholasc6a19f12018-03-29 16:46:56 -0400325 case Expression::kFunctionCall_Kind: {
326 const FunctionCall& c = (const FunctionCall&) *expr;
327 for (size_t i = 0; i < c.fFunction.fParameters.size(); ++i) {
328 if (c.fFunction.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag) {
329 this->addDefinition(
330 c.fArguments[i].get(),
331 (std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
332 definitions);
333 }
334 }
335 break;
336 }
Ethan Nicholas86a43402017-01-19 13:32:00 -0500337 case Expression::kPrefix_Kind: {
338 const PrefixExpression* p = (PrefixExpression*) expr;
339 if (p->fOperator == Token::MINUSMINUS || p->fOperator == Token::PLUSPLUS) {
340 this->addDefinition(
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400341 p->fOperand.get(),
342 (std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
343 definitions);
Ethan Nicholas86a43402017-01-19 13:32:00 -0500344 }
345 break;
346 }
347 case Expression::kPostfix_Kind: {
348 const PostfixExpression* p = (PostfixExpression*) expr;
349 if (p->fOperator == Token::MINUSMINUS || p->fOperator == Token::PLUSPLUS) {
350 this->addDefinition(
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400351 p->fOperand.get(),
352 (std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
353 definitions);
Ethan Nicholas86a43402017-01-19 13:32:00 -0500354 }
355 break;
356 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400357 case Expression::kVariableReference_Kind: {
358 const VariableReference* v = (VariableReference*) expr;
359 if (v->fRefKind != VariableReference::kRead_RefKind) {
360 this->addDefinition(
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400361 v,
362 (std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
363 definitions);
Ethan Nicholascb670962017-04-20 19:31:52 -0400364 }
365 }
Ethan Nicholas86a43402017-01-19 13:32:00 -0500366 default:
367 break;
ethannicholas22f939e2016-10-13 13:25:34 -0700368 }
369 break;
370 }
371 case BasicBlock::Node::kStatement_Kind: {
Ethan Nicholascb670962017-04-20 19:31:52 -0400372 const Statement* stmt = (Statement*) node.statement()->get();
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000373 if (stmt->fKind == Statement::kVarDeclaration_Kind) {
374 VarDeclaration& vd = (VarDeclaration&) *stmt;
375 if (vd.fValue) {
376 (*definitions)[vd.fVar] = &vd.fValue;
ethannicholas22f939e2016-10-13 13:25:34 -0700377 }
378 }
379 break;
380 }
381 }
382}
383
384void Compiler::scanCFG(CFG* cfg, BlockId blockId, std::set<BlockId>* workList) {
385 BasicBlock& block = cfg->fBlocks[blockId];
386
387 // compute definitions after this block
Ethan Nicholas86a43402017-01-19 13:32:00 -0500388 DefinitionMap after = block.fBefore;
ethannicholas22f939e2016-10-13 13:25:34 -0700389 for (const BasicBlock::Node& n : block.fNodes) {
390 this->addDefinitions(n, &after);
391 }
392
393 // propagate definitions to exits
394 for (BlockId exitId : block.fExits) {
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400395 if (exitId == blockId) {
396 continue;
397 }
ethannicholas22f939e2016-10-13 13:25:34 -0700398 BasicBlock& exit = cfg->fBlocks[exitId];
399 for (const auto& pair : after) {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500400 std::unique_ptr<Expression>* e1 = pair.second;
401 auto found = exit.fBefore.find(pair.first);
402 if (found == exit.fBefore.end()) {
403 // exit has no definition for it, just copy it
404 workList->insert(exitId);
ethannicholas22f939e2016-10-13 13:25:34 -0700405 exit.fBefore[pair.first] = e1;
406 } else {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500407 // exit has a (possibly different) value already defined
408 std::unique_ptr<Expression>* e2 = exit.fBefore[pair.first];
ethannicholas22f939e2016-10-13 13:25:34 -0700409 if (e1 != e2) {
410 // definition has changed, merge and add exit block to worklist
411 workList->insert(exitId);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500412 if (e1 && e2) {
413 exit.fBefore[pair.first] =
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400414 (std::unique_ptr<Expression>*) &fContext->fDefined_Expression;
Ethan Nicholasaf197692017-02-27 13:26:45 -0500415 } else {
416 exit.fBefore[pair.first] = nullptr;
417 }
ethannicholas22f939e2016-10-13 13:25:34 -0700418 }
419 }
420 }
421 }
422}
423
424// returns a map which maps all local variables in the function to null, indicating that their value
425// is initially unknown
Ethan Nicholas86a43402017-01-19 13:32:00 -0500426static DefinitionMap compute_start_state(const CFG& cfg) {
427 DefinitionMap result;
Mike Klein6ad99092016-10-26 10:35:22 -0400428 for (const auto& block : cfg.fBlocks) {
429 for (const auto& node : block.fNodes) {
ethannicholas22f939e2016-10-13 13:25:34 -0700430 if (node.fKind == BasicBlock::Node::kStatement_Kind) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400431 SkASSERT(node.statement());
Ethan Nicholascb670962017-04-20 19:31:52 -0400432 const Statement* s = node.statement()->get();
ethannicholas22f939e2016-10-13 13:25:34 -0700433 if (s->fKind == Statement::kVarDeclarations_Kind) {
434 const VarDeclarationsStatement* vd = (const VarDeclarationsStatement*) s;
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000435 for (const auto& decl : vd->fDeclaration->fVars) {
436 if (decl->fKind == Statement::kVarDeclaration_Kind) {
437 result[((VarDeclaration&) *decl).fVar] = nullptr;
438 }
Mike Klein6ad99092016-10-26 10:35:22 -0400439 }
ethannicholas22f939e2016-10-13 13:25:34 -0700440 }
441 }
442 }
443 }
444 return result;
445}
446
Ethan Nicholascb670962017-04-20 19:31:52 -0400447/**
448 * Returns true if assigning to this lvalue has no effect.
449 */
450static bool is_dead(const Expression& lvalue) {
451 switch (lvalue.fKind) {
452 case Expression::kVariableReference_Kind:
453 return ((VariableReference&) lvalue).fVariable.dead();
454 case Expression::kSwizzle_Kind:
455 return is_dead(*((Swizzle&) lvalue).fBase);
456 case Expression::kFieldAccess_Kind:
457 return is_dead(*((FieldAccess&) lvalue).fBase);
458 case Expression::kIndex_Kind: {
459 const IndexExpression& idx = (IndexExpression&) lvalue;
460 return is_dead(*idx.fBase) && !idx.fIndex->hasSideEffects();
461 }
Ethan Nicholasa583b812018-01-18 13:32:11 -0500462 case Expression::kTernary_Kind: {
463 const TernaryExpression& t = (TernaryExpression&) lvalue;
464 return !t.fTest->hasSideEffects() && is_dead(*t.fIfTrue) && is_dead(*t.fIfFalse);
465 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400466 default:
467 ABORT("invalid lvalue: %s\n", lvalue.description().c_str());
468 }
469}
ethannicholas22f939e2016-10-13 13:25:34 -0700470
Ethan Nicholascb670962017-04-20 19:31:52 -0400471/**
472 * Returns true if this is an assignment which can be collapsed down to just the right hand side due
473 * to a dead target and lack of side effects on the left hand side.
474 */
475static bool dead_assignment(const BinaryExpression& b) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700476 if (!Compiler::IsAssignment(b.fOperator)) {
Ethan Nicholascb670962017-04-20 19:31:52 -0400477 return false;
478 }
479 return is_dead(*b.fLeft);
480}
481
482void Compiler::computeDataFlow(CFG* cfg) {
483 cfg->fBlocks[cfg->fStart].fBefore = compute_start_state(*cfg);
ethannicholas22f939e2016-10-13 13:25:34 -0700484 std::set<BlockId> workList;
Ethan Nicholascb670962017-04-20 19:31:52 -0400485 for (BlockId i = 0; i < cfg->fBlocks.size(); i++) {
ethannicholas22f939e2016-10-13 13:25:34 -0700486 workList.insert(i);
487 }
488 while (workList.size()) {
489 BlockId next = *workList.begin();
490 workList.erase(workList.begin());
Ethan Nicholascb670962017-04-20 19:31:52 -0400491 this->scanCFG(cfg, next, &workList);
ethannicholas22f939e2016-10-13 13:25:34 -0700492 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400493}
494
495/**
496 * Attempts to replace the expression pointed to by iter with a new one (in both the CFG and the
497 * IR). If the expression can be cleanly removed, returns true and updates the iterator to point to
498 * the newly-inserted element. Otherwise updates only the IR and returns false (and the CFG will
499 * need to be regenerated).
500 */
501bool try_replace_expression(BasicBlock* b,
502 std::vector<BasicBlock::Node>::iterator* iter,
503 std::unique_ptr<Expression>* newExpression) {
504 std::unique_ptr<Expression>* target = (*iter)->expression();
505 if (!b->tryRemoveExpression(iter)) {
506 *target = std::move(*newExpression);
507 return false;
508 }
509 *target = std::move(*newExpression);
510 return b->tryInsertExpression(iter, target);
511}
512
513/**
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400514 * Returns true if the expression is a constant numeric literal with the specified value, or a
515 * constant vector with all elements equal to the specified value.
Ethan Nicholascb670962017-04-20 19:31:52 -0400516 */
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400517bool is_constant(const Expression& expr, double value) {
Ethan Nicholascb670962017-04-20 19:31:52 -0400518 switch (expr.fKind) {
519 case Expression::kIntLiteral_Kind:
520 return ((IntLiteral&) expr).fValue == value;
521 case Expression::kFloatLiteral_Kind:
522 return ((FloatLiteral&) expr).fValue == value;
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400523 case Expression::kConstructor_Kind: {
524 Constructor& c = (Constructor&) expr;
525 if (c.fType.kind() == Type::kVector_Kind && c.isConstant()) {
526 for (int i = 0; i < c.fType.columns(); ++i) {
527 if (!is_constant(c.getVecComponent(i), value)) {
528 return false;
529 }
530 }
531 return true;
532 }
533 return false;
534 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400535 default:
536 return false;
537 }
538}
539
540/**
541 * Collapses the binary expression pointed to by iter down to just the right side (in both the IR
542 * and CFG structures).
543 */
544void delete_left(BasicBlock* b,
545 std::vector<BasicBlock::Node>::iterator* iter,
546 bool* outUpdated,
547 bool* outNeedsRescan) {
548 *outUpdated = true;
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400549 std::unique_ptr<Expression>* target = (*iter)->expression();
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400550 SkASSERT((*target)->fKind == Expression::kBinary_Kind);
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400551 BinaryExpression& bin = (BinaryExpression&) **target;
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400552 SkASSERT(!bin.fLeft->hasSideEffects());
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400553 bool result;
554 if (bin.fOperator == Token::EQ) {
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400555 result = b->tryRemoveLValueBefore(iter, bin.fLeft.get());
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400556 } else {
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400557 result = b->tryRemoveExpressionBefore(iter, bin.fLeft.get());
Ethan Nicholascb670962017-04-20 19:31:52 -0400558 }
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400559 *target = std::move(bin.fRight);
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400560 if (!result) {
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400561 *outNeedsRescan = true;
562 return;
563 }
564 if (*iter == b->fNodes.begin()) {
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400565 *outNeedsRescan = true;
566 return;
567 }
568 --(*iter);
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400569 if ((*iter)->fKind != BasicBlock::Node::kExpression_Kind ||
570 (*iter)->expression() != &bin.fRight) {
571 *outNeedsRescan = true;
572 return;
573 }
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400574 *iter = b->fNodes.erase(*iter);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400575 SkASSERT((*iter)->expression() == target);
Ethan Nicholascb670962017-04-20 19:31:52 -0400576}
577
578/**
579 * Collapses the binary expression pointed to by iter down to just the left side (in both the IR and
580 * CFG structures).
581 */
582void delete_right(BasicBlock* b,
583 std::vector<BasicBlock::Node>::iterator* iter,
584 bool* outUpdated,
585 bool* outNeedsRescan) {
586 *outUpdated = true;
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400587 std::unique_ptr<Expression>* target = (*iter)->expression();
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400588 SkASSERT((*target)->fKind == Expression::kBinary_Kind);
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400589 BinaryExpression& bin = (BinaryExpression&) **target;
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400590 SkASSERT(!bin.fRight->hasSideEffects());
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400591 if (!b->tryRemoveExpressionBefore(iter, bin.fRight.get())) {
592 *target = std::move(bin.fLeft);
Ethan Nicholascb670962017-04-20 19:31:52 -0400593 *outNeedsRescan = true;
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400594 return;
Ethan Nicholascb670962017-04-20 19:31:52 -0400595 }
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400596 *target = std::move(bin.fLeft);
597 if (*iter == b->fNodes.begin()) {
598 *outNeedsRescan = true;
599 return;
600 }
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400601 --(*iter);
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400602 if (((*iter)->fKind != BasicBlock::Node::kExpression_Kind ||
603 (*iter)->expression() != &bin.fLeft)) {
604 *outNeedsRescan = true;
605 return;
606 }
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400607 *iter = b->fNodes.erase(*iter);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400608 SkASSERT((*iter)->expression() == target);
Ethan Nicholascb670962017-04-20 19:31:52 -0400609}
610
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400611/**
612 * Constructs the specified type using a single argument.
613 */
614static std::unique_ptr<Expression> construct(const Type& type, std::unique_ptr<Expression> v) {
615 std::vector<std::unique_ptr<Expression>> args;
616 args.push_back(std::move(v));
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700617 auto result = std::unique_ptr<Expression>(new Constructor(-1, type, std::move(args)));
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400618 return result;
619}
620
621/**
622 * Used in the implementations of vectorize_left and vectorize_right. Given a vector type and an
623 * expression x, deletes the expression pointed to by iter and replaces it with <type>(x).
624 */
625static void vectorize(BasicBlock* b,
626 std::vector<BasicBlock::Node>::iterator* iter,
627 const Type& type,
628 std::unique_ptr<Expression>* otherExpression,
629 bool* outUpdated,
630 bool* outNeedsRescan) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400631 SkASSERT((*(*iter)->expression())->fKind == Expression::kBinary_Kind);
632 SkASSERT(type.kind() == Type::kVector_Kind);
633 SkASSERT((*otherExpression)->fType.kind() == Type::kScalar_Kind);
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400634 *outUpdated = true;
635 std::unique_ptr<Expression>* target = (*iter)->expression();
636 if (!b->tryRemoveExpression(iter)) {
637 *target = construct(type, std::move(*otherExpression));
638 *outNeedsRescan = true;
639 } else {
640 *target = construct(type, std::move(*otherExpression));
641 if (!b->tryInsertExpression(iter, target)) {
642 *outNeedsRescan = true;
643 }
644 }
645}
646
647/**
648 * Given a binary expression of the form x <op> vec<n>(y), deletes the right side and vectorizes the
649 * left to yield vec<n>(x).
650 */
651static void vectorize_left(BasicBlock* b,
652 std::vector<BasicBlock::Node>::iterator* iter,
653 bool* outUpdated,
654 bool* outNeedsRescan) {
655 BinaryExpression& bin = (BinaryExpression&) **(*iter)->expression();
656 vectorize(b, iter, bin.fRight->fType, &bin.fLeft, outUpdated, outNeedsRescan);
657}
658
659/**
660 * Given a binary expression of the form vec<n>(x) <op> y, deletes the left side and vectorizes the
661 * right to yield vec<n>(y).
662 */
663static void vectorize_right(BasicBlock* b,
664 std::vector<BasicBlock::Node>::iterator* iter,
665 bool* outUpdated,
666 bool* outNeedsRescan) {
667 BinaryExpression& bin = (BinaryExpression&) **(*iter)->expression();
668 vectorize(b, iter, bin.fLeft->fType, &bin.fRight, outUpdated, outNeedsRescan);
669}
670
671// Mark that an expression which we were writing to is no longer being written to
672void clear_write(const Expression& expr) {
673 switch (expr.fKind) {
674 case Expression::kVariableReference_Kind: {
675 ((VariableReference&) expr).setRefKind(VariableReference::kRead_RefKind);
676 break;
677 }
678 case Expression::kFieldAccess_Kind:
679 clear_write(*((FieldAccess&) expr).fBase);
680 break;
681 case Expression::kSwizzle_Kind:
682 clear_write(*((Swizzle&) expr).fBase);
683 break;
684 case Expression::kIndex_Kind:
685 clear_write(*((IndexExpression&) expr).fBase);
686 break;
687 default:
688 ABORT("shouldn't be writing to this kind of expression\n");
689 break;
690 }
691}
692
Ethan Nicholascb670962017-04-20 19:31:52 -0400693void Compiler::simplifyExpression(DefinitionMap& definitions,
694 BasicBlock& b,
695 std::vector<BasicBlock::Node>::iterator* iter,
696 std::unordered_set<const Variable*>* undefinedVariables,
697 bool* outUpdated,
698 bool* outNeedsRescan) {
699 Expression* expr = (*iter)->expression()->get();
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400700 SkASSERT(expr);
Ethan Nicholascb670962017-04-20 19:31:52 -0400701 if ((*iter)->fConstantPropagation) {
702 std::unique_ptr<Expression> optimized = expr->constantPropagate(*fIRGenerator, definitions);
703 if (optimized) {
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400704 *outUpdated = true;
Ethan Nicholascb670962017-04-20 19:31:52 -0400705 if (!try_replace_expression(&b, iter, &optimized)) {
706 *outNeedsRescan = true;
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400707 return;
Ethan Nicholascb670962017-04-20 19:31:52 -0400708 }
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400709 SkASSERT((*iter)->fKind == BasicBlock::Node::kExpression_Kind);
Ethan Nicholascb670962017-04-20 19:31:52 -0400710 expr = (*iter)->expression()->get();
Ethan Nicholascb670962017-04-20 19:31:52 -0400711 }
712 }
713 switch (expr->fKind) {
714 case Expression::kVariableReference_Kind: {
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -0400715 const VariableReference& ref = (VariableReference&) *expr;
716 const Variable& var = ref.fVariable;
717 if (ref.refKind() != VariableReference::kWrite_RefKind &&
718 ref.refKind() != VariableReference::kPointer_RefKind &&
719 var.fStorage == Variable::kLocal_Storage && !definitions[&var] &&
Ethan Nicholascb670962017-04-20 19:31:52 -0400720 (*undefinedVariables).find(&var) == (*undefinedVariables).end()) {
721 (*undefinedVariables).insert(&var);
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000722 this->error(expr->fOffset,
723 "'" + var.fName + "' has not been assigned");
Ethan Nicholascb670962017-04-20 19:31:52 -0400724 }
725 break;
726 }
727 case Expression::kTernary_Kind: {
728 TernaryExpression* t = (TernaryExpression*) expr;
729 if (t->fTest->fKind == Expression::kBoolLiteral_Kind) {
730 // ternary has a constant test, replace it with either the true or
731 // false branch
732 if (((BoolLiteral&) *t->fTest).fValue) {
733 (*iter)->setExpression(std::move(t->fIfTrue));
734 } else {
735 (*iter)->setExpression(std::move(t->fIfFalse));
736 }
737 *outUpdated = true;
738 *outNeedsRescan = true;
739 }
740 break;
741 }
742 case Expression::kBinary_Kind: {
Ethan Nicholascb670962017-04-20 19:31:52 -0400743 BinaryExpression* bin = (BinaryExpression*) expr;
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400744 if (dead_assignment(*bin)) {
745 delete_left(&b, iter, outUpdated, outNeedsRescan);
746 break;
747 }
748 // collapse useless expressions like x * 1 or x + 0
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400749 if (((bin->fLeft->fType.kind() != Type::kScalar_Kind) &&
750 (bin->fLeft->fType.kind() != Type::kVector_Kind)) ||
751 ((bin->fRight->fType.kind() != Type::kScalar_Kind) &&
752 (bin->fRight->fType.kind() != Type::kVector_Kind))) {
753 break;
754 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400755 switch (bin->fOperator) {
756 case Token::STAR:
757 if (is_constant(*bin->fLeft, 1)) {
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400758 if (bin->fLeft->fType.kind() == Type::kVector_Kind &&
759 bin->fRight->fType.kind() == Type::kScalar_Kind) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400760 // float4(1) * x -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400761 vectorize_right(&b, iter, outUpdated, outNeedsRescan);
762 } else {
763 // 1 * x -> x
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400764 // 1 * float4(x) -> float4(x)
765 // float4(1) * float4(x) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400766 delete_left(&b, iter, outUpdated, outNeedsRescan);
767 }
768 }
769 else if (is_constant(*bin->fLeft, 0)) {
770 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
Ethan Nicholas08dae922018-01-23 10:31:56 -0500771 bin->fRight->fType.kind() == Type::kVector_Kind &&
772 !bin->fRight->hasSideEffects()) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400773 // 0 * float4(x) -> float4(0)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400774 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
775 } else {
776 // 0 * x -> 0
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400777 // float4(0) * x -> float4(0)
778 // float4(0) * float4(x) -> float4(0)
Ethan Nicholas51493ee2017-12-11 12:34:33 -0500779 if (!bin->fRight->hasSideEffects()) {
780 delete_right(&b, iter, outUpdated, outNeedsRescan);
781 }
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400782 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400783 }
784 else if (is_constant(*bin->fRight, 1)) {
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400785 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
786 bin->fRight->fType.kind() == Type::kVector_Kind) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400787 // x * float4(1) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400788 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
789 } else {
790 // x * 1 -> x
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400791 // float4(x) * 1 -> float4(x)
792 // float4(x) * float4(1) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400793 delete_right(&b, iter, outUpdated, outNeedsRescan);
794 }
795 }
796 else if (is_constant(*bin->fRight, 0)) {
797 if (bin->fLeft->fType.kind() == Type::kVector_Kind &&
Ethan Nicholas08dae922018-01-23 10:31:56 -0500798 bin->fRight->fType.kind() == Type::kScalar_Kind &&
799 !bin->fLeft->hasSideEffects()) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400800 // float4(x) * 0 -> float4(0)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400801 vectorize_right(&b, iter, outUpdated, outNeedsRescan);
802 } else {
803 // x * 0 -> 0
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400804 // x * float4(0) -> float4(0)
805 // float4(x) * float4(0) -> float4(0)
Ethan Nicholas51493ee2017-12-11 12:34:33 -0500806 if (!bin->fLeft->hasSideEffects()) {
807 delete_left(&b, iter, outUpdated, outNeedsRescan);
808 }
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400809 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400810 }
811 break;
Ethan Nicholas56e42712017-04-21 10:23:37 -0400812 case Token::PLUS:
Ethan Nicholascb670962017-04-20 19:31:52 -0400813 if (is_constant(*bin->fLeft, 0)) {
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400814 if (bin->fLeft->fType.kind() == Type::kVector_Kind &&
815 bin->fRight->fType.kind() == Type::kScalar_Kind) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400816 // float4(0) + x -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400817 vectorize_right(&b, iter, outUpdated, outNeedsRescan);
818 } else {
819 // 0 + x -> x
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400820 // 0 + float4(x) -> float4(x)
821 // float4(0) + float4(x) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400822 delete_left(&b, iter, outUpdated, outNeedsRescan);
823 }
824 } else if (is_constant(*bin->fRight, 0)) {
825 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
826 bin->fRight->fType.kind() == Type::kVector_Kind) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400827 // x + float4(0) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400828 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
829 } else {
830 // x + 0 -> x
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400831 // float4(x) + 0 -> float4(x)
832 // float4(x) + float4(0) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400833 delete_right(&b, iter, outUpdated, outNeedsRescan);
834 }
Ethan Nicholas56e42712017-04-21 10:23:37 -0400835 }
836 break;
837 case Token::MINUS:
838 if (is_constant(*bin->fRight, 0)) {
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400839 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
840 bin->fRight->fType.kind() == Type::kVector_Kind) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400841 // x - float4(0) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400842 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
843 } else {
844 // x - 0 -> x
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400845 // float4(x) - 0 -> float4(x)
846 // float4(x) - float4(0) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400847 delete_right(&b, iter, outUpdated, outNeedsRescan);
848 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400849 }
850 break;
851 case Token::SLASH:
852 if (is_constant(*bin->fRight, 1)) {
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400853 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
854 bin->fRight->fType.kind() == Type::kVector_Kind) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400855 // x / float4(1) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400856 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
857 } else {
858 // x / 1 -> x
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400859 // float4(x) / 1 -> float4(x)
860 // float4(x) / float4(1) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400861 delete_right(&b, iter, outUpdated, outNeedsRescan);
862 }
863 } else if (is_constant(*bin->fLeft, 0)) {
864 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
Ethan Nicholas08dae922018-01-23 10:31:56 -0500865 bin->fRight->fType.kind() == Type::kVector_Kind &&
866 !bin->fRight->hasSideEffects()) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400867 // 0 / float4(x) -> float4(0)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400868 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
869 } else {
870 // 0 / x -> 0
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400871 // float4(0) / x -> float4(0)
872 // float4(0) / float4(x) -> float4(0)
Ethan Nicholas51493ee2017-12-11 12:34:33 -0500873 if (!bin->fRight->hasSideEffects()) {
874 delete_right(&b, iter, outUpdated, outNeedsRescan);
875 }
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400876 }
877 }
878 break;
879 case Token::PLUSEQ:
880 if (is_constant(*bin->fRight, 0)) {
881 clear_write(*bin->fLeft);
882 delete_right(&b, iter, outUpdated, outNeedsRescan);
883 }
884 break;
885 case Token::MINUSEQ:
886 if (is_constant(*bin->fRight, 0)) {
887 clear_write(*bin->fLeft);
888 delete_right(&b, iter, outUpdated, outNeedsRescan);
889 }
890 break;
891 case Token::STAREQ:
892 if (is_constant(*bin->fRight, 1)) {
893 clear_write(*bin->fLeft);
894 delete_right(&b, iter, outUpdated, outNeedsRescan);
895 }
896 break;
897 case Token::SLASHEQ:
898 if (is_constant(*bin->fRight, 1)) {
899 clear_write(*bin->fLeft);
Ethan Nicholascb670962017-04-20 19:31:52 -0400900 delete_right(&b, iter, outUpdated, outNeedsRescan);
901 }
902 break;
903 default:
904 break;
905 }
906 }
907 default:
908 break;
909 }
910}
911
Ethan Nicholas5ac13c22017-05-10 15:06:17 -0400912// returns true if this statement could potentially execute a break at the current level (we ignore
913// nested loops and switches, since any breaks inside of them will merely break the loop / switch)
Ethan Nicholas5005a222018-08-24 13:06:27 -0400914static bool contains_conditional_break(Statement& s, bool inConditional) {
Ethan Nicholas5ac13c22017-05-10 15:06:17 -0400915 switch (s.fKind) {
916 case Statement::kBlock_Kind:
917 for (const auto& sub : ((Block&) s).fStatements) {
Ethan Nicholas5005a222018-08-24 13:06:27 -0400918 if (contains_conditional_break(*sub, inConditional)) {
919 return true;
920 }
921 }
922 return false;
923 case Statement::kBreak_Kind:
924 return inConditional;
925 case Statement::kIf_Kind: {
926 const IfStatement& i = (IfStatement&) s;
927 return contains_conditional_break(*i.fIfTrue, true) ||
928 (i.fIfFalse && contains_conditional_break(*i.fIfFalse, true));
929 }
930 default:
931 return false;
932 }
933}
934
935// returns true if this statement definitely executes a break at the current level (we ignore
936// nested loops and switches, since any breaks inside of them will merely break the loop / switch)
937static bool contains_unconditional_break(Statement& s) {
938 switch (s.fKind) {
939 case Statement::kBlock_Kind:
940 for (const auto& sub : ((Block&) s).fStatements) {
941 if (contains_unconditional_break(*sub)) {
Ethan Nicholas5ac13c22017-05-10 15:06:17 -0400942 return true;
943 }
944 }
945 return false;
946 case Statement::kBreak_Kind:
947 return true;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -0400948 default:
949 return false;
950 }
951}
952
953// Returns a block containing all of the statements that will be run if the given case matches
954// (which, owing to the statements being owned by unique_ptrs, means the switch itself will be
955// broken by this call and must then be discarded).
956// Returns null (and leaves the switch unmodified) if no such simple reduction is possible, such as
957// when break statements appear inside conditionals.
958static std::unique_ptr<Statement> block_for_case(SwitchStatement* s, SwitchCase* c) {
959 bool capturing = false;
960 std::vector<std::unique_ptr<Statement>*> statementPtrs;
961 for (const auto& current : s->fCases) {
962 if (current.get() == c) {
963 capturing = true;
964 }
965 if (capturing) {
966 for (auto& stmt : current->fStatements) {
Ethan Nicholas5005a222018-08-24 13:06:27 -0400967 if (contains_conditional_break(*stmt, s->fKind == Statement::kIf_Kind)) {
968 return nullptr;
969 }
970 if (contains_unconditional_break(*stmt)) {
Ethan Nicholas5ac13c22017-05-10 15:06:17 -0400971 capturing = false;
972 break;
973 }
Ethan Nicholas5ac13c22017-05-10 15:06:17 -0400974 statementPtrs.push_back(&stmt);
975 }
976 if (!capturing) {
977 break;
978 }
979 }
980 }
981 std::vector<std::unique_ptr<Statement>> statements;
982 for (const auto& s : statementPtrs) {
983 statements.push_back(std::move(*s));
984 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700985 return std::unique_ptr<Statement>(new Block(-1, std::move(statements), s->fSymbols));
Ethan Nicholas5ac13c22017-05-10 15:06:17 -0400986}
987
Ethan Nicholascb670962017-04-20 19:31:52 -0400988void Compiler::simplifyStatement(DefinitionMap& definitions,
Ethan Nicholas5ac13c22017-05-10 15:06:17 -0400989 BasicBlock& b,
990 std::vector<BasicBlock::Node>::iterator* iter,
991 std::unordered_set<const Variable*>* undefinedVariables,
992 bool* outUpdated,
993 bool* outNeedsRescan) {
Ethan Nicholascb670962017-04-20 19:31:52 -0400994 Statement* stmt = (*iter)->statement()->get();
995 switch (stmt->fKind) {
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000996 case Statement::kVarDeclaration_Kind: {
997 const auto& varDecl = (VarDeclaration&) *stmt;
998 if (varDecl.fVar->dead() &&
999 (!varDecl.fValue ||
1000 !varDecl.fValue->hasSideEffects())) {
1001 if (varDecl.fValue) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001002 SkASSERT((*iter)->statement()->get() == stmt);
Ethan Nicholas82a62d22017-11-07 14:42:10 +00001003 if (!b.tryRemoveExpressionBefore(iter, varDecl.fValue.get())) {
1004 *outNeedsRescan = true;
Ethan Nicholascb670962017-04-20 19:31:52 -04001005 }
Ethan Nicholascb670962017-04-20 19:31:52 -04001006 }
Ethan Nicholascb670962017-04-20 19:31:52 -04001007 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
Ethan Nicholas82a62d22017-11-07 14:42:10 +00001008 *outUpdated = true;
Ethan Nicholascb670962017-04-20 19:31:52 -04001009 }
1010 break;
1011 }
1012 case Statement::kIf_Kind: {
1013 IfStatement& i = (IfStatement&) *stmt;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001014 if (i.fTest->fKind == Expression::kBoolLiteral_Kind) {
1015 // constant if, collapse down to a single branch
1016 if (((BoolLiteral&) *i.fTest).fValue) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001017 SkASSERT(i.fIfTrue);
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001018 (*iter)->setStatement(std::move(i.fIfTrue));
1019 } else {
1020 if (i.fIfFalse) {
1021 (*iter)->setStatement(std::move(i.fIfFalse));
1022 } else {
1023 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
1024 }
1025 }
1026 *outUpdated = true;
1027 *outNeedsRescan = true;
1028 break;
1029 }
Ethan Nicholascb670962017-04-20 19:31:52 -04001030 if (i.fIfFalse && i.fIfFalse->isEmpty()) {
1031 // else block doesn't do anything, remove it
1032 i.fIfFalse.reset();
1033 *outUpdated = true;
1034 *outNeedsRescan = true;
1035 }
1036 if (!i.fIfFalse && i.fIfTrue->isEmpty()) {
1037 // if block doesn't do anything, no else block
1038 if (i.fTest->hasSideEffects()) {
1039 // test has side effects, keep it
1040 (*iter)->setStatement(std::unique_ptr<Statement>(
1041 new ExpressionStatement(std::move(i.fTest))));
1042 } else {
1043 // no if, no else, no test side effects, kill the whole if
1044 // statement
1045 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
1046 }
1047 *outUpdated = true;
1048 *outNeedsRescan = true;
1049 }
1050 break;
1051 }
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001052 case Statement::kSwitch_Kind: {
1053 SwitchStatement& s = (SwitchStatement&) *stmt;
1054 if (s.fValue->isConstant()) {
1055 // switch is constant, replace it with the case that matches
1056 bool found = false;
1057 SwitchCase* defaultCase = nullptr;
1058 for (const auto& c : s.fCases) {
1059 if (!c->fValue) {
1060 defaultCase = c.get();
1061 continue;
1062 }
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001063 SkASSERT(c->fValue->fKind == s.fValue->fKind);
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001064 found = c->fValue->compareConstant(*fContext, *s.fValue);
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001065 if (found) {
1066 std::unique_ptr<Statement> newBlock = block_for_case(&s, c.get());
1067 if (newBlock) {
1068 (*iter)->setStatement(std::move(newBlock));
1069 break;
1070 } else {
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -04001071 if (s.fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001072 this->error(s.fOffset,
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001073 "static switch contains non-static conditional break");
1074 s.fIsStatic = false;
1075 }
1076 return; // can't simplify
1077 }
1078 }
1079 }
1080 if (!found) {
1081 // no matching case. use default if it exists, or kill the whole thing
1082 if (defaultCase) {
1083 std::unique_ptr<Statement> newBlock = block_for_case(&s, defaultCase);
1084 if (newBlock) {
1085 (*iter)->setStatement(std::move(newBlock));
1086 } else {
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -04001087 if (s.fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001088 this->error(s.fOffset,
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001089 "static switch contains non-static conditional break");
1090 s.fIsStatic = false;
1091 }
1092 return; // can't simplify
1093 }
1094 } else {
1095 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
1096 }
1097 }
1098 *outUpdated = true;
1099 *outNeedsRescan = true;
1100 }
1101 break;
1102 }
Ethan Nicholascb670962017-04-20 19:31:52 -04001103 case Statement::kExpression_Kind: {
1104 ExpressionStatement& e = (ExpressionStatement&) *stmt;
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001105 SkASSERT((*iter)->statement()->get() == &e);
Ethan Nicholascb670962017-04-20 19:31:52 -04001106 if (!e.fExpression->hasSideEffects()) {
1107 // Expression statement with no side effects, kill it
1108 if (!b.tryRemoveExpressionBefore(iter, e.fExpression.get())) {
1109 *outNeedsRescan = true;
1110 }
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001111 SkASSERT((*iter)->statement()->get() == stmt);
Ethan Nicholascb670962017-04-20 19:31:52 -04001112 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
1113 *outUpdated = true;
1114 }
1115 break;
1116 }
1117 default:
1118 break;
1119 }
1120}
1121
1122void Compiler::scanCFG(FunctionDefinition& f) {
1123 CFG cfg = CFGGenerator().getCFG(f);
1124 this->computeDataFlow(&cfg);
ethannicholas22f939e2016-10-13 13:25:34 -07001125
1126 // check for unreachable code
1127 for (size_t i = 0; i < cfg.fBlocks.size(); i++) {
Mike Klein6ad99092016-10-26 10:35:22 -04001128 if (i != cfg.fStart && !cfg.fBlocks[i].fEntrances.size() &&
ethannicholas22f939e2016-10-13 13:25:34 -07001129 cfg.fBlocks[i].fNodes.size()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001130 int offset;
Ethan Nicholas86a43402017-01-19 13:32:00 -05001131 switch (cfg.fBlocks[i].fNodes[0].fKind) {
1132 case BasicBlock::Node::kStatement_Kind:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001133 offset = (*cfg.fBlocks[i].fNodes[0].statement())->fOffset;
Ethan Nicholas86a43402017-01-19 13:32:00 -05001134 break;
1135 case BasicBlock::Node::kExpression_Kind:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001136 offset = (*cfg.fBlocks[i].fNodes[0].expression())->fOffset;
Ethan Nicholas86a43402017-01-19 13:32:00 -05001137 break;
1138 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001139 this->error(offset, String("unreachable"));
ethannicholas22f939e2016-10-13 13:25:34 -07001140 }
1141 }
1142 if (fErrorCount) {
1143 return;
1144 }
1145
Ethan Nicholascb670962017-04-20 19:31:52 -04001146 // check for dead code & undefined variables, perform constant propagation
1147 std::unordered_set<const Variable*> undefinedVariables;
1148 bool updated;
1149 bool needsRescan = false;
1150 do {
1151 if (needsRescan) {
1152 cfg = CFGGenerator().getCFG(f);
1153 this->computeDataFlow(&cfg);
1154 needsRescan = false;
Ethan Nicholas113628d2017-02-02 16:11:39 -05001155 }
Ethan Nicholascb670962017-04-20 19:31:52 -04001156
1157 updated = false;
1158 for (BasicBlock& b : cfg.fBlocks) {
1159 DefinitionMap definitions = b.fBefore;
1160
1161 for (auto iter = b.fNodes.begin(); iter != b.fNodes.end() && !needsRescan; ++iter) {
1162 if (iter->fKind == BasicBlock::Node::kExpression_Kind) {
1163 this->simplifyExpression(definitions, b, &iter, &undefinedVariables, &updated,
1164 &needsRescan);
1165 } else {
1166 this->simplifyStatement(definitions, b, &iter, &undefinedVariables, &updated,
1167 &needsRescan);
1168 }
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001169 if (needsRescan) {
1170 break;
1171 }
Ethan Nicholascb670962017-04-20 19:31:52 -04001172 this->addDefinitions(*iter, &definitions);
1173 }
1174 }
1175 } while (updated);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001176 SkASSERT(!needsRescan);
ethannicholas22f939e2016-10-13 13:25:34 -07001177
Ethan Nicholas91a10532017-06-22 11:24:38 -04001178 // verify static ifs & switches, clean up dead variable decls
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001179 for (BasicBlock& b : cfg.fBlocks) {
1180 DefinitionMap definitions = b.fBefore;
1181
Ethan Nicholas91a10532017-06-22 11:24:38 -04001182 for (auto iter = b.fNodes.begin(); iter != b.fNodes.end() && !needsRescan;) {
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001183 if (iter->fKind == BasicBlock::Node::kStatement_Kind) {
1184 const Statement& s = **iter->statement();
1185 switch (s.fKind) {
1186 case Statement::kIf_Kind:
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -04001187 if (((const IfStatement&) s).fIsStatic &&
1188 !(fFlags & kPermitInvalidStaticTests_Flag)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001189 this->error(s.fOffset, "static if has non-static test");
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001190 }
Ethan Nicholas91a10532017-06-22 11:24:38 -04001191 ++iter;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001192 break;
1193 case Statement::kSwitch_Kind:
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -04001194 if (((const SwitchStatement&) s).fIsStatic &&
1195 !(fFlags & kPermitInvalidStaticTests_Flag)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001196 this->error(s.fOffset, "static switch has non-static test");
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001197 }
Ethan Nicholas91a10532017-06-22 11:24:38 -04001198 ++iter;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001199 break;
Ethan Nicholas82a62d22017-11-07 14:42:10 +00001200 case Statement::kVarDeclarations_Kind: {
1201 VarDeclarations& decls = *((VarDeclarationsStatement&) s).fDeclaration;
1202 for (auto varIter = decls.fVars.begin(); varIter != decls.fVars.end();) {
1203 if ((*varIter)->fKind == Statement::kNop_Kind) {
1204 varIter = decls.fVars.erase(varIter);
1205 } else {
1206 ++varIter;
1207 }
1208 }
1209 if (!decls.fVars.size()) {
1210 iter = b.fNodes.erase(iter);
1211 } else {
1212 ++iter;
1213 }
1214 break;
1215 }
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001216 default:
Ethan Nicholas91a10532017-06-22 11:24:38 -04001217 ++iter;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001218 break;
1219 }
Ethan Nicholas91a10532017-06-22 11:24:38 -04001220 } else {
1221 ++iter;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001222 }
1223 }
1224 }
1225
ethannicholas22f939e2016-10-13 13:25:34 -07001226 // check for missing return
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001227 if (f.fDeclaration.fReturnType != *fContext->fVoid_Type) {
ethannicholas22f939e2016-10-13 13:25:34 -07001228 if (cfg.fBlocks[cfg.fExit].fEntrances.size()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001229 this->error(f.fOffset, String("function can exit without returning a value"));
ethannicholas22f939e2016-10-13 13:25:34 -07001230 }
1231 }
1232}
1233
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001234std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String text,
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001235 const Program::Settings& settings) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001236 fErrorText = "";
1237 fErrorCount = 0;
Ethan Nicholas3c6ae622018-04-24 13:06:09 -04001238 std::vector<std::unique_ptr<ProgramElement>>* inherited;
ethannicholasd598f792016-07-25 10:08:54 -07001239 std::vector<std::unique_ptr<ProgramElement>> elements;
ethannicholasb3058bd2016-07-01 08:22:01 -07001240 switch (kind) {
1241 case Program::kVertex_Kind:
Ethan Nicholas3c6ae622018-04-24 13:06:09 -04001242 inherited = &fVertexInclude;
1243 fIRGenerator->fSymbolTable = fVertexSymbolTable;
1244 fIRGenerator->start(&settings, inherited);
ethannicholasb3058bd2016-07-01 08:22:01 -07001245 break;
1246 case Program::kFragment_Kind:
Ethan Nicholas3c6ae622018-04-24 13:06:09 -04001247 inherited = &fFragmentInclude;
1248 fIRGenerator->fSymbolTable = fFragmentSymbolTable;
1249 fIRGenerator->start(&settings, inherited);
ethannicholasb3058bd2016-07-01 08:22:01 -07001250 break;
Ethan Nicholas52cad152017-02-16 16:37:32 -05001251 case Program::kGeometry_Kind:
Ethan Nicholas3c6ae622018-04-24 13:06:09 -04001252 inherited = &fGeometryInclude;
1253 fIRGenerator->fSymbolTable = fGeometrySymbolTable;
1254 fIRGenerator->start(&settings, inherited);
Ethan Nicholas52cad152017-02-16 16:37:32 -05001255 break;
Ethan Nicholas762466e2017-06-29 10:03:38 -04001256 case Program::kFragmentProcessor_Kind:
Ethan Nicholas3c6ae622018-04-24 13:06:09 -04001257 inherited = nullptr;
1258 fIRGenerator->start(&settings, nullptr);
Robert Phillipsfe8da172018-01-24 14:52:02 +00001259 fIRGenerator->convertProgram(kind, SKSL_FP_INCLUDE, strlen(SKSL_FP_INCLUDE), *fTypes,
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001260 &elements);
Ethan Nicholas3c6ae622018-04-24 13:06:09 -04001261 fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
Ethan Nicholas762466e2017-06-29 10:03:38 -04001262 break;
Ethan Nicholas00543112018-07-31 09:44:36 -04001263 case Program::kPipelineStage_Kind:
Ethan Nicholas3c6ae622018-04-24 13:06:09 -04001264 inherited = nullptr;
1265 fIRGenerator->start(&settings, nullptr);
Ethan Nicholas00543112018-07-31 09:44:36 -04001266 fIRGenerator->convertProgram(kind, SKSL_PIPELINE_STAGE_INCLUDE,
1267 strlen(SKSL_PIPELINE_STAGE_INCLUDE), *fTypes, &elements);
Ethan Nicholas3c6ae622018-04-24 13:06:09 -04001268 fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001269 break;
ethannicholasb3058bd2016-07-01 08:22:01 -07001270 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001271 for (auto& element : elements) {
1272 if (element->fKind == ProgramElement::kEnum_Kind) {
1273 ((Enum&) *element).fBuiltin = true;
1274 }
1275 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001276 std::unique_ptr<String> textPtr(new String(std::move(text)));
1277 fSource = textPtr.get();
Robert Phillipsfe8da172018-01-24 14:52:02 +00001278 fIRGenerator->convertProgram(kind, textPtr->c_str(), textPtr->size(), *fTypes, &elements);
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001279 auto result = std::unique_ptr<Program>(new Program(kind,
1280 std::move(textPtr),
1281 settings,
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001282 fContext,
Ethan Nicholas3c6ae622018-04-24 13:06:09 -04001283 inherited,
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001284 std::move(elements),
1285 fIRGenerator->fSymbolTable,
1286 fIRGenerator->fInputs));
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001287 if (fErrorCount) {
1288 return nullptr;
1289 }
1290 return result;
1291}
1292
Ethan Nicholas00543112018-07-31 09:44:36 -04001293bool Compiler::optimize(Program& program) {
1294 SkASSERT(!fErrorCount);
1295 if (!program.fIsOptimized) {
1296 program.fIsOptimized = true;
1297 fIRGenerator->fKind = program.fKind;
1298 fIRGenerator->fSettings = &program.fSettings;
1299 for (auto& element : program) {
1300 if (element.fKind == ProgramElement::kFunction_Kind) {
1301 this->scanCFG((FunctionDefinition&) element);
1302 }
1303 }
1304 fSource = nullptr;
1305 }
1306 return fErrorCount == 0;
1307}
1308
1309std::unique_ptr<Program> Compiler::specialize(
1310 Program& program,
1311 const std::unordered_map<SkSL::String, SkSL::Program::Settings::Value>& inputs) {
1312 std::vector<std::unique_ptr<ProgramElement>> elements;
1313 for (const auto& e : program) {
1314 elements.push_back(e.clone());
1315 }
1316 Program::Settings settings;
1317 settings.fCaps = program.fSettings.fCaps;
1318 for (auto iter = inputs.begin(); iter != inputs.end(); ++iter) {
1319 settings.fArgs.insert(*iter);
1320 }
1321 std::unique_ptr<Program> result(new Program(program.fKind,
1322 nullptr,
1323 settings,
1324 program.fContext,
1325 program.fInheritedElements,
1326 std::move(elements),
1327 program.fSymbols,
1328 program.fInputs));
1329 return result;
1330}
1331
1332bool Compiler::toSPIRV(Program& program, OutputStream& out) {
1333 if (!this->optimize(program)) {
1334 return false;
1335 }
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001336#ifdef SK_ENABLE_SPIRV_VALIDATION
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001337 StringStream buffer;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001338 fSource = program.fSource.get();
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001339 SPIRVCodeGenerator cg(fContext.get(), &program, this, &buffer);
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001340 bool result = cg.generateCode();
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001341 fSource = nullptr;
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001342 if (result) {
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001343 spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0);
Ethan Nicholas762466e2017-06-29 10:03:38 -04001344 const String& data = buffer.str();
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001345 SkASSERT(0 == data.size() % 4);
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001346 auto dumpmsg = [](spv_message_level_t, const char*, const spv_position_t&, const char* m) {
1347 SkDebugf("SPIR-V validation error: %s\n", m);
1348 };
1349 tools.SetMessageConsumer(dumpmsg);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001350 // Verify that the SPIR-V we produced is valid. If this SkASSERT fails, check the logs prior
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001351 // to the failure to see the validation errors.
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001352 SkAssertResult(tools.Validate((const uint32_t*) data.c_str(), data.size() / 4));
Ethan Nicholas762466e2017-06-29 10:03:38 -04001353 out.write(data.c_str(), data.size());
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001354 }
1355#else
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001356 fSource = program.fSource.get();
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001357 SPIRVCodeGenerator cg(fContext.get(), &program, this, &out);
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001358 bool result = cg.generateCode();
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001359 fSource = nullptr;
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001360#endif
Ethan Nicholasce33f102016-12-09 17:22:59 -05001361 return result;
1362}
1363
Ethan Nicholas00543112018-07-31 09:44:36 -04001364bool Compiler::toSPIRV(Program& program, String* out) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001365 StringStream buffer;
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001366 bool result = this->toSPIRV(program, buffer);
1367 if (result) {
Ethan Nicholas762466e2017-06-29 10:03:38 -04001368 *out = buffer.str();
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001369 }
1370 return result;
1371}
1372
Ethan Nicholas00543112018-07-31 09:44:36 -04001373bool Compiler::toGLSL(Program& program, OutputStream& out) {
1374 if (!this->optimize(program)) {
1375 return false;
1376 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001377 fSource = program.fSource.get();
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001378 GLSLCodeGenerator cg(fContext.get(), &program, this, &out);
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001379 bool result = cg.generateCode();
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001380 fSource = nullptr;
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001381 return result;
1382}
1383
Ethan Nicholas00543112018-07-31 09:44:36 -04001384bool Compiler::toGLSL(Program& program, String* out) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001385 StringStream buffer;
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001386 bool result = this->toGLSL(program, buffer);
1387 if (result) {
Ethan Nicholas762466e2017-06-29 10:03:38 -04001388 *out = buffer.str();
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001389 }
1390 return result;
1391}
1392
Ethan Nicholas00543112018-07-31 09:44:36 -04001393bool Compiler::toMetal(Program& program, OutputStream& out) {
1394 if (!this->optimize(program)) {
1395 return false;
1396 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001397 MetalCodeGenerator cg(fContext.get(), &program, this, &out);
Ethan Nicholascc305772017-10-13 16:17:45 -04001398 bool result = cg.generateCode();
Ethan Nicholascc305772017-10-13 16:17:45 -04001399 return result;
1400}
1401
Ethan Nicholas00543112018-07-31 09:44:36 -04001402bool Compiler::toMetal(Program& program, String* out) {
1403 if (!this->optimize(program)) {
1404 return false;
1405 }
Timothy Liangb8eeb802018-07-23 16:46:16 -04001406 StringStream buffer;
1407 bool result = this->toMetal(program, buffer);
1408 if (result) {
1409 *out = buffer.str();
1410 }
1411 return result;
1412}
1413
Ethan Nicholas00543112018-07-31 09:44:36 -04001414bool Compiler::toCPP(Program& program, String name, OutputStream& out) {
1415 if (!this->optimize(program)) {
1416 return false;
1417 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001418 fSource = program.fSource.get();
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001419 CPPCodeGenerator cg(fContext.get(), &program, this, name, &out);
Ethan Nicholas762466e2017-06-29 10:03:38 -04001420 bool result = cg.generateCode();
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001421 fSource = nullptr;
Ethan Nicholas762466e2017-06-29 10:03:38 -04001422 return result;
1423}
1424
Ethan Nicholas00543112018-07-31 09:44:36 -04001425bool Compiler::toH(Program& program, String name, OutputStream& out) {
1426 if (!this->optimize(program)) {
1427 return false;
1428 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001429 fSource = program.fSource.get();
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001430 HCodeGenerator cg(fContext.get(), &program, this, name, &out);
Ethan Nicholas762466e2017-06-29 10:03:38 -04001431 bool result = cg.generateCode();
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001432 fSource = nullptr;
Ethan Nicholas00543112018-07-31 09:44:36 -04001433 return result;
1434}
1435
1436bool Compiler::toPipelineStage(const Program& program, String* out,
1437 std::vector<FormatArg>* outFormatArgs) {
1438 SkASSERT(program.fIsOptimized);
1439 fSource = program.fSource.get();
1440 StringStream buffer;
1441 PipelineStageCodeGenerator cg(fContext.get(), &program, this, &buffer, outFormatArgs);
1442 bool result = cg.generateCode();
1443 fSource = nullptr;
1444 if (result) {
1445 *out = buffer.str();
1446 }
Ethan Nicholas762466e2017-06-29 10:03:38 -04001447 return result;
1448}
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001449
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001450const char* Compiler::OperatorName(Token::Kind kind) {
1451 switch (kind) {
1452 case Token::PLUS: return "+";
1453 case Token::MINUS: return "-";
1454 case Token::STAR: return "*";
1455 case Token::SLASH: return "/";
1456 case Token::PERCENT: return "%";
1457 case Token::SHL: return "<<";
1458 case Token::SHR: return ">>";
1459 case Token::LOGICALNOT: return "!";
1460 case Token::LOGICALAND: return "&&";
1461 case Token::LOGICALOR: return "||";
1462 case Token::LOGICALXOR: return "^^";
1463 case Token::BITWISENOT: return "~";
1464 case Token::BITWISEAND: return "&";
1465 case Token::BITWISEOR: return "|";
1466 case Token::BITWISEXOR: return "^";
1467 case Token::EQ: return "=";
1468 case Token::EQEQ: return "==";
1469 case Token::NEQ: return "!=";
1470 case Token::LT: return "<";
1471 case Token::GT: return ">";
1472 case Token::LTEQ: return "<=";
1473 case Token::GTEQ: return ">=";
1474 case Token::PLUSEQ: return "+=";
1475 case Token::MINUSEQ: return "-=";
1476 case Token::STAREQ: return "*=";
1477 case Token::SLASHEQ: return "/=";
1478 case Token::PERCENTEQ: return "%=";
1479 case Token::SHLEQ: return "<<=";
1480 case Token::SHREQ: return ">>=";
1481 case Token::LOGICALANDEQ: return "&&=";
1482 case Token::LOGICALOREQ: return "||=";
1483 case Token::LOGICALXOREQ: return "^^=";
1484 case Token::BITWISEANDEQ: return "&=";
1485 case Token::BITWISEOREQ: return "|=";
1486 case Token::BITWISEXOREQ: return "^=";
1487 case Token::PLUSPLUS: return "++";
1488 case Token::MINUSMINUS: return "--";
1489 case Token::COMMA: return ",";
1490 default:
1491 ABORT("unsupported operator: %d\n", kind);
1492 }
1493}
1494
1495
1496bool Compiler::IsAssignment(Token::Kind op) {
1497 switch (op) {
1498 case Token::EQ: // fall through
1499 case Token::PLUSEQ: // fall through
1500 case Token::MINUSEQ: // fall through
1501 case Token::STAREQ: // fall through
1502 case Token::SLASHEQ: // fall through
1503 case Token::PERCENTEQ: // fall through
1504 case Token::SHLEQ: // fall through
1505 case Token::SHREQ: // fall through
1506 case Token::BITWISEOREQ: // fall through
1507 case Token::BITWISEXOREQ: // fall through
1508 case Token::BITWISEANDEQ: // fall through
1509 case Token::LOGICALOREQ: // fall through
1510 case Token::LOGICALXOREQ: // fall through
1511 case Token::LOGICALANDEQ:
1512 return true;
1513 default:
1514 return false;
1515 }
1516}
1517
1518Position Compiler::position(int offset) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001519 SkASSERT(fSource);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001520 int line = 1;
1521 int column = 1;
1522 for (int i = 0; i < offset; i++) {
1523 if ((*fSource)[i] == '\n') {
1524 ++line;
1525 column = 1;
1526 }
1527 else {
1528 ++column;
1529 }
1530 }
1531 return Position(line, column);
1532}
1533
1534void Compiler::error(int offset, String msg) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001535 fErrorCount++;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001536 Position pos = this->position(offset);
1537 fErrorText += "error: " + to_string(pos.fLine) + ": " + msg.c_str() + "\n";
ethannicholasb3058bd2016-07-01 08:22:01 -07001538}
1539
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001540String Compiler::errorText() {
Ethan Nicholas00543112018-07-31 09:44:36 -04001541 this->writeErrorCount();
1542 fErrorCount = 0;
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001543 String result = fErrorText;
ethannicholasb3058bd2016-07-01 08:22:01 -07001544 return result;
1545}
1546
1547void Compiler::writeErrorCount() {
1548 if (fErrorCount) {
1549 fErrorText += to_string(fErrorCount) + " error";
1550 if (fErrorCount > 1) {
1551 fErrorText += "s";
1552 }
1553 fErrorText += "\n";
1554 }
1555}
1556
ethannicholasb3058bd2016-07-01 08:22:01 -07001557} // namespace