• 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 #ifndef SKSL_COMPILER
9 #define SKSL_COMPILER
10 
11 #include <set>
12 #include <unordered_set>
13 #include <vector>
14 #include "src/sksl/SkSLByteCode.h"
15 #include "src/sksl/SkSLCFGGenerator.h"
16 #include "src/sksl/SkSLContext.h"
17 #include "src/sksl/SkSLErrorReporter.h"
18 #include "src/sksl/SkSLLexer.h"
19 #include "src/sksl/ir/SkSLProgram.h"
20 #include "src/sksl/ir/SkSLSymbolTable.h"
21 
22 #define SK_FRAGCOLOR_BUILTIN           10001
23 #define SK_IN_BUILTIN                  10002
24 #define SK_INCOLOR_BUILTIN             10003
25 #define SK_OUTCOLOR_BUILTIN            10004
26 #define SK_TRANSFORMEDCOORDS2D_BUILTIN 10005
27 #define SK_TEXTURESAMPLERS_BUILTIN     10006
28 #define SK_OUT_BUILTIN                 10007
29 #define SK_LASTFRAGCOLOR_BUILTIN       10008
30 #define SK_MAIN_X_BUILTIN              10009
31 #define SK_MAIN_Y_BUILTIN              10010
32 #define SK_WIDTH_BUILTIN               10011
33 #define SK_HEIGHT_BUILTIN              10012
34 #define SK_FRAGCOORD_BUILTIN              15
35 #define SK_CLOCKWISE_BUILTIN              17
36 #define SK_VERTEXID_BUILTIN               42
37 #define SK_INSTANCEID_BUILTIN             43
38 #define SK_CLIPDISTANCE_BUILTIN            3
39 #define SK_INVOCATIONID_BUILTIN            8
40 #define SK_POSITION_BUILTIN                0
41 
42 namespace SkSL {
43 
44 class IRGenerator;
45 
46 /**
47  * Main compiler entry point. This is a traditional compiler design which first parses the .sksl
48  * file into an abstract syntax tree (a tree of ASTNodes), then performs semantic analysis to
49  * produce a Program (a tree of IRNodes), then feeds the Program into a CodeGenerator to produce
50  * compiled output.
51  *
52  * See the README for information about SkSL.
53  */
54 class SK_API Compiler : public ErrorReporter {
55 public:
56     static constexpr const char* RTADJUST_NAME  = "sk_RTAdjust";
57     static constexpr const char* PERVERTEX_NAME = "sk_PerVertex";
58 
59     enum Flags {
60         kNone_Flags = 0,
61         // permits static if/switch statements to be used with non-constant tests. This is used when
62         // producing H and CPP code; the static tests don't have to have constant values *yet*, but
63         // the generated code will contain a static test which then does have to be a constant.
64         kPermitInvalidStaticTests_Flag = 1,
65     };
66 
67     struct FormatArg {
68         enum class Kind {
69             kInput,
70             kOutput,
71             kCoordX,
72             kCoordY,
73             kUniform,
74             kChildProcessor
75         };
76 
FormatArgFormatArg77         FormatArg(Kind kind)
78                 : fKind(kind) {}
79 
FormatArgFormatArg80         FormatArg(Kind kind, int index)
81                 : fKind(kind)
82                 , fIndex(index) {}
83 
84         Kind fKind;
85 
86         int fIndex;
87     };
88 
89     Compiler(Flags flags = kNone_Flags);
90 
91     ~Compiler() override;
92 
93     Compiler(const Compiler&) = delete;
94     Compiler& operator=(const Compiler&) = delete;
95 
96     /**
97      * Registers an ExternalValue as a top-level symbol which is visible in the global namespace.
98      */
99     void registerExternalValue(ExternalValue* value);
100 
101     std::unique_ptr<Program> convertProgram(Program::Kind kind, String text,
102                                             const Program::Settings& settings);
103 
104     bool optimize(Program& program);
105 
106     std::unique_ptr<Program> specialize(Program& program,
107                     const std::unordered_map<SkSL::String, SkSL::Program::Settings::Value>& inputs);
108 
109     bool toSPIRV(Program& program, OutputStream& out);
110 
111     bool toSPIRV(Program& program, String* out);
112 
113     bool toGLSL(Program& program, OutputStream& out);
114 
115     bool toGLSL(Program& program, String* out);
116 
117     bool toMetal(Program& program, OutputStream& out);
118 
119     bool toMetal(Program& program, String* out);
120 
121     bool toCPP(Program& program, String name, OutputStream& out);
122 
123     bool toH(Program& program, String name, OutputStream& out);
124 
125     std::unique_ptr<ByteCode> toByteCode(Program& program);
126 
127     bool toPipelineStage(const Program& program, String* out,
128                          std::vector<FormatArg>* outFormatArgs);
129 
130     /**
131      * Takes ownership of the given symbol. It will be destroyed when the compiler is destroyed.
132      */
133     Symbol* takeOwnership(std::unique_ptr<Symbol> symbol);
134 
135     void error(int offset, String msg) override;
136 
137     String errorText();
138 
139     void writeErrorCount();
140 
errorCount()141     int errorCount() override {
142         return fErrorCount;
143     }
144 
context()145     Context& context() {
146         return *fContext;
147     }
148 
149     static const char* OperatorName(Token::Kind token);
150 
151     static bool IsAssignment(Token::Kind token);
152 
153 private:
154     void processIncludeFile(Program::Kind kind, const char* src, size_t length,
155                             std::shared_ptr<SymbolTable> base,
156                             std::vector<std::unique_ptr<ProgramElement>>* outElements,
157                             std::shared_ptr<SymbolTable>* outSymbolTable);
158 
159     void addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr,
160                        DefinitionMap* definitions);
161 
162     void addDefinitions(const BasicBlock::Node& node, DefinitionMap* definitions);
163 
164     void scanCFG(CFG* cfg, BlockId block, std::set<BlockId>* workList);
165 
166     void computeDataFlow(CFG* cfg);
167 
168     /**
169      * Simplifies the expression pointed to by iter (in both the IR and CFG structures), if
170      * possible.
171      */
172     void simplifyExpression(DefinitionMap& definitions,
173                             BasicBlock& b,
174                             std::vector<BasicBlock::Node>::iterator* iter,
175                             std::unordered_set<const Variable*>* undefinedVariables,
176                             bool* outUpdated,
177                             bool* outNeedsRescan);
178 
179     /**
180      * Simplifies the statement pointed to by iter (in both the IR and CFG structures), if
181      * possible.
182      */
183     void simplifyStatement(DefinitionMap& definitions,
184                            BasicBlock& b,
185                            std::vector<BasicBlock::Node>::iterator* iter,
186                            std::unordered_set<const Variable*>* undefinedVariables,
187                            bool* outUpdated,
188                            bool* outNeedsRescan);
189 
190     void scanCFG(FunctionDefinition& f);
191 
192     Position position(int offset);
193 
194     std::shared_ptr<SymbolTable> fGpuSymbolTable;
195     std::vector<std::unique_ptr<ProgramElement>> fVertexInclude;
196     std::shared_ptr<SymbolTable> fVertexSymbolTable;
197     std::vector<std::unique_ptr<ProgramElement>> fFragmentInclude;
198     std::shared_ptr<SymbolTable> fFragmentSymbolTable;
199     std::vector<std::unique_ptr<ProgramElement>> fGeometryInclude;
200     std::shared_ptr<SymbolTable> fGeometrySymbolTable;
201     std::vector<std::unique_ptr<ProgramElement>> fPipelineInclude;
202     std::shared_ptr<SymbolTable> fPipelineSymbolTable;
203     std::vector<std::unique_ptr<ProgramElement>> fInterpreterInclude;
204     std::shared_ptr<SymbolTable> fInterpreterSymbolTable;
205 
206     std::shared_ptr<SymbolTable> fTypes;
207     IRGenerator* fIRGenerator;
208     int fFlags;
209 
210     const String* fSource;
211     std::shared_ptr<Context> fContext;
212     int fErrorCount;
213     String fErrorText;
214 };
215 
216 } // namespace
217 
218 #endif
219