1 /* 2 * Copyright 2020 Google LLC. 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_REHYDRATOR 9 #define SKSL_REHYDRATOR 10 11 #include "include/private/SkSLDefines.h" 12 #include "include/private/SkSLModifiers.h" 13 #include "include/private/SkSLSymbol.h" 14 #include "src/sksl/SkSLContext.h" 15 #include "src/sksl/ir/SkSLProgram.h" 16 17 #include <vector> 18 19 namespace SkSL { 20 21 class Compiler; 22 class Context; 23 class ErrorReporter; 24 class Expression; 25 class ProgramElement; 26 class Statement; 27 class SymbolTable; 28 class Type; 29 30 /** 31 * Interprets a simple bytecode format that encodes the structure of an SkSL IR tree. This is used 32 * to process the .sksl files representing SkSL's core include files, so that they can be quickly 33 * reconstituted at runtime. 34 */ 35 class Rehydrator { 36 public: 37 static constexpr uint16_t kVersion = 8; 38 39 // see binary_format.md for a description of the command data 40 enum Command { 41 kArrayType_Command, 42 kBinary_Command, 43 kBlock_Command, 44 kBoolLiteral_Command, 45 kBreak_Command, 46 kBuiltinLayout_Command, 47 kConstructorArray_Command, 48 kConstructorArrayCast_Command, 49 kConstructorCompound_Command, 50 kConstructorCompoundCast_Command, 51 kConstructorDiagonalMatrix_Command, 52 kConstructorMatrixResize_Command, 53 kConstructorScalarCast_Command, 54 kConstructorSplat_Command, 55 kConstructorStruct_Command, 56 kContinue_Command, 57 kDefaultLayout_Command, 58 kDefaultModifiers_Command, 59 kDiscard_Command, 60 kDo_Command, 61 kElements_Command, 62 kElementsComplete_Command, 63 kExpressionStatement_Command, 64 kField_Command, 65 kFieldAccess_Command, 66 kFloatLiteral_Command, 67 kFor_Command, 68 kFunctionCall_Command, 69 kFunctionDeclaration_Command, 70 kFunctionDefinition_Command, 71 kFunctionPrototype_Command, 72 kGlobalVar_Command, 73 kIf_Command, 74 kIndex_Command, 75 kInlineMarker_Command, 76 kInterfaceBlock_Command, 77 kIntLiteral_Command, 78 kLayout_Command, 79 kModifiers8Bit_Command, 80 kModifiers_Command, 81 kNop_Command, 82 kPostfix_Command, 83 kPrefix_Command, 84 kProgram_Command, 85 kReturn_Command, 86 kSetting_Command, 87 kSharedFunction_Command, 88 kStructDefinition_Command, 89 kStructType_Command, 90 kSwitch_Command, 91 kSwizzle_Command, 92 kSymbolRef_Command, 93 kSymbolTable_Command, 94 kTernary_Command, 95 kUnresolvedFunction_Command, 96 kVariable_Command, 97 kVarDeclaration_Command, 98 kVariableReference_Command, 99 kVoid_Command, 100 }; 101 102 // src must remain in memory as long as the objects created from it do 103 Rehydrator(Compiler& compiler, const uint8_t* src, size_t length, 104 std::shared_ptr<SymbolTable> base = nullptr); 105 106 #ifdef SK_DEBUG 107 ~Rehydrator(); 108 #endif 109 110 // Reads a symbol table and makes it current (inheriting from the previous current table) 111 std::shared_ptr<SymbolTable> symbolTable(); 112 113 // Reads a collection of program elements and returns it 114 std::vector<std::unique_ptr<ProgramElement>> elements(); 115 116 // Reads an entire program. 117 // 118 // NOTE: The program is initialized using a new ProgramConfig that may differ from the one that 119 // was assigned to the context of the Compiler this Rehydrator was constructed with. 120 std::unique_ptr<Program> program(); 121 122 private: 123 // If this ID appears in place of a symbol ID, it means the corresponding symbol isn't actually 124 // present in the file as it's a builtin. The string name of the symbol follows. 125 static constexpr uint16_t kBuiltin_Symbol = 65535; 126 readS8()127 int8_t readS8() { 128 SkASSERT(fIP < fEnd); 129 return *(fIP++); 130 } 131 readU8()132 uint8_t readU8() { 133 return this->readS8(); 134 } 135 readS16()136 int16_t readS16() { 137 uint8_t b1 = this->readU8(); 138 uint8_t b2 = this->readU8(); 139 return (b2 << 8) + b1; 140 } 141 readU16()142 uint16_t readU16() { 143 return this->readS16(); 144 } 145 readS32()146 int32_t readS32() { 147 uint8_t b1 = this->readU8(); 148 uint8_t b2 = this->readU8(); 149 uint8_t b3 = this->readU8(); 150 uint8_t b4 = this->readU8(); 151 return (b4 << 24) + (b3 << 16) + (b2 << 8) + b1; 152 } 153 readU32()154 uint32_t readU32() { 155 return this->readS32(); 156 } 157 readString()158 std::string_view readString() { 159 uint16_t offset = this->readU16(); 160 uint8_t length = *(uint8_t*) (fStringStart + offset); 161 const char* chars = (const char*) fStringStart + offset + 1; 162 return std::string_view(chars, length); 163 } 164 addSymbol(int id,const Symbol * symbol)165 void addSymbol(int id, const Symbol* symbol) { 166 while ((size_t) id >= fSymbols.size()) { 167 fSymbols.push_back(nullptr); 168 } 169 fSymbols[id] = symbol; 170 } 171 172 template<typename T> symbolRef(Symbol::Kind kind)173 T* symbolRef(Symbol::Kind kind) { 174 uint16_t result = this->readU16(); 175 SkASSERT(fSymbols.size() > result); 176 return (T*) fSymbols[result]; 177 } 178 179 /** 180 * Reads either a symbol belonging to this program, or a named reference to a builtin symbol. 181 * This has to be a separate method from symbolRef() because builtin symbols can be const, and 182 * thus this method must have a const return, but there is at least one case in which we 183 * specifically require a non-const return value. 184 */ possiblyBuiltinSymbolRef()185 const Symbol* possiblyBuiltinSymbolRef() { 186 uint16_t id = this->readU16(); 187 if (id == kBuiltin_Symbol) { 188 std::string_view name = this->readString(); 189 const Symbol* result = (*fSymbolTable)[name]; 190 SkASSERTF(result, "symbol '%s' not found", std::string(name).c_str()); 191 return result; 192 } 193 SkASSERT(fSymbols.size() > id); 194 return fSymbols[id]; 195 } 196 197 Layout layout(); 198 199 Modifiers modifiers(); 200 201 const Symbol* symbol(); 202 203 std::unique_ptr<ProgramElement> element(); 204 205 std::unique_ptr<Statement> statement(); 206 207 std::unique_ptr<Expression> expression(); 208 209 ExpressionArray expressionArray(); 210 211 const Type* type(); 212 213 Context& context() const; 214 errorReporter()215 ErrorReporter* errorReporter() const { return this->context().fErrors; } 216 modifiersPool()217 ModifiersPool& modifiersPool() const { return *this->context().fModifiersPool; } 218 219 Compiler& fCompiler; 220 std::shared_ptr<SymbolTable> fSymbolTable; 221 std::vector<const Symbol*> fSymbols; 222 223 const uint8_t* fStringStart; 224 const uint8_t* fIP; 225 SkDEBUGCODE(const uint8_t* fEnd;) 226 227 friend class AutoRehydratorSymbolTable; 228 friend class Dehydrator; 229 }; 230 231 } // namespace SkSL 232 233 #endif 234