blob: 2b46b5285bf38d7245b59c9d9f978dc523a2b25e [file] [log] [blame]
ethannicholasb3058bd2016-07-01 08:22:01 -07001/*
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 */
Ethan Nicholas0df1b042017-03-31 13:56:23 -04007
ethannicholasb3058bd2016-07-01 08:22:01 -07008#ifndef SKSL_COMPILER
9#define SKSL_COMPILER
10
ethannicholas22f939e2016-10-13 13:25:34 -070011#include <set>
Ethan Nicholascb670962017-04-20 19:31:52 -040012#include <unordered_set>
ethannicholasb3058bd2016-07-01 08:22:01 -070013#include <vector>
Ethan Nicholasdb80f692019-11-22 14:06:12 -050014#include "src/sksl/SkSLASTFile.h"
Brian Osman010ce6a2020-10-19 16:34:10 -040015#include "src/sksl/SkSLAnalysis.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "src/sksl/SkSLCFGGenerator.h"
17#include "src/sksl/SkSLContext.h"
18#include "src/sksl/SkSLErrorReporter.h"
John Stiles7b463002020-08-31 17:29:21 -040019#include "src/sksl/SkSLInliner.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050020#include "src/sksl/SkSLLexer.h"
21#include "src/sksl/ir/SkSLProgram.h"
22#include "src/sksl/ir/SkSLSymbolTable.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070023
Brian Osman2e29ab52019-09-20 12:19:11 -040024#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
25#include "src/gpu/GrShaderVar.h"
26#endif
27
Ethan Nicholas762466e2017-06-29 10:03:38 -040028#define SK_FRAGCOLOR_BUILTIN 10001
29#define SK_IN_BUILTIN 10002
Ethan Nicholas16c11962018-03-16 12:20:54 -040030#define SK_OUT_BUILTIN 10007
Ethan Nicholaseab2baa2018-04-13 15:16:27 -040031#define SK_LASTFRAGCOLOR_BUILTIN 10008
Brian Osman7353dc52020-02-07 13:37:12 -050032#define SK_MAIN_COORDS_BUILTIN 10009
Ethan Nicholascd700e92018-08-24 16:43:57 -040033#define SK_WIDTH_BUILTIN 10011
34#define SK_HEIGHT_BUILTIN 10012
Ethan Nicholas762466e2017-06-29 10:03:38 -040035#define SK_FRAGCOORD_BUILTIN 15
Chris Dalton49d14e92018-07-27 12:38:35 -060036#define SK_CLOCKWISE_BUILTIN 17
Chris Daltonb0fd4b12019-10-29 13:41:22 -060037#define SK_SAMPLEMASK_BUILTIN 20
Ethan Nicholas9eded2c2018-03-22 10:10:44 -040038#define SK_VERTEXID_BUILTIN 42
39#define SK_INSTANCEID_BUILTIN 43
Ethan Nicholas762466e2017-06-29 10:03:38 -040040#define SK_INVOCATIONID_BUILTIN 8
Ethan Nicholascc305772017-10-13 16:17:45 -040041#define SK_POSITION_BUILTIN 0
ethannicholas5961bc92016-10-12 06:39:56 -070042
John Stilese6150002020-10-05 12:03:53 -040043class SkBitSet;
Ethan Nicholasba9a04f2020-11-06 09:28:04 -050044class SkSLCompileBench;
John Stilese6150002020-10-05 12:03:53 -040045
ethannicholasb3058bd2016-07-01 08:22:01 -070046namespace SkSL {
47
Brian Osman9b8b4552019-09-30 13:23:14 -040048class ByteCode;
Brian Osmanbe0b3b72021-01-06 14:27:35 -050049class ExternalFunction;
ethannicholasb3058bd2016-07-01 08:22:01 -070050class IRGenerator;
Brian Osman2b469eb2020-09-21 11:32:10 -040051class IRIntrinsicMap;
Brian Osman107c6662019-12-30 15:02:30 -050052struct PipelineStageArgs;
Brian Osman010ce6a2020-10-19 16:34:10 -040053class ProgramUsage;
ethannicholasb3058bd2016-07-01 08:22:01 -070054
Brian Osman3d87e9f2020-10-08 11:50:22 -040055struct LoadedModule {
Brian Osman0006ad02020-11-18 15:38:39 -050056 Program::Kind fKind;
Brian Osman3d87e9f2020-10-08 11:50:22 -040057 std::shared_ptr<SymbolTable> fSymbols;
58 std::vector<std::unique_ptr<ProgramElement>> fElements;
59};
60
61struct ParsedModule {
62 std::shared_ptr<SymbolTable> fSymbols;
63 std::shared_ptr<IRIntrinsicMap> fIntrinsics;
64};
65
ethannicholasb3058bd2016-07-01 08:22:01 -070066/**
67 * Main compiler entry point. This is a traditional compiler design which first parses the .sksl
Ethan Nicholas941e7e22016-12-12 15:33:30 -050068 * file into an abstract syntax tree (a tree of ASTNodes), then performs semantic analysis to
ethannicholasb3058bd2016-07-01 08:22:01 -070069 * produce a Program (a tree of IRNodes), then feeds the Program into a CodeGenerator to produce
70 * compiled output.
ethannicholas5961bc92016-10-12 06:39:56 -070071 *
72 * See the README for information about SkSL.
ethannicholasb3058bd2016-07-01 08:22:01 -070073 */
Ethan Nicholas4100b7c2019-03-12 11:50:48 -040074class SK_API Compiler : public ErrorReporter {
ethannicholasb3058bd2016-07-01 08:22:01 -070075public:
Robert Phillipsfe8da172018-01-24 14:52:02 +000076 static constexpr const char* RTADJUST_NAME = "sk_RTAdjust";
77 static constexpr const char* PERVERTEX_NAME = "sk_PerVertex";
78
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -040079 enum Flags {
80 kNone_Flags = 0,
81 // permits static if/switch statements to be used with non-constant tests. This is used when
82 // producing H and CPP code; the static tests don't have to have constant values *yet*, but
83 // the generated code will contain a static test which then does have to be a constant.
84 kPermitInvalidStaticTests_Flag = 1,
85 };
86
Brian Osmanac9d3f62020-06-25 11:07:30 -040087 // An invalid (otherwise unused) character to mark where FormatArgs are inserted
88 static constexpr char kFormatArgPlaceholder = '\001';
89 static constexpr const char* kFormatArgPlaceholderStr = "\001";
90
Ethan Nicholasce008112018-08-30 09:19:50 -040091 struct FormatArg {
92 enum class Kind {
Brian Osman7353dc52020-02-07 13:37:12 -050093 kCoords,
Ethan Nicholasce008112018-08-30 09:19:50 -040094 kUniform,
Brian Osman2e29ab52019-09-20 12:19:11 -040095 kChildProcessor,
Brian Osmanbe1b8372020-06-18 13:40:26 -040096 kChildProcessorWithMatrix,
Brian Osman2e29ab52019-09-20 12:19:11 -040097 kFunctionName
Ethan Nicholasce008112018-08-30 09:19:50 -040098 };
99
100 FormatArg(Kind kind)
101 : fKind(kind) {}
102
103 FormatArg(Kind kind, int index)
104 : fKind(kind)
105 , fIndex(index) {}
106
107 Kind fKind;
Ethan Nicholasce008112018-08-30 09:19:50 -0400108 int fIndex;
Brian Osman87e3bef2020-01-27 16:21:34 -0500109 String fCoords;
Ethan Nicholas00543112018-07-31 09:44:36 -0400110 };
111
Ethan Nicholascdeae8c2020-10-22 14:39:46 -0400112 struct OptimizationContext {
113 // nodes we have already reported errors for and should not error on again
114 std::unordered_set<const IRNode*> fSilences;
115 // true if we have updated the CFG during this pass
116 bool fUpdated = false;
117 // true if we need to completely regenerate the CFG
118 bool fNeedsRescan = false;
Brian Osman010ce6a2020-10-19 16:34:10 -0400119 // Metadata about function and variable usage within the program
120 ProgramUsage* fUsage = nullptr;
Ethan Nicholascdeae8c2020-10-22 14:39:46 -0400121 };
122
Brian Osman2e29ab52019-09-20 12:19:11 -0400123#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
124 /**
125 * Represents the arguments to GrGLSLShaderBuilder::emitFunction.
126 */
127 struct GLSLFunction {
128 GrSLType fReturnType;
129 SkString fName;
130 std::vector<GrShaderVar> fParameters;
Brian Osmanac9d3f62020-06-25 11:07:30 -0400131 String fBody;
Ethan Nicholasfc671ad2019-11-21 11:14:11 -0500132 std::vector<Compiler::FormatArg> fFormatArgs;
Brian Osman2e29ab52019-09-20 12:19:11 -0400133 };
134#endif
135
Brian Osmand7e76592020-11-02 12:26:22 -0500136 Compiler(const ShaderCapsClass* caps, Flags flags = kNone_Flags);
ethannicholasb3058bd2016-07-01 08:22:01 -0700137
Brian Salomond3b65972017-03-22 12:05:03 -0400138 ~Compiler() override;
ethannicholasb3058bd2016-07-01 08:22:01 -0700139
Brian Osman14003822019-04-10 11:47:26 -0400140 Compiler(const Compiler&) = delete;
141 Compiler& operator=(const Compiler&) = delete;
142
Ethan Nicholas91164d12019-05-15 15:29:54 -0400143 /**
Brian Osmanbe0b3b72021-01-06 14:27:35 -0500144 * If externalFunctions is supplied, those values are registered in the symbol table of the
Brian Osman32d53552020-09-23 13:55:20 -0400145 * Program, but ownership is *not* transferred. It is up to the caller to keep them alive.
Ethan Nicholas91164d12019-05-15 15:29:54 -0400146 */
Brian Osman32d53552020-09-23 13:55:20 -0400147 std::unique_ptr<Program> convertProgram(
148 Program::Kind kind,
149 String text,
150 const Program::Settings& settings,
Brian Osmanbe0b3b72021-01-06 14:27:35 -0500151 const std::vector<std::unique_ptr<ExternalFunction>>* externalFunctions = nullptr);
ethannicholasb3058bd2016-07-01 08:22:01 -0700152
Ethan Nicholas00543112018-07-31 09:44:36 -0400153 bool toSPIRV(Program& program, OutputStream& out);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500154
Ethan Nicholas00543112018-07-31 09:44:36 -0400155 bool toSPIRV(Program& program, String* out);
ethannicholasb3058bd2016-07-01 08:22:01 -0700156
Ethan Nicholas00543112018-07-31 09:44:36 -0400157 bool toGLSL(Program& program, OutputStream& out);
Ethan Nicholascc305772017-10-13 16:17:45 -0400158
Ethan Nicholas00543112018-07-31 09:44:36 -0400159 bool toGLSL(Program& program, String* out);
Timothy Liangb8eeb802018-07-23 16:46:16 -0400160
Brian Osmanc0243912020-02-19 15:35:26 -0500161 bool toHLSL(Program& program, String* out);
162
Ethan Nicholas00543112018-07-31 09:44:36 -0400163 bool toMetal(Program& program, OutputStream& out);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400164
Ethan Nicholas00543112018-07-31 09:44:36 -0400165 bool toMetal(Program& program, String* out);
166
Greg Daniela28ea672020-09-25 11:12:56 -0400167#if defined(SKSL_STANDALONE) || GR_TEST_UTILS
Ethan Nicholas00543112018-07-31 09:44:36 -0400168 bool toCPP(Program& program, String name, OutputStream& out);
169
170 bool toH(Program& program, String name, OutputStream& out);
Ethan Nicholas2a479a52020-08-18 16:29:45 -0400171#endif
Ethan Nicholas00543112018-07-31 09:44:36 -0400172
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400173 std::unique_ptr<ByteCode> toByteCode(Program& program);
174
Brian Osman2e29ab52019-09-20 12:19:11 -0400175#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
Brian Osmana4b91692020-08-10 14:26:16 -0400176 bool toPipelineStage(Program& program, PipelineStageArgs* outArgs);
Brian Osman2e29ab52019-09-20 12:19:11 -0400177#endif
Ethan Nicholas762466e2017-06-29 10:03:38 -0400178
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700179 void error(int offset, String msg) override;
ethannicholasb3058bd2016-07-01 08:22:01 -0700180
Ethan Nicholasdcd2f862020-12-17 23:24:25 +0000181 String errorText();
ethannicholasb3058bd2016-07-01 08:22:01 -0700182
183 void writeErrorCount();
184
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500185 int errorCount() override {
186 return fErrorCount;
187 }
188
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400189 Context& context() {
190 return *fContext;
191 }
192
Brian Osman401a0092020-09-10 14:47:24 -0400193 static const char* OperatorName(Token::Kind op);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700194
Brian Osman401a0092020-09-10 14:47:24 -0400195 // Returns true if op is '=' or any compound assignment operator ('+=', '-=', etc.)
196 static bool IsAssignment(Token::Kind op);
197
198 // Given a compound assignment operator, returns the non-assignment version of the operator
199 // (e.g. '+=' becomes '+')
200 static Token::Kind RemoveAssignment(Token::Kind op);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700201
Brian Osman3d87e9f2020-10-08 11:50:22 -0400202 // When SKSL_STANDALONE, fPath is used. (fData, fSize) will be (nullptr, 0)
203 // When !SKSL_STANDALONE, fData and fSize are used. fPath will be nullptr.
204 struct ModuleData {
205 const char* fPath;
206
207 const uint8_t* fData;
208 size_t fSize;
209 };
210
211 static ModuleData MakeModulePath(const char* path) {
212 return ModuleData{path, /*fData=*/nullptr, /*fSize=*/0};
213 }
214 static ModuleData MakeModuleData(const uint8_t* data, size_t size) {
215 return ModuleData{/*fPath=*/nullptr, data, size};
216 }
217
218 LoadedModule loadModule(Program::Kind kind, ModuleData data, std::shared_ptr<SymbolTable> base);
219 ParsedModule parseModule(Program::Kind kind, ModuleData data, const ParsedModule& base);
Ethan Nicholas8da1e652019-05-24 11:01:59 -0400220
Ethan Nicholasba9a04f2020-11-06 09:28:04 -0500221 IRGenerator& irGenerator() {
222 return *fIRGenerator;
223 }
224
225 const ParsedModule& moduleForProgramKind(Program::Kind kind);
226
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400227private:
Brian Osman56269982020-11-20 12:38:07 -0500228 const ParsedModule& loadGPUModule();
229 const ParsedModule& loadFragmentModule();
230 const ParsedModule& loadVertexModule();
Brian Osman88cda172020-10-09 12:05:16 -0400231 const ParsedModule& loadFPModule();
232 const ParsedModule& loadGeometryModule();
Brian Osmanb06301e2020-11-06 11:45:36 -0500233 const ParsedModule& loadPublicModule();
Brian Osman88cda172020-10-09 12:05:16 -0400234 const ParsedModule& loadInterpreterModule();
Brian Osman91946752020-12-21 13:20:40 -0500235 const ParsedModule& loadRuntimeEffectModule();
Brian Osman88cda172020-10-09 12:05:16 -0400236
Ethan Nicholas86a43402017-01-19 13:32:00 -0500237 void addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr,
238 DefinitionMap* definitions);
Ethan Nicholas86a43402017-01-19 13:32:00 -0500239 void addDefinitions(const BasicBlock::Node& node, DefinitionMap* definitions);
ethannicholas22f939e2016-10-13 13:25:34 -0700240
John Stilese6150002020-10-05 12:03:53 -0400241 void scanCFG(CFG* cfg, BlockId block, SkBitSet* processedSet);
Ethan Nicholascb670962017-04-20 19:31:52 -0400242 void computeDataFlow(CFG* cfg);
243
244 /**
245 * Simplifies the expression pointed to by iter (in both the IR and CFG structures), if
246 * possible.
247 */
248 void simplifyExpression(DefinitionMap& definitions,
249 BasicBlock& b,
250 std::vector<BasicBlock::Node>::iterator* iter,
Ethan Nicholascdeae8c2020-10-22 14:39:46 -0400251 OptimizationContext* context);
Ethan Nicholascb670962017-04-20 19:31:52 -0400252
253 /**
254 * Simplifies the statement pointed to by iter (in both the IR and CFG structures), if
255 * possible.
256 */
257 void simplifyStatement(DefinitionMap& definitions,
258 BasicBlock& b,
259 std::vector<BasicBlock::Node>::iterator* iter,
Ethan Nicholascdeae8c2020-10-22 14:39:46 -0400260 OptimizationContext* context);
Ethan Nicholascb670962017-04-20 19:31:52 -0400261
John Stiles0cc193a2020-09-09 09:39:34 -0400262 /**
263 * Optimizes a function based on control flow analysis. Returns true if changes were made.
264 */
Brian Osman010ce6a2020-10-19 16:34:10 -0400265 bool scanCFG(FunctionDefinition& f, ProgramUsage* usage);
ethannicholasb3058bd2016-07-01 08:22:01 -0700266
Ethan Nicholas34b19c52020-09-14 11:33:47 -0400267 /**
268 * Optimize every function in the program.
269 */
270 bool optimize(Program& program);
271
Brian Osman0006ad02020-11-18 15:38:39 -0500272 bool optimize(LoadedModule& module);
273
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700274 Position position(int offset);
275
Brian Osman0006ad02020-11-18 15:38:39 -0500276 std::shared_ptr<Context> fContext;
Brian Osmand7e76592020-11-02 12:26:22 -0500277 const ShaderCapsClass* fCaps = nullptr;
278
Brian Osmaneac49832020-09-18 11:49:22 -0400279 std::shared_ptr<SymbolTable> fRootSymbolTable;
Brian Osmanb06301e2020-11-06 11:45:36 -0500280 std::shared_ptr<SymbolTable> fPrivateSymbolTable;
Brian Osman2b469eb2020-09-21 11:32:10 -0400281
Brian Osman91946752020-12-21 13:20:40 -0500282 ParsedModule fRootModule; // Core types
Brian Osmanb06301e2020-11-06 11:45:36 -0500283
Brian Osman91946752020-12-21 13:20:40 -0500284 ParsedModule fPrivateModule; // [Root] + Internal types
285 ParsedModule fGPUModule; // [Private] + GPU intrinsics, helper functions
286 ParsedModule fVertexModule; // [GPU] + Vertex stage decls
287 ParsedModule fFragmentModule; // [GPU] + Fragment stage decls
288 ParsedModule fGeometryModule; // [GPU] + Geometry stage decls
289 ParsedModule fFPModule; // [GPU] + FP features
Brian Osmanb06301e2020-11-06 11:45:36 -0500290
Brian Osman91946752020-12-21 13:20:40 -0500291 ParsedModule fPublicModule; // [Root] + Public features
292 ParsedModule fInterpreterModule; // [Public] + Interpreter-only decls
293 ParsedModule fRuntimeEffectModule; // [Public] + Runtime effect decls
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400294
Ethan Nicholas041fd0a2020-10-07 16:42:04 -0400295 // holds ModifiersPools belonging to the core includes for lifetime purposes
296 std::vector<std::unique_ptr<ModifiersPool>> fModifiers;
297
John Stiles7b463002020-08-31 17:29:21 -0400298 Inliner fInliner;
John Stiles656427a2020-08-27 15:26:26 -0400299 std::unique_ptr<IRGenerator> fIRGenerator;
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -0400300 int fFlags;
ethannicholasb3058bd2016-07-01 08:22:01 -0700301
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700302 const String* fSource;
ethannicholasb3058bd2016-07-01 08:22:01 -0700303 int fErrorCount;
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400304 String fErrorText;
Brian Osman88cda172020-10-09 12:05:16 -0400305
306 friend class AutoSource;
Ethan Nicholasba9a04f2020-11-06 09:28:04 -0500307 friend class ::SkSLCompileBench;
ethannicholasb3058bd2016-07-01 08:22:01 -0700308};
309
Brian Osman107c6662019-12-30 15:02:30 -0500310#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
311struct PipelineStageArgs {
312 String fCode;
313 std::vector<Compiler::FormatArg> fFormatArgs;
314 std::vector<Compiler::GLSLFunction> fFunctions;
315};
316#endif
317
John Stilesa6841be2020-08-06 14:11:56 -0400318} // namespace SkSL
ethannicholasb3058bd2016-07-01 08:22:01 -0700319
320#endif