blob: 92261a489b419bd652b8f09655ec06c50bfa1f1b [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
ethannicholas5961bc92016-10-12 06:39:56 -070010#include "ast/SkSLASTPrecision.h"
ethannicholas22f939e2016-10-13 13:25:34 -070011#include "SkSLCFGGenerator.h"
Ethan Nicholas941e7e22016-12-12 15:33:30 -050012#include "SkSLGLSLCodeGenerator.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070013#include "SkSLIRGenerator.h"
14#include "SkSLParser.h"
15#include "SkSLSPIRVCodeGenerator.h"
16#include "ir/SkSLExpression.h"
Ethan Nicholas113628d2017-02-02 16:11:39 -050017#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 Nicholas113628d2017-02-02 16:11:39 -050020#include "ir/SkSLNop.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070021#include "ir/SkSLSymbolTable.h"
Ethan Nicholas113628d2017-02-02 16:11:39 -050022#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#include "SkMutex.h"
26
27#define STRINGIFY(x) #x
28
29// include the built-in shader symbols as static strings
30
ethannicholas5961bc92016-10-12 06:39:56 -070031static const char* SKSL_INCLUDE =
ethannicholasb3058bd2016-07-01 08:22:01 -070032#include "sksl.include"
33;
34
ethannicholas5961bc92016-10-12 06:39:56 -070035static const char* SKSL_VERT_INCLUDE =
ethannicholasb3058bd2016-07-01 08:22:01 -070036#include "sksl_vert.include"
37;
38
ethannicholas5961bc92016-10-12 06:39:56 -070039static const char* SKSL_FRAG_INCLUDE =
ethannicholasb3058bd2016-07-01 08:22:01 -070040#include "sksl_frag.include"
41;
42
43namespace SkSL {
44
Mike Klein6ad99092016-10-26 10:35:22 -040045Compiler::Compiler()
ethannicholasb3058bd2016-07-01 08:22:01 -070046: fErrorCount(0) {
47 auto types = std::shared_ptr<SymbolTable>(new SymbolTable(*this));
48 auto symbols = std::shared_ptr<SymbolTable>(new SymbolTable(types, *this));
ethannicholasd598f792016-07-25 10:08:54 -070049 fIRGenerator = new IRGenerator(&fContext, symbols, *this);
ethannicholasb3058bd2016-07-01 08:22:01 -070050 fTypes = types;
ethannicholasd598f792016-07-25 10:08:54 -070051 #define ADD_TYPE(t) types->addWithoutOwnership(fContext.f ## t ## _Type->fName, \
52 fContext.f ## t ## _Type.get())
ethannicholasb3058bd2016-07-01 08:22:01 -070053 ADD_TYPE(Void);
54 ADD_TYPE(Float);
55 ADD_TYPE(Vec2);
56 ADD_TYPE(Vec3);
57 ADD_TYPE(Vec4);
58 ADD_TYPE(Double);
59 ADD_TYPE(DVec2);
60 ADD_TYPE(DVec3);
61 ADD_TYPE(DVec4);
62 ADD_TYPE(Int);
63 ADD_TYPE(IVec2);
64 ADD_TYPE(IVec3);
65 ADD_TYPE(IVec4);
66 ADD_TYPE(UInt);
67 ADD_TYPE(UVec2);
68 ADD_TYPE(UVec3);
69 ADD_TYPE(UVec4);
70 ADD_TYPE(Bool);
71 ADD_TYPE(BVec2);
72 ADD_TYPE(BVec3);
73 ADD_TYPE(BVec4);
74 ADD_TYPE(Mat2x2);
Ethan Nicholas9e1138d2016-11-21 10:39:35 -050075 types->addWithoutOwnership(SkString("mat2x2"), fContext.fMat2x2_Type.get());
ethannicholasb3058bd2016-07-01 08:22:01 -070076 ADD_TYPE(Mat2x3);
77 ADD_TYPE(Mat2x4);
78 ADD_TYPE(Mat3x2);
79 ADD_TYPE(Mat3x3);
Ethan Nicholas9e1138d2016-11-21 10:39:35 -050080 types->addWithoutOwnership(SkString("mat3x3"), fContext.fMat3x3_Type.get());
ethannicholasb3058bd2016-07-01 08:22:01 -070081 ADD_TYPE(Mat3x4);
82 ADD_TYPE(Mat4x2);
83 ADD_TYPE(Mat4x3);
84 ADD_TYPE(Mat4x4);
Ethan Nicholas9e1138d2016-11-21 10:39:35 -050085 types->addWithoutOwnership(SkString("mat4x4"), fContext.fMat4x4_Type.get());
ethannicholasb3058bd2016-07-01 08:22:01 -070086 ADD_TYPE(GenType);
87 ADD_TYPE(GenDType);
88 ADD_TYPE(GenIType);
89 ADD_TYPE(GenUType);
90 ADD_TYPE(GenBType);
91 ADD_TYPE(Mat);
92 ADD_TYPE(Vec);
93 ADD_TYPE(GVec);
94 ADD_TYPE(GVec2);
95 ADD_TYPE(GVec3);
96 ADD_TYPE(GVec4);
97 ADD_TYPE(DVec);
98 ADD_TYPE(IVec);
99 ADD_TYPE(UVec);
100 ADD_TYPE(BVec);
101
102 ADD_TYPE(Sampler1D);
103 ADD_TYPE(Sampler2D);
104 ADD_TYPE(Sampler3D);
ethannicholas5961bc92016-10-12 06:39:56 -0700105 ADD_TYPE(SamplerExternalOES);
ethannicholasb3058bd2016-07-01 08:22:01 -0700106 ADD_TYPE(SamplerCube);
107 ADD_TYPE(Sampler2DRect);
108 ADD_TYPE(Sampler1DArray);
109 ADD_TYPE(Sampler2DArray);
110 ADD_TYPE(SamplerCubeArray);
111 ADD_TYPE(SamplerBuffer);
112 ADD_TYPE(Sampler2DMS);
113 ADD_TYPE(Sampler2DMSArray);
114
Brian Salomonbf7b6202016-11-11 16:08:03 -0500115 ADD_TYPE(ISampler2D);
116
Brian Salomon2a51de82016-11-16 12:06:01 -0500117 ADD_TYPE(Image2D);
118 ADD_TYPE(IImage2D);
119
Greg Daniel64773e62016-11-22 09:44:03 -0500120 ADD_TYPE(SubpassInput);
121 ADD_TYPE(SubpassInputMS);
122
ethannicholasb3058bd2016-07-01 08:22:01 -0700123 ADD_TYPE(GSampler1D);
124 ADD_TYPE(GSampler2D);
125 ADD_TYPE(GSampler3D);
126 ADD_TYPE(GSamplerCube);
127 ADD_TYPE(GSampler2DRect);
128 ADD_TYPE(GSampler1DArray);
129 ADD_TYPE(GSampler2DArray);
130 ADD_TYPE(GSamplerCubeArray);
131 ADD_TYPE(GSamplerBuffer);
132 ADD_TYPE(GSampler2DMS);
133 ADD_TYPE(GSampler2DMSArray);
134
135 ADD_TYPE(Sampler1DShadow);
136 ADD_TYPE(Sampler2DShadow);
137 ADD_TYPE(SamplerCubeShadow);
138 ADD_TYPE(Sampler2DRectShadow);
139 ADD_TYPE(Sampler1DArrayShadow);
140 ADD_TYPE(Sampler2DArrayShadow);
141 ADD_TYPE(SamplerCubeArrayShadow);
142 ADD_TYPE(GSampler2DArrayShadow);
143 ADD_TYPE(GSamplerCubeArrayShadow);
144
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500145 SkString skCapsName("sk_Caps");
146 Variable* skCaps = new Variable(Position(), Modifiers(), skCapsName,
147 *fContext.fSkCaps_Type, Variable::kGlobal_Storage);
148 fIRGenerator->fSymbolTable->add(skCapsName, std::unique_ptr<Symbol>(skCaps));
149
ethannicholas5961bc92016-10-12 06:39:56 -0700150 Modifiers::Flag ignored1;
151 std::vector<std::unique_ptr<ProgramElement>> ignored2;
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500152 this->internalConvertProgram(SkString(SKSL_INCLUDE), &ignored1, &ignored2);
ethannicholasddb37d62016-10-20 09:54:00 -0700153 fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
ethannicholasb3058bd2016-07-01 08:22:01 -0700154 ASSERT(!fErrorCount);
155}
156
157Compiler::~Compiler() {
158 delete fIRGenerator;
159}
160
ethannicholas22f939e2016-10-13 13:25:34 -0700161// add the definition created by assigning to the lvalue to the definition set
Ethan Nicholas86a43402017-01-19 13:32:00 -0500162void Compiler::addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr,
163 DefinitionMap* definitions) {
ethannicholas22f939e2016-10-13 13:25:34 -0700164 switch (lvalue->fKind) {
165 case Expression::kVariableReference_Kind: {
166 const Variable& var = ((VariableReference*) lvalue)->fVariable;
167 if (var.fStorage == Variable::kLocal_Storage) {
168 (*definitions)[&var] = expr;
169 }
170 break;
171 }
172 case Expression::kSwizzle_Kind:
173 // We consider the variable written to as long as at least some of its components have
174 // been written to. This will lead to some false negatives (we won't catch it if you
175 // write to foo.x and then read foo.y), but being stricter could lead to false positives
Mike Klein6ad99092016-10-26 10:35:22 -0400176 // (we write to foo.x, and then pass foo to a function which happens to only read foo.x,
177 // 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 -0700178 // more complicated whole-program analysis. This is probably good enough.
Mike Klein6ad99092016-10-26 10:35:22 -0400179 this->addDefinition(((Swizzle*) lvalue)->fBase.get(),
Ethan Nicholas86a43402017-01-19 13:32:00 -0500180 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
ethannicholas22f939e2016-10-13 13:25:34 -0700181 definitions);
182 break;
183 case Expression::kIndex_Kind:
184 // see comments in Swizzle
Mike Klein6ad99092016-10-26 10:35:22 -0400185 this->addDefinition(((IndexExpression*) lvalue)->fBase.get(),
Ethan Nicholas86a43402017-01-19 13:32:00 -0500186 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
ethannicholas22f939e2016-10-13 13:25:34 -0700187 definitions);
188 break;
189 case Expression::kFieldAccess_Kind:
190 // see comments in Swizzle
Mike Klein6ad99092016-10-26 10:35:22 -0400191 this->addDefinition(((FieldAccess*) lvalue)->fBase.get(),
Ethan Nicholas86a43402017-01-19 13:32:00 -0500192 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
ethannicholas22f939e2016-10-13 13:25:34 -0700193 definitions);
194 break;
195 default:
196 // not an lvalue, can't happen
197 ASSERT(false);
198 }
199}
200
201// add local variables defined by this node to the set
Mike Klein6ad99092016-10-26 10:35:22 -0400202void Compiler::addDefinitions(const BasicBlock::Node& node,
Ethan Nicholas86a43402017-01-19 13:32:00 -0500203 DefinitionMap* definitions) {
ethannicholas22f939e2016-10-13 13:25:34 -0700204 switch (node.fKind) {
205 case BasicBlock::Node::kExpression_Kind: {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500206 ASSERT(node.fExpression);
207 const Expression* expr = (Expression*) node.fExpression->get();
208 switch (expr->fKind) {
209 case Expression::kBinary_Kind: {
210 BinaryExpression* b = (BinaryExpression*) expr;
211 if (b->fOperator == Token::EQ) {
212 this->addDefinition(b->fLeft.get(), &b->fRight, definitions);
213 } else if (Token::IsAssignment(b->fOperator)) {
214 this->addDefinition(
215 b->fLeft.get(),
216 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
217 definitions);
218
219 }
220 break;
ethannicholas22f939e2016-10-13 13:25:34 -0700221 }
Ethan Nicholas86a43402017-01-19 13:32:00 -0500222 case Expression::kPrefix_Kind: {
223 const PrefixExpression* p = (PrefixExpression*) expr;
224 if (p->fOperator == Token::MINUSMINUS || p->fOperator == Token::PLUSPLUS) {
225 this->addDefinition(
226 p->fOperand.get(),
227 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
228 definitions);
229 }
230 break;
231 }
232 case Expression::kPostfix_Kind: {
233 const PostfixExpression* p = (PostfixExpression*) expr;
234 if (p->fOperator == Token::MINUSMINUS || p->fOperator == Token::PLUSPLUS) {
235 this->addDefinition(
236 p->fOperand.get(),
237 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
238 definitions);
Ethan Nicholas86a43402017-01-19 13:32:00 -0500239 }
240 break;
241 }
Ethan Nicholas113628d2017-02-02 16:11:39 -0500242 case Expression::kVariableReference_Kind: {
243 const VariableReference* v = (VariableReference*) expr;
244 if (v->fRefKind != VariableReference::kRead_RefKind) {
245 this->addDefinition(
246 v,
247 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
248 definitions);
249 }
250 }
Ethan Nicholas86a43402017-01-19 13:32:00 -0500251 default:
252 break;
ethannicholas22f939e2016-10-13 13:25:34 -0700253 }
254 break;
255 }
256 case BasicBlock::Node::kStatement_Kind: {
Ethan Nicholas113628d2017-02-02 16:11:39 -0500257 const Statement* stmt = (Statement*) node.fStatement->get();
ethannicholas22f939e2016-10-13 13:25:34 -0700258 if (stmt->fKind == Statement::kVarDeclarations_Kind) {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500259 VarDeclarationsStatement* vd = (VarDeclarationsStatement*) stmt;
Ethan Nicholas113628d2017-02-02 16:11:39 -0500260 for (const auto& decl : vd->fDeclaration->fVars) {
261 if (decl->fValue) {
262 (*definitions)[decl->fVar] = &decl->fValue;
ethannicholas22f939e2016-10-13 13:25:34 -0700263 }
264 }
265 }
266 break;
267 }
268 }
269}
270
271void Compiler::scanCFG(CFG* cfg, BlockId blockId, std::set<BlockId>* workList) {
272 BasicBlock& block = cfg->fBlocks[blockId];
273
274 // compute definitions after this block
Ethan Nicholas86a43402017-01-19 13:32:00 -0500275 DefinitionMap after = block.fBefore;
ethannicholas22f939e2016-10-13 13:25:34 -0700276 for (const BasicBlock::Node& n : block.fNodes) {
277 this->addDefinitions(n, &after);
278 }
279
280 // propagate definitions to exits
281 for (BlockId exitId : block.fExits) {
282 BasicBlock& exit = cfg->fBlocks[exitId];
283 for (const auto& pair : after) {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500284 std::unique_ptr<Expression>* e1 = pair.second;
285 auto found = exit.fBefore.find(pair.first);
286 if (found == exit.fBefore.end()) {
287 // exit has no definition for it, just copy it
288 workList->insert(exitId);
ethannicholas22f939e2016-10-13 13:25:34 -0700289 exit.fBefore[pair.first] = e1;
290 } else {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500291 // exit has a (possibly different) value already defined
292 std::unique_ptr<Expression>* e2 = exit.fBefore[pair.first];
ethannicholas22f939e2016-10-13 13:25:34 -0700293 if (e1 != e2) {
294 // definition has changed, merge and add exit block to worklist
295 workList->insert(exitId);
Ethan Nicholas86a43402017-01-19 13:32:00 -0500296 exit.fBefore[pair.first] =
297 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression;
ethannicholas22f939e2016-10-13 13:25:34 -0700298 }
299 }
300 }
301 }
302}
303
304// returns a map which maps all local variables in the function to null, indicating that their value
305// is initially unknown
Ethan Nicholas86a43402017-01-19 13:32:00 -0500306static DefinitionMap compute_start_state(const CFG& cfg) {
307 DefinitionMap result;
Mike Klein6ad99092016-10-26 10:35:22 -0400308 for (const auto& block : cfg.fBlocks) {
309 for (const auto& node : block.fNodes) {
ethannicholas22f939e2016-10-13 13:25:34 -0700310 if (node.fKind == BasicBlock::Node::kStatement_Kind) {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500311 ASSERT(node.fStatement);
Ethan Nicholas113628d2017-02-02 16:11:39 -0500312 const Statement* s = node.fStatement->get();
ethannicholas22f939e2016-10-13 13:25:34 -0700313 if (s->fKind == Statement::kVarDeclarations_Kind) {
314 const VarDeclarationsStatement* vd = (const VarDeclarationsStatement*) s;
Ethan Nicholas113628d2017-02-02 16:11:39 -0500315 for (const auto& decl : vd->fDeclaration->fVars) {
316 result[decl->fVar] = nullptr;
Mike Klein6ad99092016-10-26 10:35:22 -0400317 }
ethannicholas22f939e2016-10-13 13:25:34 -0700318 }
319 }
320 }
321 }
322 return result;
323}
324
Ethan Nicholas113628d2017-02-02 16:11:39 -0500325/**
326 * Returns true if assigning to this lvalue has no effect.
327 */
328static bool is_dead(const Expression& lvalue) {
329 switch (lvalue.fKind) {
330 case Expression::kVariableReference_Kind:
331 return ((VariableReference&) lvalue).fVariable.dead();
332 case Expression::kSwizzle_Kind:
333 return is_dead(*((Swizzle&) lvalue).fBase);
334 case Expression::kFieldAccess_Kind:
335 return is_dead(*((FieldAccess&) lvalue).fBase);
336 case Expression::kIndex_Kind: {
337 const IndexExpression& idx = (IndexExpression&) lvalue;
338 return is_dead(*idx.fBase) && !idx.fIndex->hasSideEffects();
339 }
340 default:
341 SkDebugf("invalid lvalue: %s\n", lvalue.description().c_str());
342 ASSERT(false);
343 return false;
344 }
345}
ethannicholas22f939e2016-10-13 13:25:34 -0700346
Ethan Nicholas113628d2017-02-02 16:11:39 -0500347/**
348 * Returns true if this is an assignment which can be collapsed down to just the right hand side due
349 * to a dead target and lack of side effects on the left hand side.
350 */
351static bool dead_assignment(const BinaryExpression& b) {
352 if (!Token::IsAssignment(b.fOperator)) {
353 return false;
354 }
355 return is_dead(*b.fLeft);
356}
357
358void Compiler::computeDataFlow(CFG* cfg) {
359 cfg->fBlocks[cfg->fStart].fBefore = compute_start_state(*cfg);
ethannicholas22f939e2016-10-13 13:25:34 -0700360 std::set<BlockId> workList;
Ethan Nicholas113628d2017-02-02 16:11:39 -0500361 for (BlockId i = 0; i < cfg->fBlocks.size(); i++) {
ethannicholas22f939e2016-10-13 13:25:34 -0700362 workList.insert(i);
363 }
364 while (workList.size()) {
365 BlockId next = *workList.begin();
366 workList.erase(workList.begin());
Ethan Nicholas113628d2017-02-02 16:11:39 -0500367 this->scanCFG(cfg, next, &workList);
ethannicholas22f939e2016-10-13 13:25:34 -0700368 }
Ethan Nicholas113628d2017-02-02 16:11:39 -0500369}
370
371
372/**
373 * Attempts to replace the expression pointed to by iter with a new one (in both the CFG and the
374 * IR). If the expression can be cleanly removed, returns true and updates the iterator to point to
375 * the newly-inserted element. Otherwise updates only the IR and returns false (and the CFG will
376 * need to be regenerated).
377 */
378bool SK_WARN_UNUSED_RESULT try_replace_expression(BasicBlock* b,
379 std::vector<BasicBlock::Node>::iterator* iter,
380 std::unique_ptr<Expression> newExpression) {
381 std::unique_ptr<Expression>* target = (*iter)->fExpression;
382 if (!b->tryRemoveExpression(iter)) {
383 *target = std::move(newExpression);
384 return false;
385 }
386 *target = std::move(newExpression);
387 return b->tryInsertExpression( iter, target);
388}
389
390void Compiler::scanCFG(FunctionDefinition& f) {
391 CFG cfg = CFGGenerator().getCFG(f);
392 this->computeDataFlow(&cfg);
ethannicholas22f939e2016-10-13 13:25:34 -0700393
394 // check for unreachable code
395 for (size_t i = 0; i < cfg.fBlocks.size(); i++) {
Mike Klein6ad99092016-10-26 10:35:22 -0400396 if (i != cfg.fStart && !cfg.fBlocks[i].fEntrances.size() &&
ethannicholas22f939e2016-10-13 13:25:34 -0700397 cfg.fBlocks[i].fNodes.size()) {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500398 Position p;
399 switch (cfg.fBlocks[i].fNodes[0].fKind) {
400 case BasicBlock::Node::kStatement_Kind:
Ethan Nicholas113628d2017-02-02 16:11:39 -0500401 p = (*cfg.fBlocks[i].fNodes[0].fStatement)->fPosition;
Ethan Nicholas86a43402017-01-19 13:32:00 -0500402 break;
403 case BasicBlock::Node::kExpression_Kind:
404 p = (*cfg.fBlocks[i].fNodes[0].fExpression)->fPosition;
405 break;
406 }
407 this->error(p, SkString("unreachable"));
ethannicholas22f939e2016-10-13 13:25:34 -0700408 }
409 }
410 if (fErrorCount) {
411 return;
412 }
413
Ethan Nicholas113628d2017-02-02 16:11:39 -0500414 // check for dead code & undefined variables, perform constant propagation
415 std::unordered_set<const Variable*> undefinedVariables;
416 bool updated;
417 bool needsRescan = false;
418 do {
419 if (needsRescan) {
420 cfg = CFGGenerator().getCFG(f);
421 this->computeDataFlow(&cfg);
422 needsRescan = false;
ethannicholas22f939e2016-10-13 13:25:34 -0700423 }
Ethan Nicholas113628d2017-02-02 16:11:39 -0500424
425 updated = false;
426 for (BasicBlock& b : cfg.fBlocks) {
427 DefinitionMap definitions = b.fBefore;
428
429 for (auto iter = b.fNodes.begin(); iter != b.fNodes.end() && !needsRescan; ++iter) {
430 if (iter->fKind == BasicBlock::Node::kExpression_Kind) {
431 Expression* expr = iter->fExpression->get();
432 ASSERT(expr);
433 if (iter->fConstantPropagation) {
434 std::unique_ptr<Expression> optimized = expr->constantPropagate(
435 *fIRGenerator,
436 definitions);
437 if (optimized) {
438 if (!try_replace_expression(&b, &iter, std::move(optimized))) {
439 needsRescan = true;
440 }
441 ASSERT(iter->fKind == BasicBlock::Node::kExpression_Kind);
442 expr = iter->fExpression->get();
443 updated = true;
444 }
445 }
446 switch (expr->fKind) {
447 case Expression::kVariableReference_Kind: {
448 const Variable& var = ((VariableReference*) expr)->fVariable;
449 if (var.fStorage == Variable::kLocal_Storage &&
450 !definitions[&var] &&
451 undefinedVariables.find(&var) == undefinedVariables.end()) {
452 undefinedVariables.insert(&var);
453 this->error(expr->fPosition,
454 "'" + var.fName + "' has not been assigned");
455 }
456 break;
457 }
458 case Expression::kTernary_Kind: {
459 TernaryExpression* t = (TernaryExpression*) expr;
460 if (t->fTest->fKind == Expression::kBoolLiteral_Kind) {
461 // ternary has a constant test, replace it with either the true or
462 // false branch
463 if (((BoolLiteral&) *t->fTest).fValue) {
464 *iter->fExpression = std::move(t->fIfTrue);
465 } else {
466 *iter->fExpression = std::move(t->fIfFalse);
467 }
468 updated = true;
469 needsRescan = true;
470 }
471 break;
472 }
473 default:
474 break;
475 }
476 } else {
477 ASSERT(iter->fKind == BasicBlock::Node::kStatement_Kind);
478 Statement* stmt = iter->fStatement->get();
479 switch (stmt->fKind) {
480 case Statement::kVarDeclarations_Kind: {
481 VarDeclarations& vd = *((VarDeclarationsStatement&) *stmt).fDeclaration;
482 for (auto varIter = vd.fVars.begin(); varIter != vd.fVars.end(); ) {
483 const auto& varDecl = **varIter;
484 if (varDecl.fVar->dead() &&
485 (!varDecl.fValue ||
486 !varDecl.fValue->hasSideEffects())) {
487 if (varDecl.fValue) {
488 ASSERT(iter->fKind == BasicBlock::Node::kStatement_Kind &&
489 iter->fStatement->get() == stmt);
490 if (!b.tryRemoveExpressionBefore(
491 &iter,
492 varDecl.fValue.get())) {
493 needsRescan = true;
494 }
495 }
496 varIter = vd.fVars.erase(varIter);
497 updated = true;
498 } else {
499 ++varIter;
500 }
501 }
502 if (vd.fVars.size() == 0) {
503 iter->fStatement->reset(new Nop());
504 }
505 break;
506 }
507 case Statement::kIf_Kind: {
508 IfStatement& i = (IfStatement&) *stmt;
509 if (i.fIfFalse && i.fIfFalse->isEmpty()) {
510 // else block doesn't do anything, remove it
511 i.fIfFalse.reset();
512 updated = true;
513 needsRescan = true;
514 }
515 if (!i.fIfFalse && i.fIfTrue->isEmpty()) {
516 // if block doesn't do anything, no else block
517 if (i.fTest->hasSideEffects()) {
518 // test has side effects, keep it
519 iter->fStatement->reset(new ExpressionStatement(
520 std::move(i.fTest)));
521 } else {
522 // no if, no else, no test side effects, kill the whole if
523 // statement
524 iter->fStatement->reset(new Nop());
525 }
526 updated = true;
527 needsRescan = true;
528 }
529 break;
530 }
531 case Statement::kExpression_Kind: {
532 ExpressionStatement& e = (ExpressionStatement&) *stmt;
533 ASSERT(iter->fStatement->get() == &e);
534 if (e.fExpression->fKind == Expression::kBinary_Kind) {
535 BinaryExpression& bin = (BinaryExpression&) *e.fExpression;
536 if (dead_assignment(bin)) {
537 if (!b.tryRemoveExpressionBefore(&iter, &bin)) {
538 needsRescan = true;
539 }
540 if (bin.fRight->hasSideEffects()) {
541 // still have to evaluate the right due to side effects,
542 // replace the binary expression with just the right side
543 e.fExpression = std::move(bin.fRight);
544 if (!b.tryInsertExpression(&iter, &e.fExpression)) {
545 needsRescan = true;
546 }
547 } else {
548 // no side effects, kill the whole statement
549 ASSERT(iter->fKind == BasicBlock::Node::kStatement_Kind &&
550 iter->fStatement->get() == stmt);
551 iter->fStatement->reset(new Nop());
552 }
553 updated = true;
554 break;
555 }
556 }
557 if (!e.fExpression->hasSideEffects()) {
558 // Expression statement with no side effects, kill it
559 if (!b.tryRemoveExpressionBefore(&iter, e.fExpression.get())) {
560 needsRescan = true;
561 }
562 ASSERT(iter->fKind == BasicBlock::Node::kStatement_Kind &&
563 iter->fStatement->get() == stmt);
564 iter->fStatement->reset(new Nop());
565 updated = true;
566 }
567 break;
568 }
569 default:
570 break;
571 }
572 }
573 this->addDefinitions(*iter, &definitions);
574 }
575 }
576 } while (updated);
577 ASSERT(!needsRescan);
ethannicholas22f939e2016-10-13 13:25:34 -0700578
579 // check for missing return
580 if (f.fDeclaration.fReturnType != *fContext.fVoid_Type) {
581 if (cfg.fBlocks[cfg.fExit].fEntrances.size()) {
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500582 this->error(f.fPosition, SkString("function can exit without returning a value"));
ethannicholas22f939e2016-10-13 13:25:34 -0700583 }
584 }
585}
586
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500587void Compiler::internalConvertProgram(SkString text,
ethannicholas5961bc92016-10-12 06:39:56 -0700588 Modifiers::Flag* defaultPrecision,
ethannicholasb3058bd2016-07-01 08:22:01 -0700589 std::vector<std::unique_ptr<ProgramElement>>* result) {
590 Parser parser(text, *fTypes, *this);
591 std::vector<std::unique_ptr<ASTDeclaration>> parsed = parser.file();
592 if (fErrorCount) {
593 return;
594 }
ethannicholas5961bc92016-10-12 06:39:56 -0700595 *defaultPrecision = Modifiers::kHighp_Flag;
ethannicholasb3058bd2016-07-01 08:22:01 -0700596 for (size_t i = 0; i < parsed.size(); i++) {
597 ASTDeclaration& decl = *parsed[i];
598 switch (decl.fKind) {
599 case ASTDeclaration::kVar_Kind: {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700600 std::unique_ptr<VarDeclarations> s = fIRGenerator->convertVarDeclarations(
Mike Klein6ad99092016-10-26 10:35:22 -0400601 (ASTVarDeclarations&) decl,
ethannicholasb3058bd2016-07-01 08:22:01 -0700602 Variable::kGlobal_Storage);
603 if (s) {
604 result->push_back(std::move(s));
605 }
606 break;
607 }
608 case ASTDeclaration::kFunction_Kind: {
609 std::unique_ptr<FunctionDefinition> f = fIRGenerator->convertFunction(
610 (ASTFunction&) decl);
ethannicholas22f939e2016-10-13 13:25:34 -0700611 if (!fErrorCount && f) {
612 this->scanCFG(*f);
ethannicholasb3058bd2016-07-01 08:22:01 -0700613 result->push_back(std::move(f));
614 }
615 break;
616 }
ethannicholas5961bc92016-10-12 06:39:56 -0700617 case ASTDeclaration::kModifiers_Kind: {
618 std::unique_ptr<ModifiersDeclaration> f = fIRGenerator->convertModifiersDeclaration(
619 (ASTModifiersDeclaration&) decl);
620 if (f) {
621 result->push_back(std::move(f));
622 }
623 break;
624 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700625 case ASTDeclaration::kInterfaceBlock_Kind: {
626 std::unique_ptr<InterfaceBlock> i = fIRGenerator->convertInterfaceBlock(
627 (ASTInterfaceBlock&) decl);
628 if (i) {
629 result->push_back(std::move(i));
630 }
631 break;
632 }
633 case ASTDeclaration::kExtension_Kind: {
634 std::unique_ptr<Extension> e = fIRGenerator->convertExtension((ASTExtension&) decl);
635 if (e) {
636 result->push_back(std::move(e));
637 }
638 break;
639 }
ethannicholas5961bc92016-10-12 06:39:56 -0700640 case ASTDeclaration::kPrecision_Kind: {
641 *defaultPrecision = ((ASTPrecision&) decl).fPrecision;
642 break;
643 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700644 default:
645 ABORT("unsupported declaration: %s\n", decl.description().c_str());
646 }
647 }
648}
649
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500650std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, SkString text,
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500651 const Program::Settings& settings) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700652 fErrorText = "";
653 fErrorCount = 0;
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500654 fIRGenerator->start(&settings);
ethannicholasd598f792016-07-25 10:08:54 -0700655 std::vector<std::unique_ptr<ProgramElement>> elements;
ethannicholas5961bc92016-10-12 06:39:56 -0700656 Modifiers::Flag ignored;
ethannicholasb3058bd2016-07-01 08:22:01 -0700657 switch (kind) {
658 case Program::kVertex_Kind:
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500659 this->internalConvertProgram(SkString(SKSL_VERT_INCLUDE), &ignored, &elements);
ethannicholasb3058bd2016-07-01 08:22:01 -0700660 break;
661 case Program::kFragment_Kind:
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500662 this->internalConvertProgram(SkString(SKSL_FRAG_INCLUDE), &ignored, &elements);
ethannicholasb3058bd2016-07-01 08:22:01 -0700663 break;
664 }
ethannicholasddb37d62016-10-20 09:54:00 -0700665 fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
ethannicholas5961bc92016-10-12 06:39:56 -0700666 Modifiers::Flag defaultPrecision;
667 this->internalConvertProgram(text, &defaultPrecision, &elements);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500668 auto result = std::unique_ptr<Program>(new Program(kind, settings, defaultPrecision, &fContext,
669 std::move(elements),
670 fIRGenerator->fSymbolTable,
671 fIRGenerator->fInputs));
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500672 fIRGenerator->finish();
ethannicholasb3058bd2016-07-01 08:22:01 -0700673 this->writeErrorCount();
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500674 if (fErrorCount) {
675 return nullptr;
676 }
677 return result;
678}
679
680
681bool Compiler::toSPIRV(const Program& program, SkWStream& out) {
682 SPIRVCodeGenerator cg(&fContext, &program, this, &out);
683 bool result = cg.generateCode();
684 this->writeErrorCount();
Ethan Nicholasce33f102016-12-09 17:22:59 -0500685 return result;
686}
687
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500688bool Compiler::toSPIRV(const Program& program, SkString* out) {
689 SkDynamicMemoryWStream buffer;
690 bool result = this->toSPIRV(program, buffer);
691 if (result) {
692 sk_sp<SkData> data(buffer.detachAsData());
693 *out = SkString((const char*) data->data(), data->size());
694 }
695 return result;
696}
697
698bool Compiler::toGLSL(const Program& program, SkWStream& out) {
699 GLSLCodeGenerator cg(&fContext, &program, this, &out);
700 bool result = cg.generateCode();
701 this->writeErrorCount();
702 return result;
703}
704
705bool Compiler::toGLSL(const Program& program, SkString* out) {
706 SkDynamicMemoryWStream buffer;
707 bool result = this->toGLSL(program, buffer);
708 if (result) {
709 sk_sp<SkData> data(buffer.detachAsData());
710 *out = SkString((const char*) data->data(), data->size());
711 }
712 return result;
713}
714
715
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500716void Compiler::error(Position position, SkString msg) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700717 fErrorCount++;
718 fErrorText += "error: " + position.description() + ": " + msg.c_str() + "\n";
719}
720
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500721SkString Compiler::errorText() {
722 SkString result = fErrorText;
ethannicholasb3058bd2016-07-01 08:22:01 -0700723 return result;
724}
725
726void Compiler::writeErrorCount() {
727 if (fErrorCount) {
728 fErrorText += to_string(fErrorCount) + " error";
729 if (fErrorCount > 1) {
730 fErrorText += "s";
731 }
732 fErrorText += "\n";
733 }
734}
735
ethannicholasb3058bd2016-07-01 08:22:01 -0700736} // namespace