• Home
  • History
  • Annotate
  • 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 "ast/SkSLASTPrecision.h"
11 #include "SkSLCFGGenerator.h"
12 #include "SkSLGLSLCodeGenerator.h"
13 #include "SkSLIRGenerator.h"
14 #include "SkSLParser.h"
15 #include "SkSLSPIRVCodeGenerator.h"
16 #include "ir/SkSLExpression.h"
17 #include "ir/SkSLIntLiteral.h"
18 #include "ir/SkSLModifiersDeclaration.h"
19 #include "ir/SkSLSymbolTable.h"
20 #include "ir/SkSLUnresolvedFunction.h"
21 #include "ir/SkSLVarDeclarations.h"
22 #include "SkMutex.h"
23 
24 #ifdef SK_ENABLE_SPIRV_VALIDATION
25 #include "spirv-tools/libspirv.hpp"
26 #endif
27 
28 #define STRINGIFY(x) #x
29 
30 // include the built-in shader symbols as static strings
31 
32 static const char* SKSL_INCLUDE =
33 #include "sksl.include"
34 ;
35 
36 static const char* SKSL_VERT_INCLUDE =
37 #include "sksl_vert.include"
38 ;
39 
40 static const char* SKSL_FRAG_INCLUDE =
41 #include "sksl_frag.include"
42 ;
43 
44 static const char* SKSL_GEOM_INCLUDE =
45 #include "sksl_geom.include"
46 ;
47 
48 namespace SkSL {
49 
Compiler()50 Compiler::Compiler()
51 : fErrorCount(0) {
52     auto types = std::shared_ptr<SymbolTable>(new SymbolTable(*this));
53     auto symbols = std::shared_ptr<SymbolTable>(new SymbolTable(types, *this));
54     fIRGenerator = new IRGenerator(&fContext, symbols, *this);
55     fTypes = types;
56     #define ADD_TYPE(t) types->addWithoutOwnership(fContext.f ## t ## _Type->fName, \
57                                                    fContext.f ## t ## _Type.get())
58     ADD_TYPE(Void);
59     ADD_TYPE(Float);
60     ADD_TYPE(Vec2);
61     ADD_TYPE(Vec3);
62     ADD_TYPE(Vec4);
63     ADD_TYPE(Double);
64     ADD_TYPE(DVec2);
65     ADD_TYPE(DVec3);
66     ADD_TYPE(DVec4);
67     ADD_TYPE(Int);
68     ADD_TYPE(IVec2);
69     ADD_TYPE(IVec3);
70     ADD_TYPE(IVec4);
71     ADD_TYPE(UInt);
72     ADD_TYPE(UVec2);
73     ADD_TYPE(UVec3);
74     ADD_TYPE(UVec4);
75     ADD_TYPE(Bool);
76     ADD_TYPE(BVec2);
77     ADD_TYPE(BVec3);
78     ADD_TYPE(BVec4);
79     ADD_TYPE(Mat2x2);
80     types->addWithoutOwnership(SkString("mat2x2"), fContext.fMat2x2_Type.get());
81     ADD_TYPE(Mat2x3);
82     ADD_TYPE(Mat2x4);
83     ADD_TYPE(Mat3x2);
84     ADD_TYPE(Mat3x3);
85     types->addWithoutOwnership(SkString("mat3x3"), fContext.fMat3x3_Type.get());
86     ADD_TYPE(Mat3x4);
87     ADD_TYPE(Mat4x2);
88     ADD_TYPE(Mat4x3);
89     ADD_TYPE(Mat4x4);
90     types->addWithoutOwnership(SkString("mat4x4"), fContext.fMat4x4_Type.get());
91     ADD_TYPE(GenType);
92     ADD_TYPE(GenDType);
93     ADD_TYPE(GenIType);
94     ADD_TYPE(GenUType);
95     ADD_TYPE(GenBType);
96     ADD_TYPE(Mat);
97     ADD_TYPE(Vec);
98     ADD_TYPE(GVec);
99     ADD_TYPE(GVec2);
100     ADD_TYPE(GVec3);
101     ADD_TYPE(GVec4);
102     ADD_TYPE(DVec);
103     ADD_TYPE(IVec);
104     ADD_TYPE(UVec);
105     ADD_TYPE(BVec);
106 
107     ADD_TYPE(Sampler1D);
108     ADD_TYPE(Sampler2D);
109     ADD_TYPE(Sampler3D);
110     ADD_TYPE(SamplerExternalOES);
111     ADD_TYPE(SamplerCube);
112     ADD_TYPE(Sampler2DRect);
113     ADD_TYPE(Sampler1DArray);
114     ADD_TYPE(Sampler2DArray);
115     ADD_TYPE(SamplerCubeArray);
116     ADD_TYPE(SamplerBuffer);
117     ADD_TYPE(Sampler2DMS);
118     ADD_TYPE(Sampler2DMSArray);
119 
120     ADD_TYPE(ISampler2D);
121 
122     ADD_TYPE(Image2D);
123     ADD_TYPE(IImage2D);
124 
125     ADD_TYPE(SubpassInput);
126     ADD_TYPE(SubpassInputMS);
127 
128     ADD_TYPE(GSampler1D);
129     ADD_TYPE(GSampler2D);
130     ADD_TYPE(GSampler3D);
131     ADD_TYPE(GSamplerCube);
132     ADD_TYPE(GSampler2DRect);
133     ADD_TYPE(GSampler1DArray);
134     ADD_TYPE(GSampler2DArray);
135     ADD_TYPE(GSamplerCubeArray);
136     ADD_TYPE(GSamplerBuffer);
137     ADD_TYPE(GSampler2DMS);
138     ADD_TYPE(GSampler2DMSArray);
139 
140     ADD_TYPE(Sampler1DShadow);
141     ADD_TYPE(Sampler2DShadow);
142     ADD_TYPE(SamplerCubeShadow);
143     ADD_TYPE(Sampler2DRectShadow);
144     ADD_TYPE(Sampler1DArrayShadow);
145     ADD_TYPE(Sampler2DArrayShadow);
146     ADD_TYPE(SamplerCubeArrayShadow);
147     ADD_TYPE(GSampler2DArrayShadow);
148     ADD_TYPE(GSamplerCubeArrayShadow);
149 
150     SkString skCapsName("sk_Caps");
151     Variable* skCaps = new Variable(Position(), Modifiers(), skCapsName,
152                                     *fContext.fSkCaps_Type, Variable::kGlobal_Storage);
153     fIRGenerator->fSymbolTable->add(skCapsName, std::unique_ptr<Symbol>(skCaps));
154 
155     Modifiers::Flag ignored1;
156     std::vector<std::unique_ptr<ProgramElement>> ignored2;
157     this->internalConvertProgram(SkString(SKSL_INCLUDE), &ignored1, &ignored2);
158     fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
159     ASSERT(!fErrorCount);
160 }
161 
~Compiler()162 Compiler::~Compiler() {
163     delete fIRGenerator;
164 }
165 
166 // add the definition created by assigning to the lvalue to the definition set
addDefinition(const Expression * lvalue,std::unique_ptr<Expression> * expr,DefinitionMap * definitions)167 void Compiler::addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr,
168                              DefinitionMap* definitions) {
169     switch (lvalue->fKind) {
170         case Expression::kVariableReference_Kind: {
171             const Variable& var = ((VariableReference*) lvalue)->fVariable;
172             if (var.fStorage == Variable::kLocal_Storage) {
173                 (*definitions)[&var] = expr;
174             }
175             break;
176         }
177         case Expression::kSwizzle_Kind:
178             // We consider the variable written to as long as at least some of its components have
179             // been written to. This will lead to some false negatives (we won't catch it if you
180             // write to foo.x and then read foo.y), but being stricter could lead to false positives
181             // (we write to foo.x, and then pass foo to a function which happens to only read foo.x,
182             // but since we pass foo as a whole it is flagged as an error) unless we perform a much
183             // more complicated whole-program analysis. This is probably good enough.
184             this->addDefinition(((Swizzle*) lvalue)->fBase.get(),
185                                 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
186                                 definitions);
187             break;
188         case Expression::kIndex_Kind:
189             // see comments in Swizzle
190             this->addDefinition(((IndexExpression*) lvalue)->fBase.get(),
191                                 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
192                                 definitions);
193             break;
194         case Expression::kFieldAccess_Kind:
195             // see comments in Swizzle
196             this->addDefinition(((FieldAccess*) lvalue)->fBase.get(),
197                                 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
198                                 definitions);
199             break;
200         default:
201             // not an lvalue, can't happen
202             ASSERT(false);
203     }
204 }
205 
206 // add local variables defined by this node to the set
addDefinitions(const BasicBlock::Node & node,DefinitionMap * definitions)207 void Compiler::addDefinitions(const BasicBlock::Node& node,
208                               DefinitionMap* definitions) {
209     switch (node.fKind) {
210         case BasicBlock::Node::kExpression_Kind: {
211             ASSERT(node.fExpression);
212             const Expression* expr = (Expression*) node.fExpression->get();
213             switch (expr->fKind) {
214                 case Expression::kBinary_Kind: {
215                     BinaryExpression* b = (BinaryExpression*) expr;
216                     if (b->fOperator == Token::EQ) {
217                         this->addDefinition(b->fLeft.get(), &b->fRight, definitions);
218                     } else if (Token::IsAssignment(b->fOperator)) {
219                         this->addDefinition(
220                                        b->fLeft.get(),
221                                        (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
222                                        definitions);
223 
224                     }
225                     break;
226                 }
227                 case Expression::kPrefix_Kind: {
228                     const PrefixExpression* p = (PrefixExpression*) expr;
229                     if (p->fOperator == Token::MINUSMINUS || p->fOperator == Token::PLUSPLUS) {
230                         this->addDefinition(
231                                        p->fOperand.get(),
232                                        (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
233                                        definitions);
234                     }
235                     break;
236                 }
237                 case Expression::kPostfix_Kind: {
238                     const PostfixExpression* p = (PostfixExpression*) expr;
239                     if (p->fOperator == Token::MINUSMINUS || p->fOperator == Token::PLUSPLUS) {
240                         this->addDefinition(
241                                        p->fOperand.get(),
242                                        (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
243                                        definitions);
244 
245                     }
246                     break;
247                 }
248                 default:
249                     break;
250             }
251             break;
252         }
253         case BasicBlock::Node::kStatement_Kind: {
254             const Statement* stmt = (Statement*) node.fStatement;
255             if (stmt->fKind == Statement::kVarDeclarations_Kind) {
256                 VarDeclarationsStatement* vd = (VarDeclarationsStatement*) stmt;
257                 for (VarDeclaration& decl : vd->fDeclaration->fVars) {
258                     if (decl.fValue) {
259                         (*definitions)[decl.fVar] = &decl.fValue;
260                     }
261                 }
262             }
263             break;
264         }
265     }
266 }
267 
scanCFG(CFG * cfg,BlockId blockId,std::set<BlockId> * workList)268 void Compiler::scanCFG(CFG* cfg, BlockId blockId, std::set<BlockId>* workList) {
269     BasicBlock& block = cfg->fBlocks[blockId];
270 
271     // compute definitions after this block
272     DefinitionMap after = block.fBefore;
273     for (const BasicBlock::Node& n : block.fNodes) {
274         this->addDefinitions(n, &after);
275     }
276 
277     // propagate definitions to exits
278     for (BlockId exitId : block.fExits) {
279         BasicBlock& exit = cfg->fBlocks[exitId];
280         for (const auto& pair : after) {
281             std::unique_ptr<Expression>* e1 = pair.second;
282             auto found = exit.fBefore.find(pair.first);
283             if (found == exit.fBefore.end()) {
284                 // exit has no definition for it, just copy it
285                 workList->insert(exitId);
286                 exit.fBefore[pair.first] = e1;
287             } else {
288                 // exit has a (possibly different) value already defined
289                 std::unique_ptr<Expression>* e2 = exit.fBefore[pair.first];
290                 if (e1 != e2) {
291                     // definition has changed, merge and add exit block to worklist
292                     workList->insert(exitId);
293                     if (e1 && e2) {
294                         exit.fBefore[pair.first] =
295                                        (std::unique_ptr<Expression>*) &fContext.fDefined_Expression;
296                     } else {
297                         exit.fBefore[pair.first] = nullptr;
298                     }
299                 }
300             }
301         }
302     }
303 }
304 
305 // returns a map which maps all local variables in the function to null, indicating that their value
306 // is initially unknown
compute_start_state(const CFG & cfg)307 static DefinitionMap compute_start_state(const CFG& cfg) {
308     DefinitionMap result;
309     for (const auto& block : cfg.fBlocks) {
310         for (const auto& node : block.fNodes) {
311             if (node.fKind == BasicBlock::Node::kStatement_Kind) {
312                 ASSERT(node.fStatement);
313                 const Statement* s = node.fStatement;
314                 if (s->fKind == Statement::kVarDeclarations_Kind) {
315                     const VarDeclarationsStatement* vd = (const VarDeclarationsStatement*) s;
316                     for (const VarDeclaration& decl : vd->fDeclaration->fVars) {
317                         result[decl.fVar] = nullptr;
318                     }
319                 }
320             }
321         }
322     }
323     return result;
324 }
325 
scanCFG(const FunctionDefinition & f)326 void Compiler::scanCFG(const FunctionDefinition& f) {
327     CFG cfg = CFGGenerator().getCFG(f);
328 
329     // compute the data flow
330     cfg.fBlocks[cfg.fStart].fBefore = compute_start_state(cfg);
331     std::set<BlockId> workList;
332     for (BlockId i = 0; i < cfg.fBlocks.size(); i++) {
333         workList.insert(i);
334     }
335     while (workList.size()) {
336         BlockId next = *workList.begin();
337         workList.erase(workList.begin());
338         this->scanCFG(&cfg, next, &workList);
339     }
340 
341     // check for unreachable code
342     for (size_t i = 0; i < cfg.fBlocks.size(); i++) {
343         if (i != cfg.fStart && !cfg.fBlocks[i].fEntrances.size() &&
344             cfg.fBlocks[i].fNodes.size()) {
345             Position p;
346             switch (cfg.fBlocks[i].fNodes[0].fKind) {
347                 case BasicBlock::Node::kStatement_Kind:
348                     p = cfg.fBlocks[i].fNodes[0].fStatement->fPosition;
349                     break;
350                 case BasicBlock::Node::kExpression_Kind:
351                     p = (*cfg.fBlocks[i].fNodes[0].fExpression)->fPosition;
352                     break;
353             }
354             this->error(p, SkString("unreachable"));
355         }
356     }
357     if (fErrorCount) {
358         return;
359     }
360 
361     // check for undefined variables, perform constant propagation
362     for (BasicBlock& b : cfg.fBlocks) {
363         DefinitionMap definitions = b.fBefore;
364         for (BasicBlock::Node& n : b.fNodes) {
365             if (n.fKind == BasicBlock::Node::kExpression_Kind) {
366                 ASSERT(n.fExpression);
367                 Expression* expr = n.fExpression->get();
368                 if (n.fConstantPropagation) {
369                     std::unique_ptr<Expression> optimized = expr->constantPropagate(*fIRGenerator,
370                                                                                     definitions);
371                     if (optimized) {
372                         n.fExpression->reset(optimized.release());
373                         expr = n.fExpression->get();
374                     }
375                 }
376                 if (expr->fKind == Expression::kVariableReference_Kind) {
377                     const Variable& var = ((VariableReference*) expr)->fVariable;
378                     if (var.fStorage == Variable::kLocal_Storage &&
379                         !definitions[&var]) {
380                         this->error(expr->fPosition,
381                                     "'" + var.fName + "' has not been assigned");
382                     }
383                 }
384             }
385             this->addDefinitions(n, &definitions);
386         }
387     }
388 
389     // check for missing return
390     if (f.fDeclaration.fReturnType != *fContext.fVoid_Type) {
391         if (cfg.fBlocks[cfg.fExit].fEntrances.size()) {
392             this->error(f.fPosition, SkString("function can exit without returning a value"));
393         }
394     }
395 }
396 
internalConvertProgram(SkString text,Modifiers::Flag * defaultPrecision,std::vector<std::unique_ptr<ProgramElement>> * result)397 void Compiler::internalConvertProgram(SkString text,
398                                       Modifiers::Flag* defaultPrecision,
399                                       std::vector<std::unique_ptr<ProgramElement>>* result) {
400     Parser parser(text, *fTypes, *this);
401     std::vector<std::unique_ptr<ASTDeclaration>> parsed = parser.file();
402     if (fErrorCount) {
403         return;
404     }
405     *defaultPrecision = Modifiers::kHighp_Flag;
406     for (size_t i = 0; i < parsed.size(); i++) {
407         ASTDeclaration& decl = *parsed[i];
408         switch (decl.fKind) {
409             case ASTDeclaration::kVar_Kind: {
410                 std::unique_ptr<VarDeclarations> s = fIRGenerator->convertVarDeclarations(
411                                                                          (ASTVarDeclarations&) decl,
412                                                                          Variable::kGlobal_Storage);
413                 if (s) {
414                     result->push_back(std::move(s));
415                 }
416                 break;
417             }
418             case ASTDeclaration::kFunction_Kind: {
419                 std::unique_ptr<FunctionDefinition> f = fIRGenerator->convertFunction(
420                                                                                (ASTFunction&) decl);
421                 if (!fErrorCount && f) {
422                     this->scanCFG(*f);
423                     result->push_back(std::move(f));
424                 }
425                 break;
426             }
427             case ASTDeclaration::kModifiers_Kind: {
428                 std::unique_ptr<ModifiersDeclaration> f = fIRGenerator->convertModifiersDeclaration(
429                                                                    (ASTModifiersDeclaration&) decl);
430                 if (f) {
431                     result->push_back(std::move(f));
432                 }
433                 break;
434             }
435             case ASTDeclaration::kInterfaceBlock_Kind: {
436                 std::unique_ptr<InterfaceBlock> i = fIRGenerator->convertInterfaceBlock(
437                                                                          (ASTInterfaceBlock&) decl);
438                 if (i) {
439                     result->push_back(std::move(i));
440                 }
441                 break;
442             }
443             case ASTDeclaration::kExtension_Kind: {
444                 std::unique_ptr<Extension> e = fIRGenerator->convertExtension((ASTExtension&) decl);
445                 if (e) {
446                     result->push_back(std::move(e));
447                 }
448                 break;
449             }
450             case ASTDeclaration::kPrecision_Kind: {
451                 *defaultPrecision = ((ASTPrecision&) decl).fPrecision;
452                 break;
453             }
454             default:
455                 ABORT("unsupported declaration: %s\n", decl.description().c_str());
456         }
457     }
458 }
459 
convertProgram(Program::Kind kind,SkString text,const Program::Settings & settings)460 std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, SkString text,
461                                                   const Program::Settings& settings) {
462     fErrorText = "";
463     fErrorCount = 0;
464     fIRGenerator->start(&settings);
465     std::vector<std::unique_ptr<ProgramElement>> elements;
466     Modifiers::Flag ignored;
467     switch (kind) {
468         case Program::kVertex_Kind:
469             this->internalConvertProgram(SkString(SKSL_VERT_INCLUDE), &ignored, &elements);
470             break;
471         case Program::kFragment_Kind:
472             this->internalConvertProgram(SkString(SKSL_FRAG_INCLUDE), &ignored, &elements);
473             break;
474         case Program::kGeometry_Kind:
475             this->internalConvertProgram(SkString(SKSL_GEOM_INCLUDE), &ignored, &elements);
476             break;
477     }
478     fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
479     Modifiers::Flag defaultPrecision;
480     this->internalConvertProgram(text, &defaultPrecision, &elements);
481     auto result = std::unique_ptr<Program>(new Program(kind, settings, defaultPrecision, &fContext,
482                                                        std::move(elements),
483                                                        fIRGenerator->fSymbolTable,
484                                                        fIRGenerator->fInputs));
485     fIRGenerator->finish();
486     this->writeErrorCount();
487     if (fErrorCount) {
488         return nullptr;
489     }
490     return result;
491 }
492 
toSPIRV(const Program & program,SkWStream & out)493 bool Compiler::toSPIRV(const Program& program, SkWStream& out) {
494 #ifdef SK_ENABLE_SPIRV_VALIDATION
495     SkDynamicMemoryWStream buffer;
496     SPIRVCodeGenerator cg(&fContext, &program, this, &buffer);
497     bool result = cg.generateCode();
498     if (result) {
499         sk_sp<SkData> data(buffer.detachAsData());
500         spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0);
501         SkASSERT(0 == data->size() % 4);
502         auto dumpmsg = [](spv_message_level_t, const char*, const spv_position_t&, const char* m) {
503             SkDebugf("SPIR-V validation error: %s\n", m);
504         };
505         tools.SetMessageConsumer(dumpmsg);
506         // Verify that the SPIR-V we produced is valid. If this assert fails, check the logs prior
507         // to the failure to see the validation errors.
508         SkAssertResult(tools.Validate((const uint32_t*) data->data(), data->size() / 4));
509         out.write(data->data(), data->size());
510     }
511 #else
512     SPIRVCodeGenerator cg(&fContext, &program, this, &out);
513     bool result = cg.generateCode();
514 #endif
515     this->writeErrorCount();
516     return result;
517 }
518 
toSPIRV(const Program & program,SkString * out)519 bool Compiler::toSPIRV(const Program& program, SkString* out) {
520     SkDynamicMemoryWStream buffer;
521     bool result = this->toSPIRV(program, buffer);
522     if (result) {
523         sk_sp<SkData> data(buffer.detachAsData());
524         *out = SkString((const char*) data->data(), data->size());
525     }
526     return result;
527 }
528 
toGLSL(const Program & program,SkWStream & out)529 bool Compiler::toGLSL(const Program& program, SkWStream& out) {
530     GLSLCodeGenerator cg(&fContext, &program, this, &out);
531     bool result = cg.generateCode();
532     this->writeErrorCount();
533     return result;
534 }
535 
toGLSL(const Program & program,SkString * out)536 bool Compiler::toGLSL(const Program& program, SkString* out) {
537     SkDynamicMemoryWStream buffer;
538     bool result = this->toGLSL(program, buffer);
539     if (result) {
540         sk_sp<SkData> data(buffer.detachAsData());
541         *out = SkString((const char*) data->data(), data->size());
542     }
543     return result;
544 }
545 
546 
error(Position position,SkString msg)547 void Compiler::error(Position position, SkString msg) {
548     fErrorCount++;
549     fErrorText += "error: " + position.description() + ": " + msg.c_str() + "\n";
550 }
551 
errorText()552 SkString Compiler::errorText() {
553     SkString result = fErrorText;
554     return result;
555 }
556 
writeErrorCount()557 void Compiler::writeErrorCount() {
558     if (fErrorCount) {
559         fErrorText += to_string(fErrorCount) + " error";
560         if (fErrorCount > 1) {
561             fErrorText += "s";
562         }
563         fErrorText += "\n";
564     }
565 }
566 
567 } // namespace
568