• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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  */
7 
8 #include "SkSLCompiler.h"
9 
10 #include "SkSLCFGGenerator.h"
11 #include "SkSLCPPCodeGenerator.h"
12 #include "SkSLGLSLCodeGenerator.h"
13 #include "SkSLHCodeGenerator.h"
14 #include "SkSLIRGenerator.h"
15 #include "SkSLSPIRVCodeGenerator.h"
16 #include "ir/SkSLExpression.h"
17 #include "ir/SkSLExpressionStatement.h"
18 #include "ir/SkSLIntLiteral.h"
19 #include "ir/SkSLModifiersDeclaration.h"
20 #include "ir/SkSLNop.h"
21 #include "ir/SkSLSymbolTable.h"
22 #include "ir/SkSLTernaryExpression.h"
23 #include "ir/SkSLUnresolvedFunction.h"
24 #include "ir/SkSLVarDeclarations.h"
25 
26 #ifdef SK_ENABLE_SPIRV_VALIDATION
27 #include "spirv-tools/libspirv.hpp"
28 #endif
29 
30 #define STRINGIFY(x) #x
31 
32 // include the built-in shader symbols as static strings
33 
34 static const char* SKSL_INCLUDE =
35 #include "sksl.include"
36 ;
37 
38 static const char* SKSL_VERT_INCLUDE =
39 #include "sksl_vert.include"
40 ;
41 
42 static const char* SKSL_FRAG_INCLUDE =
43 #include "sksl_frag.include"
44 ;
45 
46 static const char* SKSL_GEOM_INCLUDE =
47 #include "sksl_geom.include"
48 ;
49 
50 static const char* SKSL_FP_INCLUDE =
51 #include "sksl_fp.include"
52 ;
53 
54 
55 namespace SkSL {
56 
Compiler(Flags flags)57 Compiler::Compiler(Flags flags)
58 : fFlags(flags)
59 , fErrorCount(0) {
60     auto types = std::shared_ptr<SymbolTable>(new SymbolTable(this));
61     auto symbols = std::shared_ptr<SymbolTable>(new SymbolTable(types, this));
62     fIRGenerator = new IRGenerator(&fContext, symbols, *this);
63     fTypes = types;
64     #define ADD_TYPE(t) types->addWithoutOwnership(fContext.f ## t ## _Type->fName, \
65                                                    fContext.f ## t ## _Type.get())
66     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);
88     types->addWithoutOwnership(String("mat2x2"), fContext.fMat2x2_Type.get());
89     ADD_TYPE(Mat2x3);
90     ADD_TYPE(Mat2x4);
91     ADD_TYPE(Mat3x2);
92     ADD_TYPE(Mat3x3);
93     types->addWithoutOwnership(String("mat3x3"), fContext.fMat3x3_Type.get());
94     ADD_TYPE(Mat3x4);
95     ADD_TYPE(Mat4x2);
96     ADD_TYPE(Mat4x3);
97     ADD_TYPE(Mat4x4);
98     types->addWithoutOwnership(String("mat4x4"), fContext.fMat4x4_Type.get());
99     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);
118     ADD_TYPE(SamplerExternalOES);
119     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 
128     ADD_TYPE(ISampler2D);
129 
130     ADD_TYPE(Image2D);
131     ADD_TYPE(IImage2D);
132 
133     ADD_TYPE(SubpassInput);
134     ADD_TYPE(SubpassInputMS);
135 
136     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);
157     ADD_TYPE(ColorSpaceXform);
158 
159     String skCapsName("sk_Caps");
160     Variable* skCaps = new Variable(Position(), Modifiers(), skCapsName,
161                                     *fContext.fSkCaps_Type, Variable::kGlobal_Storage);
162     fIRGenerator->fSymbolTable->add(skCapsName, std::unique_ptr<Symbol>(skCaps));
163 
164     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 
169     Modifiers::Flag ignored1;
170     std::vector<std::unique_ptr<ProgramElement>> ignored2;
171     fIRGenerator->convertProgram(String(SKSL_INCLUDE), *fTypes, &ignored1, &ignored2);
172     fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
173     ASSERT(!fErrorCount);
174 }
175 
~Compiler()176 Compiler::~Compiler() {
177     delete fIRGenerator;
178 }
179 
180 // add the definition created by assigning to the lvalue to the definition set
addDefinition(const Expression * lvalue,std::unique_ptr<Expression> * expr,DefinitionMap * definitions)181 void Compiler::addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr,
182                              DefinitionMap* definitions) {
183     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
195             // (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
197             // more complicated whole-program analysis. This is probably good enough.
198             this->addDefinition(((Swizzle*) lvalue)->fBase.get(),
199                                 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
200                                 definitions);
201             break;
202         case Expression::kIndex_Kind:
203             // see comments in Swizzle
204             this->addDefinition(((IndexExpression*) lvalue)->fBase.get(),
205                                 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
206                                 definitions);
207             break;
208         case Expression::kFieldAccess_Kind:
209             // see comments in Swizzle
210             this->addDefinition(((FieldAccess*) lvalue)->fBase.get(),
211                                 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
212                                 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
addDefinitions(const BasicBlock::Node & node,DefinitionMap * definitions)221 void Compiler::addDefinitions(const BasicBlock::Node& node,
222                               DefinitionMap* definitions) {
223     switch (node.fKind) {
224         case BasicBlock::Node::kExpression_Kind: {
225             ASSERT(node.expression());
226             const Expression* expr = (Expression*) node.expression()->get();
227             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;
240                 }
241                 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);
258                     }
259                     break;
260                 }
261                 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                 }
270                 default:
271                     break;
272             }
273             break;
274         }
275         case BasicBlock::Node::kStatement_Kind: {
276             const Statement* stmt = (Statement*) node.statement()->get();
277             if (stmt->fKind == Statement::kVarDeclaration_Kind) {
278                 VarDeclaration& vd = (VarDeclaration&) *stmt;
279                 if (vd.fValue) {
280                     (*definitions)[vd.fVar] = &vd.fValue;
281                 }
282             }
283             break;
284         }
285     }
286 }
287 
scanCFG(CFG * cfg,BlockId blockId,std::set<BlockId> * workList)288 void Compiler::scanCFG(CFG* cfg, BlockId blockId, std::set<BlockId>* workList) {
289     BasicBlock& block = cfg->fBlocks[blockId];
290 
291     // compute definitions after this block
292     DefinitionMap after = block.fBefore;
293     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) {
301             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);
306                 exit.fBefore[pair.first] = e1;
307             } else {
308                 // exit has a (possibly different) value already defined
309                 std::unique_ptr<Expression>* e2 = exit.fBefore[pair.first];
310                 if (e1 != e2) {
311                     // definition has changed, merge and add exit block to worklist
312                     workList->insert(exitId);
313                     if (e1 && e2) {
314                         exit.fBefore[pair.first] =
315                                        (std::unique_ptr<Expression>*) &fContext.fDefined_Expression;
316                     } else {
317                         exit.fBefore[pair.first] = nullptr;
318                     }
319                 }
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
compute_start_state(const CFG & cfg)327 static DefinitionMap compute_start_state(const CFG& cfg) {
328     DefinitionMap result;
329     for (const auto& block : cfg.fBlocks) {
330         for (const auto& node : block.fNodes) {
331             if (node.fKind == BasicBlock::Node::kStatement_Kind) {
332                 ASSERT(node.statement());
333                 const Statement* s = node.statement()->get();
334                 if (s->fKind == Statement::kVarDeclarations_Kind) {
335                     const VarDeclarationsStatement* vd = (const VarDeclarationsStatement*) s;
336                     for (const auto& decl : vd->fDeclaration->fVars) {
337                         if (decl->fKind == Statement::kVarDeclaration_Kind) {
338                             result[((VarDeclaration&) *decl).fVar] = nullptr;
339                         }
340                     }
341                 }
342             }
343         }
344     }
345     return result;
346 }
347 
348 /**
349  * Returns true if assigning to this lvalue has no effect.
350  */
is_dead(const Expression & lvalue)351 static 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 }
367 
368 /**
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  */
dead_assignment(const BinaryExpression & b)372 static bool dead_assignment(const BinaryExpression& b) {
373     if (!Token::IsAssignment(b.fOperator)) {
374         return false;
375     }
376     return is_dead(*b.fLeft);
377 }
378 
computeDataFlow(CFG * cfg)379 void Compiler::computeDataFlow(CFG* cfg) {
380     cfg->fBlocks[cfg->fStart].fBefore = compute_start_state(*cfg);
381     std::set<BlockId> workList;
382     for (BlockId i = 0; i < cfg->fBlocks.size(); i++) {
383         workList.insert(i);
384     }
385     while (workList.size()) {
386         BlockId next = *workList.begin();
387         workList.erase(workList.begin());
388         this->scanCFG(cfg, next, &workList);
389     }
390 }
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  */
try_replace_expression(BasicBlock * b,std::vector<BasicBlock::Node>::iterator * iter,std::unique_ptr<Expression> * newExpression)398 bool 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 /**
411  * 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.
413  */
is_constant(const Expression & expr,double value)414 bool is_constant(const Expression& expr, double value) {
415     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;
420         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         }
432         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  */
delete_left(BasicBlock * b,std::vector<BasicBlock::Node>::iterator * iter,bool * outUpdated,bool * outNeedsRescan)441 void delete_left(BasicBlock* b,
442                  std::vector<BasicBlock::Node>::iterator* iter,
443                  bool* outUpdated,
444                  bool* outNeedsRescan) {
445     *outUpdated = true;
446     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) {
451         result = b->tryRemoveLValueBefore(iter, bin.fLeft.get());
452     } else {
453         result = b->tryRemoveExpressionBefore(iter, bin.fLeft.get());
454     }
455     *target = std::move(bin.fRight);
456     if (!result) {
457         *outNeedsRescan = true;
458         return;
459     }
460     if (*iter == b->fNodes.begin()) {
461         *outNeedsRescan = true;
462         return;
463     }
464     --(*iter);
465     if ((*iter)->fKind != BasicBlock::Node::kExpression_Kind ||
466         (*iter)->expression() != &bin.fRight) {
467         *outNeedsRescan = true;
468         return;
469     }
470     *iter = b->fNodes.erase(*iter);
471     ASSERT((*iter)->expression() == target);
472 }
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  */
delete_right(BasicBlock * b,std::vector<BasicBlock::Node>::iterator * iter,bool * outUpdated,bool * outNeedsRescan)478 void delete_right(BasicBlock* b,
479                   std::vector<BasicBlock::Node>::iterator* iter,
480                   bool* outUpdated,
481                   bool* outNeedsRescan) {
482     *outUpdated = true;
483     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);
488         *outNeedsRescan = true;
489         return;
490     }
491     *target = std::move(bin.fLeft);
492     if (*iter == b->fNodes.begin()) {
493         *outNeedsRescan = true;
494         return;
495     }
496     --(*iter);
497     if (((*iter)->fKind != BasicBlock::Node::kExpression_Kind ||
498         (*iter)->expression() != &bin.fLeft)) {
499         *outNeedsRescan = true;
500         return;
501     }
502     *iter = b->fNodes.erase(*iter);
503     ASSERT((*iter)->expression() == target);
504 }
505 
506 /**
507  * Constructs the specified type using a single argument.
508  */
construct(const Type & type,std::unique_ptr<Expression> v)509 static 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  */
vectorize(BasicBlock * b,std::vector<BasicBlock::Node>::iterator * iter,const Type & type,std::unique_ptr<Expression> * otherExpression,bool * outUpdated,bool * outNeedsRescan)520 static 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  */
vectorize_left(BasicBlock * b,std::vector<BasicBlock::Node>::iterator * iter,bool * outUpdated,bool * outNeedsRescan)546 static 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  */
vectorize_right(BasicBlock * b,std::vector<BasicBlock::Node>::iterator * iter,bool * outUpdated,bool * outNeedsRescan)558 static 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
clear_write(const Expression & expr)567 void 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 
simplifyExpression(DefinitionMap & definitions,BasicBlock & b,std::vector<BasicBlock::Node>::iterator * iter,std::unordered_set<const Variable * > * undefinedVariables,bool * outUpdated,bool * outNeedsRescan)588 void 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) {
599             *outUpdated = true;
600             if (!try_replace_expression(&b, iter, &optimized)) {
601                 *outNeedsRescan = true;
602                 return;
603             }
604             ASSERT((*iter)->fKind == BasicBlock::Node::kExpression_Kind);
605             expr = (*iter)->expression()->get();
606         }
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: {
635             BinaryExpression* bin = (BinaryExpression*) expr;
636             if (dead_assignment(*bin)) {
637                 delete_left(&b, iter, outUpdated, outNeedsRescan);
638                 break;
639             }
640             // collapse useless expressions like x * 1 or x + 0
641             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             }
647             switch (bin->fOperator) {
648                 case Token::STAR:
649                     if (is_constant(*bin->fLeft, 1)) {
650                         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                         }
672                     }
673                     else if (is_constant(*bin->fRight, 1)) {
674                         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                         }
696                     }
697                     break;
698                 case Token::PLUS:
699                     if (is_constant(*bin->fLeft, 0)) {
700                         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                         }
721                     }
722                     break;
723                 case Token::MINUS:
724                     if (is_constant(*bin->fRight, 0)) {
725                         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                         }
735                     }
736                     break;
737                 case Token::SLASH:
738                     if (is_constant(*bin->fRight, 1)) {
739                         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);
783                         delete_right(&b, iter, outUpdated, outNeedsRescan);
784                     }
785                     break;
786                 default:
787                     break;
788             }
789         }
790         default:
791             break;
792     }
793 }
794 
795 // 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)
contains_break(Statement & s)797 static 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.
block_for_case(SwitchStatement * s,SwitchCase * c)822 static 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), s->fSymbols));
850 }
851 
simplifyStatement(DefinitionMap & definitions,BasicBlock & b,std::vector<BasicBlock::Node>::iterator * iter,std::unordered_set<const Variable * > * undefinedVariables,bool * outUpdated,bool * outNeedsRescan)852 void Compiler::simplifyStatement(DefinitionMap& definitions,
853                                  BasicBlock& b,
854                                  std::vector<BasicBlock::Node>::iterator* iter,
855                                  std::unordered_set<const Variable*>* undefinedVariables,
856                                  bool* outUpdated,
857                                  bool* outNeedsRescan) {
858     Statement* stmt = (*iter)->statement()->get();
859     switch (stmt->fKind) {
860         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;
869                     }
870                 }
871                 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
872                 *outUpdated = true;
873             }
874             break;
875         }
876         case Statement::kIf_Kind: {
877             IfStatement& i = (IfStatement&) *stmt;
878             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             }
894             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         }
916         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 {
935                             if (s.fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) {
936                                 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 {
951                             if (s.fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) {
952                                 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         }
967         case Statement::kExpression_Kind: {
968             ExpressionStatement& e = (ExpressionStatement&) *stmt;
969             ASSERT((*iter)->statement()->get() == &e);
970             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 
scanCFG(FunctionDefinition & f)986 void Compiler::scanCFG(FunctionDefinition& f) {
987     CFG cfg = CFGGenerator().getCFG(f);
988     this->computeDataFlow(&cfg);
989 
990     // check for unreachable code
991     for (size_t i = 0; i < cfg.fBlocks.size(); i++) {
992         if (i != cfg.fStart && !cfg.fBlocks[i].fEntrances.size() &&
993             cfg.fBlocks[i].fNodes.size()) {
994             Position p;
995             switch (cfg.fBlocks[i].fNodes[0].fKind) {
996                 case BasicBlock::Node::kStatement_Kind:
997                     p = (*cfg.fBlocks[i].fNodes[0].statement())->fPosition;
998                     break;
999                 case BasicBlock::Node::kExpression_Kind:
1000                     p = (*cfg.fBlocks[i].fNodes[0].expression())->fPosition;
1001                     break;
1002             }
1003             this->error(p, String("unreachable"));
1004         }
1005     }
1006     if (fErrorCount) {
1007         return;
1008     }
1009 
1010     // 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;
1019         }
1020 
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                 }
1033                 if (needsRescan) {
1034                     break;
1035                 }
1036                 this->addDefinitions(*iter, &definitions);
1037             }
1038         }
1039     } while (updated);
1040     ASSERT(!needsRescan);
1041 
1042     // verify static ifs & switches, clean up dead variable decls
1043     for (BasicBlock& b : cfg.fBlocks) {
1044         DefinitionMap definitions = b.fBefore;
1045 
1046         for (auto iter = b.fNodes.begin(); iter != b.fNodes.end() && !needsRescan;) {
1047             if (iter->fKind == BasicBlock::Node::kStatement_Kind) {
1048                 const Statement& s = **iter->statement();
1049                 switch (s.fKind) {
1050                     case Statement::kIf_Kind:
1051                         if (((const IfStatement&) s).fIsStatic &&
1052                             !(fFlags & kPermitInvalidStaticTests_Flag)) {
1053                             this->error(s.fPosition, "static if has non-static test");
1054                         }
1055                         ++iter;
1056                         break;
1057                     case Statement::kSwitch_Kind:
1058                         if (((const SwitchStatement&) s).fIsStatic &&
1059                              !(fFlags & kPermitInvalidStaticTests_Flag)) {
1060                             this->error(s.fPosition, "static switch has non-static test");
1061                         }
1062                         ++iter;
1063                         break;
1064                     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                     }
1080                     default:
1081                         ++iter;
1082                         break;
1083                 }
1084             } else {
1085                 ++iter;
1086             }
1087         }
1088     }
1089 
1090     // check for missing return
1091     if (f.fDeclaration.fReturnType != *fContext.fVoid_Type) {
1092         if (cfg.fBlocks[cfg.fExit].fEntrances.size()) {
1093             this->error(f.fPosition, String("function can exit without returning a value"));
1094         }
1095     }
1096 }
1097 
convertProgram(Program::Kind kind,String text,const Program::Settings & settings)1098 std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String text,
1099                                                   const Program::Settings& settings) {
1100     fErrorText = "";
1101     fErrorCount = 0;
1102     fIRGenerator->start(&settings);
1103     std::vector<std::unique_ptr<ProgramElement>> elements;
1104     Modifiers::Flag ignored;
1105     switch (kind) {
1106         case Program::kVertex_Kind:
1107             fIRGenerator->convertProgram(String(SKSL_VERT_INCLUDE), *fTypes, &ignored, &elements);
1108             break;
1109         case Program::kFragment_Kind:
1110             fIRGenerator->convertProgram(String(SKSL_FRAG_INCLUDE), *fTypes, &ignored, &elements);
1111             break;
1112         case Program::kGeometry_Kind:
1113             fIRGenerator->convertProgram(String(SKSL_GEOM_INCLUDE), *fTypes, &ignored, &elements);
1114             break;
1115         case Program::kFragmentProcessor_Kind:
1116             fIRGenerator->convertProgram(String(SKSL_FP_INCLUDE), *fTypes, &ignored, &elements);
1117             break;
1118     }
1119     fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
1120     Modifiers::Flag defaultPrecision;
1121     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     }
1129     auto result = std::unique_ptr<Program>(new Program(kind, settings, defaultPrecision, &fContext,
1130                                                        std::move(elements),
1131                                                        fIRGenerator->fSymbolTable,
1132                                                        fIRGenerator->fInputs));
1133     fIRGenerator->finish();
1134     this->writeErrorCount();
1135     if (fErrorCount) {
1136         return nullptr;
1137     }
1138     return result;
1139 }
1140 
toSPIRV(const Program & program,OutputStream & out)1141 bool Compiler::toSPIRV(const Program& program, OutputStream& out) {
1142 #ifdef SK_ENABLE_SPIRV_VALIDATION
1143     StringStream buffer;
1144     SPIRVCodeGenerator cg(&fContext, &program, this, &buffer);
1145     bool result = cg.generateCode();
1146     if (result) {
1147         spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0);
1148         const String& data = buffer.str();
1149         ASSERT(0 == data.size() % 4);
1150         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.
1156         ASSERT_RESULT(tools.Validate((const uint32_t*) data.c_str(), data.size() / 4));
1157         out.write(data.c_str(), data.size());
1158     }
1159 #else
1160     SPIRVCodeGenerator cg(&fContext, &program, this, &out);
1161     bool result = cg.generateCode();
1162 #endif
1163     this->writeErrorCount();
1164     return result;
1165 }
1166 
toSPIRV(const Program & program,String * out)1167 bool Compiler::toSPIRV(const Program& program, String* out) {
1168     StringStream buffer;
1169     bool result = this->toSPIRV(program, buffer);
1170     if (result) {
1171         *out = buffer.str();
1172     }
1173     return result;
1174 }
1175 
toGLSL(const Program & program,OutputStream & out)1176 bool Compiler::toGLSL(const Program& program, OutputStream& out) {
1177     GLSLCodeGenerator cg(&fContext, &program, this, &out);
1178     bool result = cg.generateCode();
1179     this->writeErrorCount();
1180     return result;
1181 }
1182 
toGLSL(const Program & program,String * out)1183 bool Compiler::toGLSL(const Program& program, String* out) {
1184     StringStream buffer;
1185     bool result = this->toGLSL(program, buffer);
1186     if (result) {
1187         *out = buffer.str();
1188     }
1189     return result;
1190 }
1191 
toCPP(const Program & program,String name,OutputStream & out)1192 bool 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 
toH(const Program & program,String name,OutputStream & out)1199 bool 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 }
1205 
error(Position position,String msg)1206 void Compiler::error(Position position, String msg) {
1207     fErrorCount++;
1208     fErrorText += "error: " + position.description() + ": " + msg.c_str() + "\n";
1209 }
1210 
errorText()1211 String Compiler::errorText() {
1212     String result = fErrorText;
1213     return result;
1214 }
1215 
writeErrorCount()1216 void 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 
1226 } // namespace
1227