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 <map>
12#include <set>
13#include <unordered_set>
14#include <vector>
15#include "src/sksl/SkSLASTFile.h"
16#include "src/sksl/SkSLCFGGenerator.h"
17#include "src/sksl/SkSLContext.h"
18#include "src/sksl/SkSLErrorReporter.h"
19#include "src/sksl/SkSLLexer.h"
20#include "src/sksl/ir/SkSLProgram.h"
21#include "src/sksl/ir/SkSLSymbolTable.h"
22
23#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
24#include "src/gpu/GrShaderVar.h"
25#endif
26
27#define SK_FRAGCOLOR_BUILTIN 10001
28#define SK_IN_BUILTIN 10002
29#define SK_INCOLOR_BUILTIN 10003
30#define SK_OUTCOLOR_BUILTIN 10004
31#define SK_TEXTURESAMPLERS_BUILTIN 10006
32#define SK_OUT_BUILTIN 10007
33#define SK_LASTFRAGCOLOR_BUILTIN 10008
34#define SK_MAIN_COORDS_BUILTIN 10009
35#define SK_WIDTH_BUILTIN 10011
36#define SK_HEIGHT_BUILTIN 10012
37#define SK_FRAGCOORD_BUILTIN 15
38#define SK_CLOCKWISE_BUILTIN 17
39#define SK_SAMPLEMASK_BUILTIN 20
40#define SK_VERTEXID_BUILTIN 42
41#define SK_INSTANCEID_BUILTIN 43
42#define SK_CLIPDISTANCE_BUILTIN 3
43#define SK_INVOCATIONID_BUILTIN 8
44#define SK_POSITION_BUILTIN 0
45
46namespace SkSL {
47
48class ByteCode;
49class ExternalValue;
50class IRGenerator;
51struct PipelineStageArgs;
52
53/**
54 * Main compiler entry point. This is a traditional compiler design which first parses the .sksl
55 * file into an abstract syntax tree (a tree of ASTNodes), then performs semantic analysis to
56 * produce a Program (a tree of IRNodes), then feeds the Program into a CodeGenerator to produce
57 * compiled output.
58 *
59 * See the README for information about SkSL.
60 */
61class SK_API Compiler : public ErrorReporter {
62public:
63 static constexpr const char* RTADJUST_NAME = "sk_RTAdjust";
64 static constexpr const char* PERVERTEX_NAME = "sk_PerVertex";
65
66 enum Flags {
67 kNone_Flags = 0,
68 // permits static if/switch statements to be used with non-constant tests. This is used when
69 // producing H and CPP code; the static tests don't have to have constant values *yet*, but
70 // the generated code will contain a static test which then does have to be a constant.
71 kPermitInvalidStaticTests_Flag = 1,
72 };
73
74 // An invalid (otherwise unused) character to mark where FormatArgs are inserted
75 static constexpr char kFormatArgPlaceholder = '\001';
76 static constexpr const char* kFormatArgPlaceholderStr = "\001";
77
78 struct FormatArg {
79 enum class Kind {
80 kInput,
81 kOutput,
82 kCoords,
83 kUniform,
84 kChildProcessor,
85 kChildProcessorWithMatrix,
86 kFunctionName
87 };
88
89 FormatArg(Kind kind)
90 : fKind(kind) {}
91
92 FormatArg(Kind kind, int index)
93 : fKind(kind)
94 , fIndex(index) {}
95
96 Kind fKind;
97 int fIndex;
98 String fCoords;
99 };
100
101#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
102 /**
103 * Represents the arguments to GrGLSLShaderBuilder::emitFunction.
104 */
105 struct GLSLFunction {
106 GrSLType fReturnType;
107 SkString fName;
108 std::vector<GrShaderVar> fParameters;
109 String fBody;
110 std::vector<Compiler::FormatArg> fFormatArgs;
111 };
112#endif
113
114 Compiler(Flags flags = kNone_Flags);
115
116 ~Compiler() override;
117
118 Compiler(const Compiler&) = delete;
119 Compiler& operator=(const Compiler&) = delete;
120
121 /**
122 * Registers an ExternalValue as a top-level symbol which is visible in the global namespace.
123 */
124 void registerExternalValue(ExternalValue* value);
125
126 std::unique_ptr<Program> convertProgram(Program::Kind kind, String text,
127 const Program::Settings& settings);
128
129 bool optimize(Program& program);
130
131 bool toSPIRV(Program& program, OutputStream& out);
132
133 bool toSPIRV(Program& program, String* out);
134
135 bool toGLSL(Program& program, OutputStream& out);
136
137 bool toGLSL(Program& program, String* out);
138
139 bool toHLSL(Program& program, String* out);
140
141 bool toMetal(Program& program, OutputStream& out);
142
143 bool toMetal(Program& program, String* out);
144
145 bool toCPP(Program& program, String name, OutputStream& out);
146
147 bool toH(Program& program, String name, OutputStream& out);
148
149 std::unique_ptr<ByteCode> toByteCode(Program& program);
150
151#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
152 bool toPipelineStage(Program& program, PipelineStageArgs* outArgs);
153#endif
154
155 /**
156 * Takes ownership of the given symbol. It will be destroyed when the compiler is destroyed.
157 */
158 const Symbol* takeOwnership(std::unique_ptr<const Symbol> symbol);
159
160 void error(int offset, String msg) override;
161
162 String errorText();
163
164 void writeErrorCount();
165
166 int errorCount() override {
167 return fErrorCount;
168 }
169
170 Context& context() {
171 return *fContext;
172 }
173
174 static const char* OperatorName(Token::Kind token);
175
176 static bool IsAssignment(Token::Kind token);
177
178 void processIncludeFile(Program::Kind kind, const char* path,
179 std::shared_ptr<SymbolTable> base,
180 std::vector<std::unique_ptr<ProgramElement>>* outElements,
181 std::shared_ptr<SymbolTable>* outSymbolTable);
182
183private:
184
185 void loadGeometryIntrinsics();
186
187 void loadInterpreterIntrinsics();
188
189 void loadPipelineIntrinsics();
190
191 void addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr,
192 DefinitionMap* definitions);
193
194 void addDefinitions(const BasicBlock::Node& node, DefinitionMap* definitions);
195
196 void scanCFG(CFG* cfg, BlockId block, std::set<BlockId>* workList);
197
198 void computeDataFlow(CFG* cfg);
199
200 /**
201 * Simplifies the expression pointed to by iter (in both the IR and CFG structures), if
202 * possible.
203 */
204 void simplifyExpression(DefinitionMap& definitions,
205 BasicBlock& b,
206 std::vector<BasicBlock::Node>::iterator* iter,
207 std::unordered_set<const Variable*>* undefinedVariables,
208 bool* outUpdated,
209 bool* outNeedsRescan);
210
211 /**
212 * Simplifies the statement pointed to by iter (in both the IR and CFG structures), if
213 * possible.
214 */
215 void simplifyStatement(DefinitionMap& definitions,
216 BasicBlock& b,
217 std::vector<BasicBlock::Node>::iterator* iter,
218 std::unordered_set<const Variable*>* undefinedVariables,
219 bool* outUpdated,
220 bool* outNeedsRescan);
221
222 void scanCFG(FunctionDefinition& f);
223
224 Position position(int offset);
225
226 std::shared_ptr<SymbolTable> fGpuSymbolTable;
227 std::map<String, std::pair<std::unique_ptr<ProgramElement>, bool>> fGPUIntrinsics;
228 std::map<String, std::pair<std::unique_ptr<ProgramElement>, bool>> fInterpreterIntrinsics;
229 std::unique_ptr<ASTFile> fGpuIncludeSource;
230 std::vector<std::unique_ptr<ProgramElement>> fVertexInclude;
231 std::shared_ptr<SymbolTable> fVertexSymbolTable;
232 std::vector<std::unique_ptr<ProgramElement>> fFragmentInclude;
233 std::shared_ptr<SymbolTable> fFragmentSymbolTable;
234 std::vector<std::unique_ptr<ProgramElement>> fGeometryInclude;
235 std::shared_ptr<SymbolTable> fGeometrySymbolTable;
236 std::vector<std::unique_ptr<ProgramElement>> fPipelineInclude;
237 std::shared_ptr<SymbolTable> fPipelineSymbolTable;
238 std::shared_ptr<SymbolTable> fInterpreterSymbolTable;
239 std::vector<std::unique_ptr<ProgramElement>> fInterpreterInclude;
240 std::vector<std::unique_ptr<ProgramElement>> fFPInclude;
241 std::shared_ptr<SymbolTable> fFPSymbolTable;
242
243 IRGenerator* fIRGenerator;
244 int fFlags;
245
246 const String* fSource;
247 std::shared_ptr<Context> fContext;
248 int fErrorCount;
249 String fErrorText;
250};
251
252#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
253struct PipelineStageArgs {
254 String fCode;
255 std::vector<Compiler::FormatArg> fFormatArgs;
256 std::vector<Compiler::GLSLFunction> fFunctions;
257};
258#endif
259
260} // namespace SkSL
261
262#endif
263