blob: d4fbc95d395d75a3ab0ee78e6a260314e5544c2a [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 */
7
8#include "SkSLCompiler.h"
9
10#include <fstream>
11#include <streambuf>
12
ethannicholas5961bc92016-10-12 06:39:56 -070013#include "ast/SkSLASTPrecision.h"
ethannicholas22f939e2016-10-13 13:25:34 -070014#include "SkSLCFGGenerator.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070015#include "SkSLIRGenerator.h"
16#include "SkSLParser.h"
17#include "SkSLSPIRVCodeGenerator.h"
18#include "ir/SkSLExpression.h"
19#include "ir/SkSLIntLiteral.h"
ethannicholas5961bc92016-10-12 06:39:56 -070020#include "ir/SkSLModifiersDeclaration.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070021#include "ir/SkSLSymbolTable.h"
ethannicholas22f939e2016-10-13 13:25:34 -070022#include "ir/SkSLVarDeclarations.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070023#include "SkMutex.h"
24
25#define STRINGIFY(x) #x
26
27// include the built-in shader symbols as static strings
28
ethannicholas5961bc92016-10-12 06:39:56 -070029static const char* SKSL_INCLUDE =
ethannicholasb3058bd2016-07-01 08:22:01 -070030#include "sksl.include"
31;
32
ethannicholas5961bc92016-10-12 06:39:56 -070033static const char* SKSL_VERT_INCLUDE =
ethannicholasb3058bd2016-07-01 08:22:01 -070034#include "sksl_vert.include"
35;
36
ethannicholas5961bc92016-10-12 06:39:56 -070037static const char* SKSL_FRAG_INCLUDE =
ethannicholasb3058bd2016-07-01 08:22:01 -070038#include "sksl_frag.include"
39;
40
41namespace SkSL {
42
43Compiler::Compiler()
44: fErrorCount(0) {
45 auto types = std::shared_ptr<SymbolTable>(new SymbolTable(*this));
46 auto symbols = std::shared_ptr<SymbolTable>(new SymbolTable(types, *this));
ethannicholasd598f792016-07-25 10:08:54 -070047 fIRGenerator = new IRGenerator(&fContext, symbols, *this);
ethannicholasb3058bd2016-07-01 08:22:01 -070048 fTypes = types;
ethannicholasd598f792016-07-25 10:08:54 -070049 #define ADD_TYPE(t) types->addWithoutOwnership(fContext.f ## t ## _Type->fName, \
50 fContext.f ## t ## _Type.get())
ethannicholasb3058bd2016-07-01 08:22:01 -070051 ADD_TYPE(Void);
52 ADD_TYPE(Float);
53 ADD_TYPE(Vec2);
54 ADD_TYPE(Vec3);
55 ADD_TYPE(Vec4);
56 ADD_TYPE(Double);
57 ADD_TYPE(DVec2);
58 ADD_TYPE(DVec3);
59 ADD_TYPE(DVec4);
60 ADD_TYPE(Int);
61 ADD_TYPE(IVec2);
62 ADD_TYPE(IVec3);
63 ADD_TYPE(IVec4);
64 ADD_TYPE(UInt);
65 ADD_TYPE(UVec2);
66 ADD_TYPE(UVec3);
67 ADD_TYPE(UVec4);
68 ADD_TYPE(Bool);
69 ADD_TYPE(BVec2);
70 ADD_TYPE(BVec3);
71 ADD_TYPE(BVec4);
72 ADD_TYPE(Mat2x2);
ethannicholasf789b382016-08-03 12:43:36 -070073 types->addWithoutOwnership("mat2x2", fContext.fMat2x2_Type.get());
ethannicholasb3058bd2016-07-01 08:22:01 -070074 ADD_TYPE(Mat2x3);
75 ADD_TYPE(Mat2x4);
76 ADD_TYPE(Mat3x2);
77 ADD_TYPE(Mat3x3);
ethannicholasf789b382016-08-03 12:43:36 -070078 types->addWithoutOwnership("mat3x3", fContext.fMat3x3_Type.get());
ethannicholasb3058bd2016-07-01 08:22:01 -070079 ADD_TYPE(Mat3x4);
80 ADD_TYPE(Mat4x2);
81 ADD_TYPE(Mat4x3);
82 ADD_TYPE(Mat4x4);
ethannicholasf789b382016-08-03 12:43:36 -070083 types->addWithoutOwnership("mat4x4", fContext.fMat4x4_Type.get());
ethannicholasb3058bd2016-07-01 08:22:01 -070084 ADD_TYPE(GenType);
85 ADD_TYPE(GenDType);
86 ADD_TYPE(GenIType);
87 ADD_TYPE(GenUType);
88 ADD_TYPE(GenBType);
89 ADD_TYPE(Mat);
90 ADD_TYPE(Vec);
91 ADD_TYPE(GVec);
92 ADD_TYPE(GVec2);
93 ADD_TYPE(GVec3);
94 ADD_TYPE(GVec4);
95 ADD_TYPE(DVec);
96 ADD_TYPE(IVec);
97 ADD_TYPE(UVec);
98 ADD_TYPE(BVec);
99
100 ADD_TYPE(Sampler1D);
101 ADD_TYPE(Sampler2D);
102 ADD_TYPE(Sampler3D);
ethannicholas5961bc92016-10-12 06:39:56 -0700103 ADD_TYPE(SamplerExternalOES);
ethannicholasb3058bd2016-07-01 08:22:01 -0700104 ADD_TYPE(SamplerCube);
105 ADD_TYPE(Sampler2DRect);
106 ADD_TYPE(Sampler1DArray);
107 ADD_TYPE(Sampler2DArray);
108 ADD_TYPE(SamplerCubeArray);
109 ADD_TYPE(SamplerBuffer);
110 ADD_TYPE(Sampler2DMS);
111 ADD_TYPE(Sampler2DMSArray);
112
113 ADD_TYPE(GSampler1D);
114 ADD_TYPE(GSampler2D);
115 ADD_TYPE(GSampler3D);
116 ADD_TYPE(GSamplerCube);
117 ADD_TYPE(GSampler2DRect);
118 ADD_TYPE(GSampler1DArray);
119 ADD_TYPE(GSampler2DArray);
120 ADD_TYPE(GSamplerCubeArray);
121 ADD_TYPE(GSamplerBuffer);
122 ADD_TYPE(GSampler2DMS);
123 ADD_TYPE(GSampler2DMSArray);
124
125 ADD_TYPE(Sampler1DShadow);
126 ADD_TYPE(Sampler2DShadow);
127 ADD_TYPE(SamplerCubeShadow);
128 ADD_TYPE(Sampler2DRectShadow);
129 ADD_TYPE(Sampler1DArrayShadow);
130 ADD_TYPE(Sampler2DArrayShadow);
131 ADD_TYPE(SamplerCubeArrayShadow);
132 ADD_TYPE(GSampler2DArrayShadow);
133 ADD_TYPE(GSamplerCubeArrayShadow);
134
ethannicholas5961bc92016-10-12 06:39:56 -0700135 Modifiers::Flag ignored1;
136 std::vector<std::unique_ptr<ProgramElement>> ignored2;
137 this->internalConvertProgram(SKSL_INCLUDE, &ignored1, &ignored2);
ethannicholasb3058bd2016-07-01 08:22:01 -0700138 ASSERT(!fErrorCount);
139}
140
141Compiler::~Compiler() {
142 delete fIRGenerator;
143}
144
ethannicholas22f939e2016-10-13 13:25:34 -0700145// add the definition created by assigning to the lvalue to the definition set
146void Compiler::addDefinition(const Expression* lvalue, const Expression* expr,
147 std::unordered_map<const Variable*, const Expression*>* definitions) {
148 switch (lvalue->fKind) {
149 case Expression::kVariableReference_Kind: {
150 const Variable& var = ((VariableReference*) lvalue)->fVariable;
151 if (var.fStorage == Variable::kLocal_Storage) {
152 (*definitions)[&var] = expr;
153 }
154 break;
155 }
156 case Expression::kSwizzle_Kind:
157 // We consider the variable written to as long as at least some of its components have
158 // been written to. This will lead to some false negatives (we won't catch it if you
159 // write to foo.x and then read foo.y), but being stricter could lead to false positives
160 // (we write to foo.x, and then pass foo to a function which happens to only read foo.x,
161 // but since we pass foo as a whole it is flagged as an error) unless we perform a much
162 // more complicated whole-program analysis. This is probably good enough.
163 this->addDefinition(((Swizzle*) lvalue)->fBase.get(),
164 fContext.fDefined_Expression.get(),
165 definitions);
166 break;
167 case Expression::kIndex_Kind:
168 // see comments in Swizzle
169 this->addDefinition(((IndexExpression*) lvalue)->fBase.get(),
170 fContext.fDefined_Expression.get(),
171 definitions);
172 break;
173 case Expression::kFieldAccess_Kind:
174 // see comments in Swizzle
175 this->addDefinition(((FieldAccess*) lvalue)->fBase.get(),
176 fContext.fDefined_Expression.get(),
177 definitions);
178 break;
179 default:
180 // not an lvalue, can't happen
181 ASSERT(false);
182 }
183}
184
185// add local variables defined by this node to the set
186void Compiler::addDefinitions(const BasicBlock::Node& node,
187 std::unordered_map<const Variable*, const Expression*>* definitions) {
188 switch (node.fKind) {
189 case BasicBlock::Node::kExpression_Kind: {
190 const Expression* expr = (Expression*) node.fNode;
191 if (expr->fKind == Expression::kBinary_Kind) {
192 const BinaryExpression* b = (BinaryExpression*) expr;
193 if (b->fOperator == Token::EQ) {
194 this->addDefinition(b->fLeft.get(), b->fRight.get(), definitions);
195 }
196 }
197 break;
198 }
199 case BasicBlock::Node::kStatement_Kind: {
200 const Statement* stmt = (Statement*) node.fNode;
201 if (stmt->fKind == Statement::kVarDeclarations_Kind) {
202 const VarDeclarationsStatement* vd = (VarDeclarationsStatement*) stmt;
203 for (const VarDeclaration& decl : vd->fDeclaration->fVars) {
204 if (decl.fValue) {
205 (*definitions)[decl.fVar] = decl.fValue.get();
206 }
207 }
208 }
209 break;
210 }
211 }
212}
213
214void Compiler::scanCFG(CFG* cfg, BlockId blockId, std::set<BlockId>* workList) {
215 BasicBlock& block = cfg->fBlocks[blockId];
216
217 // compute definitions after this block
218 std::unordered_map<const Variable*, const Expression*> after = block.fBefore;
219 for (const BasicBlock::Node& n : block.fNodes) {
220 this->addDefinitions(n, &after);
221 }
222
223 // propagate definitions to exits
224 for (BlockId exitId : block.fExits) {
225 BasicBlock& exit = cfg->fBlocks[exitId];
226 for (const auto& pair : after) {
227 const Expression* e1 = pair.second;
228 if (exit.fBefore.find(pair.first) == exit.fBefore.end()) {
229 exit.fBefore[pair.first] = e1;
230 } else {
231 const Expression* e2 = exit.fBefore[pair.first];
232 if (e1 != e2) {
233 // definition has changed, merge and add exit block to worklist
234 workList->insert(exitId);
235 if (!e1 || !e2) {
236 exit.fBefore[pair.first] = nullptr;
237 } else {
238 exit.fBefore[pair.first] = fContext.fDefined_Expression.get();
239 }
240 }
241 }
242 }
243 }
244}
245
246// returns a map which maps all local variables in the function to null, indicating that their value
247// is initially unknown
248static std::unordered_map<const Variable*, const Expression*> compute_start_state(const CFG& cfg) {
249 std::unordered_map<const Variable*, const Expression*> result;
250 for (const auto block : cfg.fBlocks) {
251 for (const auto node : block.fNodes) {
252 if (node.fKind == BasicBlock::Node::kStatement_Kind) {
253 const Statement* s = (Statement*) node.fNode;
254 if (s->fKind == Statement::kVarDeclarations_Kind) {
255 const VarDeclarationsStatement* vd = (const VarDeclarationsStatement*) s;
256 for (const VarDeclaration& decl : vd->fDeclaration->fVars) {
257 result[decl.fVar] = nullptr;
258 }
259 }
260 }
261 }
262 }
263 return result;
264}
265
266void Compiler::scanCFG(const FunctionDefinition& f) {
267 CFG cfg = CFGGenerator().getCFG(f);
268
269 // compute the data flow
270 cfg.fBlocks[cfg.fStart].fBefore = compute_start_state(cfg);
271 std::set<BlockId> workList;
272 for (BlockId i = 0; i < cfg.fBlocks.size(); i++) {
273 workList.insert(i);
274 }
275 while (workList.size()) {
276 BlockId next = *workList.begin();
277 workList.erase(workList.begin());
278 this->scanCFG(&cfg, next, &workList);
279 }
280
281 // check for unreachable code
282 for (size_t i = 0; i < cfg.fBlocks.size(); i++) {
283 if (i != cfg.fStart && !cfg.fBlocks[i].fEntrances.size() &&
284 cfg.fBlocks[i].fNodes.size()) {
285 this->error(cfg.fBlocks[i].fNodes[0].fNode->fPosition, "unreachable");
286 }
287 }
288 if (fErrorCount) {
289 return;
290 }
291
292 // check for undefined variables
293 for (const BasicBlock& b : cfg.fBlocks) {
294 std::unordered_map<const Variable*, const Expression*> definitions = b.fBefore;
295 for (const BasicBlock::Node& n : b.fNodes) {
296 if (n.fKind == BasicBlock::Node::kExpression_Kind) {
297 const Expression* expr = (const Expression*) n.fNode;
298 if (expr->fKind == Expression::kVariableReference_Kind) {
299 const Variable& var = ((VariableReference*) expr)->fVariable;
300 if (var.fStorage == Variable::kLocal_Storage &&
301 !definitions[&var]) {
302 this->error(expr->fPosition,
303 "'" + var.fName + "' has not been assigned");
304 }
305 }
306 }
307 this->addDefinitions(n, &definitions);
308 }
309 }
310
311 // check for missing return
312 if (f.fDeclaration.fReturnType != *fContext.fVoid_Type) {
313 if (cfg.fBlocks[cfg.fExit].fEntrances.size()) {
314 this->error(f.fPosition, "function can exit without returning a value");
315 }
316 }
317}
318
ethannicholasb3058bd2016-07-01 08:22:01 -0700319void Compiler::internalConvertProgram(std::string text,
ethannicholas5961bc92016-10-12 06:39:56 -0700320 Modifiers::Flag* defaultPrecision,
ethannicholasb3058bd2016-07-01 08:22:01 -0700321 std::vector<std::unique_ptr<ProgramElement>>* result) {
322 Parser parser(text, *fTypes, *this);
323 std::vector<std::unique_ptr<ASTDeclaration>> parsed = parser.file();
324 if (fErrorCount) {
325 return;
326 }
ethannicholas5961bc92016-10-12 06:39:56 -0700327 *defaultPrecision = Modifiers::kHighp_Flag;
ethannicholasb3058bd2016-07-01 08:22:01 -0700328 for (size_t i = 0; i < parsed.size(); i++) {
329 ASTDeclaration& decl = *parsed[i];
330 switch (decl.fKind) {
331 case ASTDeclaration::kVar_Kind: {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700332 std::unique_ptr<VarDeclarations> s = fIRGenerator->convertVarDeclarations(
333 (ASTVarDeclarations&) decl,
ethannicholasb3058bd2016-07-01 08:22:01 -0700334 Variable::kGlobal_Storage);
335 if (s) {
336 result->push_back(std::move(s));
337 }
338 break;
339 }
340 case ASTDeclaration::kFunction_Kind: {
341 std::unique_ptr<FunctionDefinition> f = fIRGenerator->convertFunction(
342 (ASTFunction&) decl);
ethannicholas22f939e2016-10-13 13:25:34 -0700343 if (!fErrorCount && f) {
344 this->scanCFG(*f);
ethannicholasb3058bd2016-07-01 08:22:01 -0700345 result->push_back(std::move(f));
346 }
347 break;
348 }
ethannicholas5961bc92016-10-12 06:39:56 -0700349 case ASTDeclaration::kModifiers_Kind: {
350 std::unique_ptr<ModifiersDeclaration> f = fIRGenerator->convertModifiersDeclaration(
351 (ASTModifiersDeclaration&) decl);
352 if (f) {
353 result->push_back(std::move(f));
354 }
355 break;
356 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700357 case ASTDeclaration::kInterfaceBlock_Kind: {
358 std::unique_ptr<InterfaceBlock> i = fIRGenerator->convertInterfaceBlock(
359 (ASTInterfaceBlock&) decl);
360 if (i) {
361 result->push_back(std::move(i));
362 }
363 break;
364 }
365 case ASTDeclaration::kExtension_Kind: {
366 std::unique_ptr<Extension> e = fIRGenerator->convertExtension((ASTExtension&) decl);
367 if (e) {
368 result->push_back(std::move(e));
369 }
370 break;
371 }
ethannicholas5961bc92016-10-12 06:39:56 -0700372 case ASTDeclaration::kPrecision_Kind: {
373 *defaultPrecision = ((ASTPrecision&) decl).fPrecision;
374 break;
375 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700376 default:
377 ABORT("unsupported declaration: %s\n", decl.description().c_str());
378 }
379 }
380}
381
382std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, std::string text) {
383 fErrorText = "";
384 fErrorCount = 0;
385 fIRGenerator->pushSymbolTable();
ethannicholasd598f792016-07-25 10:08:54 -0700386 std::vector<std::unique_ptr<ProgramElement>> elements;
ethannicholas5961bc92016-10-12 06:39:56 -0700387 Modifiers::Flag ignored;
ethannicholasb3058bd2016-07-01 08:22:01 -0700388 switch (kind) {
389 case Program::kVertex_Kind:
ethannicholas5961bc92016-10-12 06:39:56 -0700390 this->internalConvertProgram(SKSL_VERT_INCLUDE, &ignored, &elements);
ethannicholasb3058bd2016-07-01 08:22:01 -0700391 break;
392 case Program::kFragment_Kind:
ethannicholas5961bc92016-10-12 06:39:56 -0700393 this->internalConvertProgram(SKSL_FRAG_INCLUDE, &ignored, &elements);
ethannicholasb3058bd2016-07-01 08:22:01 -0700394 break;
395 }
ethannicholas5961bc92016-10-12 06:39:56 -0700396 Modifiers::Flag defaultPrecision;
397 this->internalConvertProgram(text, &defaultPrecision, &elements);
398 auto result = std::unique_ptr<Program>(new Program(kind, defaultPrecision, std::move(elements),
ethannicholasd598f792016-07-25 10:08:54 -0700399 fIRGenerator->fSymbolTable));;
ethannicholasb3058bd2016-07-01 08:22:01 -0700400 fIRGenerator->popSymbolTable();
401 this->writeErrorCount();
ethannicholasd598f792016-07-25 10:08:54 -0700402 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700403}
404
405void Compiler::error(Position position, std::string msg) {
406 fErrorCount++;
407 fErrorText += "error: " + position.description() + ": " + msg.c_str() + "\n";
408}
409
410std::string Compiler::errorText() {
411 std::string result = fErrorText;
412 return result;
413}
414
415void Compiler::writeErrorCount() {
416 if (fErrorCount) {
417 fErrorText += to_string(fErrorCount) + " error";
418 if (fErrorCount > 1) {
419 fErrorText += "s";
420 }
421 fErrorText += "\n";
422 }
423}
424
ethannicholasf789b382016-08-03 12:43:36 -0700425bool Compiler::toSPIRV(Program::Kind kind, const std::string& text, std::ostream& out) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700426 auto program = this->convertProgram(kind, text);
427 if (fErrorCount == 0) {
ethannicholasd598f792016-07-25 10:08:54 -0700428 SkSL::SPIRVCodeGenerator cg(&fContext);
ethannicholasb3058bd2016-07-01 08:22:01 -0700429 cg.generateCode(*program.get(), out);
430 ASSERT(!out.rdstate());
431 }
432 return fErrorCount == 0;
433}
434
ethannicholasf789b382016-08-03 12:43:36 -0700435bool Compiler::toSPIRV(Program::Kind kind, const std::string& text, std::string* out) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700436 std::stringstream buffer;
437 bool result = this->toSPIRV(kind, text, buffer);
438 if (result) {
439 *out = buffer.str();
440 }
ethannicholasf789b382016-08-03 12:43:36 -0700441 return result;
442}
443
444bool Compiler::toGLSL(Program::Kind kind, const std::string& text, GLCaps caps,
445 std::ostream& out) {
446 auto program = this->convertProgram(kind, text);
447 if (fErrorCount == 0) {
448 SkSL::GLSLCodeGenerator cg(&fContext, caps);
449 cg.generateCode(*program.get(), out);
450 ASSERT(!out.rdstate());
451 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700452 return fErrorCount == 0;
453}
454
ethannicholasf789b382016-08-03 12:43:36 -0700455bool Compiler::toGLSL(Program::Kind kind, const std::string& text, GLCaps caps,
456 std::string* out) {
457 std::stringstream buffer;
458 bool result = this->toGLSL(kind, text, caps, buffer);
459 if (result) {
460 *out = buffer.str();
461 }
462 return result;
463}
464
ethannicholasb3058bd2016-07-01 08:22:01 -0700465} // namespace