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