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_IRGENERATOR
9 #define SKSL_IRGENERATOR
10 
11 #include <unordered_map>
12 #include <unordered_set>
13 
14 #include "include/private/SkSLModifiers.h"
15 #include "include/private/SkSLStatement.h"
16 #include "src/sksl/SkSLASTFile.h"
17 #include "src/sksl/SkSLASTNode.h"
18 #include "src/sksl/SkSLErrorReporter.h"
19 #include "src/sksl/SkSLOperators.h"
20 #include "src/sksl/ir/SkSLBlock.h"
21 #include "src/sksl/ir/SkSLExpression.h"
22 #include "src/sksl/ir/SkSLExtension.h"
23 #include "src/sksl/ir/SkSLFunctionDefinition.h"
24 #include "src/sksl/ir/SkSLInterfaceBlock.h"
25 #include "src/sksl/ir/SkSLModifiersDeclaration.h"
26 #include "src/sksl/ir/SkSLProgram.h"
27 #include "src/sksl/ir/SkSLSection.h"
28 #include "src/sksl/ir/SkSLSymbolTable.h"
29 #include "src/sksl/ir/SkSLType.h"
30 #include "src/sksl/ir/SkSLTypeReference.h"
31 #include "src/sksl/ir/SkSLVarDeclarations.h"
32 #include "src/sksl/ir/SkSLVariableReference.h"
33 
34 namespace SkSL {
35 
36 namespace dsl {
37     class DSLCore;
38     class DSLFunction;
39     class DSLVar;
40     class DSLWriter;
41 }
42 
43 class ExternalFunction;
44 class FunctionCall;
45 class StructDefinition;
46 struct ParsedModule;
47 struct Swizzle;
48 
49 /**
50  * Intrinsics are passed between the Compiler and the IRGenerator using IRIntrinsicMaps.
51  */
52 class IRIntrinsicMap {
53 public:
IRIntrinsicMap(IRIntrinsicMap * parent)54     IRIntrinsicMap(IRIntrinsicMap* parent) : fParent(parent) {}
55 
insertOrDie(String key,std::unique_ptr<ProgramElement> element)56     void insertOrDie(String key, std::unique_ptr<ProgramElement> element) {
57         SkASSERT(fIntrinsics.find(key) == fIntrinsics.end());
58         fIntrinsics[key] = Intrinsic{std::move(element), false};
59     }
60 
find(const String & key)61     const ProgramElement* find(const String& key) {
62         auto iter = fIntrinsics.find(key);
63         if (iter == fIntrinsics.end()) {
64             return fParent ? fParent->find(key) : nullptr;
65         }
66         return iter->second.fIntrinsic.get();
67     }
68 
69     // Only returns an intrinsic that isn't already marked as included, and then marks it.
findAndInclude(const String & key)70     const ProgramElement* findAndInclude(const String& key) {
71         auto iter = fIntrinsics.find(key);
72         if (iter == fIntrinsics.end()) {
73             return fParent ? fParent->findAndInclude(key) : nullptr;
74         }
75         if (iter->second.fAlreadyIncluded) {
76             return nullptr;
77         }
78         iter->second.fAlreadyIncluded = true;
79         return iter->second.fIntrinsic.get();
80     }
81 
resetAlreadyIncluded()82     void resetAlreadyIncluded() {
83         for (auto& pair : fIntrinsics) {
84             pair.second.fAlreadyIncluded = false;
85         }
86         if (fParent) {
87             fParent->resetAlreadyIncluded();
88         }
89     }
90 
91 private:
92     struct Intrinsic {
93         std::unique_ptr<ProgramElement> fIntrinsic;
94         bool fAlreadyIncluded = false;
95     };
96 
97     std::unordered_map<String, Intrinsic> fIntrinsics;
98     IRIntrinsicMap* fParent = nullptr;
99 };
100 
101 /**
102  * Performs semantic analysis on an abstract syntax tree (AST) and produces the corresponding
103  * (unoptimized) intermediate representation (IR).
104  */
105 class IRGenerator {
106 public:
107     IRGenerator(const Context* context);
108 
109     struct IRBundle {
110         std::vector<std::unique_ptr<ProgramElement>> fElements;
111         std::vector<const ProgramElement*>           fSharedElements;
112         std::shared_ptr<SymbolTable>                 fSymbolTable;
113         Program::Inputs                              fInputs;
114     };
115 
116     /**
117      * If externalFuncs is supplied, those values are registered in the symbol table of the
118      * Program, but ownership is *not* transferred. It is up to the caller to keep them alive.
119      */
120     IRBundle convertProgram(
121             const ParsedModule& base,
122             bool isBuiltinCode,
123             const char* text,
124             size_t length,
125             const std::vector<std::unique_ptr<ExternalFunction>>* externalFunctions);
126 
settings()127     const Program::Settings& settings() const { return fContext.fConfig->fSettings; }
programKind()128     ProgramKind programKind() const { return fContext.fConfig->fKind; }
129 
errorReporter()130     ErrorReporter& errorReporter() const { return fContext.fErrors; }
131 
symbolTable()132     std::shared_ptr<SymbolTable>& symbolTable() {
133         return fSymbolTable;
134     }
135 
setSymbolTable(std::shared_ptr<SymbolTable> & symbolTable)136     void setSymbolTable(std::shared_ptr<SymbolTable>& symbolTable) {
137         fSymbolTable = symbolTable;
138     }
139 
140     void pushSymbolTable();
141     void popSymbolTable();
142 
143     static void CheckModifiers(const Context& context,
144                                int offset,
145                                const Modifiers& modifiers,
146                                int permittedModifierFlags,
147                                int permittedLayoutFlags);
148 
149     std::unique_ptr<Expression> convertIdentifier(int offset, StringFragment identifier);
150 
151     const Context& fContext;
152 
153 private:
154     void start(const ParsedModule& base,
155                bool isBuiltinCode,
156                const std::vector<std::unique_ptr<ExternalFunction>>* externalFunctions,
157                std::vector<std::unique_ptr<ProgramElement>>* elements,
158                std::vector<const ProgramElement*>* sharedElements);
159 
160     IRGenerator::IRBundle finish();
161 
162     void checkVarDeclaration(int offset,
163                              const Modifiers& modifiers,
164                              const Type* baseType,
165                              Variable::Storage storage);
166     std::unique_ptr<Variable> convertVar(int offset, const Modifiers& modifiers,
167                                          const Type* baseType, StringFragment name, bool isArray,
168                                          std::unique_ptr<Expression> arraySize,
169                                          Variable::Storage storage);
170     std::unique_ptr<Statement> convertVarDeclaration(std::unique_ptr<Variable> var,
171                                                      std::unique_ptr<Expression> value);
172     std::unique_ptr<Statement> convertVarDeclaration(int offset, const Modifiers& modifiers,
173                                                      const Type* baseType, StringFragment name,
174                                                      bool isArray,
175                                                      std::unique_ptr<Expression> arraySize,
176                                                      std::unique_ptr<Expression> value,
177                                                      Variable::Storage storage);
178     StatementArray convertVarDeclarations(const ASTNode& decl, Variable::Storage storage);
179     void convertFunction(const ASTNode& f);
180     std::unique_ptr<Statement> convertStatement(const ASTNode& statement);
181     std::unique_ptr<Expression> convertExpression(const ASTNode& expression);
182     std::unique_ptr<ModifiersDeclaration> convertModifiersDeclaration(const ASTNode& m);
183 
184     const Type* convertType(const ASTNode& type, bool allowVoid = false);
185     std::unique_ptr<Expression> call(int offset,
186                                      std::unique_ptr<Expression> function,
187                                      ExpressionArray arguments);
188     std::unique_ptr<Expression> call(int offset,
189                                      const FunctionDeclaration& function,
190                                      ExpressionArray arguments);
191     CoercionCost callCost(const FunctionDeclaration& function,
192                           const ExpressionArray& arguments);
193     std::unique_ptr<Expression> coerce(std::unique_ptr<Expression> expr, const Type& type);
194     CoercionCost coercionCost(const Expression& expr, const Type& type);
195     int convertArraySize(const Type& type, int offset, const ASTNode& s);
196     int convertArraySize(const Type& type, std::unique_ptr<Expression> s);
197     bool containsConstantZero(Expression& expr);
198     bool dividesByZero(Operator op, Expression& right);
199     std::unique_ptr<Block> convertBlock(const ASTNode& block);
200     std::unique_ptr<Statement> convertBreak(const ASTNode& b);
201     std::unique_ptr<Statement> convertContinue(const ASTNode& c);
202     std::unique_ptr<Statement> convertDiscard(const ASTNode& d);
203     std::unique_ptr<Statement> convertDo(const ASTNode& d);
204     std::unique_ptr<Statement> convertSwitch(const ASTNode& s);
205     std::unique_ptr<Expression> convertBinaryExpression(const ASTNode& expression);
206     std::unique_ptr<Extension> convertExtension(int offset, StringFragment name);
207     std::unique_ptr<Statement> convertExpressionStatement(const ASTNode& s);
208     std::unique_ptr<Expression> convertField(std::unique_ptr<Expression> base,
209                                              StringFragment field);
210     std::unique_ptr<Statement> convertFor(const ASTNode& f);
211     std::unique_ptr<Expression> convertIdentifier(const ASTNode& identifier);
212     std::unique_ptr<Statement> convertIf(const ASTNode& s);
213     std::unique_ptr<InterfaceBlock> convertInterfaceBlock(const ASTNode& s);
214     Modifiers convertModifiers(const Modifiers& m);
215     std::unique_ptr<Expression> convertPrefixExpression(const ASTNode& expression);
216     std::unique_ptr<Statement> convertReturn(int offset, std::unique_ptr<Expression> result);
217     std::unique_ptr<Statement> convertReturn(const ASTNode& r);
218     std::unique_ptr<Section> convertSection(const ASTNode& e);
219     std::unique_ptr<Expression> convertCallExpression(const ASTNode& expression);
220     std::unique_ptr<Expression> convertFieldExpression(const ASTNode& expression);
221     std::unique_ptr<Expression> convertIndexExpression(const ASTNode& expression);
222     std::unique_ptr<Expression> convertPostfixExpression(const ASTNode& expression);
223     std::unique_ptr<Expression> convertScopeExpression(const ASTNode& expression);
224     std::unique_ptr<StructDefinition> convertStructDefinition(const ASTNode& expression);
225     std::unique_ptr<Expression> convertTypeField(int offset, const Type& type,
226                                                  StringFragment field);
227     std::unique_ptr<Expression> convertSwizzle(std::unique_ptr<Expression> base, String fields);
228     std::unique_ptr<Expression> convertTernaryExpression(const ASTNode& expression);
229     std::unique_ptr<Statement> convertVarDeclarationStatement(const ASTNode& s);
230     std::unique_ptr<Statement> convertWhile(const ASTNode& w);
231     void convertGlobalVarDeclarations(const ASTNode& decl);
232     void convertEnum(const ASTNode& e);
233     std::unique_ptr<Block> applyInvocationIDWorkaround(std::unique_ptr<Block> main);
234     // returns a statement which converts sk_Position from device to normalized coordinates
235     std::unique_ptr<Statement> getNormalizeSkPositionCode();
236 
237     void checkValid(const Expression& expr);
238     bool typeContainsPrivateFields(const Type& type);
239     bool setRefKind(Expression& expr, VariableReference::RefKind kind);
240     void copyIntrinsicIfNeeded(const FunctionDeclaration& function);
241     void findAndDeclareBuiltinVariables();
242     bool detectVarDeclarationWithoutScope(const Statement& stmt);
243     // Coerces returns to correct type and detects invalid break / continue placement
244     void finalizeFunction(const FunctionDeclaration& funcDecl, Statement* body);
245 
246     // Runtime effects (and the interpreter, which uses the same CPU runtime) require adherence to
247     // the strict rules from The OpenGL ES Shading Language Version 1.00. (Including Appendix A).
strictES2Mode()248     bool strictES2Mode() const {
249         return fContext.fConfig->strictES2Mode();
250     }
251 
caps()252     const ShaderCapsClass& caps() const {
253         return fContext.fCaps;
254     }
255 
modifiersPool()256     ModifiersPool& modifiersPool() const {
257         return *fContext.fModifiersPool;
258     }
259 
260     Program::Inputs fInputs;
261 
262     std::unique_ptr<ASTFile> fFile;
263 
264     std::shared_ptr<SymbolTable> fSymbolTable = nullptr;
265     // Symbols which have definitions in the include files.
266     IRIntrinsicMap* fIntrinsics = nullptr;
267     std::unordered_set<const FunctionDeclaration*> fReferencedIntrinsics;
268     int fInvocations;
269     std::unordered_set<const Type*> fDefinedStructs;
270     std::vector<std::unique_ptr<ProgramElement>>* fProgramElements = nullptr;
271     std::vector<const ProgramElement*>*           fSharedElements = nullptr;
272     const Variable* fRTAdjust = nullptr;
273     const Variable* fRTAdjustInterfaceBlock = nullptr;
274     int fRTAdjustFieldIndex;
275     // true if we are currently processing one of the built-in SkSL include files
276     bool fIsBuiltinCode = false;
277 
278     friend class AutoSymbolTable;
279     friend class AutoLoopLevel;
280     friend class AutoSwitchLevel;
281     friend class AutoDisableInline;
282     friend class Compiler;
283     friend class dsl::DSLCore;
284     friend class dsl::DSLFunction;
285     friend class dsl::DSLVar;
286     friend class dsl::DSLWriter;
287 };
288 
289 }  // namespace SkSL
290 
291 #endif
292