blob: d5742390a9675f805bd881d2da4864b28f24aaf1 [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 */
Mike Klein6ad99092016-10-26 10:35:22 -04007
ethannicholasb3058bd2016-07-01 08:22:01 -07008#include "SkSLCompiler.h"
9
ethannicholas5961bc92016-10-12 06:39:56 -070010#include "ast/SkSLASTPrecision.h"
ethannicholas22f939e2016-10-13 13:25:34 -070011#include "SkSLCFGGenerator.h"
Ethan Nicholas941e7e22016-12-12 15:33:30 -050012#include "SkSLGLSLCodeGenerator.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070013#include "SkSLIRGenerator.h"
14#include "SkSLParser.h"
15#include "SkSLSPIRVCodeGenerator.h"
16#include "ir/SkSLExpression.h"
17#include "ir/SkSLIntLiteral.h"
ethannicholas5961bc92016-10-12 06:39:56 -070018#include "ir/SkSLModifiersDeclaration.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070019#include "ir/SkSLSymbolTable.h"
ethannicholasddb37d62016-10-20 09:54:00 -070020#include "ir/SkSLUnresolvedFunction.h"
ethannicholas22f939e2016-10-13 13:25:34 -070021#include "ir/SkSLVarDeclarations.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070022#include "SkMutex.h"
23
24#define STRINGIFY(x) #x
25
26// include the built-in shader symbols as static strings
27
ethannicholas5961bc92016-10-12 06:39:56 -070028static const char* SKSL_INCLUDE =
ethannicholasb3058bd2016-07-01 08:22:01 -070029#include "sksl.include"
30;
31
ethannicholas5961bc92016-10-12 06:39:56 -070032static const char* SKSL_VERT_INCLUDE =
ethannicholasb3058bd2016-07-01 08:22:01 -070033#include "sksl_vert.include"
34;
35
ethannicholas5961bc92016-10-12 06:39:56 -070036static const char* SKSL_FRAG_INCLUDE =
ethannicholasb3058bd2016-07-01 08:22:01 -070037#include "sksl_frag.include"
38;
39
Ethan Nicholas52cad152017-02-16 16:37:32 -050040static const char* SKSL_GEOM_INCLUDE =
41#include "sksl_geom.include"
42;
43
ethannicholasb3058bd2016-07-01 08:22:01 -070044namespace SkSL {
45
Mike Klein6ad99092016-10-26 10:35:22 -040046Compiler::Compiler()
ethannicholasb3058bd2016-07-01 08:22:01 -070047: fErrorCount(0) {
48 auto types = std::shared_ptr<SymbolTable>(new SymbolTable(*this));
49 auto symbols = std::shared_ptr<SymbolTable>(new SymbolTable(types, *this));
ethannicholasd598f792016-07-25 10:08:54 -070050 fIRGenerator = new IRGenerator(&fContext, symbols, *this);
ethannicholasb3058bd2016-07-01 08:22:01 -070051 fTypes = types;
ethannicholasd598f792016-07-25 10:08:54 -070052 #define ADD_TYPE(t) types->addWithoutOwnership(fContext.f ## t ## _Type->fName, \
53 fContext.f ## t ## _Type.get())
ethannicholasb3058bd2016-07-01 08:22:01 -070054 ADD_TYPE(Void);
55 ADD_TYPE(Float);
56 ADD_TYPE(Vec2);
57 ADD_TYPE(Vec3);
58 ADD_TYPE(Vec4);
59 ADD_TYPE(Double);
60 ADD_TYPE(DVec2);
61 ADD_TYPE(DVec3);
62 ADD_TYPE(DVec4);
63 ADD_TYPE(Int);
64 ADD_TYPE(IVec2);
65 ADD_TYPE(IVec3);
66 ADD_TYPE(IVec4);
67 ADD_TYPE(UInt);
68 ADD_TYPE(UVec2);
69 ADD_TYPE(UVec3);
70 ADD_TYPE(UVec4);
71 ADD_TYPE(Bool);
72 ADD_TYPE(BVec2);
73 ADD_TYPE(BVec3);
74 ADD_TYPE(BVec4);
75 ADD_TYPE(Mat2x2);
Ethan Nicholas9e1138d2016-11-21 10:39:35 -050076 types->addWithoutOwnership(SkString("mat2x2"), fContext.fMat2x2_Type.get());
ethannicholasb3058bd2016-07-01 08:22:01 -070077 ADD_TYPE(Mat2x3);
78 ADD_TYPE(Mat2x4);
79 ADD_TYPE(Mat3x2);
80 ADD_TYPE(Mat3x3);
Ethan Nicholas9e1138d2016-11-21 10:39:35 -050081 types->addWithoutOwnership(SkString("mat3x3"), fContext.fMat3x3_Type.get());
ethannicholasb3058bd2016-07-01 08:22:01 -070082 ADD_TYPE(Mat3x4);
83 ADD_TYPE(Mat4x2);
84 ADD_TYPE(Mat4x3);
85 ADD_TYPE(Mat4x4);
Ethan Nicholas9e1138d2016-11-21 10:39:35 -050086 types->addWithoutOwnership(SkString("mat4x4"), fContext.fMat4x4_Type.get());
ethannicholasb3058bd2016-07-01 08:22:01 -070087 ADD_TYPE(GenType);
88 ADD_TYPE(GenDType);
89 ADD_TYPE(GenIType);
90 ADD_TYPE(GenUType);
91 ADD_TYPE(GenBType);
92 ADD_TYPE(Mat);
93 ADD_TYPE(Vec);
94 ADD_TYPE(GVec);
95 ADD_TYPE(GVec2);
96 ADD_TYPE(GVec3);
97 ADD_TYPE(GVec4);
98 ADD_TYPE(DVec);
99 ADD_TYPE(IVec);
100 ADD_TYPE(UVec);
101 ADD_TYPE(BVec);
102
103 ADD_TYPE(Sampler1D);
104 ADD_TYPE(Sampler2D);
105 ADD_TYPE(Sampler3D);
ethannicholas5961bc92016-10-12 06:39:56 -0700106 ADD_TYPE(SamplerExternalOES);
ethannicholasb3058bd2016-07-01 08:22:01 -0700107 ADD_TYPE(SamplerCube);
108 ADD_TYPE(Sampler2DRect);
109 ADD_TYPE(Sampler1DArray);
110 ADD_TYPE(Sampler2DArray);
111 ADD_TYPE(SamplerCubeArray);
112 ADD_TYPE(SamplerBuffer);
113 ADD_TYPE(Sampler2DMS);
114 ADD_TYPE(Sampler2DMSArray);
115
Brian Salomonbf7b6202016-11-11 16:08:03 -0500116 ADD_TYPE(ISampler2D);
117
Brian Salomon2a51de82016-11-16 12:06:01 -0500118 ADD_TYPE(Image2D);
119 ADD_TYPE(IImage2D);
120
Greg Daniel64773e62016-11-22 09:44:03 -0500121 ADD_TYPE(SubpassInput);
122 ADD_TYPE(SubpassInputMS);
123
ethannicholasb3058bd2016-07-01 08:22:01 -0700124 ADD_TYPE(GSampler1D);
125 ADD_TYPE(GSampler2D);
126 ADD_TYPE(GSampler3D);
127 ADD_TYPE(GSamplerCube);
128 ADD_TYPE(GSampler2DRect);
129 ADD_TYPE(GSampler1DArray);
130 ADD_TYPE(GSampler2DArray);
131 ADD_TYPE(GSamplerCubeArray);
132 ADD_TYPE(GSamplerBuffer);
133 ADD_TYPE(GSampler2DMS);
134 ADD_TYPE(GSampler2DMSArray);
135
136 ADD_TYPE(Sampler1DShadow);
137 ADD_TYPE(Sampler2DShadow);
138 ADD_TYPE(SamplerCubeShadow);
139 ADD_TYPE(Sampler2DRectShadow);
140 ADD_TYPE(Sampler1DArrayShadow);
141 ADD_TYPE(Sampler2DArrayShadow);
142 ADD_TYPE(SamplerCubeArrayShadow);
143 ADD_TYPE(GSampler2DArrayShadow);
144 ADD_TYPE(GSamplerCubeArrayShadow);
145
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500146 SkString skCapsName("sk_Caps");
147 Variable* skCaps = new Variable(Position(), Modifiers(), skCapsName,
148 *fContext.fSkCaps_Type, Variable::kGlobal_Storage);
149 fIRGenerator->fSymbolTable->add(skCapsName, std::unique_ptr<Symbol>(skCaps));
150
ethannicholas5961bc92016-10-12 06:39:56 -0700151 Modifiers::Flag ignored1;
152 std::vector<std::unique_ptr<ProgramElement>> ignored2;
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500153 this->internalConvertProgram(SkString(SKSL_INCLUDE), &ignored1, &ignored2);
ethannicholasddb37d62016-10-20 09:54:00 -0700154 fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
ethannicholasb3058bd2016-07-01 08:22:01 -0700155 ASSERT(!fErrorCount);
156}
157
158Compiler::~Compiler() {
159 delete fIRGenerator;
160}
161
ethannicholas22f939e2016-10-13 13:25:34 -0700162// add the definition created by assigning to the lvalue to the definition set
Ethan Nicholas86a43402017-01-19 13:32:00 -0500163void Compiler::addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr,
164 DefinitionMap* definitions) {
ethannicholas22f939e2016-10-13 13:25:34 -0700165 switch (lvalue->fKind) {
166 case Expression::kVariableReference_Kind: {
167 const Variable& var = ((VariableReference*) lvalue)->fVariable;
168 if (var.fStorage == Variable::kLocal_Storage) {
169 (*definitions)[&var] = expr;
170 }
171 break;
172 }
173 case Expression::kSwizzle_Kind:
174 // We consider the variable written to as long as at least some of its components have
175 // been written to. This will lead to some false negatives (we won't catch it if you
176 // write to foo.x and then read foo.y), but being stricter could lead to false positives
Mike Klein6ad99092016-10-26 10:35:22 -0400177 // (we write to foo.x, and then pass foo to a function which happens to only read foo.x,
178 // but since we pass foo as a whole it is flagged as an error) unless we perform a much
ethannicholas22f939e2016-10-13 13:25:34 -0700179 // more complicated whole-program analysis. This is probably good enough.
Mike Klein6ad99092016-10-26 10:35:22 -0400180 this->addDefinition(((Swizzle*) lvalue)->fBase.get(),
Ethan Nicholas86a43402017-01-19 13:32:00 -0500181 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
ethannicholas22f939e2016-10-13 13:25:34 -0700182 definitions);
183 break;
184 case Expression::kIndex_Kind:
185 // see comments in Swizzle
Mike Klein6ad99092016-10-26 10:35:22 -0400186 this->addDefinition(((IndexExpression*) lvalue)->fBase.get(),
Ethan Nicholas86a43402017-01-19 13:32:00 -0500187 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
ethannicholas22f939e2016-10-13 13:25:34 -0700188 definitions);
189 break;
190 case Expression::kFieldAccess_Kind:
191 // see comments in Swizzle
Mike Klein6ad99092016-10-26 10:35:22 -0400192 this->addDefinition(((FieldAccess*) lvalue)->fBase.get(),
Ethan Nicholas86a43402017-01-19 13:32:00 -0500193 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
ethannicholas22f939e2016-10-13 13:25:34 -0700194 definitions);
195 break;
196 default:
197 // not an lvalue, can't happen
198 ASSERT(false);
199 }
200}
201
202// add local variables defined by this node to the set
Mike Klein6ad99092016-10-26 10:35:22 -0400203void Compiler::addDefinitions(const BasicBlock::Node& node,
Ethan Nicholas86a43402017-01-19 13:32:00 -0500204 DefinitionMap* definitions) {
ethannicholas22f939e2016-10-13 13:25:34 -0700205 switch (node.fKind) {
206 case BasicBlock::Node::kExpression_Kind: {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500207 ASSERT(node.fExpression);
208 const Expression* expr = (Expression*) node.fExpression->get();
209 switch (expr->fKind) {
210 case Expression::kBinary_Kind: {
211 BinaryExpression* b = (BinaryExpression*) expr;
212 if (b->fOperator == Token::EQ) {
213 this->addDefinition(b->fLeft.get(), &b->fRight, definitions);
214 } else if (Token::IsAssignment(b->fOperator)) {
215 this->addDefinition(
216 b->fLeft.get(),
217 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
218 definitions);
219
220 }
221 break;
ethannicholas22f939e2016-10-13 13:25:34 -0700222 }
Ethan Nicholas86a43402017-01-19 13:32:00 -0500223 case Expression::kPrefix_Kind: {
224 const PrefixExpression* p = (PrefixExpression*) expr;
225 if (p->fOperator == Token::MINUSMINUS || p->fOperator == Token::PLUSPLUS) {
226 this->addDefinition(
227 p->fOperand.get(),
228 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
229 definitions);
230 }
231 break;
232 }
233 case Expression::kPostfix_Kind: {
234 const PostfixExpression* p = (PostfixExpression*) expr;
235 if (p->fOperator == Token::MINUSMINUS || p->fOperator == Token::PLUSPLUS) {
236 this->addDefinition(
237 p->fOperand.get(),
238 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
239 definitions);
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000240
Ethan Nicholas86a43402017-01-19 13:32:00 -0500241 }
242 break;
243 }
244 default:
245 break;
ethannicholas22f939e2016-10-13 13:25:34 -0700246 }
247 break;
248 }
249 case BasicBlock::Node::kStatement_Kind: {
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000250 const Statement* stmt = (Statement*) node.fStatement;
ethannicholas22f939e2016-10-13 13:25:34 -0700251 if (stmt->fKind == Statement::kVarDeclarations_Kind) {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500252 VarDeclarationsStatement* vd = (VarDeclarationsStatement*) stmt;
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000253 for (VarDeclaration& decl : vd->fDeclaration->fVars) {
254 if (decl.fValue) {
255 (*definitions)[decl.fVar] = &decl.fValue;
ethannicholas22f939e2016-10-13 13:25:34 -0700256 }
257 }
258 }
259 break;
260 }
261 }
262}
263
264void Compiler::scanCFG(CFG* cfg, BlockId blockId, std::set<BlockId>* workList) {
265 BasicBlock& block = cfg->fBlocks[blockId];
266
267 // compute definitions after this block
Ethan Nicholas86a43402017-01-19 13:32:00 -0500268 DefinitionMap after = block.fBefore;
ethannicholas22f939e2016-10-13 13:25:34 -0700269 for (const BasicBlock::Node& n : block.fNodes) {
270 this->addDefinitions(n, &after);
271 }
272
273 // propagate definitions to exits
274 for (BlockId exitId : block.fExits) {
275 BasicBlock& exit = cfg->fBlocks[exitId];
276 for (const auto& pair : after) {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500277 std::unique_ptr<Expression>* e1 = pair.second;
278 auto found = exit.fBefore.find(pair.first);
279 if (found == exit.fBefore.end()) {
280 // exit has no definition for it, just copy it
281 workList->insert(exitId);
ethannicholas22f939e2016-10-13 13:25:34 -0700282 exit.fBefore[pair.first] = e1;
283 } else {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500284 // exit has a (possibly different) value already defined
285 std::unique_ptr<Expression>* e2 = exit.fBefore[pair.first];
ethannicholas22f939e2016-10-13 13:25:34 -0700286 if (e1 != e2) {
287 // definition has changed, merge and add exit block to worklist
288 workList->insert(exitId);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500289 if (e1 && e2) {
290 exit.fBefore[pair.first] =
Ethan Nicholas86a43402017-01-19 13:32:00 -0500291 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression;
Ethan Nicholasaf197692017-02-27 13:26:45 -0500292 } else {
293 exit.fBefore[pair.first] = nullptr;
294 }
ethannicholas22f939e2016-10-13 13:25:34 -0700295 }
296 }
297 }
298 }
299}
300
301// returns a map which maps all local variables in the function to null, indicating that their value
302// is initially unknown
Ethan Nicholas86a43402017-01-19 13:32:00 -0500303static DefinitionMap compute_start_state(const CFG& cfg) {
304 DefinitionMap result;
Mike Klein6ad99092016-10-26 10:35:22 -0400305 for (const auto& block : cfg.fBlocks) {
306 for (const auto& node : block.fNodes) {
ethannicholas22f939e2016-10-13 13:25:34 -0700307 if (node.fKind == BasicBlock::Node::kStatement_Kind) {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500308 ASSERT(node.fStatement);
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000309 const Statement* s = node.fStatement;
ethannicholas22f939e2016-10-13 13:25:34 -0700310 if (s->fKind == Statement::kVarDeclarations_Kind) {
311 const VarDeclarationsStatement* vd = (const VarDeclarationsStatement*) s;
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000312 for (const VarDeclaration& decl : vd->fDeclaration->fVars) {
313 result[decl.fVar] = nullptr;
Mike Klein6ad99092016-10-26 10:35:22 -0400314 }
ethannicholas22f939e2016-10-13 13:25:34 -0700315 }
316 }
317 }
318 }
319 return result;
320}
321
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000322void Compiler::scanCFG(const FunctionDefinition& f) {
323 CFG cfg = CFGGenerator().getCFG(f);
ethannicholas22f939e2016-10-13 13:25:34 -0700324
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000325 // compute the data flow
326 cfg.fBlocks[cfg.fStart].fBefore = compute_start_state(cfg);
ethannicholas22f939e2016-10-13 13:25:34 -0700327 std::set<BlockId> workList;
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000328 for (BlockId i = 0; i < cfg.fBlocks.size(); i++) {
ethannicholas22f939e2016-10-13 13:25:34 -0700329 workList.insert(i);
330 }
331 while (workList.size()) {
332 BlockId next = *workList.begin();
333 workList.erase(workList.begin());
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000334 this->scanCFG(&cfg, next, &workList);
ethannicholas22f939e2016-10-13 13:25:34 -0700335 }
336
337 // check for unreachable code
338 for (size_t i = 0; i < cfg.fBlocks.size(); i++) {
Mike Klein6ad99092016-10-26 10:35:22 -0400339 if (i != cfg.fStart && !cfg.fBlocks[i].fEntrances.size() &&
ethannicholas22f939e2016-10-13 13:25:34 -0700340 cfg.fBlocks[i].fNodes.size()) {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500341 Position p;
342 switch (cfg.fBlocks[i].fNodes[0].fKind) {
343 case BasicBlock::Node::kStatement_Kind:
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000344 p = cfg.fBlocks[i].fNodes[0].fStatement->fPosition;
Ethan Nicholas86a43402017-01-19 13:32:00 -0500345 break;
346 case BasicBlock::Node::kExpression_Kind:
347 p = (*cfg.fBlocks[i].fNodes[0].fExpression)->fPosition;
348 break;
349 }
350 this->error(p, SkString("unreachable"));
ethannicholas22f939e2016-10-13 13:25:34 -0700351 }
352 }
353 if (fErrorCount) {
354 return;
355 }
356
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000357 // check for undefined variables, perform constant propagation
358 for (BasicBlock& b : cfg.fBlocks) {
359 DefinitionMap definitions = b.fBefore;
360 for (BasicBlock::Node& n : b.fNodes) {
361 if (n.fKind == BasicBlock::Node::kExpression_Kind) {
362 ASSERT(n.fExpression);
363 Expression* expr = n.fExpression->get();
364 if (n.fConstantPropagation) {
365 std::unique_ptr<Expression> optimized = expr->constantPropagate(*fIRGenerator,
366 definitions);
367 if (optimized) {
368 n.fExpression->reset(optimized.release());
369 expr = n.fExpression->get();
Ethan Nicholas113628d2017-02-02 16:11:39 -0500370 }
371 }
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000372 if (expr->fKind == Expression::kVariableReference_Kind) {
373 const Variable& var = ((VariableReference*) expr)->fVariable;
374 if (var.fStorage == Variable::kLocal_Storage &&
375 !definitions[&var]) {
376 this->error(expr->fPosition,
377 "'" + var.fName + "' has not been assigned");
378 }
379 }
Ethan Nicholas113628d2017-02-02 16:11:39 -0500380 }
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000381 this->addDefinitions(n, &definitions);
Ethan Nicholas113628d2017-02-02 16:11:39 -0500382 }
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000383 }
ethannicholas22f939e2016-10-13 13:25:34 -0700384
385 // check for missing return
386 if (f.fDeclaration.fReturnType != *fContext.fVoid_Type) {
387 if (cfg.fBlocks[cfg.fExit].fEntrances.size()) {
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500388 this->error(f.fPosition, SkString("function can exit without returning a value"));
ethannicholas22f939e2016-10-13 13:25:34 -0700389 }
390 }
391}
392
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500393void Compiler::internalConvertProgram(SkString text,
ethannicholas5961bc92016-10-12 06:39:56 -0700394 Modifiers::Flag* defaultPrecision,
ethannicholasb3058bd2016-07-01 08:22:01 -0700395 std::vector<std::unique_ptr<ProgramElement>>* result) {
396 Parser parser(text, *fTypes, *this);
397 std::vector<std::unique_ptr<ASTDeclaration>> parsed = parser.file();
398 if (fErrorCount) {
399 return;
400 }
ethannicholas5961bc92016-10-12 06:39:56 -0700401 *defaultPrecision = Modifiers::kHighp_Flag;
ethannicholasb3058bd2016-07-01 08:22:01 -0700402 for (size_t i = 0; i < parsed.size(); i++) {
403 ASTDeclaration& decl = *parsed[i];
404 switch (decl.fKind) {
405 case ASTDeclaration::kVar_Kind: {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700406 std::unique_ptr<VarDeclarations> s = fIRGenerator->convertVarDeclarations(
Mike Klein6ad99092016-10-26 10:35:22 -0400407 (ASTVarDeclarations&) decl,
ethannicholasb3058bd2016-07-01 08:22:01 -0700408 Variable::kGlobal_Storage);
409 if (s) {
410 result->push_back(std::move(s));
411 }
412 break;
413 }
414 case ASTDeclaration::kFunction_Kind: {
415 std::unique_ptr<FunctionDefinition> f = fIRGenerator->convertFunction(
416 (ASTFunction&) decl);
ethannicholas22f939e2016-10-13 13:25:34 -0700417 if (!fErrorCount && f) {
418 this->scanCFG(*f);
ethannicholasb3058bd2016-07-01 08:22:01 -0700419 result->push_back(std::move(f));
420 }
421 break;
422 }
ethannicholas5961bc92016-10-12 06:39:56 -0700423 case ASTDeclaration::kModifiers_Kind: {
424 std::unique_ptr<ModifiersDeclaration> f = fIRGenerator->convertModifiersDeclaration(
425 (ASTModifiersDeclaration&) decl);
426 if (f) {
427 result->push_back(std::move(f));
428 }
429 break;
430 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700431 case ASTDeclaration::kInterfaceBlock_Kind: {
432 std::unique_ptr<InterfaceBlock> i = fIRGenerator->convertInterfaceBlock(
433 (ASTInterfaceBlock&) decl);
434 if (i) {
435 result->push_back(std::move(i));
436 }
437 break;
438 }
439 case ASTDeclaration::kExtension_Kind: {
440 std::unique_ptr<Extension> e = fIRGenerator->convertExtension((ASTExtension&) decl);
441 if (e) {
442 result->push_back(std::move(e));
443 }
444 break;
445 }
ethannicholas5961bc92016-10-12 06:39:56 -0700446 case ASTDeclaration::kPrecision_Kind: {
447 *defaultPrecision = ((ASTPrecision&) decl).fPrecision;
448 break;
449 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700450 default:
451 ABORT("unsupported declaration: %s\n", decl.description().c_str());
452 }
453 }
454}
455
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500456std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, SkString text,
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500457 const Program::Settings& settings) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700458 fErrorText = "";
459 fErrorCount = 0;
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500460 fIRGenerator->start(&settings);
ethannicholasd598f792016-07-25 10:08:54 -0700461 std::vector<std::unique_ptr<ProgramElement>> elements;
ethannicholas5961bc92016-10-12 06:39:56 -0700462 Modifiers::Flag ignored;
ethannicholasb3058bd2016-07-01 08:22:01 -0700463 switch (kind) {
464 case Program::kVertex_Kind:
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500465 this->internalConvertProgram(SkString(SKSL_VERT_INCLUDE), &ignored, &elements);
ethannicholasb3058bd2016-07-01 08:22:01 -0700466 break;
467 case Program::kFragment_Kind:
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500468 this->internalConvertProgram(SkString(SKSL_FRAG_INCLUDE), &ignored, &elements);
ethannicholasb3058bd2016-07-01 08:22:01 -0700469 break;
Ethan Nicholas52cad152017-02-16 16:37:32 -0500470 case Program::kGeometry_Kind:
471 this->internalConvertProgram(SkString(SKSL_GEOM_INCLUDE), &ignored, &elements);
472 break;
ethannicholasb3058bd2016-07-01 08:22:01 -0700473 }
ethannicholasddb37d62016-10-20 09:54:00 -0700474 fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
ethannicholas5961bc92016-10-12 06:39:56 -0700475 Modifiers::Flag defaultPrecision;
476 this->internalConvertProgram(text, &defaultPrecision, &elements);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500477 auto result = std::unique_ptr<Program>(new Program(kind, settings, defaultPrecision, &fContext,
478 std::move(elements),
479 fIRGenerator->fSymbolTable,
480 fIRGenerator->fInputs));
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500481 fIRGenerator->finish();
ethannicholasb3058bd2016-07-01 08:22:01 -0700482 this->writeErrorCount();
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500483 if (fErrorCount) {
484 return nullptr;
485 }
486 return result;
487}
488
489
490bool Compiler::toSPIRV(const Program& program, SkWStream& out) {
491 SPIRVCodeGenerator cg(&fContext, &program, this, &out);
492 bool result = cg.generateCode();
493 this->writeErrorCount();
Ethan Nicholasce33f102016-12-09 17:22:59 -0500494 return result;
495}
496
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500497bool Compiler::toSPIRV(const Program& program, SkString* out) {
498 SkDynamicMemoryWStream buffer;
499 bool result = this->toSPIRV(program, buffer);
500 if (result) {
501 sk_sp<SkData> data(buffer.detachAsData());
502 *out = SkString((const char*) data->data(), data->size());
503 }
504 return result;
505}
506
507bool Compiler::toGLSL(const Program& program, SkWStream& out) {
508 GLSLCodeGenerator cg(&fContext, &program, this, &out);
509 bool result = cg.generateCode();
510 this->writeErrorCount();
511 return result;
512}
513
514bool Compiler::toGLSL(const Program& program, SkString* out) {
515 SkDynamicMemoryWStream buffer;
516 bool result = this->toGLSL(program, buffer);
517 if (result) {
518 sk_sp<SkData> data(buffer.detachAsData());
519 *out = SkString((const char*) data->data(), data->size());
520 }
521 return result;
522}
523
524
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500525void Compiler::error(Position position, SkString msg) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700526 fErrorCount++;
527 fErrorText += "error: " + position.description() + ": " + msg.c_str() + "\n";
528}
529
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500530SkString Compiler::errorText() {
531 SkString result = fErrorText;
ethannicholasb3058bd2016-07-01 08:22:01 -0700532 return result;
533}
534
535void Compiler::writeErrorCount() {
536 if (fErrorCount) {
537 fErrorText += to_string(fErrorCount) + " error";
538 if (fErrorCount > 1) {
539 fErrorText += "s";
540 }
541 fErrorText += "\n";
542 }
543}
544
ethannicholasb3058bd2016-07-01 08:22:01 -0700545} // namespace