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_COMPILER 9 #define SKSL_COMPILER 10 11 #include <set> 12 #include <unordered_set> 13 #include <vector> 14 #include "src/sksl/SkSLByteCode.h" 15 #include "src/sksl/SkSLCFGGenerator.h" 16 #include "src/sksl/SkSLContext.h" 17 #include "src/sksl/SkSLErrorReporter.h" 18 #include "src/sksl/SkSLLexer.h" 19 #include "src/sksl/ir/SkSLProgram.h" 20 #include "src/sksl/ir/SkSLSymbolTable.h" 21 22 #define SK_FRAGCOLOR_BUILTIN 10001 23 #define SK_IN_BUILTIN 10002 24 #define SK_INCOLOR_BUILTIN 10003 25 #define SK_OUTCOLOR_BUILTIN 10004 26 #define SK_TRANSFORMEDCOORDS2D_BUILTIN 10005 27 #define SK_TEXTURESAMPLERS_BUILTIN 10006 28 #define SK_OUT_BUILTIN 10007 29 #define SK_LASTFRAGCOLOR_BUILTIN 10008 30 #define SK_MAIN_X_BUILTIN 10009 31 #define SK_MAIN_Y_BUILTIN 10010 32 #define SK_WIDTH_BUILTIN 10011 33 #define SK_HEIGHT_BUILTIN 10012 34 #define SK_FRAGCOORD_BUILTIN 15 35 #define SK_CLOCKWISE_BUILTIN 17 36 #define SK_VERTEXID_BUILTIN 42 37 #define SK_INSTANCEID_BUILTIN 43 38 #define SK_CLIPDISTANCE_BUILTIN 3 39 #define SK_INVOCATIONID_BUILTIN 8 40 #define SK_POSITION_BUILTIN 0 41 42 namespace SkSL { 43 44 class IRGenerator; 45 46 /** 47 * Main compiler entry point. This is a traditional compiler design which first parses the .sksl 48 * file into an abstract syntax tree (a tree of ASTNodes), then performs semantic analysis to 49 * produce a Program (a tree of IRNodes), then feeds the Program into a CodeGenerator to produce 50 * compiled output. 51 * 52 * See the README for information about SkSL. 53 */ 54 class SK_API Compiler : public ErrorReporter { 55 public: 56 static constexpr const char* RTADJUST_NAME = "sk_RTAdjust"; 57 static constexpr const char* PERVERTEX_NAME = "sk_PerVertex"; 58 59 enum Flags { 60 kNone_Flags = 0, 61 // permits static if/switch statements to be used with non-constant tests. This is used when 62 // producing H and CPP code; the static tests don't have to have constant values *yet*, but 63 // the generated code will contain a static test which then does have to be a constant. 64 kPermitInvalidStaticTests_Flag = 1, 65 }; 66 67 struct FormatArg { 68 enum class Kind { 69 kInput, 70 kOutput, 71 kCoordX, 72 kCoordY, 73 kUniform, 74 kChildProcessor 75 }; 76 FormatArgFormatArg77 FormatArg(Kind kind) 78 : fKind(kind) {} 79 FormatArgFormatArg80 FormatArg(Kind kind, int index) 81 : fKind(kind) 82 , fIndex(index) {} 83 84 Kind fKind; 85 86 int fIndex; 87 }; 88 89 Compiler(Flags flags = kNone_Flags); 90 91 ~Compiler() override; 92 93 Compiler(const Compiler&) = delete; 94 Compiler& operator=(const Compiler&) = delete; 95 96 /** 97 * Registers an ExternalValue as a top-level symbol which is visible in the global namespace. 98 */ 99 void registerExternalValue(ExternalValue* value); 100 101 std::unique_ptr<Program> convertProgram(Program::Kind kind, String text, 102 const Program::Settings& settings); 103 104 bool optimize(Program& program); 105 106 std::unique_ptr<Program> specialize(Program& program, 107 const std::unordered_map<SkSL::String, SkSL::Program::Settings::Value>& inputs); 108 109 bool toSPIRV(Program& program, OutputStream& out); 110 111 bool toSPIRV(Program& program, String* out); 112 113 bool toGLSL(Program& program, OutputStream& out); 114 115 bool toGLSL(Program& program, String* out); 116 117 bool toMetal(Program& program, OutputStream& out); 118 119 bool toMetal(Program& program, String* out); 120 121 bool toCPP(Program& program, String name, OutputStream& out); 122 123 bool toH(Program& program, String name, OutputStream& out); 124 125 std::unique_ptr<ByteCode> toByteCode(Program& program); 126 127 bool toPipelineStage(const Program& program, String* out, 128 std::vector<FormatArg>* outFormatArgs); 129 130 /** 131 * Takes ownership of the given symbol. It will be destroyed when the compiler is destroyed. 132 */ 133 Symbol* takeOwnership(std::unique_ptr<Symbol> symbol); 134 135 void error(int offset, String msg) override; 136 137 String errorText(); 138 139 void writeErrorCount(); 140 errorCount()141 int errorCount() override { 142 return fErrorCount; 143 } 144 context()145 Context& context() { 146 return *fContext; 147 } 148 149 static const char* OperatorName(Token::Kind token); 150 151 static bool IsAssignment(Token::Kind token); 152 153 private: 154 void processIncludeFile(Program::Kind kind, const char* src, size_t length, 155 std::shared_ptr<SymbolTable> base, 156 std::vector<std::unique_ptr<ProgramElement>>* outElements, 157 std::shared_ptr<SymbolTable>* outSymbolTable); 158 159 void addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr, 160 DefinitionMap* definitions); 161 162 void addDefinitions(const BasicBlock::Node& node, DefinitionMap* definitions); 163 164 void scanCFG(CFG* cfg, BlockId block, std::set<BlockId>* workList); 165 166 void computeDataFlow(CFG* cfg); 167 168 /** 169 * Simplifies the expression pointed to by iter (in both the IR and CFG structures), if 170 * possible. 171 */ 172 void simplifyExpression(DefinitionMap& definitions, 173 BasicBlock& b, 174 std::vector<BasicBlock::Node>::iterator* iter, 175 std::unordered_set<const Variable*>* undefinedVariables, 176 bool* outUpdated, 177 bool* outNeedsRescan); 178 179 /** 180 * Simplifies the statement pointed to by iter (in both the IR and CFG structures), if 181 * possible. 182 */ 183 void simplifyStatement(DefinitionMap& definitions, 184 BasicBlock& b, 185 std::vector<BasicBlock::Node>::iterator* iter, 186 std::unordered_set<const Variable*>* undefinedVariables, 187 bool* outUpdated, 188 bool* outNeedsRescan); 189 190 void scanCFG(FunctionDefinition& f); 191 192 Position position(int offset); 193 194 std::shared_ptr<SymbolTable> fGpuSymbolTable; 195 std::vector<std::unique_ptr<ProgramElement>> fVertexInclude; 196 std::shared_ptr<SymbolTable> fVertexSymbolTable; 197 std::vector<std::unique_ptr<ProgramElement>> fFragmentInclude; 198 std::shared_ptr<SymbolTable> fFragmentSymbolTable; 199 std::vector<std::unique_ptr<ProgramElement>> fGeometryInclude; 200 std::shared_ptr<SymbolTable> fGeometrySymbolTable; 201 std::vector<std::unique_ptr<ProgramElement>> fPipelineInclude; 202 std::shared_ptr<SymbolTable> fPipelineSymbolTable; 203 std::vector<std::unique_ptr<ProgramElement>> fInterpreterInclude; 204 std::shared_ptr<SymbolTable> fInterpreterSymbolTable; 205 206 std::shared_ptr<SymbolTable> fTypes; 207 IRGenerator* fIRGenerator; 208 int fFlags; 209 210 const String* fSource; 211 std::shared_ptr<Context> fContext; 212 int fErrorCount; 213 String fErrorText; 214 }; 215 216 } // namespace 217 218 #endif 219