blob: 593397bd2a0a3445a7d8da473c28405104491080 [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
Mike Klein6ad99092016-10-26 10:35:22 -040057Compiler::Compiler()
ethannicholasb3058bd2016-07-01 08:22:01 -070058: fErrorCount(0) {
Ethan Nicholas8feeff92017-03-30 14:11:58 -040059 auto types = std::shared_ptr<SymbolTable>(new SymbolTable(this));
60 auto symbols = std::shared_ptr<SymbolTable>(new SymbolTable(types, this));
ethannicholasd598f792016-07-25 10:08:54 -070061 fIRGenerator = new IRGenerator(&fContext, symbols, *this);
ethannicholasb3058bd2016-07-01 08:22:01 -070062 fTypes = types;
ethannicholasd598f792016-07-25 10:08:54 -070063 #define ADD_TYPE(t) types->addWithoutOwnership(fContext.f ## t ## _Type->fName, \
64 fContext.f ## t ## _Type.get())
ethannicholasb3058bd2016-07-01 08:22:01 -070065 ADD_TYPE(Void);
66 ADD_TYPE(Float);
67 ADD_TYPE(Vec2);
68 ADD_TYPE(Vec3);
69 ADD_TYPE(Vec4);
70 ADD_TYPE(Double);
71 ADD_TYPE(DVec2);
72 ADD_TYPE(DVec3);
73 ADD_TYPE(DVec4);
74 ADD_TYPE(Int);
75 ADD_TYPE(IVec2);
76 ADD_TYPE(IVec3);
77 ADD_TYPE(IVec4);
78 ADD_TYPE(UInt);
79 ADD_TYPE(UVec2);
80 ADD_TYPE(UVec3);
81 ADD_TYPE(UVec4);
82 ADD_TYPE(Bool);
83 ADD_TYPE(BVec2);
84 ADD_TYPE(BVec3);
85 ADD_TYPE(BVec4);
86 ADD_TYPE(Mat2x2);
Ethan Nicholas0df1b042017-03-31 13:56:23 -040087 types->addWithoutOwnership(String("mat2x2"), fContext.fMat2x2_Type.get());
ethannicholasb3058bd2016-07-01 08:22:01 -070088 ADD_TYPE(Mat2x3);
89 ADD_TYPE(Mat2x4);
90 ADD_TYPE(Mat3x2);
91 ADD_TYPE(Mat3x3);
Ethan Nicholas0df1b042017-03-31 13:56:23 -040092 types->addWithoutOwnership(String("mat3x3"), fContext.fMat3x3_Type.get());
ethannicholasb3058bd2016-07-01 08:22:01 -070093 ADD_TYPE(Mat3x4);
94 ADD_TYPE(Mat4x2);
95 ADD_TYPE(Mat4x3);
96 ADD_TYPE(Mat4x4);
Ethan Nicholas0df1b042017-03-31 13:56:23 -040097 types->addWithoutOwnership(String("mat4x4"), fContext.fMat4x4_Type.get());
ethannicholasb3058bd2016-07-01 08:22:01 -070098 ADD_TYPE(GenType);
99 ADD_TYPE(GenDType);
100 ADD_TYPE(GenIType);
101 ADD_TYPE(GenUType);
102 ADD_TYPE(GenBType);
103 ADD_TYPE(Mat);
104 ADD_TYPE(Vec);
105 ADD_TYPE(GVec);
106 ADD_TYPE(GVec2);
107 ADD_TYPE(GVec3);
108 ADD_TYPE(GVec4);
109 ADD_TYPE(DVec);
110 ADD_TYPE(IVec);
111 ADD_TYPE(UVec);
112 ADD_TYPE(BVec);
113
114 ADD_TYPE(Sampler1D);
115 ADD_TYPE(Sampler2D);
116 ADD_TYPE(Sampler3D);
ethannicholas5961bc92016-10-12 06:39:56 -0700117 ADD_TYPE(SamplerExternalOES);
ethannicholasb3058bd2016-07-01 08:22:01 -0700118 ADD_TYPE(SamplerCube);
119 ADD_TYPE(Sampler2DRect);
120 ADD_TYPE(Sampler1DArray);
121 ADD_TYPE(Sampler2DArray);
122 ADD_TYPE(SamplerCubeArray);
123 ADD_TYPE(SamplerBuffer);
124 ADD_TYPE(Sampler2DMS);
125 ADD_TYPE(Sampler2DMSArray);
126
Brian Salomonbf7b6202016-11-11 16:08:03 -0500127 ADD_TYPE(ISampler2D);
128
Brian Salomon2a51de82016-11-16 12:06:01 -0500129 ADD_TYPE(Image2D);
130 ADD_TYPE(IImage2D);
131
Greg Daniel64773e62016-11-22 09:44:03 -0500132 ADD_TYPE(SubpassInput);
133 ADD_TYPE(SubpassInputMS);
134
ethannicholasb3058bd2016-07-01 08:22:01 -0700135 ADD_TYPE(GSampler1D);
136 ADD_TYPE(GSampler2D);
137 ADD_TYPE(GSampler3D);
138 ADD_TYPE(GSamplerCube);
139 ADD_TYPE(GSampler2DRect);
140 ADD_TYPE(GSampler1DArray);
141 ADD_TYPE(GSampler2DArray);
142 ADD_TYPE(GSamplerCubeArray);
143 ADD_TYPE(GSamplerBuffer);
144 ADD_TYPE(GSampler2DMS);
145 ADD_TYPE(GSampler2DMSArray);
146
147 ADD_TYPE(Sampler1DShadow);
148 ADD_TYPE(Sampler2DShadow);
149 ADD_TYPE(SamplerCubeShadow);
150 ADD_TYPE(Sampler2DRectShadow);
151 ADD_TYPE(Sampler1DArrayShadow);
152 ADD_TYPE(Sampler2DArrayShadow);
153 ADD_TYPE(SamplerCubeArrayShadow);
154 ADD_TYPE(GSampler2DArrayShadow);
155 ADD_TYPE(GSamplerCubeArrayShadow);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400156 ADD_TYPE(ColorSpaceXform);
ethannicholasb3058bd2016-07-01 08:22:01 -0700157
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400158 String skCapsName("sk_Caps");
159 Variable* skCaps = new Variable(Position(), Modifiers(), skCapsName,
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500160 *fContext.fSkCaps_Type, Variable::kGlobal_Storage);
161 fIRGenerator->fSymbolTable->add(skCapsName, std::unique_ptr<Symbol>(skCaps));
162
Ethan Nicholas762466e2017-06-29 10:03:38 -0400163 String skArgsName("sk_Args");
164 Variable* skArgs = new Variable(Position(), Modifiers(), skArgsName,
165 *fContext.fSkArgs_Type, Variable::kGlobal_Storage);
166 fIRGenerator->fSymbolTable->add(skArgsName, std::unique_ptr<Symbol>(skArgs));
167
ethannicholas5961bc92016-10-12 06:39:56 -0700168 Modifiers::Flag ignored1;
169 std::vector<std::unique_ptr<ProgramElement>> ignored2;
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400170 fIRGenerator->convertProgram(String(SKSL_INCLUDE), *fTypes, &ignored1, &ignored2);
ethannicholasddb37d62016-10-20 09:54:00 -0700171 fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
ethannicholasb3058bd2016-07-01 08:22:01 -0700172 ASSERT(!fErrorCount);
173}
174
175Compiler::~Compiler() {
176 delete fIRGenerator;
177}
178
ethannicholas22f939e2016-10-13 13:25:34 -0700179// add the definition created by assigning to the lvalue to the definition set
Ethan Nicholas86a43402017-01-19 13:32:00 -0500180void Compiler::addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr,
181 DefinitionMap* definitions) {
ethannicholas22f939e2016-10-13 13:25:34 -0700182 switch (lvalue->fKind) {
183 case Expression::kVariableReference_Kind: {
184 const Variable& var = ((VariableReference*) lvalue)->fVariable;
185 if (var.fStorage == Variable::kLocal_Storage) {
186 (*definitions)[&var] = expr;
187 }
188 break;
189 }
190 case Expression::kSwizzle_Kind:
191 // We consider the variable written to as long as at least some of its components have
192 // been written to. This will lead to some false negatives (we won't catch it if you
193 // write to foo.x and then read foo.y), but being stricter could lead to false positives
Mike Klein6ad99092016-10-26 10:35:22 -0400194 // (we write to foo.x, and then pass foo to a function which happens to only read foo.x,
195 // 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 -0700196 // more complicated whole-program analysis. This is probably good enough.
Mike Klein6ad99092016-10-26 10:35:22 -0400197 this->addDefinition(((Swizzle*) lvalue)->fBase.get(),
Ethan Nicholas86a43402017-01-19 13:32:00 -0500198 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
ethannicholas22f939e2016-10-13 13:25:34 -0700199 definitions);
200 break;
201 case Expression::kIndex_Kind:
202 // see comments in Swizzle
Mike Klein6ad99092016-10-26 10:35:22 -0400203 this->addDefinition(((IndexExpression*) lvalue)->fBase.get(),
Ethan Nicholas86a43402017-01-19 13:32:00 -0500204 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
ethannicholas22f939e2016-10-13 13:25:34 -0700205 definitions);
206 break;
207 case Expression::kFieldAccess_Kind:
208 // see comments in Swizzle
Mike Klein6ad99092016-10-26 10:35:22 -0400209 this->addDefinition(((FieldAccess*) lvalue)->fBase.get(),
Ethan Nicholas86a43402017-01-19 13:32:00 -0500210 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
ethannicholas22f939e2016-10-13 13:25:34 -0700211 definitions);
212 break;
213 default:
214 // not an lvalue, can't happen
215 ASSERT(false);
216 }
217}
218
219// add local variables defined by this node to the set
Mike Klein6ad99092016-10-26 10:35:22 -0400220void Compiler::addDefinitions(const BasicBlock::Node& node,
Ethan Nicholas86a43402017-01-19 13:32:00 -0500221 DefinitionMap* definitions) {
ethannicholas22f939e2016-10-13 13:25:34 -0700222 switch (node.fKind) {
223 case BasicBlock::Node::kExpression_Kind: {
Ethan Nicholascb670962017-04-20 19:31:52 -0400224 ASSERT(node.expression());
225 const Expression* expr = (Expression*) node.expression()->get();
Ethan Nicholas86a43402017-01-19 13:32:00 -0500226 switch (expr->fKind) {
227 case Expression::kBinary_Kind: {
228 BinaryExpression* b = (BinaryExpression*) expr;
229 if (b->fOperator == Token::EQ) {
230 this->addDefinition(b->fLeft.get(), &b->fRight, definitions);
231 } else if (Token::IsAssignment(b->fOperator)) {
232 this->addDefinition(
233 b->fLeft.get(),
234 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
235 definitions);
236
237 }
238 break;
ethannicholas22f939e2016-10-13 13:25:34 -0700239 }
Ethan Nicholas86a43402017-01-19 13:32:00 -0500240 case Expression::kPrefix_Kind: {
241 const PrefixExpression* p = (PrefixExpression*) expr;
242 if (p->fOperator == Token::MINUSMINUS || p->fOperator == Token::PLUSPLUS) {
243 this->addDefinition(
244 p->fOperand.get(),
245 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
246 definitions);
247 }
248 break;
249 }
250 case Expression::kPostfix_Kind: {
251 const PostfixExpression* p = (PostfixExpression*) expr;
252 if (p->fOperator == Token::MINUSMINUS || p->fOperator == Token::PLUSPLUS) {
253 this->addDefinition(
254 p->fOperand.get(),
255 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
256 definitions);
Ethan Nicholas86a43402017-01-19 13:32:00 -0500257 }
258 break;
259 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400260 case Expression::kVariableReference_Kind: {
261 const VariableReference* v = (VariableReference*) expr;
262 if (v->fRefKind != VariableReference::kRead_RefKind) {
263 this->addDefinition(
264 v,
265 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
266 definitions);
267 }
268 }
Ethan Nicholas86a43402017-01-19 13:32:00 -0500269 default:
270 break;
ethannicholas22f939e2016-10-13 13:25:34 -0700271 }
272 break;
273 }
274 case BasicBlock::Node::kStatement_Kind: {
Ethan Nicholascb670962017-04-20 19:31:52 -0400275 const Statement* stmt = (Statement*) node.statement()->get();
Ethan Nicholasb4dc4192017-06-02 10:16:28 -0400276 if (stmt->fKind == Statement::kVarDeclaration_Kind) {
277 VarDeclaration& vd = (VarDeclaration&) *stmt;
278 if (vd.fValue) {
279 (*definitions)[vd.fVar] = &vd.fValue;
ethannicholas22f939e2016-10-13 13:25:34 -0700280 }
281 }
282 break;
283 }
284 }
285}
286
287void Compiler::scanCFG(CFG* cfg, BlockId blockId, std::set<BlockId>* workList) {
288 BasicBlock& block = cfg->fBlocks[blockId];
289
290 // compute definitions after this block
Ethan Nicholas86a43402017-01-19 13:32:00 -0500291 DefinitionMap after = block.fBefore;
ethannicholas22f939e2016-10-13 13:25:34 -0700292 for (const BasicBlock::Node& n : block.fNodes) {
293 this->addDefinitions(n, &after);
294 }
295
296 // propagate definitions to exits
297 for (BlockId exitId : block.fExits) {
298 BasicBlock& exit = cfg->fBlocks[exitId];
299 for (const auto& pair : after) {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500300 std::unique_ptr<Expression>* e1 = pair.second;
301 auto found = exit.fBefore.find(pair.first);
302 if (found == exit.fBefore.end()) {
303 // exit has no definition for it, just copy it
304 workList->insert(exitId);
ethannicholas22f939e2016-10-13 13:25:34 -0700305 exit.fBefore[pair.first] = e1;
306 } else {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500307 // exit has a (possibly different) value already defined
308 std::unique_ptr<Expression>* e2 = exit.fBefore[pair.first];
ethannicholas22f939e2016-10-13 13:25:34 -0700309 if (e1 != e2) {
310 // definition has changed, merge and add exit block to worklist
311 workList->insert(exitId);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500312 if (e1 && e2) {
313 exit.fBefore[pair.first] =
Ethan Nicholas86a43402017-01-19 13:32:00 -0500314 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression;
Ethan Nicholasaf197692017-02-27 13:26:45 -0500315 } else {
316 exit.fBefore[pair.first] = nullptr;
317 }
ethannicholas22f939e2016-10-13 13:25:34 -0700318 }
319 }
320 }
321 }
322}
323
324// returns a map which maps all local variables in the function to null, indicating that their value
325// is initially unknown
Ethan Nicholas86a43402017-01-19 13:32:00 -0500326static DefinitionMap compute_start_state(const CFG& cfg) {
327 DefinitionMap result;
Mike Klein6ad99092016-10-26 10:35:22 -0400328 for (const auto& block : cfg.fBlocks) {
329 for (const auto& node : block.fNodes) {
ethannicholas22f939e2016-10-13 13:25:34 -0700330 if (node.fKind == BasicBlock::Node::kStatement_Kind) {
Ethan Nicholascb670962017-04-20 19:31:52 -0400331 ASSERT(node.statement());
332 const Statement* s = node.statement()->get();
ethannicholas22f939e2016-10-13 13:25:34 -0700333 if (s->fKind == Statement::kVarDeclarations_Kind) {
334 const VarDeclarationsStatement* vd = (const VarDeclarationsStatement*) s;
Ethan Nicholascb670962017-04-20 19:31:52 -0400335 for (const auto& decl : vd->fDeclaration->fVars) {
Ethan Nicholas91a10532017-06-22 11:24:38 -0400336 if (decl->fKind == Statement::kVarDeclaration_Kind) {
337 result[((VarDeclaration&) *decl).fVar] = nullptr;
338 }
Mike Klein6ad99092016-10-26 10:35:22 -0400339 }
ethannicholas22f939e2016-10-13 13:25:34 -0700340 }
341 }
342 }
343 }
344 return result;
345}
346
Ethan Nicholascb670962017-04-20 19:31:52 -0400347/**
348 * Returns true if assigning to this lvalue has no effect.
349 */
350static bool is_dead(const Expression& lvalue) {
351 switch (lvalue.fKind) {
352 case Expression::kVariableReference_Kind:
353 return ((VariableReference&) lvalue).fVariable.dead();
354 case Expression::kSwizzle_Kind:
355 return is_dead(*((Swizzle&) lvalue).fBase);
356 case Expression::kFieldAccess_Kind:
357 return is_dead(*((FieldAccess&) lvalue).fBase);
358 case Expression::kIndex_Kind: {
359 const IndexExpression& idx = (IndexExpression&) lvalue;
360 return is_dead(*idx.fBase) && !idx.fIndex->hasSideEffects();
361 }
362 default:
363 ABORT("invalid lvalue: %s\n", lvalue.description().c_str());
364 }
365}
ethannicholas22f939e2016-10-13 13:25:34 -0700366
Ethan Nicholascb670962017-04-20 19:31:52 -0400367/**
368 * Returns true if this is an assignment which can be collapsed down to just the right hand side due
369 * to a dead target and lack of side effects on the left hand side.
370 */
371static bool dead_assignment(const BinaryExpression& b) {
372 if (!Token::IsAssignment(b.fOperator)) {
373 return false;
374 }
375 return is_dead(*b.fLeft);
376}
377
378void Compiler::computeDataFlow(CFG* cfg) {
379 cfg->fBlocks[cfg->fStart].fBefore = compute_start_state(*cfg);
ethannicholas22f939e2016-10-13 13:25:34 -0700380 std::set<BlockId> workList;
Ethan Nicholascb670962017-04-20 19:31:52 -0400381 for (BlockId i = 0; i < cfg->fBlocks.size(); i++) {
ethannicholas22f939e2016-10-13 13:25:34 -0700382 workList.insert(i);
383 }
384 while (workList.size()) {
385 BlockId next = *workList.begin();
386 workList.erase(workList.begin());
Ethan Nicholascb670962017-04-20 19:31:52 -0400387 this->scanCFG(cfg, next, &workList);
ethannicholas22f939e2016-10-13 13:25:34 -0700388 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400389}
390
391/**
392 * Attempts to replace the expression pointed to by iter with a new one (in both the CFG and the
393 * IR). If the expression can be cleanly removed, returns true and updates the iterator to point to
394 * the newly-inserted element. Otherwise updates only the IR and returns false (and the CFG will
395 * need to be regenerated).
396 */
397bool try_replace_expression(BasicBlock* b,
398 std::vector<BasicBlock::Node>::iterator* iter,
399 std::unique_ptr<Expression>* newExpression) {
400 std::unique_ptr<Expression>* target = (*iter)->expression();
401 if (!b->tryRemoveExpression(iter)) {
402 *target = std::move(*newExpression);
403 return false;
404 }
405 *target = std::move(*newExpression);
406 return b->tryInsertExpression(iter, target);
407}
408
409/**
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400410 * Returns true if the expression is a constant numeric literal with the specified value, or a
411 * constant vector with all elements equal to the specified value.
Ethan Nicholascb670962017-04-20 19:31:52 -0400412 */
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400413bool is_constant(const Expression& expr, double value) {
Ethan Nicholascb670962017-04-20 19:31:52 -0400414 switch (expr.fKind) {
415 case Expression::kIntLiteral_Kind:
416 return ((IntLiteral&) expr).fValue == value;
417 case Expression::kFloatLiteral_Kind:
418 return ((FloatLiteral&) expr).fValue == value;
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400419 case Expression::kConstructor_Kind: {
420 Constructor& c = (Constructor&) expr;
421 if (c.fType.kind() == Type::kVector_Kind && c.isConstant()) {
422 for (int i = 0; i < c.fType.columns(); ++i) {
423 if (!is_constant(c.getVecComponent(i), value)) {
424 return false;
425 }
426 }
427 return true;
428 }
429 return false;
430 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400431 default:
432 return false;
433 }
434}
435
436/**
437 * Collapses the binary expression pointed to by iter down to just the right side (in both the IR
438 * and CFG structures).
439 */
440void delete_left(BasicBlock* b,
441 std::vector<BasicBlock::Node>::iterator* iter,
442 bool* outUpdated,
443 bool* outNeedsRescan) {
444 *outUpdated = true;
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400445 std::unique_ptr<Expression>* target = (*iter)->expression();
446 ASSERT((*target)->fKind == Expression::kBinary_Kind);
447 BinaryExpression& bin = (BinaryExpression&) **target;
448 bool result;
449 if (bin.fOperator == Token::EQ) {
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400450 result = b->tryRemoveLValueBefore(iter, bin.fLeft.get());
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400451 } else {
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400452 result = b->tryRemoveExpressionBefore(iter, bin.fLeft.get());
Ethan Nicholascb670962017-04-20 19:31:52 -0400453 }
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400454 *target = std::move(bin.fRight);
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400455 if (!result) {
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400456 *outNeedsRescan = true;
457 return;
458 }
459 if (*iter == b->fNodes.begin()) {
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400460 *outNeedsRescan = true;
461 return;
462 }
463 --(*iter);
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400464 if ((*iter)->fKind != BasicBlock::Node::kExpression_Kind ||
465 (*iter)->expression() != &bin.fRight) {
466 *outNeedsRescan = true;
467 return;
468 }
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400469 *iter = b->fNodes.erase(*iter);
470 ASSERT((*iter)->expression() == target);
Ethan Nicholascb670962017-04-20 19:31:52 -0400471}
472
473/**
474 * Collapses the binary expression pointed to by iter down to just the left side (in both the IR and
475 * CFG structures).
476 */
477void delete_right(BasicBlock* b,
478 std::vector<BasicBlock::Node>::iterator* iter,
479 bool* outUpdated,
480 bool* outNeedsRescan) {
481 *outUpdated = true;
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400482 std::unique_ptr<Expression>* target = (*iter)->expression();
483 ASSERT((*target)->fKind == Expression::kBinary_Kind);
484 BinaryExpression& bin = (BinaryExpression&) **target;
485 if (!b->tryRemoveExpressionBefore(iter, bin.fRight.get())) {
486 *target = std::move(bin.fLeft);
Ethan Nicholascb670962017-04-20 19:31:52 -0400487 *outNeedsRescan = true;
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400488 return;
Ethan Nicholascb670962017-04-20 19:31:52 -0400489 }
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400490 *target = std::move(bin.fLeft);
491 if (*iter == b->fNodes.begin()) {
492 *outNeedsRescan = true;
493 return;
494 }
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400495 --(*iter);
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400496 if (((*iter)->fKind != BasicBlock::Node::kExpression_Kind ||
497 (*iter)->expression() != &bin.fLeft)) {
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
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400505/**
506 * Constructs the specified type using a single argument.
507 */
508static std::unique_ptr<Expression> construct(const Type& type, std::unique_ptr<Expression> v) {
509 std::vector<std::unique_ptr<Expression>> args;
510 args.push_back(std::move(v));
511 auto result = std::unique_ptr<Expression>(new Constructor(Position(), type, std::move(args)));
512 return result;
513}
514
515/**
516 * Used in the implementations of vectorize_left and vectorize_right. Given a vector type and an
517 * expression x, deletes the expression pointed to by iter and replaces it with <type>(x).
518 */
519static void vectorize(BasicBlock* b,
520 std::vector<BasicBlock::Node>::iterator* iter,
521 const Type& type,
522 std::unique_ptr<Expression>* otherExpression,
523 bool* outUpdated,
524 bool* outNeedsRescan) {
525 ASSERT((*(*iter)->expression())->fKind == Expression::kBinary_Kind);
526 ASSERT(type.kind() == Type::kVector_Kind);
527 ASSERT((*otherExpression)->fType.kind() == Type::kScalar_Kind);
528 *outUpdated = true;
529 std::unique_ptr<Expression>* target = (*iter)->expression();
530 if (!b->tryRemoveExpression(iter)) {
531 *target = construct(type, std::move(*otherExpression));
532 *outNeedsRescan = true;
533 } else {
534 *target = construct(type, std::move(*otherExpression));
535 if (!b->tryInsertExpression(iter, target)) {
536 *outNeedsRescan = true;
537 }
538 }
539}
540
541/**
542 * Given a binary expression of the form x <op> vec<n>(y), deletes the right side and vectorizes the
543 * left to yield vec<n>(x).
544 */
545static void vectorize_left(BasicBlock* b,
546 std::vector<BasicBlock::Node>::iterator* iter,
547 bool* outUpdated,
548 bool* outNeedsRescan) {
549 BinaryExpression& bin = (BinaryExpression&) **(*iter)->expression();
550 vectorize(b, iter, bin.fRight->fType, &bin.fLeft, outUpdated, outNeedsRescan);
551}
552
553/**
554 * Given a binary expression of the form vec<n>(x) <op> y, deletes the left side and vectorizes the
555 * right to yield vec<n>(y).
556 */
557static void vectorize_right(BasicBlock* b,
558 std::vector<BasicBlock::Node>::iterator* iter,
559 bool* outUpdated,
560 bool* outNeedsRescan) {
561 BinaryExpression& bin = (BinaryExpression&) **(*iter)->expression();
562 vectorize(b, iter, bin.fLeft->fType, &bin.fRight, outUpdated, outNeedsRescan);
563}
564
565// Mark that an expression which we were writing to is no longer being written to
566void clear_write(const Expression& expr) {
567 switch (expr.fKind) {
568 case Expression::kVariableReference_Kind: {
569 ((VariableReference&) expr).setRefKind(VariableReference::kRead_RefKind);
570 break;
571 }
572 case Expression::kFieldAccess_Kind:
573 clear_write(*((FieldAccess&) expr).fBase);
574 break;
575 case Expression::kSwizzle_Kind:
576 clear_write(*((Swizzle&) expr).fBase);
577 break;
578 case Expression::kIndex_Kind:
579 clear_write(*((IndexExpression&) expr).fBase);
580 break;
581 default:
582 ABORT("shouldn't be writing to this kind of expression\n");
583 break;
584 }
585}
586
Ethan Nicholascb670962017-04-20 19:31:52 -0400587void Compiler::simplifyExpression(DefinitionMap& definitions,
588 BasicBlock& b,
589 std::vector<BasicBlock::Node>::iterator* iter,
590 std::unordered_set<const Variable*>* undefinedVariables,
591 bool* outUpdated,
592 bool* outNeedsRescan) {
593 Expression* expr = (*iter)->expression()->get();
594 ASSERT(expr);
595 if ((*iter)->fConstantPropagation) {
596 std::unique_ptr<Expression> optimized = expr->constantPropagate(*fIRGenerator, definitions);
597 if (optimized) {
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400598 *outUpdated = true;
Ethan Nicholascb670962017-04-20 19:31:52 -0400599 if (!try_replace_expression(&b, iter, &optimized)) {
600 *outNeedsRescan = true;
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400601 return;
Ethan Nicholascb670962017-04-20 19:31:52 -0400602 }
603 ASSERT((*iter)->fKind == BasicBlock::Node::kExpression_Kind);
604 expr = (*iter)->expression()->get();
Ethan Nicholascb670962017-04-20 19:31:52 -0400605 }
606 }
607 switch (expr->fKind) {
608 case Expression::kVariableReference_Kind: {
609 const Variable& var = ((VariableReference*) expr)->fVariable;
610 if (var.fStorage == Variable::kLocal_Storage && !definitions[&var] &&
611 (*undefinedVariables).find(&var) == (*undefinedVariables).end()) {
612 (*undefinedVariables).insert(&var);
613 this->error(expr->fPosition,
614 "'" + var.fName + "' has not been assigned");
615 }
616 break;
617 }
618 case Expression::kTernary_Kind: {
619 TernaryExpression* t = (TernaryExpression*) expr;
620 if (t->fTest->fKind == Expression::kBoolLiteral_Kind) {
621 // ternary has a constant test, replace it with either the true or
622 // false branch
623 if (((BoolLiteral&) *t->fTest).fValue) {
624 (*iter)->setExpression(std::move(t->fIfTrue));
625 } else {
626 (*iter)->setExpression(std::move(t->fIfFalse));
627 }
628 *outUpdated = true;
629 *outNeedsRescan = true;
630 }
631 break;
632 }
633 case Expression::kBinary_Kind: {
Ethan Nicholascb670962017-04-20 19:31:52 -0400634 BinaryExpression* bin = (BinaryExpression*) expr;
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400635 if (dead_assignment(*bin)) {
636 delete_left(&b, iter, outUpdated, outNeedsRescan);
637 break;
638 }
639 // collapse useless expressions like x * 1 or x + 0
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400640 if (((bin->fLeft->fType.kind() != Type::kScalar_Kind) &&
641 (bin->fLeft->fType.kind() != Type::kVector_Kind)) ||
642 ((bin->fRight->fType.kind() != Type::kScalar_Kind) &&
643 (bin->fRight->fType.kind() != Type::kVector_Kind))) {
644 break;
645 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400646 switch (bin->fOperator) {
647 case Token::STAR:
648 if (is_constant(*bin->fLeft, 1)) {
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400649 if (bin->fLeft->fType.kind() == Type::kVector_Kind &&
650 bin->fRight->fType.kind() == Type::kScalar_Kind) {
651 // vec4(1) * x -> vec4(x)
652 vectorize_right(&b, iter, outUpdated, outNeedsRescan);
653 } else {
654 // 1 * x -> x
655 // 1 * vec4(x) -> vec4(x)
656 // vec4(1) * vec4(x) -> vec4(x)
657 delete_left(&b, iter, outUpdated, outNeedsRescan);
658 }
659 }
660 else if (is_constant(*bin->fLeft, 0)) {
661 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
662 bin->fRight->fType.kind() == Type::kVector_Kind) {
663 // 0 * vec4(x) -> vec4(0)
664 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
665 } else {
666 // 0 * x -> 0
667 // vec4(0) * x -> vec4(0)
668 // vec4(0) * vec4(x) -> vec4(0)
669 delete_right(&b, iter, outUpdated, outNeedsRescan);
670 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400671 }
672 else if (is_constant(*bin->fRight, 1)) {
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400673 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
674 bin->fRight->fType.kind() == Type::kVector_Kind) {
675 // x * vec4(1) -> vec4(x)
676 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
677 } else {
678 // x * 1 -> x
679 // vec4(x) * 1 -> vec4(x)
680 // vec4(x) * vec4(1) -> vec4(x)
681 delete_right(&b, iter, outUpdated, outNeedsRescan);
682 }
683 }
684 else if (is_constant(*bin->fRight, 0)) {
685 if (bin->fLeft->fType.kind() == Type::kVector_Kind &&
686 bin->fRight->fType.kind() == Type::kScalar_Kind) {
687 // vec4(x) * 0 -> vec4(0)
688 vectorize_right(&b, iter, outUpdated, outNeedsRescan);
689 } else {
690 // x * 0 -> 0
691 // x * vec4(0) -> vec4(0)
692 // vec4(x) * vec4(0) -> vec4(0)
693 delete_left(&b, iter, outUpdated, outNeedsRescan);
694 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400695 }
696 break;
Ethan Nicholas56e42712017-04-21 10:23:37 -0400697 case Token::PLUS:
Ethan Nicholascb670962017-04-20 19:31:52 -0400698 if (is_constant(*bin->fLeft, 0)) {
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400699 if (bin->fLeft->fType.kind() == Type::kVector_Kind &&
700 bin->fRight->fType.kind() == Type::kScalar_Kind) {
701 // vec4(0) + x -> vec4(x)
702 vectorize_right(&b, iter, outUpdated, outNeedsRescan);
703 } else {
704 // 0 + x -> x
705 // 0 + vec4(x) -> vec4(x)
706 // vec4(0) + vec4(x) -> vec4(x)
707 delete_left(&b, iter, outUpdated, outNeedsRescan);
708 }
709 } else if (is_constant(*bin->fRight, 0)) {
710 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
711 bin->fRight->fType.kind() == Type::kVector_Kind) {
712 // x + vec4(0) -> vec4(x)
713 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
714 } else {
715 // x + 0 -> x
716 // vec4(x) + 0 -> vec4(x)
717 // vec4(x) + vec4(0) -> vec4(x)
718 delete_right(&b, iter, outUpdated, outNeedsRescan);
719 }
Ethan Nicholas56e42712017-04-21 10:23:37 -0400720 }
721 break;
722 case Token::MINUS:
723 if (is_constant(*bin->fRight, 0)) {
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400724 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
725 bin->fRight->fType.kind() == Type::kVector_Kind) {
726 // x - vec4(0) -> vec4(x)
727 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
728 } else {
729 // x - 0 -> x
730 // vec4(x) - 0 -> vec4(x)
731 // vec4(x) - vec4(0) -> vec4(x)
732 delete_right(&b, iter, outUpdated, outNeedsRescan);
733 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400734 }
735 break;
736 case Token::SLASH:
737 if (is_constant(*bin->fRight, 1)) {
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400738 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
739 bin->fRight->fType.kind() == Type::kVector_Kind) {
740 // x / vec4(1) -> vec4(x)
741 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
742 } else {
743 // x / 1 -> x
744 // vec4(x) / 1 -> vec4(x)
745 // vec4(x) / vec4(1) -> vec4(x)
746 delete_right(&b, iter, outUpdated, outNeedsRescan);
747 }
748 } else if (is_constant(*bin->fLeft, 0)) {
749 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
750 bin->fRight->fType.kind() == Type::kVector_Kind) {
751 // 0 / vec4(x) -> vec4(0)
752 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
753 } else {
754 // 0 / x -> 0
755 // vec4(0) / x -> vec4(0)
756 // vec4(0) / vec4(x) -> vec4(0)
757 delete_right(&b, iter, outUpdated, outNeedsRescan);
758 }
759 }
760 break;
761 case Token::PLUSEQ:
762 if (is_constant(*bin->fRight, 0)) {
763 clear_write(*bin->fLeft);
764 delete_right(&b, iter, outUpdated, outNeedsRescan);
765 }
766 break;
767 case Token::MINUSEQ:
768 if (is_constant(*bin->fRight, 0)) {
769 clear_write(*bin->fLeft);
770 delete_right(&b, iter, outUpdated, outNeedsRescan);
771 }
772 break;
773 case Token::STAREQ:
774 if (is_constant(*bin->fRight, 1)) {
775 clear_write(*bin->fLeft);
776 delete_right(&b, iter, outUpdated, outNeedsRescan);
777 }
778 break;
779 case Token::SLASHEQ:
780 if (is_constant(*bin->fRight, 1)) {
781 clear_write(*bin->fLeft);
Ethan Nicholascb670962017-04-20 19:31:52 -0400782 delete_right(&b, iter, outUpdated, outNeedsRescan);
783 }
784 break;
785 default:
786 break;
787 }
788 }
789 default:
790 break;
791 }
792}
793
Ethan Nicholas5ac13c22017-05-10 15:06:17 -0400794// returns true if this statement could potentially execute a break at the current level (we ignore
795// nested loops and switches, since any breaks inside of them will merely break the loop / switch)
796static bool contains_break(Statement& s) {
797 switch (s.fKind) {
798 case Statement::kBlock_Kind:
799 for (const auto& sub : ((Block&) s).fStatements) {
800 if (contains_break(*sub)) {
801 return true;
802 }
803 }
804 return false;
805 case Statement::kBreak_Kind:
806 return true;
807 case Statement::kIf_Kind: {
808 const IfStatement& i = (IfStatement&) s;
809 return contains_break(*i.fIfTrue) || (i.fIfFalse && contains_break(*i.fIfFalse));
810 }
811 default:
812 return false;
813 }
814}
815
816// Returns a block containing all of the statements that will be run if the given case matches
817// (which, owing to the statements being owned by unique_ptrs, means the switch itself will be
818// broken by this call and must then be discarded).
819// Returns null (and leaves the switch unmodified) if no such simple reduction is possible, such as
820// when break statements appear inside conditionals.
821static std::unique_ptr<Statement> block_for_case(SwitchStatement* s, SwitchCase* c) {
822 bool capturing = false;
823 std::vector<std::unique_ptr<Statement>*> statementPtrs;
824 for (const auto& current : s->fCases) {
825 if (current.get() == c) {
826 capturing = true;
827 }
828 if (capturing) {
829 for (auto& stmt : current->fStatements) {
830 if (stmt->fKind == Statement::kBreak_Kind) {
831 capturing = false;
832 break;
833 }
834 if (contains_break(*stmt)) {
835 return nullptr;
836 }
837 statementPtrs.push_back(&stmt);
838 }
839 if (!capturing) {
840 break;
841 }
842 }
843 }
844 std::vector<std::unique_ptr<Statement>> statements;
845 for (const auto& s : statementPtrs) {
846 statements.push_back(std::move(*s));
847 }
848 return std::unique_ptr<Statement>(new Block(Position(), std::move(statements)));
849}
850
Ethan Nicholascb670962017-04-20 19:31:52 -0400851void Compiler::simplifyStatement(DefinitionMap& definitions,
Ethan Nicholas5ac13c22017-05-10 15:06:17 -0400852 BasicBlock& b,
853 std::vector<BasicBlock::Node>::iterator* iter,
854 std::unordered_set<const Variable*>* undefinedVariables,
855 bool* outUpdated,
856 bool* outNeedsRescan) {
Ethan Nicholascb670962017-04-20 19:31:52 -0400857 Statement* stmt = (*iter)->statement()->get();
858 switch (stmt->fKind) {
Ethan Nicholasb4dc4192017-06-02 10:16:28 -0400859 case Statement::kVarDeclaration_Kind: {
860 const auto& varDecl = (VarDeclaration&) *stmt;
861 if (varDecl.fVar->dead() &&
862 (!varDecl.fValue ||
863 !varDecl.fValue->hasSideEffects())) {
864 if (varDecl.fValue) {
865 ASSERT((*iter)->statement()->get() == stmt);
866 if (!b.tryRemoveExpressionBefore(iter, varDecl.fValue.get())) {
867 *outNeedsRescan = true;
Ethan Nicholascb670962017-04-20 19:31:52 -0400868 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400869 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400870 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
Ethan Nicholasb4dc4192017-06-02 10:16:28 -0400871 *outUpdated = true;
Ethan Nicholascb670962017-04-20 19:31:52 -0400872 }
873 break;
874 }
875 case Statement::kIf_Kind: {
876 IfStatement& i = (IfStatement&) *stmt;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -0400877 if (i.fTest->fKind == Expression::kBoolLiteral_Kind) {
878 // constant if, collapse down to a single branch
879 if (((BoolLiteral&) *i.fTest).fValue) {
880 ASSERT(i.fIfTrue);
881 (*iter)->setStatement(std::move(i.fIfTrue));
882 } else {
883 if (i.fIfFalse) {
884 (*iter)->setStatement(std::move(i.fIfFalse));
885 } else {
886 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
887 }
888 }
889 *outUpdated = true;
890 *outNeedsRescan = true;
891 break;
892 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400893 if (i.fIfFalse && i.fIfFalse->isEmpty()) {
894 // else block doesn't do anything, remove it
895 i.fIfFalse.reset();
896 *outUpdated = true;
897 *outNeedsRescan = true;
898 }
899 if (!i.fIfFalse && i.fIfTrue->isEmpty()) {
900 // if block doesn't do anything, no else block
901 if (i.fTest->hasSideEffects()) {
902 // test has side effects, keep it
903 (*iter)->setStatement(std::unique_ptr<Statement>(
904 new ExpressionStatement(std::move(i.fTest))));
905 } else {
906 // no if, no else, no test side effects, kill the whole if
907 // statement
908 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
909 }
910 *outUpdated = true;
911 *outNeedsRescan = true;
912 }
913 break;
914 }
Ethan Nicholas5ac13c22017-05-10 15:06:17 -0400915 case Statement::kSwitch_Kind: {
916 SwitchStatement& s = (SwitchStatement&) *stmt;
917 if (s.fValue->isConstant()) {
918 // switch is constant, replace it with the case that matches
919 bool found = false;
920 SwitchCase* defaultCase = nullptr;
921 for (const auto& c : s.fCases) {
922 if (!c->fValue) {
923 defaultCase = c.get();
924 continue;
925 }
926 ASSERT(c->fValue->fKind == s.fValue->fKind);
927 found = c->fValue->compareConstant(fContext, *s.fValue);
928 if (found) {
929 std::unique_ptr<Statement> newBlock = block_for_case(&s, c.get());
930 if (newBlock) {
931 (*iter)->setStatement(std::move(newBlock));
932 break;
933 } else {
934 if (s.fIsStatic) {
935 this->error(s.fPosition,
936 "static switch contains non-static conditional break");
937 s.fIsStatic = false;
938 }
939 return; // can't simplify
940 }
941 }
942 }
943 if (!found) {
944 // no matching case. use default if it exists, or kill the whole thing
945 if (defaultCase) {
946 std::unique_ptr<Statement> newBlock = block_for_case(&s, defaultCase);
947 if (newBlock) {
948 (*iter)->setStatement(std::move(newBlock));
949 } else {
950 if (s.fIsStatic) {
951 this->error(s.fPosition,
952 "static switch contains non-static conditional break");
953 s.fIsStatic = false;
954 }
955 return; // can't simplify
956 }
957 } else {
958 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
959 }
960 }
961 *outUpdated = true;
962 *outNeedsRescan = true;
963 }
964 break;
965 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400966 case Statement::kExpression_Kind: {
967 ExpressionStatement& e = (ExpressionStatement&) *stmt;
968 ASSERT((*iter)->statement()->get() == &e);
Ethan Nicholascb670962017-04-20 19:31:52 -0400969 if (!e.fExpression->hasSideEffects()) {
970 // Expression statement with no side effects, kill it
971 if (!b.tryRemoveExpressionBefore(iter, e.fExpression.get())) {
972 *outNeedsRescan = true;
973 }
974 ASSERT((*iter)->statement()->get() == stmt);
975 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
976 *outUpdated = true;
977 }
978 break;
979 }
980 default:
981 break;
982 }
983}
984
985void Compiler::scanCFG(FunctionDefinition& f) {
986 CFG cfg = CFGGenerator().getCFG(f);
987 this->computeDataFlow(&cfg);
ethannicholas22f939e2016-10-13 13:25:34 -0700988
989 // check for unreachable code
990 for (size_t i = 0; i < cfg.fBlocks.size(); i++) {
Mike Klein6ad99092016-10-26 10:35:22 -0400991 if (i != cfg.fStart && !cfg.fBlocks[i].fEntrances.size() &&
ethannicholas22f939e2016-10-13 13:25:34 -0700992 cfg.fBlocks[i].fNodes.size()) {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500993 Position p;
994 switch (cfg.fBlocks[i].fNodes[0].fKind) {
995 case BasicBlock::Node::kStatement_Kind:
Ethan Nicholascb670962017-04-20 19:31:52 -0400996 p = (*cfg.fBlocks[i].fNodes[0].statement())->fPosition;
Ethan Nicholas86a43402017-01-19 13:32:00 -0500997 break;
998 case BasicBlock::Node::kExpression_Kind:
Ethan Nicholascb670962017-04-20 19:31:52 -0400999 p = (*cfg.fBlocks[i].fNodes[0].expression())->fPosition;
Ethan Nicholas86a43402017-01-19 13:32:00 -05001000 break;
1001 }
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001002 this->error(p, String("unreachable"));
ethannicholas22f939e2016-10-13 13:25:34 -07001003 }
1004 }
1005 if (fErrorCount) {
1006 return;
1007 }
1008
Ethan Nicholascb670962017-04-20 19:31:52 -04001009 // check for dead code & undefined variables, perform constant propagation
1010 std::unordered_set<const Variable*> undefinedVariables;
1011 bool updated;
1012 bool needsRescan = false;
1013 do {
1014 if (needsRescan) {
1015 cfg = CFGGenerator().getCFG(f);
1016 this->computeDataFlow(&cfg);
1017 needsRescan = false;
Ethan Nicholas113628d2017-02-02 16:11:39 -05001018 }
Ethan Nicholascb670962017-04-20 19:31:52 -04001019
1020 updated = false;
1021 for (BasicBlock& b : cfg.fBlocks) {
1022 DefinitionMap definitions = b.fBefore;
1023
1024 for (auto iter = b.fNodes.begin(); iter != b.fNodes.end() && !needsRescan; ++iter) {
1025 if (iter->fKind == BasicBlock::Node::kExpression_Kind) {
1026 this->simplifyExpression(definitions, b, &iter, &undefinedVariables, &updated,
1027 &needsRescan);
1028 } else {
1029 this->simplifyStatement(definitions, b, &iter, &undefinedVariables, &updated,
1030 &needsRescan);
1031 }
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001032 if (needsRescan) {
1033 break;
1034 }
Ethan Nicholascb670962017-04-20 19:31:52 -04001035 this->addDefinitions(*iter, &definitions);
1036 }
1037 }
1038 } while (updated);
1039 ASSERT(!needsRescan);
ethannicholas22f939e2016-10-13 13:25:34 -07001040
Ethan Nicholas91a10532017-06-22 11:24:38 -04001041 // verify static ifs & switches, clean up dead variable decls
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001042 for (BasicBlock& b : cfg.fBlocks) {
1043 DefinitionMap definitions = b.fBefore;
1044
Ethan Nicholas91a10532017-06-22 11:24:38 -04001045 for (auto iter = b.fNodes.begin(); iter != b.fNodes.end() && !needsRescan;) {
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001046 if (iter->fKind == BasicBlock::Node::kStatement_Kind) {
1047 const Statement& s = **iter->statement();
1048 switch (s.fKind) {
1049 case Statement::kIf_Kind:
1050 if (((const IfStatement&) s).fIsStatic) {
1051 this->error(s.fPosition, "static if has non-static test");
1052 }
Ethan Nicholas91a10532017-06-22 11:24:38 -04001053 ++iter;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001054 break;
1055 case Statement::kSwitch_Kind:
1056 if (((const SwitchStatement&) s).fIsStatic) {
1057 this->error(s.fPosition, "static switch has non-static test");
1058 }
Ethan Nicholas91a10532017-06-22 11:24:38 -04001059 ++iter;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001060 break;
Ethan Nicholas91a10532017-06-22 11:24:38 -04001061 case Statement::kVarDeclarations_Kind: {
1062 VarDeclarations& decls = *((VarDeclarationsStatement&) s).fDeclaration;
1063 for (auto varIter = decls.fVars.begin(); varIter != decls.fVars.end();) {
1064 if ((*varIter)->fKind == Statement::kNop_Kind) {
1065 varIter = decls.fVars.erase(varIter);
1066 } else {
1067 ++varIter;
1068 }
1069 }
1070 if (!decls.fVars.size()) {
1071 iter = b.fNodes.erase(iter);
1072 } else {
1073 ++iter;
1074 }
1075 break;
1076 }
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001077 default:
Ethan Nicholas91a10532017-06-22 11:24:38 -04001078 ++iter;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001079 break;
1080 }
Ethan Nicholas91a10532017-06-22 11:24:38 -04001081 } else {
1082 ++iter;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001083 }
1084 }
1085 }
1086
ethannicholas22f939e2016-10-13 13:25:34 -07001087 // check for missing return
1088 if (f.fDeclaration.fReturnType != *fContext.fVoid_Type) {
1089 if (cfg.fBlocks[cfg.fExit].fEntrances.size()) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001090 this->error(f.fPosition, String("function can exit without returning a value"));
ethannicholas22f939e2016-10-13 13:25:34 -07001091 }
1092 }
1093}
1094
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001095std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String text,
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001096 const Program::Settings& settings) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001097 fErrorText = "";
1098 fErrorCount = 0;
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001099 fIRGenerator->start(&settings);
ethannicholasd598f792016-07-25 10:08:54 -07001100 std::vector<std::unique_ptr<ProgramElement>> elements;
ethannicholas5961bc92016-10-12 06:39:56 -07001101 Modifiers::Flag ignored;
ethannicholasb3058bd2016-07-01 08:22:01 -07001102 switch (kind) {
1103 case Program::kVertex_Kind:
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04001104 fIRGenerator->convertProgram(String(SKSL_VERT_INCLUDE), *fTypes, &ignored, &elements);
ethannicholasb3058bd2016-07-01 08:22:01 -07001105 break;
1106 case Program::kFragment_Kind:
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04001107 fIRGenerator->convertProgram(String(SKSL_FRAG_INCLUDE), *fTypes, &ignored, &elements);
ethannicholasb3058bd2016-07-01 08:22:01 -07001108 break;
Ethan Nicholas52cad152017-02-16 16:37:32 -05001109 case Program::kGeometry_Kind:
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04001110 fIRGenerator->convertProgram(String(SKSL_GEOM_INCLUDE), *fTypes, &ignored, &elements);
Ethan Nicholas52cad152017-02-16 16:37:32 -05001111 break;
Ethan Nicholas762466e2017-06-29 10:03:38 -04001112 case Program::kFragmentProcessor_Kind:
1113 fIRGenerator->convertProgram(String(SKSL_FP_INCLUDE), *fTypes, &ignored, &elements);
1114 break;
ethannicholasb3058bd2016-07-01 08:22:01 -07001115 }
ethannicholasddb37d62016-10-20 09:54:00 -07001116 fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
ethannicholas5961bc92016-10-12 06:39:56 -07001117 Modifiers::Flag defaultPrecision;
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04001118 fIRGenerator->convertProgram(text, *fTypes, &defaultPrecision, &elements);
1119 if (!fErrorCount) {
1120 for (auto& element : elements) {
1121 if (element->fKind == ProgramElement::kFunction_Kind) {
1122 this->scanCFG((FunctionDefinition&) *element);
1123 }
1124 }
1125 }
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001126 auto result = std::unique_ptr<Program>(new Program(kind, settings, defaultPrecision, &fContext,
1127 std::move(elements),
1128 fIRGenerator->fSymbolTable,
1129 fIRGenerator->fInputs));
Ethan Nicholas3605ace2016-11-21 15:59:48 -05001130 fIRGenerator->finish();
ethannicholasb3058bd2016-07-01 08:22:01 -07001131 this->writeErrorCount();
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001132 if (fErrorCount) {
1133 return nullptr;
1134 }
1135 return result;
1136}
1137
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001138bool Compiler::toSPIRV(const Program& program, OutputStream& out) {
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001139#ifdef SK_ENABLE_SPIRV_VALIDATION
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001140 StringStream buffer;
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001141 SPIRVCodeGenerator cg(&fContext, &program, this, &buffer);
1142 bool result = cg.generateCode();
1143 if (result) {
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001144 spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0);
Ethan Nicholas762466e2017-06-29 10:03:38 -04001145 const String& data = buffer.str();
1146 ASSERT(0 == data.size() % 4);
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001147 auto dumpmsg = [](spv_message_level_t, const char*, const spv_position_t&, const char* m) {
1148 SkDebugf("SPIR-V validation error: %s\n", m);
1149 };
1150 tools.SetMessageConsumer(dumpmsg);
1151 // Verify that the SPIR-V we produced is valid. If this assert fails, check the logs prior
1152 // to the failure to see the validation errors.
Ethan Nicholas762466e2017-06-29 10:03:38 -04001153 ASSERT_RESULT(tools.Validate((const uint32_t*) data.c_str(), data.size() / 4));
1154 out.write(data.c_str(), data.size());
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001155 }
1156#else
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001157 SPIRVCodeGenerator cg(&fContext, &program, this, &out);
1158 bool result = cg.generateCode();
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001159#endif
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001160 this->writeErrorCount();
Ethan Nicholasce33f102016-12-09 17:22:59 -05001161 return result;
1162}
1163
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001164bool Compiler::toSPIRV(const Program& program, String* out) {
1165 StringStream buffer;
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001166 bool result = this->toSPIRV(program, buffer);
1167 if (result) {
Ethan Nicholas762466e2017-06-29 10:03:38 -04001168 *out = buffer.str();
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001169 }
1170 return result;
1171}
1172
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001173bool Compiler::toGLSL(const Program& program, OutputStream& out) {
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001174 GLSLCodeGenerator cg(&fContext, &program, this, &out);
1175 bool result = cg.generateCode();
1176 this->writeErrorCount();
1177 return result;
1178}
1179
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001180bool Compiler::toGLSL(const Program& program, String* out) {
1181 StringStream buffer;
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001182 bool result = this->toGLSL(program, buffer);
1183 if (result) {
Ethan Nicholas762466e2017-06-29 10:03:38 -04001184 *out = buffer.str();
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001185 }
1186 return result;
1187}
1188
Ethan Nicholas762466e2017-06-29 10:03:38 -04001189bool Compiler::toCPP(const Program& program, String name, OutputStream& out) {
1190 CPPCodeGenerator cg(&fContext, &program, this, name, &out);
1191 bool result = cg.generateCode();
1192 this->writeErrorCount();
1193 return result;
1194}
1195
1196bool Compiler::toH(const Program& program, String name, OutputStream& out) {
1197 HCodeGenerator cg(&program, this, name, &out);
1198 bool result = cg.generateCode();
1199 this->writeErrorCount();
1200 return result;
1201}
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001202
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001203void Compiler::error(Position position, String msg) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001204 fErrorCount++;
1205 fErrorText += "error: " + position.description() + ": " + msg.c_str() + "\n";
1206}
1207
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001208String Compiler::errorText() {
1209 String result = fErrorText;
ethannicholasb3058bd2016-07-01 08:22:01 -07001210 return result;
1211}
1212
1213void Compiler::writeErrorCount() {
1214 if (fErrorCount) {
1215 fErrorText += to_string(fErrorCount) + " error";
1216 if (fErrorCount > 1) {
1217 fErrorText += "s";
1218 }
1219 fErrorText += "\n";
1220 }
1221}
1222
ethannicholasb3058bd2016-07-01 08:22:01 -07001223} // namespace