blob: 4ea956ce0f202984e688ad78eb4db544f63b902c [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"
ethannicholasb3058bd2016-07-01 08:22:01 -070015#include "SkSLSPIRVCodeGenerator.h"
16#include "ir/SkSLExpression.h"
Ethan Nicholascb670962017-04-20 19:31:52 -040017#include "ir/SkSLExpressionStatement.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070018#include "ir/SkSLIntLiteral.h"
ethannicholas5961bc92016-10-12 06:39:56 -070019#include "ir/SkSLModifiersDeclaration.h"
Ethan Nicholascb670962017-04-20 19:31:52 -040020#include "ir/SkSLNop.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070021#include "ir/SkSLSymbolTable.h"
Ethan Nicholascb670962017-04-20 19:31:52 -040022#include "ir/SkSLTernaryExpression.h"
ethannicholasddb37d62016-10-20 09:54:00 -070023#include "ir/SkSLUnresolvedFunction.h"
ethannicholas22f939e2016-10-13 13:25:34 -070024#include "ir/SkSLVarDeclarations.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070025
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -040026#ifdef SK_ENABLE_SPIRV_VALIDATION
27#include "spirv-tools/libspirv.hpp"
28#endif
29
ethannicholasb3058bd2016-07-01 08:22:01 -070030#define STRINGIFY(x) #x
31
32// include the built-in shader symbols as static strings
33
ethannicholas5961bc92016-10-12 06:39:56 -070034static const char* SKSL_INCLUDE =
ethannicholasb3058bd2016-07-01 08:22:01 -070035#include "sksl.include"
36;
37
ethannicholas5961bc92016-10-12 06:39:56 -070038static const char* SKSL_VERT_INCLUDE =
ethannicholasb3058bd2016-07-01 08:22:01 -070039#include "sksl_vert.include"
40;
41
ethannicholas5961bc92016-10-12 06:39:56 -070042static const char* SKSL_FRAG_INCLUDE =
ethannicholasb3058bd2016-07-01 08:22:01 -070043#include "sksl_frag.include"
44;
45
Ethan Nicholas52cad152017-02-16 16:37:32 -050046static const char* SKSL_GEOM_INCLUDE =
47#include "sksl_geom.include"
48;
49
Ethan Nicholas762466e2017-06-29 10:03:38 -040050static const char* SKSL_FP_INCLUDE =
51#include "sksl_fp.include"
52;
53
54
ethannicholasb3058bd2016-07-01 08:22:01 -070055namespace SkSL {
56
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -040057Compiler::Compiler(Flags flags)
58: fFlags(flags)
59, fErrorCount(0) {
Ethan Nicholas8feeff92017-03-30 14:11:58 -040060 auto types = std::shared_ptr<SymbolTable>(new SymbolTable(this));
61 auto symbols = std::shared_ptr<SymbolTable>(new SymbolTable(types, this));
ethannicholasd598f792016-07-25 10:08:54 -070062 fIRGenerator = new IRGenerator(&fContext, symbols, *this);
ethannicholasb3058bd2016-07-01 08:22:01 -070063 fTypes = types;
ethannicholasd598f792016-07-25 10:08:54 -070064 #define ADD_TYPE(t) types->addWithoutOwnership(fContext.f ## t ## _Type->fName, \
65 fContext.f ## t ## _Type.get())
ethannicholasb3058bd2016-07-01 08:22:01 -070066 ADD_TYPE(Void);
67 ADD_TYPE(Float);
Ethan Nicholas5af9ea32017-07-28 15:19:46 -040068 ADD_TYPE(Float2);
69 ADD_TYPE(Float3);
70 ADD_TYPE(Float4);
Ethan Nicholasdcba08e2017-08-02 10:52:54 -040071 ADD_TYPE(Half);
72 ADD_TYPE(Half2);
73 ADD_TYPE(Half3);
74 ADD_TYPE(Half4);
ethannicholasb3058bd2016-07-01 08:22:01 -070075 ADD_TYPE(Double);
Ethan Nicholas5af9ea32017-07-28 15:19:46 -040076 ADD_TYPE(Double2);
77 ADD_TYPE(Double3);
78 ADD_TYPE(Double4);
ethannicholasb3058bd2016-07-01 08:22:01 -070079 ADD_TYPE(Int);
Ethan Nicholas5af9ea32017-07-28 15:19:46 -040080 ADD_TYPE(Int2);
81 ADD_TYPE(Int3);
82 ADD_TYPE(Int4);
ethannicholasb3058bd2016-07-01 08:22:01 -070083 ADD_TYPE(UInt);
Ethan Nicholas5af9ea32017-07-28 15:19:46 -040084 ADD_TYPE(UInt2);
85 ADD_TYPE(UInt3);
86 ADD_TYPE(UInt4);
Ethan Nicholasdcba08e2017-08-02 10:52:54 -040087 ADD_TYPE(Short);
88 ADD_TYPE(Short2);
89 ADD_TYPE(Short3);
90 ADD_TYPE(Short4);
91 ADD_TYPE(UShort);
92 ADD_TYPE(UShort2);
93 ADD_TYPE(UShort3);
94 ADD_TYPE(UShort4);
ethannicholasb3058bd2016-07-01 08:22:01 -070095 ADD_TYPE(Bool);
Ethan Nicholas5af9ea32017-07-28 15:19:46 -040096 ADD_TYPE(Bool2);
97 ADD_TYPE(Bool3);
98 ADD_TYPE(Bool4);
99 ADD_TYPE(Float2x2);
100 ADD_TYPE(Float2x3);
101 ADD_TYPE(Float2x4);
102 ADD_TYPE(Float3x2);
103 ADD_TYPE(Float3x3);
104 ADD_TYPE(Float3x4);
105 ADD_TYPE(Float4x2);
106 ADD_TYPE(Float4x3);
107 ADD_TYPE(Float4x4);
Ethan Nicholasdcba08e2017-08-02 10:52:54 -0400108 ADD_TYPE(Half2x2);
109 ADD_TYPE(Half2x3);
110 ADD_TYPE(Half2x4);
111 ADD_TYPE(Half3x2);
112 ADD_TYPE(Half3x3);
113 ADD_TYPE(Half3x4);
114 ADD_TYPE(Half4x2);
115 ADD_TYPE(Half4x3);
116 ADD_TYPE(Half4x4);
117 ADD_TYPE(Double2x2);
118 ADD_TYPE(Double2x3);
119 ADD_TYPE(Double2x4);
120 ADD_TYPE(Double3x2);
121 ADD_TYPE(Double3x3);
122 ADD_TYPE(Double3x4);
123 ADD_TYPE(Double4x2);
124 ADD_TYPE(Double4x3);
125 ADD_TYPE(Double4x4);
ethannicholasb3058bd2016-07-01 08:22:01 -0700126 ADD_TYPE(GenType);
Ethan Nicholasdcba08e2017-08-02 10:52:54 -0400127 ADD_TYPE(GenHType);
ethannicholasb3058bd2016-07-01 08:22:01 -0700128 ADD_TYPE(GenDType);
129 ADD_TYPE(GenIType);
130 ADD_TYPE(GenUType);
131 ADD_TYPE(GenBType);
132 ADD_TYPE(Mat);
133 ADD_TYPE(Vec);
134 ADD_TYPE(GVec);
135 ADD_TYPE(GVec2);
136 ADD_TYPE(GVec3);
137 ADD_TYPE(GVec4);
Ethan Nicholasdcba08e2017-08-02 10:52:54 -0400138 ADD_TYPE(HVec);
ethannicholasb3058bd2016-07-01 08:22:01 -0700139 ADD_TYPE(DVec);
140 ADD_TYPE(IVec);
141 ADD_TYPE(UVec);
Ethan Nicholasdcba08e2017-08-02 10:52:54 -0400142 ADD_TYPE(SVec);
143 ADD_TYPE(USVec);
ethannicholasb3058bd2016-07-01 08:22:01 -0700144 ADD_TYPE(BVec);
145
146 ADD_TYPE(Sampler1D);
147 ADD_TYPE(Sampler2D);
148 ADD_TYPE(Sampler3D);
ethannicholas5961bc92016-10-12 06:39:56 -0700149 ADD_TYPE(SamplerExternalOES);
ethannicholasb3058bd2016-07-01 08:22:01 -0700150 ADD_TYPE(SamplerCube);
151 ADD_TYPE(Sampler2DRect);
152 ADD_TYPE(Sampler1DArray);
153 ADD_TYPE(Sampler2DArray);
154 ADD_TYPE(SamplerCubeArray);
155 ADD_TYPE(SamplerBuffer);
156 ADD_TYPE(Sampler2DMS);
157 ADD_TYPE(Sampler2DMSArray);
158
Brian Salomonbf7b6202016-11-11 16:08:03 -0500159 ADD_TYPE(ISampler2D);
160
Brian Salomon2a51de82016-11-16 12:06:01 -0500161 ADD_TYPE(Image2D);
162 ADD_TYPE(IImage2D);
163
Greg Daniel64773e62016-11-22 09:44:03 -0500164 ADD_TYPE(SubpassInput);
165 ADD_TYPE(SubpassInputMS);
166
ethannicholasb3058bd2016-07-01 08:22:01 -0700167 ADD_TYPE(GSampler1D);
168 ADD_TYPE(GSampler2D);
169 ADD_TYPE(GSampler3D);
170 ADD_TYPE(GSamplerCube);
171 ADD_TYPE(GSampler2DRect);
172 ADD_TYPE(GSampler1DArray);
173 ADD_TYPE(GSampler2DArray);
174 ADD_TYPE(GSamplerCubeArray);
175 ADD_TYPE(GSamplerBuffer);
176 ADD_TYPE(GSampler2DMS);
177 ADD_TYPE(GSampler2DMSArray);
178
179 ADD_TYPE(Sampler1DShadow);
180 ADD_TYPE(Sampler2DShadow);
181 ADD_TYPE(SamplerCubeShadow);
182 ADD_TYPE(Sampler2DRectShadow);
183 ADD_TYPE(Sampler1DArrayShadow);
184 ADD_TYPE(Sampler2DArrayShadow);
185 ADD_TYPE(SamplerCubeArrayShadow);
186 ADD_TYPE(GSampler2DArrayShadow);
187 ADD_TYPE(GSamplerCubeArrayShadow);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400188 ADD_TYPE(ColorSpaceXform);
ethannicholasb3058bd2016-07-01 08:22:01 -0700189
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400190 String skCapsName("sk_Caps");
191 Variable* skCaps = new Variable(Position(), Modifiers(), skCapsName,
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500192 *fContext.fSkCaps_Type, Variable::kGlobal_Storage);
193 fIRGenerator->fSymbolTable->add(skCapsName, std::unique_ptr<Symbol>(skCaps));
194
Ethan Nicholas762466e2017-06-29 10:03:38 -0400195 String skArgsName("sk_Args");
196 Variable* skArgs = new Variable(Position(), Modifiers(), skArgsName,
197 *fContext.fSkArgs_Type, Variable::kGlobal_Storage);
198 fIRGenerator->fSymbolTable->add(skArgsName, std::unique_ptr<Symbol>(skArgs));
199
Brian Salomon1d816b92017-08-17 11:07:59 -0400200 Modifiers::Flag ignored1;
201 std::vector<std::unique_ptr<ProgramElement>> ignored2;
202 fIRGenerator->convertProgram(String(SKSL_INCLUDE), *fTypes, &ignored1, &ignored2);
ethannicholasddb37d62016-10-20 09:54:00 -0700203 fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
ethannicholasb3058bd2016-07-01 08:22:01 -0700204 ASSERT(!fErrorCount);
205}
206
207Compiler::~Compiler() {
208 delete fIRGenerator;
209}
210
ethannicholas22f939e2016-10-13 13:25:34 -0700211// add the definition created by assigning to the lvalue to the definition set
Ethan Nicholas86a43402017-01-19 13:32:00 -0500212void Compiler::addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr,
213 DefinitionMap* definitions) {
ethannicholas22f939e2016-10-13 13:25:34 -0700214 switch (lvalue->fKind) {
215 case Expression::kVariableReference_Kind: {
216 const Variable& var = ((VariableReference*) lvalue)->fVariable;
217 if (var.fStorage == Variable::kLocal_Storage) {
218 (*definitions)[&var] = expr;
219 }
220 break;
221 }
222 case Expression::kSwizzle_Kind:
223 // We consider the variable written to as long as at least some of its components have
224 // been written to. This will lead to some false negatives (we won't catch it if you
225 // write to foo.x and then read foo.y), but being stricter could lead to false positives
Mike Klein6ad99092016-10-26 10:35:22 -0400226 // (we write to foo.x, and then pass foo to a function which happens to only read foo.x,
227 // 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 -0700228 // more complicated whole-program analysis. This is probably good enough.
Mike Klein6ad99092016-10-26 10:35:22 -0400229 this->addDefinition(((Swizzle*) lvalue)->fBase.get(),
Ethan Nicholas86a43402017-01-19 13:32:00 -0500230 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
ethannicholas22f939e2016-10-13 13:25:34 -0700231 definitions);
232 break;
233 case Expression::kIndex_Kind:
234 // see comments in Swizzle
Mike Klein6ad99092016-10-26 10:35:22 -0400235 this->addDefinition(((IndexExpression*) lvalue)->fBase.get(),
Ethan Nicholas86a43402017-01-19 13:32:00 -0500236 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
ethannicholas22f939e2016-10-13 13:25:34 -0700237 definitions);
238 break;
239 case Expression::kFieldAccess_Kind:
240 // see comments in Swizzle
Mike Klein6ad99092016-10-26 10:35:22 -0400241 this->addDefinition(((FieldAccess*) lvalue)->fBase.get(),
Ethan Nicholas86a43402017-01-19 13:32:00 -0500242 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
ethannicholas22f939e2016-10-13 13:25:34 -0700243 definitions);
244 break;
245 default:
246 // not an lvalue, can't happen
247 ASSERT(false);
248 }
249}
250
251// add local variables defined by this node to the set
Mike Klein6ad99092016-10-26 10:35:22 -0400252void Compiler::addDefinitions(const BasicBlock::Node& node,
Ethan Nicholas86a43402017-01-19 13:32:00 -0500253 DefinitionMap* definitions) {
ethannicholas22f939e2016-10-13 13:25:34 -0700254 switch (node.fKind) {
255 case BasicBlock::Node::kExpression_Kind: {
Ethan Nicholascb670962017-04-20 19:31:52 -0400256 ASSERT(node.expression());
257 const Expression* expr = (Expression*) node.expression()->get();
Ethan Nicholas86a43402017-01-19 13:32:00 -0500258 switch (expr->fKind) {
259 case Expression::kBinary_Kind: {
260 BinaryExpression* b = (BinaryExpression*) expr;
261 if (b->fOperator == Token::EQ) {
262 this->addDefinition(b->fLeft.get(), &b->fRight, definitions);
263 } else if (Token::IsAssignment(b->fOperator)) {
264 this->addDefinition(
265 b->fLeft.get(),
266 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
267 definitions);
268
269 }
270 break;
ethannicholas22f939e2016-10-13 13:25:34 -0700271 }
Ethan Nicholas86a43402017-01-19 13:32:00 -0500272 case Expression::kPrefix_Kind: {
273 const PrefixExpression* p = (PrefixExpression*) expr;
274 if (p->fOperator == Token::MINUSMINUS || p->fOperator == Token::PLUSPLUS) {
275 this->addDefinition(
276 p->fOperand.get(),
277 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
278 definitions);
279 }
280 break;
281 }
282 case Expression::kPostfix_Kind: {
283 const PostfixExpression* p = (PostfixExpression*) expr;
284 if (p->fOperator == Token::MINUSMINUS || p->fOperator == Token::PLUSPLUS) {
285 this->addDefinition(
286 p->fOperand.get(),
287 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
288 definitions);
Ethan Nicholas86a43402017-01-19 13:32:00 -0500289 }
290 break;
291 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400292 case Expression::kVariableReference_Kind: {
293 const VariableReference* v = (VariableReference*) expr;
294 if (v->fRefKind != VariableReference::kRead_RefKind) {
295 this->addDefinition(
296 v,
297 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
298 definitions);
299 }
300 }
Ethan Nicholas86a43402017-01-19 13:32:00 -0500301 default:
302 break;
ethannicholas22f939e2016-10-13 13:25:34 -0700303 }
304 break;
305 }
306 case BasicBlock::Node::kStatement_Kind: {
Ethan Nicholascb670962017-04-20 19:31:52 -0400307 const Statement* stmt = (Statement*) node.statement()->get();
Ethan Nicholasb4dc4192017-06-02 10:16:28 -0400308 if (stmt->fKind == Statement::kVarDeclaration_Kind) {
309 VarDeclaration& vd = (VarDeclaration&) *stmt;
310 if (vd.fValue) {
311 (*definitions)[vd.fVar] = &vd.fValue;
ethannicholas22f939e2016-10-13 13:25:34 -0700312 }
313 }
314 break;
315 }
316 }
317}
318
319void Compiler::scanCFG(CFG* cfg, BlockId blockId, std::set<BlockId>* workList) {
320 BasicBlock& block = cfg->fBlocks[blockId];
321
322 // compute definitions after this block
Ethan Nicholas86a43402017-01-19 13:32:00 -0500323 DefinitionMap after = block.fBefore;
ethannicholas22f939e2016-10-13 13:25:34 -0700324 for (const BasicBlock::Node& n : block.fNodes) {
325 this->addDefinitions(n, &after);
326 }
327
328 // propagate definitions to exits
329 for (BlockId exitId : block.fExits) {
330 BasicBlock& exit = cfg->fBlocks[exitId];
331 for (const auto& pair : after) {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500332 std::unique_ptr<Expression>* e1 = pair.second;
333 auto found = exit.fBefore.find(pair.first);
334 if (found == exit.fBefore.end()) {
335 // exit has no definition for it, just copy it
336 workList->insert(exitId);
ethannicholas22f939e2016-10-13 13:25:34 -0700337 exit.fBefore[pair.first] = e1;
338 } else {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500339 // exit has a (possibly different) value already defined
340 std::unique_ptr<Expression>* e2 = exit.fBefore[pair.first];
ethannicholas22f939e2016-10-13 13:25:34 -0700341 if (e1 != e2) {
342 // definition has changed, merge and add exit block to worklist
343 workList->insert(exitId);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500344 if (e1 && e2) {
345 exit.fBefore[pair.first] =
Ethan Nicholas86a43402017-01-19 13:32:00 -0500346 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression;
Ethan Nicholasaf197692017-02-27 13:26:45 -0500347 } else {
348 exit.fBefore[pair.first] = nullptr;
349 }
ethannicholas22f939e2016-10-13 13:25:34 -0700350 }
351 }
352 }
353 }
354}
355
356// returns a map which maps all local variables in the function to null, indicating that their value
357// is initially unknown
Ethan Nicholas86a43402017-01-19 13:32:00 -0500358static DefinitionMap compute_start_state(const CFG& cfg) {
359 DefinitionMap result;
Mike Klein6ad99092016-10-26 10:35:22 -0400360 for (const auto& block : cfg.fBlocks) {
361 for (const auto& node : block.fNodes) {
ethannicholas22f939e2016-10-13 13:25:34 -0700362 if (node.fKind == BasicBlock::Node::kStatement_Kind) {
Ethan Nicholascb670962017-04-20 19:31:52 -0400363 ASSERT(node.statement());
364 const Statement* s = node.statement()->get();
ethannicholas22f939e2016-10-13 13:25:34 -0700365 if (s->fKind == Statement::kVarDeclarations_Kind) {
366 const VarDeclarationsStatement* vd = (const VarDeclarationsStatement*) s;
Ethan Nicholascb670962017-04-20 19:31:52 -0400367 for (const auto& decl : vd->fDeclaration->fVars) {
Ethan Nicholas91a10532017-06-22 11:24:38 -0400368 if (decl->fKind == Statement::kVarDeclaration_Kind) {
369 result[((VarDeclaration&) *decl).fVar] = nullptr;
370 }
Mike Klein6ad99092016-10-26 10:35:22 -0400371 }
ethannicholas22f939e2016-10-13 13:25:34 -0700372 }
373 }
374 }
375 }
376 return result;
377}
378
Ethan Nicholascb670962017-04-20 19:31:52 -0400379/**
380 * Returns true if assigning to this lvalue has no effect.
381 */
382static bool is_dead(const Expression& lvalue) {
383 switch (lvalue.fKind) {
384 case Expression::kVariableReference_Kind:
385 return ((VariableReference&) lvalue).fVariable.dead();
386 case Expression::kSwizzle_Kind:
387 return is_dead(*((Swizzle&) lvalue).fBase);
388 case Expression::kFieldAccess_Kind:
389 return is_dead(*((FieldAccess&) lvalue).fBase);
390 case Expression::kIndex_Kind: {
391 const IndexExpression& idx = (IndexExpression&) lvalue;
392 return is_dead(*idx.fBase) && !idx.fIndex->hasSideEffects();
393 }
394 default:
395 ABORT("invalid lvalue: %s\n", lvalue.description().c_str());
396 }
397}
ethannicholas22f939e2016-10-13 13:25:34 -0700398
Ethan Nicholascb670962017-04-20 19:31:52 -0400399/**
400 * Returns true if this is an assignment which can be collapsed down to just the right hand side due
401 * to a dead target and lack of side effects on the left hand side.
402 */
403static bool dead_assignment(const BinaryExpression& b) {
404 if (!Token::IsAssignment(b.fOperator)) {
405 return false;
406 }
407 return is_dead(*b.fLeft);
408}
409
410void Compiler::computeDataFlow(CFG* cfg) {
411 cfg->fBlocks[cfg->fStart].fBefore = compute_start_state(*cfg);
ethannicholas22f939e2016-10-13 13:25:34 -0700412 std::set<BlockId> workList;
Ethan Nicholascb670962017-04-20 19:31:52 -0400413 for (BlockId i = 0; i < cfg->fBlocks.size(); i++) {
ethannicholas22f939e2016-10-13 13:25:34 -0700414 workList.insert(i);
415 }
416 while (workList.size()) {
417 BlockId next = *workList.begin();
418 workList.erase(workList.begin());
Ethan Nicholascb670962017-04-20 19:31:52 -0400419 this->scanCFG(cfg, next, &workList);
ethannicholas22f939e2016-10-13 13:25:34 -0700420 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400421}
422
423/**
424 * Attempts to replace the expression pointed to by iter with a new one (in both the CFG and the
425 * IR). If the expression can be cleanly removed, returns true and updates the iterator to point to
426 * the newly-inserted element. Otherwise updates only the IR and returns false (and the CFG will
427 * need to be regenerated).
428 */
429bool try_replace_expression(BasicBlock* b,
430 std::vector<BasicBlock::Node>::iterator* iter,
431 std::unique_ptr<Expression>* newExpression) {
432 std::unique_ptr<Expression>* target = (*iter)->expression();
433 if (!b->tryRemoveExpression(iter)) {
434 *target = std::move(*newExpression);
435 return false;
436 }
437 *target = std::move(*newExpression);
438 return b->tryInsertExpression(iter, target);
439}
440
441/**
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400442 * Returns true if the expression is a constant numeric literal with the specified value, or a
443 * constant vector with all elements equal to the specified value.
Ethan Nicholascb670962017-04-20 19:31:52 -0400444 */
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400445bool is_constant(const Expression& expr, double value) {
Ethan Nicholascb670962017-04-20 19:31:52 -0400446 switch (expr.fKind) {
447 case Expression::kIntLiteral_Kind:
448 return ((IntLiteral&) expr).fValue == value;
449 case Expression::kFloatLiteral_Kind:
450 return ((FloatLiteral&) expr).fValue == value;
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400451 case Expression::kConstructor_Kind: {
452 Constructor& c = (Constructor&) expr;
453 if (c.fType.kind() == Type::kVector_Kind && c.isConstant()) {
454 for (int i = 0; i < c.fType.columns(); ++i) {
455 if (!is_constant(c.getVecComponent(i), value)) {
456 return false;
457 }
458 }
459 return true;
460 }
461 return false;
462 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400463 default:
464 return false;
465 }
466}
467
468/**
469 * Collapses the binary expression pointed to by iter down to just the right side (in both the IR
470 * and CFG structures).
471 */
472void delete_left(BasicBlock* b,
473 std::vector<BasicBlock::Node>::iterator* iter,
474 bool* outUpdated,
475 bool* outNeedsRescan) {
476 *outUpdated = true;
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400477 std::unique_ptr<Expression>* target = (*iter)->expression();
478 ASSERT((*target)->fKind == Expression::kBinary_Kind);
479 BinaryExpression& bin = (BinaryExpression&) **target;
480 bool result;
481 if (bin.fOperator == Token::EQ) {
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400482 result = b->tryRemoveLValueBefore(iter, bin.fLeft.get());
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400483 } else {
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400484 result = b->tryRemoveExpressionBefore(iter, bin.fLeft.get());
Ethan Nicholascb670962017-04-20 19:31:52 -0400485 }
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400486 *target = std::move(bin.fRight);
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400487 if (!result) {
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400488 *outNeedsRescan = true;
489 return;
490 }
491 if (*iter == b->fNodes.begin()) {
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400492 *outNeedsRescan = true;
493 return;
494 }
495 --(*iter);
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400496 if ((*iter)->fKind != BasicBlock::Node::kExpression_Kind ||
497 (*iter)->expression() != &bin.fRight) {
498 *outNeedsRescan = true;
499 return;
500 }
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400501 *iter = b->fNodes.erase(*iter);
502 ASSERT((*iter)->expression() == target);
Ethan Nicholascb670962017-04-20 19:31:52 -0400503}
504
505/**
506 * Collapses the binary expression pointed to by iter down to just the left side (in both the IR and
507 * CFG structures).
508 */
509void delete_right(BasicBlock* b,
510 std::vector<BasicBlock::Node>::iterator* iter,
511 bool* outUpdated,
512 bool* outNeedsRescan) {
513 *outUpdated = true;
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400514 std::unique_ptr<Expression>* target = (*iter)->expression();
515 ASSERT((*target)->fKind == Expression::kBinary_Kind);
516 BinaryExpression& bin = (BinaryExpression&) **target;
517 if (!b->tryRemoveExpressionBefore(iter, bin.fRight.get())) {
518 *target = std::move(bin.fLeft);
Ethan Nicholascb670962017-04-20 19:31:52 -0400519 *outNeedsRescan = true;
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400520 return;
Ethan Nicholascb670962017-04-20 19:31:52 -0400521 }
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400522 *target = std::move(bin.fLeft);
523 if (*iter == b->fNodes.begin()) {
524 *outNeedsRescan = true;
525 return;
526 }
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400527 --(*iter);
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400528 if (((*iter)->fKind != BasicBlock::Node::kExpression_Kind ||
529 (*iter)->expression() != &bin.fLeft)) {
530 *outNeedsRescan = true;
531 return;
532 }
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400533 *iter = b->fNodes.erase(*iter);
534 ASSERT((*iter)->expression() == target);
Ethan Nicholascb670962017-04-20 19:31:52 -0400535}
536
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400537/**
538 * Constructs the specified type using a single argument.
539 */
540static std::unique_ptr<Expression> construct(const Type& type, std::unique_ptr<Expression> v) {
541 std::vector<std::unique_ptr<Expression>> args;
542 args.push_back(std::move(v));
543 auto result = std::unique_ptr<Expression>(new Constructor(Position(), type, std::move(args)));
544 return result;
545}
546
547/**
548 * Used in the implementations of vectorize_left and vectorize_right. Given a vector type and an
549 * expression x, deletes the expression pointed to by iter and replaces it with <type>(x).
550 */
551static void vectorize(BasicBlock* b,
552 std::vector<BasicBlock::Node>::iterator* iter,
553 const Type& type,
554 std::unique_ptr<Expression>* otherExpression,
555 bool* outUpdated,
556 bool* outNeedsRescan) {
557 ASSERT((*(*iter)->expression())->fKind == Expression::kBinary_Kind);
558 ASSERT(type.kind() == Type::kVector_Kind);
559 ASSERT((*otherExpression)->fType.kind() == Type::kScalar_Kind);
560 *outUpdated = true;
561 std::unique_ptr<Expression>* target = (*iter)->expression();
562 if (!b->tryRemoveExpression(iter)) {
563 *target = construct(type, std::move(*otherExpression));
564 *outNeedsRescan = true;
565 } else {
566 *target = construct(type, std::move(*otherExpression));
567 if (!b->tryInsertExpression(iter, target)) {
568 *outNeedsRescan = true;
569 }
570 }
571}
572
573/**
574 * Given a binary expression of the form x <op> vec<n>(y), deletes the right side and vectorizes the
575 * left to yield vec<n>(x).
576 */
577static void vectorize_left(BasicBlock* b,
578 std::vector<BasicBlock::Node>::iterator* iter,
579 bool* outUpdated,
580 bool* outNeedsRescan) {
581 BinaryExpression& bin = (BinaryExpression&) **(*iter)->expression();
582 vectorize(b, iter, bin.fRight->fType, &bin.fLeft, outUpdated, outNeedsRescan);
583}
584
585/**
586 * Given a binary expression of the form vec<n>(x) <op> y, deletes the left side and vectorizes the
587 * right to yield vec<n>(y).
588 */
589static void vectorize_right(BasicBlock* b,
590 std::vector<BasicBlock::Node>::iterator* iter,
591 bool* outUpdated,
592 bool* outNeedsRescan) {
593 BinaryExpression& bin = (BinaryExpression&) **(*iter)->expression();
594 vectorize(b, iter, bin.fLeft->fType, &bin.fRight, outUpdated, outNeedsRescan);
595}
596
597// Mark that an expression which we were writing to is no longer being written to
598void clear_write(const Expression& expr) {
599 switch (expr.fKind) {
600 case Expression::kVariableReference_Kind: {
601 ((VariableReference&) expr).setRefKind(VariableReference::kRead_RefKind);
602 break;
603 }
604 case Expression::kFieldAccess_Kind:
605 clear_write(*((FieldAccess&) expr).fBase);
606 break;
607 case Expression::kSwizzle_Kind:
608 clear_write(*((Swizzle&) expr).fBase);
609 break;
610 case Expression::kIndex_Kind:
611 clear_write(*((IndexExpression&) expr).fBase);
612 break;
613 default:
614 ABORT("shouldn't be writing to this kind of expression\n");
615 break;
616 }
617}
618
Ethan Nicholascb670962017-04-20 19:31:52 -0400619void Compiler::simplifyExpression(DefinitionMap& definitions,
620 BasicBlock& b,
621 std::vector<BasicBlock::Node>::iterator* iter,
622 std::unordered_set<const Variable*>* undefinedVariables,
623 bool* outUpdated,
624 bool* outNeedsRescan) {
625 Expression* expr = (*iter)->expression()->get();
626 ASSERT(expr);
627 if ((*iter)->fConstantPropagation) {
628 std::unique_ptr<Expression> optimized = expr->constantPropagate(*fIRGenerator, definitions);
629 if (optimized) {
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400630 *outUpdated = true;
Ethan Nicholascb670962017-04-20 19:31:52 -0400631 if (!try_replace_expression(&b, iter, &optimized)) {
632 *outNeedsRescan = true;
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400633 return;
Ethan Nicholascb670962017-04-20 19:31:52 -0400634 }
635 ASSERT((*iter)->fKind == BasicBlock::Node::kExpression_Kind);
636 expr = (*iter)->expression()->get();
Ethan Nicholascb670962017-04-20 19:31:52 -0400637 }
638 }
639 switch (expr->fKind) {
640 case Expression::kVariableReference_Kind: {
641 const Variable& var = ((VariableReference*) expr)->fVariable;
642 if (var.fStorage == Variable::kLocal_Storage && !definitions[&var] &&
643 (*undefinedVariables).find(&var) == (*undefinedVariables).end()) {
644 (*undefinedVariables).insert(&var);
645 this->error(expr->fPosition,
646 "'" + var.fName + "' has not been assigned");
647 }
648 break;
649 }
650 case Expression::kTernary_Kind: {
651 TernaryExpression* t = (TernaryExpression*) expr;
652 if (t->fTest->fKind == Expression::kBoolLiteral_Kind) {
653 // ternary has a constant test, replace it with either the true or
654 // false branch
655 if (((BoolLiteral&) *t->fTest).fValue) {
656 (*iter)->setExpression(std::move(t->fIfTrue));
657 } else {
658 (*iter)->setExpression(std::move(t->fIfFalse));
659 }
660 *outUpdated = true;
661 *outNeedsRescan = true;
662 }
663 break;
664 }
665 case Expression::kBinary_Kind: {
Ethan Nicholascb670962017-04-20 19:31:52 -0400666 BinaryExpression* bin = (BinaryExpression*) expr;
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400667 if (dead_assignment(*bin)) {
668 delete_left(&b, iter, outUpdated, outNeedsRescan);
669 break;
670 }
671 // collapse useless expressions like x * 1 or x + 0
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400672 if (((bin->fLeft->fType.kind() != Type::kScalar_Kind) &&
673 (bin->fLeft->fType.kind() != Type::kVector_Kind)) ||
674 ((bin->fRight->fType.kind() != Type::kScalar_Kind) &&
675 (bin->fRight->fType.kind() != Type::kVector_Kind))) {
676 break;
677 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400678 switch (bin->fOperator) {
679 case Token::STAR:
680 if (is_constant(*bin->fLeft, 1)) {
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400681 if (bin->fLeft->fType.kind() == Type::kVector_Kind &&
682 bin->fRight->fType.kind() == Type::kScalar_Kind) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400683 // float4(1) * x -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400684 vectorize_right(&b, iter, outUpdated, outNeedsRescan);
685 } else {
686 // 1 * x -> x
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400687 // 1 * float4(x) -> float4(x)
688 // float4(1) * float4(x) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400689 delete_left(&b, iter, outUpdated, outNeedsRescan);
690 }
691 }
692 else if (is_constant(*bin->fLeft, 0)) {
693 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
694 bin->fRight->fType.kind() == Type::kVector_Kind) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400695 // 0 * float4(x) -> float4(0)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400696 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
697 } else {
698 // 0 * x -> 0
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400699 // float4(0) * x -> float4(0)
700 // float4(0) * float4(x) -> float4(0)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400701 delete_right(&b, iter, outUpdated, outNeedsRescan);
702 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400703 }
704 else if (is_constant(*bin->fRight, 1)) {
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400705 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
706 bin->fRight->fType.kind() == Type::kVector_Kind) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400707 // x * float4(1) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400708 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
709 } else {
710 // x * 1 -> x
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400711 // float4(x) * 1 -> float4(x)
712 // float4(x) * float4(1) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400713 delete_right(&b, iter, outUpdated, outNeedsRescan);
714 }
715 }
716 else if (is_constant(*bin->fRight, 0)) {
717 if (bin->fLeft->fType.kind() == Type::kVector_Kind &&
718 bin->fRight->fType.kind() == Type::kScalar_Kind) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400719 // float4(x) * 0 -> float4(0)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400720 vectorize_right(&b, iter, outUpdated, outNeedsRescan);
721 } else {
722 // x * 0 -> 0
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400723 // x * float4(0) -> float4(0)
724 // float4(x) * float4(0) -> float4(0)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400725 delete_left(&b, iter, outUpdated, outNeedsRescan);
726 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400727 }
728 break;
Ethan Nicholas56e42712017-04-21 10:23:37 -0400729 case Token::PLUS:
Ethan Nicholascb670962017-04-20 19:31:52 -0400730 if (is_constant(*bin->fLeft, 0)) {
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400731 if (bin->fLeft->fType.kind() == Type::kVector_Kind &&
732 bin->fRight->fType.kind() == Type::kScalar_Kind) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400733 // float4(0) + x -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400734 vectorize_right(&b, iter, outUpdated, outNeedsRescan);
735 } else {
736 // 0 + x -> x
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400737 // 0 + float4(x) -> float4(x)
738 // float4(0) + float4(x) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400739 delete_left(&b, iter, outUpdated, outNeedsRescan);
740 }
741 } else if (is_constant(*bin->fRight, 0)) {
742 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
743 bin->fRight->fType.kind() == Type::kVector_Kind) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400744 // x + float4(0) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400745 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
746 } else {
747 // x + 0 -> x
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400748 // float4(x) + 0 -> float4(x)
749 // float4(x) + float4(0) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400750 delete_right(&b, iter, outUpdated, outNeedsRescan);
751 }
Ethan Nicholas56e42712017-04-21 10:23:37 -0400752 }
753 break;
754 case Token::MINUS:
755 if (is_constant(*bin->fRight, 0)) {
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400756 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
757 bin->fRight->fType.kind() == Type::kVector_Kind) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400758 // x - float4(0) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400759 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
760 } else {
761 // x - 0 -> x
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400762 // float4(x) - 0 -> float4(x)
763 // float4(x) - float4(0) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400764 delete_right(&b, iter, outUpdated, outNeedsRescan);
765 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400766 }
767 break;
768 case Token::SLASH:
769 if (is_constant(*bin->fRight, 1)) {
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400770 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
771 bin->fRight->fType.kind() == Type::kVector_Kind) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400772 // x / float4(1) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400773 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
774 } else {
775 // x / 1 -> x
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400776 // float4(x) / 1 -> float4(x)
777 // float4(x) / float4(1) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400778 delete_right(&b, iter, outUpdated, outNeedsRescan);
779 }
780 } else if (is_constant(*bin->fLeft, 0)) {
781 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
782 bin->fRight->fType.kind() == Type::kVector_Kind) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400783 // 0 / float4(x) -> float4(0)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400784 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
785 } else {
786 // 0 / x -> 0
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400787 // float4(0) / x -> float4(0)
788 // float4(0) / float4(x) -> float4(0)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400789 delete_right(&b, iter, outUpdated, outNeedsRescan);
790 }
791 }
792 break;
793 case Token::PLUSEQ:
794 if (is_constant(*bin->fRight, 0)) {
795 clear_write(*bin->fLeft);
796 delete_right(&b, iter, outUpdated, outNeedsRescan);
797 }
798 break;
799 case Token::MINUSEQ:
800 if (is_constant(*bin->fRight, 0)) {
801 clear_write(*bin->fLeft);
802 delete_right(&b, iter, outUpdated, outNeedsRescan);
803 }
804 break;
805 case Token::STAREQ:
806 if (is_constant(*bin->fRight, 1)) {
807 clear_write(*bin->fLeft);
808 delete_right(&b, iter, outUpdated, outNeedsRescan);
809 }
810 break;
811 case Token::SLASHEQ:
812 if (is_constant(*bin->fRight, 1)) {
813 clear_write(*bin->fLeft);
Ethan Nicholascb670962017-04-20 19:31:52 -0400814 delete_right(&b, iter, outUpdated, outNeedsRescan);
815 }
816 break;
817 default:
818 break;
819 }
820 }
821 default:
822 break;
823 }
824}
825
Ethan Nicholas5ac13c22017-05-10 15:06:17 -0400826// returns true if this statement could potentially execute a break at the current level (we ignore
827// nested loops and switches, since any breaks inside of them will merely break the loop / switch)
828static bool contains_break(Statement& s) {
829 switch (s.fKind) {
830 case Statement::kBlock_Kind:
831 for (const auto& sub : ((Block&) s).fStatements) {
832 if (contains_break(*sub)) {
833 return true;
834 }
835 }
836 return false;
837 case Statement::kBreak_Kind:
838 return true;
839 case Statement::kIf_Kind: {
840 const IfStatement& i = (IfStatement&) s;
841 return contains_break(*i.fIfTrue) || (i.fIfFalse && contains_break(*i.fIfFalse));
842 }
843 default:
844 return false;
845 }
846}
847
848// Returns a block containing all of the statements that will be run if the given case matches
849// (which, owing to the statements being owned by unique_ptrs, means the switch itself will be
850// broken by this call and must then be discarded).
851// Returns null (and leaves the switch unmodified) if no such simple reduction is possible, such as
852// when break statements appear inside conditionals.
853static std::unique_ptr<Statement> block_for_case(SwitchStatement* s, SwitchCase* c) {
854 bool capturing = false;
855 std::vector<std::unique_ptr<Statement>*> statementPtrs;
856 for (const auto& current : s->fCases) {
857 if (current.get() == c) {
858 capturing = true;
859 }
860 if (capturing) {
861 for (auto& stmt : current->fStatements) {
862 if (stmt->fKind == Statement::kBreak_Kind) {
863 capturing = false;
864 break;
865 }
866 if (contains_break(*stmt)) {
867 return nullptr;
868 }
869 statementPtrs.push_back(&stmt);
870 }
871 if (!capturing) {
872 break;
873 }
874 }
875 }
876 std::vector<std::unique_ptr<Statement>> statements;
877 for (const auto& s : statementPtrs) {
878 statements.push_back(std::move(*s));
879 }
Ethan Nicholasc432b0c2017-07-18 13:22:37 -0400880 return std::unique_ptr<Statement>(new Block(Position(), std::move(statements), s->fSymbols));
Ethan Nicholas5ac13c22017-05-10 15:06:17 -0400881}
882
Ethan Nicholascb670962017-04-20 19:31:52 -0400883void Compiler::simplifyStatement(DefinitionMap& definitions,
Ethan Nicholas5ac13c22017-05-10 15:06:17 -0400884 BasicBlock& b,
885 std::vector<BasicBlock::Node>::iterator* iter,
886 std::unordered_set<const Variable*>* undefinedVariables,
887 bool* outUpdated,
888 bool* outNeedsRescan) {
Ethan Nicholascb670962017-04-20 19:31:52 -0400889 Statement* stmt = (*iter)->statement()->get();
890 switch (stmt->fKind) {
Ethan Nicholasb4dc4192017-06-02 10:16:28 -0400891 case Statement::kVarDeclaration_Kind: {
892 const auto& varDecl = (VarDeclaration&) *stmt;
893 if (varDecl.fVar->dead() &&
894 (!varDecl.fValue ||
895 !varDecl.fValue->hasSideEffects())) {
896 if (varDecl.fValue) {
897 ASSERT((*iter)->statement()->get() == stmt);
898 if (!b.tryRemoveExpressionBefore(iter, varDecl.fValue.get())) {
899 *outNeedsRescan = true;
Ethan Nicholascb670962017-04-20 19:31:52 -0400900 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400901 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400902 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
Ethan Nicholasb4dc4192017-06-02 10:16:28 -0400903 *outUpdated = true;
Ethan Nicholascb670962017-04-20 19:31:52 -0400904 }
905 break;
906 }
907 case Statement::kIf_Kind: {
908 IfStatement& i = (IfStatement&) *stmt;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -0400909 if (i.fTest->fKind == Expression::kBoolLiteral_Kind) {
910 // constant if, collapse down to a single branch
911 if (((BoolLiteral&) *i.fTest).fValue) {
912 ASSERT(i.fIfTrue);
913 (*iter)->setStatement(std::move(i.fIfTrue));
914 } else {
915 if (i.fIfFalse) {
916 (*iter)->setStatement(std::move(i.fIfFalse));
917 } else {
918 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
919 }
920 }
921 *outUpdated = true;
922 *outNeedsRescan = true;
923 break;
924 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400925 if (i.fIfFalse && i.fIfFalse->isEmpty()) {
926 // else block doesn't do anything, remove it
927 i.fIfFalse.reset();
928 *outUpdated = true;
929 *outNeedsRescan = true;
930 }
931 if (!i.fIfFalse && i.fIfTrue->isEmpty()) {
932 // if block doesn't do anything, no else block
933 if (i.fTest->hasSideEffects()) {
934 // test has side effects, keep it
935 (*iter)->setStatement(std::unique_ptr<Statement>(
936 new ExpressionStatement(std::move(i.fTest))));
937 } else {
938 // no if, no else, no test side effects, kill the whole if
939 // statement
940 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
941 }
942 *outUpdated = true;
943 *outNeedsRescan = true;
944 }
945 break;
946 }
Ethan Nicholas5ac13c22017-05-10 15:06:17 -0400947 case Statement::kSwitch_Kind: {
948 SwitchStatement& s = (SwitchStatement&) *stmt;
949 if (s.fValue->isConstant()) {
950 // switch is constant, replace it with the case that matches
951 bool found = false;
952 SwitchCase* defaultCase = nullptr;
953 for (const auto& c : s.fCases) {
954 if (!c->fValue) {
955 defaultCase = c.get();
956 continue;
957 }
958 ASSERT(c->fValue->fKind == s.fValue->fKind);
959 found = c->fValue->compareConstant(fContext, *s.fValue);
960 if (found) {
961 std::unique_ptr<Statement> newBlock = block_for_case(&s, c.get());
962 if (newBlock) {
963 (*iter)->setStatement(std::move(newBlock));
964 break;
965 } else {
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -0400966 if (s.fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) {
Ethan Nicholas5ac13c22017-05-10 15:06:17 -0400967 this->error(s.fPosition,
968 "static switch contains non-static conditional break");
969 s.fIsStatic = false;
970 }
971 return; // can't simplify
972 }
973 }
974 }
975 if (!found) {
976 // no matching case. use default if it exists, or kill the whole thing
977 if (defaultCase) {
978 std::unique_ptr<Statement> newBlock = block_for_case(&s, defaultCase);
979 if (newBlock) {
980 (*iter)->setStatement(std::move(newBlock));
981 } else {
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -0400982 if (s.fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) {
Ethan Nicholas5ac13c22017-05-10 15:06:17 -0400983 this->error(s.fPosition,
984 "static switch contains non-static conditional break");
985 s.fIsStatic = false;
986 }
987 return; // can't simplify
988 }
989 } else {
990 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
991 }
992 }
993 *outUpdated = true;
994 *outNeedsRescan = true;
995 }
996 break;
997 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400998 case Statement::kExpression_Kind: {
999 ExpressionStatement& e = (ExpressionStatement&) *stmt;
1000 ASSERT((*iter)->statement()->get() == &e);
Ethan Nicholascb670962017-04-20 19:31:52 -04001001 if (!e.fExpression->hasSideEffects()) {
1002 // Expression statement with no side effects, kill it
1003 if (!b.tryRemoveExpressionBefore(iter, e.fExpression.get())) {
1004 *outNeedsRescan = true;
1005 }
1006 ASSERT((*iter)->statement()->get() == stmt);
1007 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
1008 *outUpdated = true;
1009 }
1010 break;
1011 }
1012 default:
1013 break;
1014 }
1015}
1016
1017void Compiler::scanCFG(FunctionDefinition& f) {
1018 CFG cfg = CFGGenerator().getCFG(f);
1019 this->computeDataFlow(&cfg);
ethannicholas22f939e2016-10-13 13:25:34 -07001020
1021 // check for unreachable code
1022 for (size_t i = 0; i < cfg.fBlocks.size(); i++) {
Mike Klein6ad99092016-10-26 10:35:22 -04001023 if (i != cfg.fStart && !cfg.fBlocks[i].fEntrances.size() &&
ethannicholas22f939e2016-10-13 13:25:34 -07001024 cfg.fBlocks[i].fNodes.size()) {
Ethan Nicholas86a43402017-01-19 13:32:00 -05001025 Position p;
1026 switch (cfg.fBlocks[i].fNodes[0].fKind) {
1027 case BasicBlock::Node::kStatement_Kind:
Ethan Nicholascb670962017-04-20 19:31:52 -04001028 p = (*cfg.fBlocks[i].fNodes[0].statement())->fPosition;
Ethan Nicholas86a43402017-01-19 13:32:00 -05001029 break;
1030 case BasicBlock::Node::kExpression_Kind:
Ethan Nicholascb670962017-04-20 19:31:52 -04001031 p = (*cfg.fBlocks[i].fNodes[0].expression())->fPosition;
Ethan Nicholas86a43402017-01-19 13:32:00 -05001032 break;
1033 }
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001034 this->error(p, String("unreachable"));
ethannicholas22f939e2016-10-13 13:25:34 -07001035 }
1036 }
1037 if (fErrorCount) {
1038 return;
1039 }
1040
Ethan Nicholascb670962017-04-20 19:31:52 -04001041 // check for dead code & undefined variables, perform constant propagation
1042 std::unordered_set<const Variable*> undefinedVariables;
1043 bool updated;
1044 bool needsRescan = false;
1045 do {
1046 if (needsRescan) {
1047 cfg = CFGGenerator().getCFG(f);
1048 this->computeDataFlow(&cfg);
1049 needsRescan = false;
Ethan Nicholas113628d2017-02-02 16:11:39 -05001050 }
Ethan Nicholascb670962017-04-20 19:31:52 -04001051
1052 updated = false;
1053 for (BasicBlock& b : cfg.fBlocks) {
1054 DefinitionMap definitions = b.fBefore;
1055
1056 for (auto iter = b.fNodes.begin(); iter != b.fNodes.end() && !needsRescan; ++iter) {
1057 if (iter->fKind == BasicBlock::Node::kExpression_Kind) {
1058 this->simplifyExpression(definitions, b, &iter, &undefinedVariables, &updated,
1059 &needsRescan);
1060 } else {
1061 this->simplifyStatement(definitions, b, &iter, &undefinedVariables, &updated,
1062 &needsRescan);
1063 }
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001064 if (needsRescan) {
1065 break;
1066 }
Ethan Nicholascb670962017-04-20 19:31:52 -04001067 this->addDefinitions(*iter, &definitions);
1068 }
1069 }
1070 } while (updated);
1071 ASSERT(!needsRescan);
ethannicholas22f939e2016-10-13 13:25:34 -07001072
Ethan Nicholas91a10532017-06-22 11:24:38 -04001073 // verify static ifs & switches, clean up dead variable decls
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001074 for (BasicBlock& b : cfg.fBlocks) {
1075 DefinitionMap definitions = b.fBefore;
1076
Ethan Nicholas91a10532017-06-22 11:24:38 -04001077 for (auto iter = b.fNodes.begin(); iter != b.fNodes.end() && !needsRescan;) {
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001078 if (iter->fKind == BasicBlock::Node::kStatement_Kind) {
1079 const Statement& s = **iter->statement();
1080 switch (s.fKind) {
1081 case Statement::kIf_Kind:
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -04001082 if (((const IfStatement&) s).fIsStatic &&
1083 !(fFlags & kPermitInvalidStaticTests_Flag)) {
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001084 this->error(s.fPosition, "static if has non-static test");
1085 }
Ethan Nicholas91a10532017-06-22 11:24:38 -04001086 ++iter;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001087 break;
1088 case Statement::kSwitch_Kind:
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -04001089 if (((const SwitchStatement&) s).fIsStatic &&
1090 !(fFlags & kPermitInvalidStaticTests_Flag)) {
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001091 this->error(s.fPosition, "static switch has non-static test");
1092 }
Ethan Nicholas91a10532017-06-22 11:24:38 -04001093 ++iter;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001094 break;
Ethan Nicholas91a10532017-06-22 11:24:38 -04001095 case Statement::kVarDeclarations_Kind: {
1096 VarDeclarations& decls = *((VarDeclarationsStatement&) s).fDeclaration;
1097 for (auto varIter = decls.fVars.begin(); varIter != decls.fVars.end();) {
1098 if ((*varIter)->fKind == Statement::kNop_Kind) {
1099 varIter = decls.fVars.erase(varIter);
1100 } else {
1101 ++varIter;
1102 }
1103 }
1104 if (!decls.fVars.size()) {
1105 iter = b.fNodes.erase(iter);
1106 } else {
1107 ++iter;
1108 }
1109 break;
1110 }
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001111 default:
Ethan Nicholas91a10532017-06-22 11:24:38 -04001112 ++iter;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001113 break;
1114 }
Ethan Nicholas91a10532017-06-22 11:24:38 -04001115 } else {
1116 ++iter;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001117 }
1118 }
1119 }
1120
ethannicholas22f939e2016-10-13 13:25:34 -07001121 // check for missing return
1122 if (f.fDeclaration.fReturnType != *fContext.fVoid_Type) {
1123 if (cfg.fBlocks[cfg.fExit].fEntrances.size()) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001124 this->error(f.fPosition, String("function can exit without returning a value"));
ethannicholas22f939e2016-10-13 13:25:34 -07001125 }
1126 }
1127}
1128
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001129std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String text,
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001130 const Program::Settings& settings) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001131 fErrorText = "";
1132 fErrorCount = 0;
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001133 fIRGenerator->start(&settings);
ethannicholasd598f792016-07-25 10:08:54 -07001134 std::vector<std::unique_ptr<ProgramElement>> elements;
Brian Salomon1d816b92017-08-17 11:07:59 -04001135 Modifiers::Flag ignored;
ethannicholasb3058bd2016-07-01 08:22:01 -07001136 switch (kind) {
1137 case Program::kVertex_Kind:
Brian Salomon1d816b92017-08-17 11:07:59 -04001138 fIRGenerator->convertProgram(String(SKSL_VERT_INCLUDE), *fTypes, &ignored, &elements);
ethannicholasb3058bd2016-07-01 08:22:01 -07001139 break;
1140 case Program::kFragment_Kind:
Brian Salomon1d816b92017-08-17 11:07:59 -04001141 fIRGenerator->convertProgram(String(SKSL_FRAG_INCLUDE), *fTypes, &ignored, &elements);
ethannicholasb3058bd2016-07-01 08:22:01 -07001142 break;
Ethan Nicholas52cad152017-02-16 16:37:32 -05001143 case Program::kGeometry_Kind:
Brian Salomon1d816b92017-08-17 11:07:59 -04001144 fIRGenerator->convertProgram(String(SKSL_GEOM_INCLUDE), *fTypes, &ignored, &elements);
Ethan Nicholas52cad152017-02-16 16:37:32 -05001145 break;
Ethan Nicholas762466e2017-06-29 10:03:38 -04001146 case Program::kFragmentProcessor_Kind:
Brian Salomon1d816b92017-08-17 11:07:59 -04001147 fIRGenerator->convertProgram(String(SKSL_FP_INCLUDE), *fTypes, &ignored, &elements);
Ethan Nicholas762466e2017-06-29 10:03:38 -04001148 break;
ethannicholasb3058bd2016-07-01 08:22:01 -07001149 }
ethannicholasddb37d62016-10-20 09:54:00 -07001150 fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
Brian Salomon1d816b92017-08-17 11:07:59 -04001151 Modifiers::Flag defaultPrecision;
1152 fIRGenerator->convertProgram(text, *fTypes, &defaultPrecision, &elements);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04001153 if (!fErrorCount) {
1154 for (auto& element : elements) {
1155 if (element->fKind == ProgramElement::kFunction_Kind) {
1156 this->scanCFG((FunctionDefinition&) *element);
1157 }
1158 }
1159 }
Brian Salomon1d816b92017-08-17 11:07:59 -04001160 auto result = std::unique_ptr<Program>(new Program(kind, settings, defaultPrecision, &fContext,
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001161 std::move(elements),
1162 fIRGenerator->fSymbolTable,
1163 fIRGenerator->fInputs));
Ethan Nicholas3605ace2016-11-21 15:59:48 -05001164 fIRGenerator->finish();
ethannicholasb3058bd2016-07-01 08:22:01 -07001165 this->writeErrorCount();
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001166 if (fErrorCount) {
1167 return nullptr;
1168 }
1169 return result;
1170}
1171
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001172bool Compiler::toSPIRV(const Program& program, OutputStream& out) {
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001173#ifdef SK_ENABLE_SPIRV_VALIDATION
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001174 StringStream buffer;
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001175 SPIRVCodeGenerator cg(&fContext, &program, this, &buffer);
1176 bool result = cg.generateCode();
1177 if (result) {
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001178 spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0);
Ethan Nicholas762466e2017-06-29 10:03:38 -04001179 const String& data = buffer.str();
1180 ASSERT(0 == data.size() % 4);
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001181 auto dumpmsg = [](spv_message_level_t, const char*, const spv_position_t&, const char* m) {
1182 SkDebugf("SPIR-V validation error: %s\n", m);
1183 };
1184 tools.SetMessageConsumer(dumpmsg);
1185 // Verify that the SPIR-V we produced is valid. If this assert fails, check the logs prior
1186 // to the failure to see the validation errors.
Ethan Nicholas762466e2017-06-29 10:03:38 -04001187 ASSERT_RESULT(tools.Validate((const uint32_t*) data.c_str(), data.size() / 4));
1188 out.write(data.c_str(), data.size());
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001189 }
1190#else
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001191 SPIRVCodeGenerator cg(&fContext, &program, this, &out);
1192 bool result = cg.generateCode();
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001193#endif
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001194 this->writeErrorCount();
Ethan Nicholasce33f102016-12-09 17:22:59 -05001195 return result;
1196}
1197
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001198bool Compiler::toSPIRV(const Program& program, String* out) {
1199 StringStream buffer;
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001200 bool result = this->toSPIRV(program, buffer);
1201 if (result) {
Ethan Nicholas762466e2017-06-29 10:03:38 -04001202 *out = buffer.str();
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001203 }
1204 return result;
1205}
1206
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001207bool Compiler::toGLSL(const Program& program, OutputStream& out) {
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001208 GLSLCodeGenerator cg(&fContext, &program, this, &out);
1209 bool result = cg.generateCode();
1210 this->writeErrorCount();
1211 return result;
1212}
1213
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001214bool Compiler::toGLSL(const Program& program, String* out) {
1215 StringStream buffer;
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001216 bool result = this->toGLSL(program, buffer);
1217 if (result) {
Ethan Nicholas762466e2017-06-29 10:03:38 -04001218 *out = buffer.str();
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001219 }
1220 return result;
1221}
1222
Ethan Nicholas762466e2017-06-29 10:03:38 -04001223bool Compiler::toCPP(const Program& program, String name, OutputStream& out) {
1224 CPPCodeGenerator cg(&fContext, &program, this, name, &out);
1225 bool result = cg.generateCode();
1226 this->writeErrorCount();
1227 return result;
1228}
1229
1230bool Compiler::toH(const Program& program, String name, OutputStream& out) {
1231 HCodeGenerator cg(&program, this, name, &out);
1232 bool result = cg.generateCode();
1233 this->writeErrorCount();
1234 return result;
1235}
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001236
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001237void Compiler::error(Position position, String msg) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001238 fErrorCount++;
1239 fErrorText += "error: " + position.description() + ": " + msg.c_str() + "\n";
1240}
1241
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001242String Compiler::errorText() {
1243 String result = fErrorText;
ethannicholasb3058bd2016-07-01 08:22:01 -07001244 return result;
1245}
1246
1247void Compiler::writeErrorCount() {
1248 if (fErrorCount) {
1249 fErrorText += to_string(fErrorCount) + " error";
1250 if (fErrorCount > 1) {
1251 fErrorText += "s";
1252 }
1253 fErrorText += "\n";
1254 }
1255}
1256
ethannicholasb3058bd2016-07-01 08:22:01 -07001257} // namespace