• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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