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 #ifndef SKSL_COMPILER
9 #define SKSL_COMPILER
10 
11 #include <set>
12 #include <unordered_set>
13 #include <vector>
14 #include "ir/SkSLProgram.h"
15 #include "ir/SkSLSymbolTable.h"
16 #include "SkSLCFGGenerator.h"
17 #include "SkSLContext.h"
18 #include "SkSLErrorReporter.h"
19 #include "SkSLLexer.h"
20 
21 #define SK_FRAGCOLOR_BUILTIN           10001
22 #define SK_IN_BUILTIN                  10002
23 #define SK_INCOLOR_BUILTIN             10003
24 #define SK_OUTCOLOR_BUILTIN            10004
25 #define SK_TRANSFORMEDCOORDS2D_BUILTIN 10005
26 #define SK_TEXTURESAMPLERS_BUILTIN     10006
27 #define SK_FRAGCOORD_BUILTIN              15
28 #define SK_VERTEXID_BUILTIN                5
29 #define SK_INSTANCEID_BUILTIN              6
30 #define SK_CLIPDISTANCE_BUILTIN            3
31 #define SK_INVOCATIONID_BUILTIN            8
32 #define SK_POSITION_BUILTIN                0
33 
34 namespace SkSL {
35 
36 class IRGenerator;
37 
38 /**
39  * Main compiler entry point. This is a traditional compiler design which first parses the .sksl
40  * file into an abstract syntax tree (a tree of ASTNodes), then performs semantic analysis to
41  * produce a Program (a tree of IRNodes), then feeds the Program into a CodeGenerator to produce
42  * compiled output.
43  *
44  * See the README for information about SkSL.
45  */
46 class Compiler : public ErrorReporter {
47 public:
48     static constexpr const char* RTADJUST_NAME  = "sk_RTAdjust";
49     static constexpr const char* PERVERTEX_NAME = "sk_PerVertex";
50 
51     enum Flags {
52         kNone_Flags = 0,
53         // permits static if/switch statements to be used with non-constant tests. This is used when
54         // producing H and CPP code; the static tests don't have to have constant values *yet*, but
55         // the generated code will contain a static test which then does have to be a constant.
56         kPermitInvalidStaticTests_Flag = 1,
57     };
58 
59     Compiler(Flags flags = kNone_Flags);
60 
61     ~Compiler() override;
62 
63     std::unique_ptr<Program> convertProgram(Program::Kind kind, String text,
64                                             const Program::Settings& settings);
65 
66     bool toSPIRV(const Program& program, OutputStream& out);
67 
68     bool toSPIRV(const Program& program, String* out);
69 
70     bool toGLSL(const Program& program, OutputStream& out);
71 
72     bool toGLSL(const Program& program, String* out);
73 
74     bool toMetal(const Program& program, OutputStream& out);
75 
76     bool toCPP(const Program& program, String name, OutputStream& out);
77 
78     bool toH(const Program& program, String name, OutputStream& out);
79 
80     void error(int offset, String msg) override;
81 
82     String errorText();
83 
84     void writeErrorCount();
85 
86     int errorCount() override {
87         return fErrorCount;
88     }
89 
90     static const char* OperatorName(Token::Kind token);
91 
92     static bool IsAssignment(Token::Kind token);
93 
94 private:
95     void addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr,
96                        DefinitionMap* definitions);
97 
98     void addDefinitions(const BasicBlock::Node& node, DefinitionMap* definitions);
99 
100     void scanCFG(CFG* cfg, BlockId block, std::set<BlockId>* workList);
101 
102     void computeDataFlow(CFG* cfg);
103 
104     /**
105      * Simplifies the expression pointed to by iter (in both the IR and CFG structures), if
106      * possible.
107      */
108     void simplifyExpression(DefinitionMap& definitions,
109                             BasicBlock& b,
110                             std::vector<BasicBlock::Node>::iterator* iter,
111                             std::unordered_set<const Variable*>* undefinedVariables,
112                             bool* outUpdated,
113                             bool* outNeedsRescan);
114 
115     /**
116      * Simplifies the statement pointed to by iter (in both the IR and CFG structures), if
117      * possible.
118      */
119     void simplifyStatement(DefinitionMap& definitions,
120                            BasicBlock& b,
121                            std::vector<BasicBlock::Node>::iterator* iter,
122                            std::unordered_set<const Variable*>* undefinedVariables,
123                            bool* outUpdated,
124                            bool* outNeedsRescan);
125 
126     void scanCFG(FunctionDefinition& f);
127 
128     Position position(int offset);
129 
130     std::shared_ptr<SymbolTable> fTypes;
131     IRGenerator* fIRGenerator;
132     String fSkiaVertText; // FIXME store parsed version instead
133     int fFlags;
134 
135     const String* fSource;
136     Context fContext;
137     int fErrorCount;
138     String fErrorText;
139 };
140 
141 } // namespace
142 
143 #endif
144