blob: 3a037e798e48421fa459e2fc52d28b1601c01781 [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);
68 ADD_TYPE(Vec2);
69 ADD_TYPE(Vec3);
70 ADD_TYPE(Vec4);
71 ADD_TYPE(Double);
72 ADD_TYPE(DVec2);
73 ADD_TYPE(DVec3);
74 ADD_TYPE(DVec4);
75 ADD_TYPE(Int);
76 ADD_TYPE(IVec2);
77 ADD_TYPE(IVec3);
78 ADD_TYPE(IVec4);
79 ADD_TYPE(UInt);
80 ADD_TYPE(UVec2);
81 ADD_TYPE(UVec3);
82 ADD_TYPE(UVec4);
83 ADD_TYPE(Bool);
84 ADD_TYPE(BVec2);
85 ADD_TYPE(BVec3);
86 ADD_TYPE(BVec4);
87 ADD_TYPE(Mat2x2);
Ethan Nicholas0df1b042017-03-31 13:56:23 -040088 types->addWithoutOwnership(String("mat2x2"), fContext.fMat2x2_Type.get());
ethannicholasb3058bd2016-07-01 08:22:01 -070089 ADD_TYPE(Mat2x3);
90 ADD_TYPE(Mat2x4);
91 ADD_TYPE(Mat3x2);
92 ADD_TYPE(Mat3x3);
Ethan Nicholas0df1b042017-03-31 13:56:23 -040093 types->addWithoutOwnership(String("mat3x3"), fContext.fMat3x3_Type.get());
ethannicholasb3058bd2016-07-01 08:22:01 -070094 ADD_TYPE(Mat3x4);
95 ADD_TYPE(Mat4x2);
96 ADD_TYPE(Mat4x3);
97 ADD_TYPE(Mat4x4);
Ethan Nicholas0df1b042017-03-31 13:56:23 -040098 types->addWithoutOwnership(String("mat4x4"), fContext.fMat4x4_Type.get());
ethannicholasb3058bd2016-07-01 08:22:01 -070099 ADD_TYPE(GenType);
100 ADD_TYPE(GenDType);
101 ADD_TYPE(GenIType);
102 ADD_TYPE(GenUType);
103 ADD_TYPE(GenBType);
104 ADD_TYPE(Mat);
105 ADD_TYPE(Vec);
106 ADD_TYPE(GVec);
107 ADD_TYPE(GVec2);
108 ADD_TYPE(GVec3);
109 ADD_TYPE(GVec4);
110 ADD_TYPE(DVec);
111 ADD_TYPE(IVec);
112 ADD_TYPE(UVec);
113 ADD_TYPE(BVec);
114
115 ADD_TYPE(Sampler1D);
116 ADD_TYPE(Sampler2D);
117 ADD_TYPE(Sampler3D);
ethannicholas5961bc92016-10-12 06:39:56 -0700118 ADD_TYPE(SamplerExternalOES);
ethannicholasb3058bd2016-07-01 08:22:01 -0700119 ADD_TYPE(SamplerCube);
120 ADD_TYPE(Sampler2DRect);
121 ADD_TYPE(Sampler1DArray);
122 ADD_TYPE(Sampler2DArray);
123 ADD_TYPE(SamplerCubeArray);
124 ADD_TYPE(SamplerBuffer);
125 ADD_TYPE(Sampler2DMS);
126 ADD_TYPE(Sampler2DMSArray);
127
Brian Salomonbf7b6202016-11-11 16:08:03 -0500128 ADD_TYPE(ISampler2D);
129
Brian Salomon2a51de82016-11-16 12:06:01 -0500130 ADD_TYPE(Image2D);
131 ADD_TYPE(IImage2D);
132
Greg Daniel64773e62016-11-22 09:44:03 -0500133 ADD_TYPE(SubpassInput);
134 ADD_TYPE(SubpassInputMS);
135
ethannicholasb3058bd2016-07-01 08:22:01 -0700136 ADD_TYPE(GSampler1D);
137 ADD_TYPE(GSampler2D);
138 ADD_TYPE(GSampler3D);
139 ADD_TYPE(GSamplerCube);
140 ADD_TYPE(GSampler2DRect);
141 ADD_TYPE(GSampler1DArray);
142 ADD_TYPE(GSampler2DArray);
143 ADD_TYPE(GSamplerCubeArray);
144 ADD_TYPE(GSamplerBuffer);
145 ADD_TYPE(GSampler2DMS);
146 ADD_TYPE(GSampler2DMSArray);
147
148 ADD_TYPE(Sampler1DShadow);
149 ADD_TYPE(Sampler2DShadow);
150 ADD_TYPE(SamplerCubeShadow);
151 ADD_TYPE(Sampler2DRectShadow);
152 ADD_TYPE(Sampler1DArrayShadow);
153 ADD_TYPE(Sampler2DArrayShadow);
154 ADD_TYPE(SamplerCubeArrayShadow);
155 ADD_TYPE(GSampler2DArrayShadow);
156 ADD_TYPE(GSamplerCubeArrayShadow);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400157 ADD_TYPE(ColorSpaceXform);
ethannicholasb3058bd2016-07-01 08:22:01 -0700158
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400159 String skCapsName("sk_Caps");
160 Variable* skCaps = new Variable(Position(), Modifiers(), skCapsName,
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500161 *fContext.fSkCaps_Type, Variable::kGlobal_Storage);
162 fIRGenerator->fSymbolTable->add(skCapsName, std::unique_ptr<Symbol>(skCaps));
163
Ethan Nicholas762466e2017-06-29 10:03:38 -0400164 String skArgsName("sk_Args");
165 Variable* skArgs = new Variable(Position(), Modifiers(), skArgsName,
166 *fContext.fSkArgs_Type, Variable::kGlobal_Storage);
167 fIRGenerator->fSymbolTable->add(skArgsName, std::unique_ptr<Symbol>(skArgs));
168
ethannicholas5961bc92016-10-12 06:39:56 -0700169 Modifiers::Flag ignored1;
170 std::vector<std::unique_ptr<ProgramElement>> ignored2;
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400171 fIRGenerator->convertProgram(String(SKSL_INCLUDE), *fTypes, &ignored1, &ignored2);
ethannicholasddb37d62016-10-20 09:54:00 -0700172 fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
ethannicholasb3058bd2016-07-01 08:22:01 -0700173 ASSERT(!fErrorCount);
174}
175
176Compiler::~Compiler() {
177 delete fIRGenerator;
178}
179
ethannicholas22f939e2016-10-13 13:25:34 -0700180// add the definition created by assigning to the lvalue to the definition set
Ethan Nicholas86a43402017-01-19 13:32:00 -0500181void Compiler::addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr,
182 DefinitionMap* definitions) {
ethannicholas22f939e2016-10-13 13:25:34 -0700183 switch (lvalue->fKind) {
184 case Expression::kVariableReference_Kind: {
185 const Variable& var = ((VariableReference*) lvalue)->fVariable;
186 if (var.fStorage == Variable::kLocal_Storage) {
187 (*definitions)[&var] = expr;
188 }
189 break;
190 }
191 case Expression::kSwizzle_Kind:
192 // We consider the variable written to as long as at least some of its components have
193 // been written to. This will lead to some false negatives (we won't catch it if you
194 // write to foo.x and then read foo.y), but being stricter could lead to false positives
Mike Klein6ad99092016-10-26 10:35:22 -0400195 // (we write to foo.x, and then pass foo to a function which happens to only read foo.x,
196 // 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 -0700197 // more complicated whole-program analysis. This is probably good enough.
Mike Klein6ad99092016-10-26 10:35:22 -0400198 this->addDefinition(((Swizzle*) lvalue)->fBase.get(),
Ethan Nicholas86a43402017-01-19 13:32:00 -0500199 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
ethannicholas22f939e2016-10-13 13:25:34 -0700200 definitions);
201 break;
202 case Expression::kIndex_Kind:
203 // see comments in Swizzle
Mike Klein6ad99092016-10-26 10:35:22 -0400204 this->addDefinition(((IndexExpression*) lvalue)->fBase.get(),
Ethan Nicholas86a43402017-01-19 13:32:00 -0500205 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
ethannicholas22f939e2016-10-13 13:25:34 -0700206 definitions);
207 break;
208 case Expression::kFieldAccess_Kind:
209 // see comments in Swizzle
Mike Klein6ad99092016-10-26 10:35:22 -0400210 this->addDefinition(((FieldAccess*) lvalue)->fBase.get(),
Ethan Nicholas86a43402017-01-19 13:32:00 -0500211 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
ethannicholas22f939e2016-10-13 13:25:34 -0700212 definitions);
213 break;
214 default:
215 // not an lvalue, can't happen
216 ASSERT(false);
217 }
218}
219
220// add local variables defined by this node to the set
Mike Klein6ad99092016-10-26 10:35:22 -0400221void Compiler::addDefinitions(const BasicBlock::Node& node,
Ethan Nicholas86a43402017-01-19 13:32:00 -0500222 DefinitionMap* definitions) {
ethannicholas22f939e2016-10-13 13:25:34 -0700223 switch (node.fKind) {
224 case BasicBlock::Node::kExpression_Kind: {
Ethan Nicholascb670962017-04-20 19:31:52 -0400225 ASSERT(node.expression());
226 const Expression* expr = (Expression*) node.expression()->get();
Ethan Nicholas86a43402017-01-19 13:32:00 -0500227 switch (expr->fKind) {
228 case Expression::kBinary_Kind: {
229 BinaryExpression* b = (BinaryExpression*) expr;
230 if (b->fOperator == Token::EQ) {
231 this->addDefinition(b->fLeft.get(), &b->fRight, definitions);
232 } else if (Token::IsAssignment(b->fOperator)) {
233 this->addDefinition(
234 b->fLeft.get(),
235 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
236 definitions);
237
238 }
239 break;
ethannicholas22f939e2016-10-13 13:25:34 -0700240 }
Ethan Nicholas86a43402017-01-19 13:32:00 -0500241 case Expression::kPrefix_Kind: {
242 const PrefixExpression* p = (PrefixExpression*) expr;
243 if (p->fOperator == Token::MINUSMINUS || p->fOperator == Token::PLUSPLUS) {
244 this->addDefinition(
245 p->fOperand.get(),
246 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
247 definitions);
248 }
249 break;
250 }
251 case Expression::kPostfix_Kind: {
252 const PostfixExpression* p = (PostfixExpression*) expr;
253 if (p->fOperator == Token::MINUSMINUS || p->fOperator == Token::PLUSPLUS) {
254 this->addDefinition(
255 p->fOperand.get(),
256 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
257 definitions);
Ethan Nicholas86a43402017-01-19 13:32:00 -0500258 }
259 break;
260 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400261 case Expression::kVariableReference_Kind: {
262 const VariableReference* v = (VariableReference*) expr;
263 if (v->fRefKind != VariableReference::kRead_RefKind) {
264 this->addDefinition(
265 v,
266 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
267 definitions);
268 }
269 }
Ethan Nicholas86a43402017-01-19 13:32:00 -0500270 default:
271 break;
ethannicholas22f939e2016-10-13 13:25:34 -0700272 }
273 break;
274 }
275 case BasicBlock::Node::kStatement_Kind: {
Ethan Nicholascb670962017-04-20 19:31:52 -0400276 const Statement* stmt = (Statement*) node.statement()->get();
Ethan Nicholasb4dc4192017-06-02 10:16:28 -0400277 if (stmt->fKind == Statement::kVarDeclaration_Kind) {
278 VarDeclaration& vd = (VarDeclaration&) *stmt;
279 if (vd.fValue) {
280 (*definitions)[vd.fVar] = &vd.fValue;
ethannicholas22f939e2016-10-13 13:25:34 -0700281 }
282 }
283 break;
284 }
285 }
286}
287
288void Compiler::scanCFG(CFG* cfg, BlockId blockId, std::set<BlockId>* workList) {
289 BasicBlock& block = cfg->fBlocks[blockId];
290
291 // compute definitions after this block
Ethan Nicholas86a43402017-01-19 13:32:00 -0500292 DefinitionMap after = block.fBefore;
ethannicholas22f939e2016-10-13 13:25:34 -0700293 for (const BasicBlock::Node& n : block.fNodes) {
294 this->addDefinitions(n, &after);
295 }
296
297 // propagate definitions to exits
298 for (BlockId exitId : block.fExits) {
299 BasicBlock& exit = cfg->fBlocks[exitId];
300 for (const auto& pair : after) {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500301 std::unique_ptr<Expression>* e1 = pair.second;
302 auto found = exit.fBefore.find(pair.first);
303 if (found == exit.fBefore.end()) {
304 // exit has no definition for it, just copy it
305 workList->insert(exitId);
ethannicholas22f939e2016-10-13 13:25:34 -0700306 exit.fBefore[pair.first] = e1;
307 } else {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500308 // exit has a (possibly different) value already defined
309 std::unique_ptr<Expression>* e2 = exit.fBefore[pair.first];
ethannicholas22f939e2016-10-13 13:25:34 -0700310 if (e1 != e2) {
311 // definition has changed, merge and add exit block to worklist
312 workList->insert(exitId);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500313 if (e1 && e2) {
314 exit.fBefore[pair.first] =
Ethan Nicholas86a43402017-01-19 13:32:00 -0500315 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression;
Ethan Nicholasaf197692017-02-27 13:26:45 -0500316 } else {
317 exit.fBefore[pair.first] = nullptr;
318 }
ethannicholas22f939e2016-10-13 13:25:34 -0700319 }
320 }
321 }
322 }
323}
324
325// returns a map which maps all local variables in the function to null, indicating that their value
326// is initially unknown
Ethan Nicholas86a43402017-01-19 13:32:00 -0500327static DefinitionMap compute_start_state(const CFG& cfg) {
328 DefinitionMap result;
Mike Klein6ad99092016-10-26 10:35:22 -0400329 for (const auto& block : cfg.fBlocks) {
330 for (const auto& node : block.fNodes) {
ethannicholas22f939e2016-10-13 13:25:34 -0700331 if (node.fKind == BasicBlock::Node::kStatement_Kind) {
Ethan Nicholascb670962017-04-20 19:31:52 -0400332 ASSERT(node.statement());
333 const Statement* s = node.statement()->get();
ethannicholas22f939e2016-10-13 13:25:34 -0700334 if (s->fKind == Statement::kVarDeclarations_Kind) {
335 const VarDeclarationsStatement* vd = (const VarDeclarationsStatement*) s;
Ethan Nicholascb670962017-04-20 19:31:52 -0400336 for (const auto& decl : vd->fDeclaration->fVars) {
Ethan Nicholas91a10532017-06-22 11:24:38 -0400337 if (decl->fKind == Statement::kVarDeclaration_Kind) {
338 result[((VarDeclaration&) *decl).fVar] = nullptr;
339 }
Mike Klein6ad99092016-10-26 10:35:22 -0400340 }
ethannicholas22f939e2016-10-13 13:25:34 -0700341 }
342 }
343 }
344 }
345 return result;
346}
347
Ethan Nicholascb670962017-04-20 19:31:52 -0400348/**
349 * Returns true if assigning to this lvalue has no effect.
350 */
351static bool is_dead(const Expression& lvalue) {
352 switch (lvalue.fKind) {
353 case Expression::kVariableReference_Kind:
354 return ((VariableReference&) lvalue).fVariable.dead();
355 case Expression::kSwizzle_Kind:
356 return is_dead(*((Swizzle&) lvalue).fBase);
357 case Expression::kFieldAccess_Kind:
358 return is_dead(*((FieldAccess&) lvalue).fBase);
359 case Expression::kIndex_Kind: {
360 const IndexExpression& idx = (IndexExpression&) lvalue;
361 return is_dead(*idx.fBase) && !idx.fIndex->hasSideEffects();
362 }
363 default:
364 ABORT("invalid lvalue: %s\n", lvalue.description().c_str());
365 }
366}
ethannicholas22f939e2016-10-13 13:25:34 -0700367
Ethan Nicholascb670962017-04-20 19:31:52 -0400368/**
369 * Returns true if this is an assignment which can be collapsed down to just the right hand side due
370 * to a dead target and lack of side effects on the left hand side.
371 */
372static bool dead_assignment(const BinaryExpression& b) {
373 if (!Token::IsAssignment(b.fOperator)) {
374 return false;
375 }
376 return is_dead(*b.fLeft);
377}
378
379void Compiler::computeDataFlow(CFG* cfg) {
380 cfg->fBlocks[cfg->fStart].fBefore = compute_start_state(*cfg);
ethannicholas22f939e2016-10-13 13:25:34 -0700381 std::set<BlockId> workList;
Ethan Nicholascb670962017-04-20 19:31:52 -0400382 for (BlockId i = 0; i < cfg->fBlocks.size(); i++) {
ethannicholas22f939e2016-10-13 13:25:34 -0700383 workList.insert(i);
384 }
385 while (workList.size()) {
386 BlockId next = *workList.begin();
387 workList.erase(workList.begin());
Ethan Nicholascb670962017-04-20 19:31:52 -0400388 this->scanCFG(cfg, next, &workList);
ethannicholas22f939e2016-10-13 13:25:34 -0700389 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400390}
391
392/**
393 * Attempts to replace the expression pointed to by iter with a new one (in both the CFG and the
394 * IR). If the expression can be cleanly removed, returns true and updates the iterator to point to
395 * the newly-inserted element. Otherwise updates only the IR and returns false (and the CFG will
396 * need to be regenerated).
397 */
398bool try_replace_expression(BasicBlock* b,
399 std::vector<BasicBlock::Node>::iterator* iter,
400 std::unique_ptr<Expression>* newExpression) {
401 std::unique_ptr<Expression>* target = (*iter)->expression();
402 if (!b->tryRemoveExpression(iter)) {
403 *target = std::move(*newExpression);
404 return false;
405 }
406 *target = std::move(*newExpression);
407 return b->tryInsertExpression(iter, target);
408}
409
410/**
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400411 * Returns true if the expression is a constant numeric literal with the specified value, or a
412 * constant vector with all elements equal to the specified value.
Ethan Nicholascb670962017-04-20 19:31:52 -0400413 */
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400414bool is_constant(const Expression& expr, double value) {
Ethan Nicholascb670962017-04-20 19:31:52 -0400415 switch (expr.fKind) {
416 case Expression::kIntLiteral_Kind:
417 return ((IntLiteral&) expr).fValue == value;
418 case Expression::kFloatLiteral_Kind:
419 return ((FloatLiteral&) expr).fValue == value;
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400420 case Expression::kConstructor_Kind: {
421 Constructor& c = (Constructor&) expr;
422 if (c.fType.kind() == Type::kVector_Kind && c.isConstant()) {
423 for (int i = 0; i < c.fType.columns(); ++i) {
424 if (!is_constant(c.getVecComponent(i), value)) {
425 return false;
426 }
427 }
428 return true;
429 }
430 return false;
431 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400432 default:
433 return false;
434 }
435}
436
437/**
438 * Collapses the binary expression pointed to by iter down to just the right side (in both the IR
439 * and CFG structures).
440 */
441void delete_left(BasicBlock* b,
442 std::vector<BasicBlock::Node>::iterator* iter,
443 bool* outUpdated,
444 bool* outNeedsRescan) {
445 *outUpdated = true;
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400446 std::unique_ptr<Expression>* target = (*iter)->expression();
447 ASSERT((*target)->fKind == Expression::kBinary_Kind);
448 BinaryExpression& bin = (BinaryExpression&) **target;
449 bool result;
450 if (bin.fOperator == Token::EQ) {
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400451 result = b->tryRemoveLValueBefore(iter, bin.fLeft.get());
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400452 } else {
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400453 result = b->tryRemoveExpressionBefore(iter, bin.fLeft.get());
Ethan Nicholascb670962017-04-20 19:31:52 -0400454 }
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400455 *target = std::move(bin.fRight);
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400456 if (!result) {
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400457 *outNeedsRescan = true;
458 return;
459 }
460 if (*iter == b->fNodes.begin()) {
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400461 *outNeedsRescan = true;
462 return;
463 }
464 --(*iter);
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400465 if ((*iter)->fKind != BasicBlock::Node::kExpression_Kind ||
466 (*iter)->expression() != &bin.fRight) {
467 *outNeedsRescan = true;
468 return;
469 }
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400470 *iter = b->fNodes.erase(*iter);
471 ASSERT((*iter)->expression() == target);
Ethan Nicholascb670962017-04-20 19:31:52 -0400472}
473
474/**
475 * Collapses the binary expression pointed to by iter down to just the left side (in both the IR and
476 * CFG structures).
477 */
478void delete_right(BasicBlock* b,
479 std::vector<BasicBlock::Node>::iterator* iter,
480 bool* outUpdated,
481 bool* outNeedsRescan) {
482 *outUpdated = true;
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400483 std::unique_ptr<Expression>* target = (*iter)->expression();
484 ASSERT((*target)->fKind == Expression::kBinary_Kind);
485 BinaryExpression& bin = (BinaryExpression&) **target;
486 if (!b->tryRemoveExpressionBefore(iter, bin.fRight.get())) {
487 *target = std::move(bin.fLeft);
Ethan Nicholascb670962017-04-20 19:31:52 -0400488 *outNeedsRescan = true;
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400489 return;
Ethan Nicholascb670962017-04-20 19:31:52 -0400490 }
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400491 *target = std::move(bin.fLeft);
492 if (*iter == b->fNodes.begin()) {
493 *outNeedsRescan = true;
494 return;
495 }
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400496 --(*iter);
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400497 if (((*iter)->fKind != BasicBlock::Node::kExpression_Kind ||
498 (*iter)->expression() != &bin.fLeft)) {
499 *outNeedsRescan = true;
500 return;
501 }
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400502 *iter = b->fNodes.erase(*iter);
503 ASSERT((*iter)->expression() == target);
Ethan Nicholascb670962017-04-20 19:31:52 -0400504}
505
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400506/**
507 * Constructs the specified type using a single argument.
508 */
509static std::unique_ptr<Expression> construct(const Type& type, std::unique_ptr<Expression> v) {
510 std::vector<std::unique_ptr<Expression>> args;
511 args.push_back(std::move(v));
512 auto result = std::unique_ptr<Expression>(new Constructor(Position(), type, std::move(args)));
513 return result;
514}
515
516/**
517 * Used in the implementations of vectorize_left and vectorize_right. Given a vector type and an
518 * expression x, deletes the expression pointed to by iter and replaces it with <type>(x).
519 */
520static void vectorize(BasicBlock* b,
521 std::vector<BasicBlock::Node>::iterator* iter,
522 const Type& type,
523 std::unique_ptr<Expression>* otherExpression,
524 bool* outUpdated,
525 bool* outNeedsRescan) {
526 ASSERT((*(*iter)->expression())->fKind == Expression::kBinary_Kind);
527 ASSERT(type.kind() == Type::kVector_Kind);
528 ASSERT((*otherExpression)->fType.kind() == Type::kScalar_Kind);
529 *outUpdated = true;
530 std::unique_ptr<Expression>* target = (*iter)->expression();
531 if (!b->tryRemoveExpression(iter)) {
532 *target = construct(type, std::move(*otherExpression));
533 *outNeedsRescan = true;
534 } else {
535 *target = construct(type, std::move(*otherExpression));
536 if (!b->tryInsertExpression(iter, target)) {
537 *outNeedsRescan = true;
538 }
539 }
540}
541
542/**
543 * Given a binary expression of the form x <op> vec<n>(y), deletes the right side and vectorizes the
544 * left to yield vec<n>(x).
545 */
546static void vectorize_left(BasicBlock* b,
547 std::vector<BasicBlock::Node>::iterator* iter,
548 bool* outUpdated,
549 bool* outNeedsRescan) {
550 BinaryExpression& bin = (BinaryExpression&) **(*iter)->expression();
551 vectorize(b, iter, bin.fRight->fType, &bin.fLeft, outUpdated, outNeedsRescan);
552}
553
554/**
555 * Given a binary expression of the form vec<n>(x) <op> y, deletes the left side and vectorizes the
556 * right to yield vec<n>(y).
557 */
558static void vectorize_right(BasicBlock* b,
559 std::vector<BasicBlock::Node>::iterator* iter,
560 bool* outUpdated,
561 bool* outNeedsRescan) {
562 BinaryExpression& bin = (BinaryExpression&) **(*iter)->expression();
563 vectorize(b, iter, bin.fLeft->fType, &bin.fRight, outUpdated, outNeedsRescan);
564}
565
566// Mark that an expression which we were writing to is no longer being written to
567void clear_write(const Expression& expr) {
568 switch (expr.fKind) {
569 case Expression::kVariableReference_Kind: {
570 ((VariableReference&) expr).setRefKind(VariableReference::kRead_RefKind);
571 break;
572 }
573 case Expression::kFieldAccess_Kind:
574 clear_write(*((FieldAccess&) expr).fBase);
575 break;
576 case Expression::kSwizzle_Kind:
577 clear_write(*((Swizzle&) expr).fBase);
578 break;
579 case Expression::kIndex_Kind:
580 clear_write(*((IndexExpression&) expr).fBase);
581 break;
582 default:
583 ABORT("shouldn't be writing to this kind of expression\n");
584 break;
585 }
586}
587
Ethan Nicholascb670962017-04-20 19:31:52 -0400588void Compiler::simplifyExpression(DefinitionMap& definitions,
589 BasicBlock& b,
590 std::vector<BasicBlock::Node>::iterator* iter,
591 std::unordered_set<const Variable*>* undefinedVariables,
592 bool* outUpdated,
593 bool* outNeedsRescan) {
594 Expression* expr = (*iter)->expression()->get();
595 ASSERT(expr);
596 if ((*iter)->fConstantPropagation) {
597 std::unique_ptr<Expression> optimized = expr->constantPropagate(*fIRGenerator, definitions);
598 if (optimized) {
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400599 *outUpdated = true;
Ethan Nicholascb670962017-04-20 19:31:52 -0400600 if (!try_replace_expression(&b, iter, &optimized)) {
601 *outNeedsRescan = true;
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400602 return;
Ethan Nicholascb670962017-04-20 19:31:52 -0400603 }
604 ASSERT((*iter)->fKind == BasicBlock::Node::kExpression_Kind);
605 expr = (*iter)->expression()->get();
Ethan Nicholascb670962017-04-20 19:31:52 -0400606 }
607 }
608 switch (expr->fKind) {
609 case Expression::kVariableReference_Kind: {
610 const Variable& var = ((VariableReference*) expr)->fVariable;
611 if (var.fStorage == Variable::kLocal_Storage && !definitions[&var] &&
612 (*undefinedVariables).find(&var) == (*undefinedVariables).end()) {
613 (*undefinedVariables).insert(&var);
614 this->error(expr->fPosition,
615 "'" + var.fName + "' has not been assigned");
616 }
617 break;
618 }
619 case Expression::kTernary_Kind: {
620 TernaryExpression* t = (TernaryExpression*) expr;
621 if (t->fTest->fKind == Expression::kBoolLiteral_Kind) {
622 // ternary has a constant test, replace it with either the true or
623 // false branch
624 if (((BoolLiteral&) *t->fTest).fValue) {
625 (*iter)->setExpression(std::move(t->fIfTrue));
626 } else {
627 (*iter)->setExpression(std::move(t->fIfFalse));
628 }
629 *outUpdated = true;
630 *outNeedsRescan = true;
631 }
632 break;
633 }
634 case Expression::kBinary_Kind: {
Ethan Nicholascb670962017-04-20 19:31:52 -0400635 BinaryExpression* bin = (BinaryExpression*) expr;
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400636 if (dead_assignment(*bin)) {
637 delete_left(&b, iter, outUpdated, outNeedsRescan);
638 break;
639 }
640 // collapse useless expressions like x * 1 or x + 0
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400641 if (((bin->fLeft->fType.kind() != Type::kScalar_Kind) &&
642 (bin->fLeft->fType.kind() != Type::kVector_Kind)) ||
643 ((bin->fRight->fType.kind() != Type::kScalar_Kind) &&
644 (bin->fRight->fType.kind() != Type::kVector_Kind))) {
645 break;
646 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400647 switch (bin->fOperator) {
648 case Token::STAR:
649 if (is_constant(*bin->fLeft, 1)) {
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400650 if (bin->fLeft->fType.kind() == Type::kVector_Kind &&
651 bin->fRight->fType.kind() == Type::kScalar_Kind) {
652 // vec4(1) * x -> vec4(x)
653 vectorize_right(&b, iter, outUpdated, outNeedsRescan);
654 } else {
655 // 1 * x -> x
656 // 1 * vec4(x) -> vec4(x)
657 // vec4(1) * vec4(x) -> vec4(x)
658 delete_left(&b, iter, outUpdated, outNeedsRescan);
659 }
660 }
661 else if (is_constant(*bin->fLeft, 0)) {
662 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
663 bin->fRight->fType.kind() == Type::kVector_Kind) {
664 // 0 * vec4(x) -> vec4(0)
665 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
666 } else {
667 // 0 * x -> 0
668 // vec4(0) * x -> vec4(0)
669 // vec4(0) * vec4(x) -> vec4(0)
670 delete_right(&b, iter, outUpdated, outNeedsRescan);
671 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400672 }
673 else if (is_constant(*bin->fRight, 1)) {
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400674 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
675 bin->fRight->fType.kind() == Type::kVector_Kind) {
676 // x * vec4(1) -> vec4(x)
677 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
678 } else {
679 // x * 1 -> x
680 // vec4(x) * 1 -> vec4(x)
681 // vec4(x) * vec4(1) -> vec4(x)
682 delete_right(&b, iter, outUpdated, outNeedsRescan);
683 }
684 }
685 else if (is_constant(*bin->fRight, 0)) {
686 if (bin->fLeft->fType.kind() == Type::kVector_Kind &&
687 bin->fRight->fType.kind() == Type::kScalar_Kind) {
688 // vec4(x) * 0 -> vec4(0)
689 vectorize_right(&b, iter, outUpdated, outNeedsRescan);
690 } else {
691 // x * 0 -> 0
692 // x * vec4(0) -> vec4(0)
693 // vec4(x) * vec4(0) -> vec4(0)
694 delete_left(&b, iter, outUpdated, outNeedsRescan);
695 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400696 }
697 break;
Ethan Nicholas56e42712017-04-21 10:23:37 -0400698 case Token::PLUS:
Ethan Nicholascb670962017-04-20 19:31:52 -0400699 if (is_constant(*bin->fLeft, 0)) {
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400700 if (bin->fLeft->fType.kind() == Type::kVector_Kind &&
701 bin->fRight->fType.kind() == Type::kScalar_Kind) {
702 // vec4(0) + x -> vec4(x)
703 vectorize_right(&b, iter, outUpdated, outNeedsRescan);
704 } else {
705 // 0 + x -> x
706 // 0 + vec4(x) -> vec4(x)
707 // vec4(0) + vec4(x) -> vec4(x)
708 delete_left(&b, iter, outUpdated, outNeedsRescan);
709 }
710 } else if (is_constant(*bin->fRight, 0)) {
711 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
712 bin->fRight->fType.kind() == Type::kVector_Kind) {
713 // x + vec4(0) -> vec4(x)
714 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
715 } else {
716 // x + 0 -> x
717 // vec4(x) + 0 -> vec4(x)
718 // vec4(x) + vec4(0) -> vec4(x)
719 delete_right(&b, iter, outUpdated, outNeedsRescan);
720 }
Ethan Nicholas56e42712017-04-21 10:23:37 -0400721 }
722 break;
723 case Token::MINUS:
724 if (is_constant(*bin->fRight, 0)) {
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400725 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
726 bin->fRight->fType.kind() == Type::kVector_Kind) {
727 // x - vec4(0) -> vec4(x)
728 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
729 } else {
730 // x - 0 -> x
731 // vec4(x) - 0 -> vec4(x)
732 // vec4(x) - vec4(0) -> vec4(x)
733 delete_right(&b, iter, outUpdated, outNeedsRescan);
734 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400735 }
736 break;
737 case Token::SLASH:
738 if (is_constant(*bin->fRight, 1)) {
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400739 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
740 bin->fRight->fType.kind() == Type::kVector_Kind) {
741 // x / vec4(1) -> vec4(x)
742 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
743 } else {
744 // x / 1 -> x
745 // vec4(x) / 1 -> vec4(x)
746 // vec4(x) / vec4(1) -> vec4(x)
747 delete_right(&b, iter, outUpdated, outNeedsRescan);
748 }
749 } else if (is_constant(*bin->fLeft, 0)) {
750 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
751 bin->fRight->fType.kind() == Type::kVector_Kind) {
752 // 0 / vec4(x) -> vec4(0)
753 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
754 } else {
755 // 0 / x -> 0
756 // vec4(0) / x -> vec4(0)
757 // vec4(0) / vec4(x) -> vec4(0)
758 delete_right(&b, iter, outUpdated, outNeedsRescan);
759 }
760 }
761 break;
762 case Token::PLUSEQ:
763 if (is_constant(*bin->fRight, 0)) {
764 clear_write(*bin->fLeft);
765 delete_right(&b, iter, outUpdated, outNeedsRescan);
766 }
767 break;
768 case Token::MINUSEQ:
769 if (is_constant(*bin->fRight, 0)) {
770 clear_write(*bin->fLeft);
771 delete_right(&b, iter, outUpdated, outNeedsRescan);
772 }
773 break;
774 case Token::STAREQ:
775 if (is_constant(*bin->fRight, 1)) {
776 clear_write(*bin->fLeft);
777 delete_right(&b, iter, outUpdated, outNeedsRescan);
778 }
779 break;
780 case Token::SLASHEQ:
781 if (is_constant(*bin->fRight, 1)) {
782 clear_write(*bin->fLeft);
Ethan Nicholascb670962017-04-20 19:31:52 -0400783 delete_right(&b, iter, outUpdated, outNeedsRescan);
784 }
785 break;
786 default:
787 break;
788 }
789 }
790 default:
791 break;
792 }
793}
794
Ethan Nicholas5ac13c22017-05-10 15:06:17 -0400795// returns true if this statement could potentially execute a break at the current level (we ignore
796// nested loops and switches, since any breaks inside of them will merely break the loop / switch)
797static bool contains_break(Statement& s) {
798 switch (s.fKind) {
799 case Statement::kBlock_Kind:
800 for (const auto& sub : ((Block&) s).fStatements) {
801 if (contains_break(*sub)) {
802 return true;
803 }
804 }
805 return false;
806 case Statement::kBreak_Kind:
807 return true;
808 case Statement::kIf_Kind: {
809 const IfStatement& i = (IfStatement&) s;
810 return contains_break(*i.fIfTrue) || (i.fIfFalse && contains_break(*i.fIfFalse));
811 }
812 default:
813 return false;
814 }
815}
816
817// Returns a block containing all of the statements that will be run if the given case matches
818// (which, owing to the statements being owned by unique_ptrs, means the switch itself will be
819// broken by this call and must then be discarded).
820// Returns null (and leaves the switch unmodified) if no such simple reduction is possible, such as
821// when break statements appear inside conditionals.
822static std::unique_ptr<Statement> block_for_case(SwitchStatement* s, SwitchCase* c) {
823 bool capturing = false;
824 std::vector<std::unique_ptr<Statement>*> statementPtrs;
825 for (const auto& current : s->fCases) {
826 if (current.get() == c) {
827 capturing = true;
828 }
829 if (capturing) {
830 for (auto& stmt : current->fStatements) {
831 if (stmt->fKind == Statement::kBreak_Kind) {
832 capturing = false;
833 break;
834 }
835 if (contains_break(*stmt)) {
836 return nullptr;
837 }
838 statementPtrs.push_back(&stmt);
839 }
840 if (!capturing) {
841 break;
842 }
843 }
844 }
845 std::vector<std::unique_ptr<Statement>> statements;
846 for (const auto& s : statementPtrs) {
847 statements.push_back(std::move(*s));
848 }
849 return std::unique_ptr<Statement>(new Block(Position(), std::move(statements)));
850}
851
Ethan Nicholascb670962017-04-20 19:31:52 -0400852void Compiler::simplifyStatement(DefinitionMap& definitions,
Ethan Nicholas5ac13c22017-05-10 15:06:17 -0400853 BasicBlock& b,
854 std::vector<BasicBlock::Node>::iterator* iter,
855 std::unordered_set<const Variable*>* undefinedVariables,
856 bool* outUpdated,
857 bool* outNeedsRescan) {
Ethan Nicholascb670962017-04-20 19:31:52 -0400858 Statement* stmt = (*iter)->statement()->get();
859 switch (stmt->fKind) {
Ethan Nicholasb4dc4192017-06-02 10:16:28 -0400860 case Statement::kVarDeclaration_Kind: {
861 const auto& varDecl = (VarDeclaration&) *stmt;
862 if (varDecl.fVar->dead() &&
863 (!varDecl.fValue ||
864 !varDecl.fValue->hasSideEffects())) {
865 if (varDecl.fValue) {
866 ASSERT((*iter)->statement()->get() == stmt);
867 if (!b.tryRemoveExpressionBefore(iter, varDecl.fValue.get())) {
868 *outNeedsRescan = true;
Ethan Nicholascb670962017-04-20 19:31:52 -0400869 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400870 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400871 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
Ethan Nicholasb4dc4192017-06-02 10:16:28 -0400872 *outUpdated = true;
Ethan Nicholascb670962017-04-20 19:31:52 -0400873 }
874 break;
875 }
876 case Statement::kIf_Kind: {
877 IfStatement& i = (IfStatement&) *stmt;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -0400878 if (i.fTest->fKind == Expression::kBoolLiteral_Kind) {
879 // constant if, collapse down to a single branch
880 if (((BoolLiteral&) *i.fTest).fValue) {
881 ASSERT(i.fIfTrue);
882 (*iter)->setStatement(std::move(i.fIfTrue));
883 } else {
884 if (i.fIfFalse) {
885 (*iter)->setStatement(std::move(i.fIfFalse));
886 } else {
887 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
888 }
889 }
890 *outUpdated = true;
891 *outNeedsRescan = true;
892 break;
893 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400894 if (i.fIfFalse && i.fIfFalse->isEmpty()) {
895 // else block doesn't do anything, remove it
896 i.fIfFalse.reset();
897 *outUpdated = true;
898 *outNeedsRescan = true;
899 }
900 if (!i.fIfFalse && i.fIfTrue->isEmpty()) {
901 // if block doesn't do anything, no else block
902 if (i.fTest->hasSideEffects()) {
903 // test has side effects, keep it
904 (*iter)->setStatement(std::unique_ptr<Statement>(
905 new ExpressionStatement(std::move(i.fTest))));
906 } else {
907 // no if, no else, no test side effects, kill the whole if
908 // statement
909 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
910 }
911 *outUpdated = true;
912 *outNeedsRescan = true;
913 }
914 break;
915 }
Ethan Nicholas5ac13c22017-05-10 15:06:17 -0400916 case Statement::kSwitch_Kind: {
917 SwitchStatement& s = (SwitchStatement&) *stmt;
918 if (s.fValue->isConstant()) {
919 // switch is constant, replace it with the case that matches
920 bool found = false;
921 SwitchCase* defaultCase = nullptr;
922 for (const auto& c : s.fCases) {
923 if (!c->fValue) {
924 defaultCase = c.get();
925 continue;
926 }
927 ASSERT(c->fValue->fKind == s.fValue->fKind);
928 found = c->fValue->compareConstant(fContext, *s.fValue);
929 if (found) {
930 std::unique_ptr<Statement> newBlock = block_for_case(&s, c.get());
931 if (newBlock) {
932 (*iter)->setStatement(std::move(newBlock));
933 break;
934 } else {
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -0400935 if (s.fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) {
Ethan Nicholas5ac13c22017-05-10 15:06:17 -0400936 this->error(s.fPosition,
937 "static switch contains non-static conditional break");
938 s.fIsStatic = false;
939 }
940 return; // can't simplify
941 }
942 }
943 }
944 if (!found) {
945 // no matching case. use default if it exists, or kill the whole thing
946 if (defaultCase) {
947 std::unique_ptr<Statement> newBlock = block_for_case(&s, defaultCase);
948 if (newBlock) {
949 (*iter)->setStatement(std::move(newBlock));
950 } else {
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -0400951 if (s.fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) {
Ethan Nicholas5ac13c22017-05-10 15:06:17 -0400952 this->error(s.fPosition,
953 "static switch contains non-static conditional break");
954 s.fIsStatic = false;
955 }
956 return; // can't simplify
957 }
958 } else {
959 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
960 }
961 }
962 *outUpdated = true;
963 *outNeedsRescan = true;
964 }
965 break;
966 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400967 case Statement::kExpression_Kind: {
968 ExpressionStatement& e = (ExpressionStatement&) *stmt;
969 ASSERT((*iter)->statement()->get() == &e);
Ethan Nicholascb670962017-04-20 19:31:52 -0400970 if (!e.fExpression->hasSideEffects()) {
971 // Expression statement with no side effects, kill it
972 if (!b.tryRemoveExpressionBefore(iter, e.fExpression.get())) {
973 *outNeedsRescan = true;
974 }
975 ASSERT((*iter)->statement()->get() == stmt);
976 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
977 *outUpdated = true;
978 }
979 break;
980 }
981 default:
982 break;
983 }
984}
985
986void Compiler::scanCFG(FunctionDefinition& f) {
987 CFG cfg = CFGGenerator().getCFG(f);
988 this->computeDataFlow(&cfg);
ethannicholas22f939e2016-10-13 13:25:34 -0700989
990 // check for unreachable code
991 for (size_t i = 0; i < cfg.fBlocks.size(); i++) {
Mike Klein6ad99092016-10-26 10:35:22 -0400992 if (i != cfg.fStart && !cfg.fBlocks[i].fEntrances.size() &&
ethannicholas22f939e2016-10-13 13:25:34 -0700993 cfg.fBlocks[i].fNodes.size()) {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500994 Position p;
995 switch (cfg.fBlocks[i].fNodes[0].fKind) {
996 case BasicBlock::Node::kStatement_Kind:
Ethan Nicholascb670962017-04-20 19:31:52 -0400997 p = (*cfg.fBlocks[i].fNodes[0].statement())->fPosition;
Ethan Nicholas86a43402017-01-19 13:32:00 -0500998 break;
999 case BasicBlock::Node::kExpression_Kind:
Ethan Nicholascb670962017-04-20 19:31:52 -04001000 p = (*cfg.fBlocks[i].fNodes[0].expression())->fPosition;
Ethan Nicholas86a43402017-01-19 13:32:00 -05001001 break;
1002 }
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001003 this->error(p, String("unreachable"));
ethannicholas22f939e2016-10-13 13:25:34 -07001004 }
1005 }
1006 if (fErrorCount) {
1007 return;
1008 }
1009
Ethan Nicholascb670962017-04-20 19:31:52 -04001010 // check for dead code & undefined variables, perform constant propagation
1011 std::unordered_set<const Variable*> undefinedVariables;
1012 bool updated;
1013 bool needsRescan = false;
1014 do {
1015 if (needsRescan) {
1016 cfg = CFGGenerator().getCFG(f);
1017 this->computeDataFlow(&cfg);
1018 needsRescan = false;
Ethan Nicholas113628d2017-02-02 16:11:39 -05001019 }
Ethan Nicholascb670962017-04-20 19:31:52 -04001020
1021 updated = false;
1022 for (BasicBlock& b : cfg.fBlocks) {
1023 DefinitionMap definitions = b.fBefore;
1024
1025 for (auto iter = b.fNodes.begin(); iter != b.fNodes.end() && !needsRescan; ++iter) {
1026 if (iter->fKind == BasicBlock::Node::kExpression_Kind) {
1027 this->simplifyExpression(definitions, b, &iter, &undefinedVariables, &updated,
1028 &needsRescan);
1029 } else {
1030 this->simplifyStatement(definitions, b, &iter, &undefinedVariables, &updated,
1031 &needsRescan);
1032 }
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001033 if (needsRescan) {
1034 break;
1035 }
Ethan Nicholascb670962017-04-20 19:31:52 -04001036 this->addDefinitions(*iter, &definitions);
1037 }
1038 }
1039 } while (updated);
1040 ASSERT(!needsRescan);
ethannicholas22f939e2016-10-13 13:25:34 -07001041
Ethan Nicholas91a10532017-06-22 11:24:38 -04001042 // verify static ifs & switches, clean up dead variable decls
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001043 for (BasicBlock& b : cfg.fBlocks) {
1044 DefinitionMap definitions = b.fBefore;
1045
Ethan Nicholas91a10532017-06-22 11:24:38 -04001046 for (auto iter = b.fNodes.begin(); iter != b.fNodes.end() && !needsRescan;) {
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001047 if (iter->fKind == BasicBlock::Node::kStatement_Kind) {
1048 const Statement& s = **iter->statement();
1049 switch (s.fKind) {
1050 case Statement::kIf_Kind:
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -04001051 if (((const IfStatement&) s).fIsStatic &&
1052 !(fFlags & kPermitInvalidStaticTests_Flag)) {
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001053 this->error(s.fPosition, "static if has non-static test");
1054 }
Ethan Nicholas91a10532017-06-22 11:24:38 -04001055 ++iter;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001056 break;
1057 case Statement::kSwitch_Kind:
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -04001058 if (((const SwitchStatement&) s).fIsStatic &&
1059 !(fFlags & kPermitInvalidStaticTests_Flag)) {
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001060 this->error(s.fPosition, "static switch has non-static test");
1061 }
Ethan Nicholas91a10532017-06-22 11:24:38 -04001062 ++iter;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001063 break;
Ethan Nicholas91a10532017-06-22 11:24:38 -04001064 case Statement::kVarDeclarations_Kind: {
1065 VarDeclarations& decls = *((VarDeclarationsStatement&) s).fDeclaration;
1066 for (auto varIter = decls.fVars.begin(); varIter != decls.fVars.end();) {
1067 if ((*varIter)->fKind == Statement::kNop_Kind) {
1068 varIter = decls.fVars.erase(varIter);
1069 } else {
1070 ++varIter;
1071 }
1072 }
1073 if (!decls.fVars.size()) {
1074 iter = b.fNodes.erase(iter);
1075 } else {
1076 ++iter;
1077 }
1078 break;
1079 }
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001080 default:
Ethan Nicholas91a10532017-06-22 11:24:38 -04001081 ++iter;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001082 break;
1083 }
Ethan Nicholas91a10532017-06-22 11:24:38 -04001084 } else {
1085 ++iter;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001086 }
1087 }
1088 }
1089
ethannicholas22f939e2016-10-13 13:25:34 -07001090 // check for missing return
1091 if (f.fDeclaration.fReturnType != *fContext.fVoid_Type) {
1092 if (cfg.fBlocks[cfg.fExit].fEntrances.size()) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001093 this->error(f.fPosition, String("function can exit without returning a value"));
ethannicholas22f939e2016-10-13 13:25:34 -07001094 }
1095 }
1096}
1097
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001098std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String text,
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001099 const Program::Settings& settings) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001100 fErrorText = "";
1101 fErrorCount = 0;
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001102 fIRGenerator->start(&settings);
ethannicholasd598f792016-07-25 10:08:54 -07001103 std::vector<std::unique_ptr<ProgramElement>> elements;
ethannicholas5961bc92016-10-12 06:39:56 -07001104 Modifiers::Flag ignored;
ethannicholasb3058bd2016-07-01 08:22:01 -07001105 switch (kind) {
1106 case Program::kVertex_Kind:
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04001107 fIRGenerator->convertProgram(String(SKSL_VERT_INCLUDE), *fTypes, &ignored, &elements);
ethannicholasb3058bd2016-07-01 08:22:01 -07001108 break;
1109 case Program::kFragment_Kind:
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04001110 fIRGenerator->convertProgram(String(SKSL_FRAG_INCLUDE), *fTypes, &ignored, &elements);
ethannicholasb3058bd2016-07-01 08:22:01 -07001111 break;
Ethan Nicholas52cad152017-02-16 16:37:32 -05001112 case Program::kGeometry_Kind:
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04001113 fIRGenerator->convertProgram(String(SKSL_GEOM_INCLUDE), *fTypes, &ignored, &elements);
Ethan Nicholas52cad152017-02-16 16:37:32 -05001114 break;
Ethan Nicholas762466e2017-06-29 10:03:38 -04001115 case Program::kFragmentProcessor_Kind:
1116 fIRGenerator->convertProgram(String(SKSL_FP_INCLUDE), *fTypes, &ignored, &elements);
1117 break;
ethannicholasb3058bd2016-07-01 08:22:01 -07001118 }
ethannicholasddb37d62016-10-20 09:54:00 -07001119 fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
ethannicholas5961bc92016-10-12 06:39:56 -07001120 Modifiers::Flag defaultPrecision;
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04001121 fIRGenerator->convertProgram(text, *fTypes, &defaultPrecision, &elements);
1122 if (!fErrorCount) {
1123 for (auto& element : elements) {
1124 if (element->fKind == ProgramElement::kFunction_Kind) {
1125 this->scanCFG((FunctionDefinition&) *element);
1126 }
1127 }
1128 }
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001129 auto result = std::unique_ptr<Program>(new Program(kind, settings, defaultPrecision, &fContext,
1130 std::move(elements),
1131 fIRGenerator->fSymbolTable,
1132 fIRGenerator->fInputs));
Ethan Nicholas3605ace2016-11-21 15:59:48 -05001133 fIRGenerator->finish();
ethannicholasb3058bd2016-07-01 08:22:01 -07001134 this->writeErrorCount();
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001135 if (fErrorCount) {
1136 return nullptr;
1137 }
1138 return result;
1139}
1140
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001141bool Compiler::toSPIRV(const Program& program, OutputStream& out) {
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001142#ifdef SK_ENABLE_SPIRV_VALIDATION
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001143 StringStream buffer;
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001144 SPIRVCodeGenerator cg(&fContext, &program, this, &buffer);
1145 bool result = cg.generateCode();
1146 if (result) {
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001147 spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0);
Ethan Nicholas762466e2017-06-29 10:03:38 -04001148 const String& data = buffer.str();
1149 ASSERT(0 == data.size() % 4);
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001150 auto dumpmsg = [](spv_message_level_t, const char*, const spv_position_t&, const char* m) {
1151 SkDebugf("SPIR-V validation error: %s\n", m);
1152 };
1153 tools.SetMessageConsumer(dumpmsg);
1154 // Verify that the SPIR-V we produced is valid. If this assert fails, check the logs prior
1155 // to the failure to see the validation errors.
Ethan Nicholas762466e2017-06-29 10:03:38 -04001156 ASSERT_RESULT(tools.Validate((const uint32_t*) data.c_str(), data.size() / 4));
1157 out.write(data.c_str(), data.size());
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001158 }
1159#else
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001160 SPIRVCodeGenerator cg(&fContext, &program, this, &out);
1161 bool result = cg.generateCode();
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001162#endif
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001163 this->writeErrorCount();
Ethan Nicholasce33f102016-12-09 17:22:59 -05001164 return result;
1165}
1166
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001167bool Compiler::toSPIRV(const Program& program, String* out) {
1168 StringStream buffer;
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001169 bool result = this->toSPIRV(program, buffer);
1170 if (result) {
Ethan Nicholas762466e2017-06-29 10:03:38 -04001171 *out = buffer.str();
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001172 }
1173 return result;
1174}
1175
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001176bool Compiler::toGLSL(const Program& program, OutputStream& out) {
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001177 GLSLCodeGenerator cg(&fContext, &program, this, &out);
1178 bool result = cg.generateCode();
1179 this->writeErrorCount();
1180 return result;
1181}
1182
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001183bool Compiler::toGLSL(const Program& program, String* out) {
1184 StringStream buffer;
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001185 bool result = this->toGLSL(program, buffer);
1186 if (result) {
Ethan Nicholas762466e2017-06-29 10:03:38 -04001187 *out = buffer.str();
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001188 }
1189 return result;
1190}
1191
Ethan Nicholas762466e2017-06-29 10:03:38 -04001192bool Compiler::toCPP(const Program& program, String name, OutputStream& out) {
1193 CPPCodeGenerator cg(&fContext, &program, this, name, &out);
1194 bool result = cg.generateCode();
1195 this->writeErrorCount();
1196 return result;
1197}
1198
1199bool Compiler::toH(const Program& program, String name, OutputStream& out) {
1200 HCodeGenerator cg(&program, this, name, &out);
1201 bool result = cg.generateCode();
1202 this->writeErrorCount();
1203 return result;
1204}
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001205
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001206void Compiler::error(Position position, String msg) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001207 fErrorCount++;
1208 fErrorText += "error: " + position.description() + ": " + msg.c_str() + "\n";
1209}
1210
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001211String Compiler::errorText() {
1212 String result = fErrorText;
ethannicholasb3058bd2016-07-01 08:22:01 -07001213 return result;
1214}
1215
1216void Compiler::writeErrorCount() {
1217 if (fErrorCount) {
1218 fErrorText += to_string(fErrorCount) + " error";
1219 if (fErrorCount > 1) {
1220 fErrorText += "s";
1221 }
1222 fErrorText += "\n";
1223 }
1224}
1225
ethannicholasb3058bd2016-07-01 08:22:01 -07001226} // namespace