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 "src/sksl/SkSLDefines.h"
12
13#include "src/sksl/ir/SkSLModifiers.h"
14#include "src/sksl/ir/SkSLSymbol.h"
15
16#include <vector>
17
18namespace SkSL {
19
20class Context;
21class ErrorReporter;
22struct Expression;
23struct ProgramElement;
24struct Statement;
25class SymbolTable;
26class Type;
27
28union FloatIntUnion {
29 float fFloat;
30 int32_t fInt;
31};
32
33/**
34 * Interprets a simple bytecode format that encodes the structure of an SkSL IR tree. This is used
35 * to process the .sksl files representing SkSL's core include files, so that they can be quickly
36 * reconstituted at runtime.
37 */
38class Rehydrator {
39public:
40 enum Command {
41 // uint16 id, Type componentType, uint8 count
42 kArrayType_Command,
43 // Expression left, uint8 op, Expression right, Type type
44 kBinary_Command,
45 // SymbolTable symbolTable, uint8 statementCount, Statement[] statements, bool isScope
46 kBlock_Command,
47 // bool value
48 kBoolLiteral_Command,
49 kBreak_Command,
50 // int16 builtin
51 kBuiltinLayout_Command,
52 // Type type, uint8 argCount, Expression[] arguments
53 kConstructor_Command,
54 kContinue_Command,
55 kDefaultLayout_Command,
56 kDefaultModifiers_Command,
57 kDiscard_Command,
58 // Statement stmt, Expression test
59 kDo_Command,
60 // uint8 count, uint8 index
61 kElements_Command,
62 // String typeName, SymbolTable symbols, int32[] values
63 kEnum_Command,
64 // uint16 id, String name
65 kEnumType_Command,
66 // Expression expression
67 kExpressionStatement_Command,
68 // uint16 ownerId, uint8 index
69 kField_Command,
70 // Expression base, uint8 index, uint8 ownerKind
71 kFieldAccess_Command,
72 // float value
73 kFloatLiteral_Command,
74 // Statement initializer, Expression test, Expression next, Statement body,
75 // SymbolTable symbols
76 kFor_Command,
77 // Type type, uint16 function, uint8 argCount, Expression[] arguments
78 kFunctionCall_Command,
79 // uint16 declaration, Statement body, uint8 refCount, uint16[] referencedIntrinsics
80 kFunctionDefinition_Command,
81 // uint16 id, Modifiers modifiers, String name, uint8 parameterCount, uint16[] parameterIds,
82 // Type returnType
83 kFunctionDeclaration_Command,
84 // bool isStatic, Expression test, Statement ifTrue, Statement ifFalse
85 kIf_Command,
86 // Expression base, Expression index
87 kIndex_Command,
88 // Variable* var, String typeName, String instanceName, uint8 sizeCount, Expression[] sizes
89 kInterfaceBlock_Command,
90 // int32 value
91 kIntLiteral_Command,
92 // int32 flags, int8 location, int8 offset, int8 binding, int8 index, int8 set,
93 // int16 builtin, int8 inputAttachmentIndex, int8 format, int8 primitive, int8 maxVertices,
94 // int8 invocations, String marker, String when, int8 key, int8 ctype
95 kLayout_Command,
96 // Layout layout, uint8 flags
97 kModifiers8Bit_Command,
98 // Layout layout, uint32 flags
99 kModifiers_Command,
100 // uint16 id, Type baseType
101 kNullableType_Command,
102 kNullLiteral_Command,
103 // uint8 op, Expression operand
104 kPostfix_Command,
105 // uint8 op, Expression operand
106 kPrefix_Command,
107 // Expression value
108 kReturn_Command,
109 // String name, Expression value
110 kSetting_Command,
111 // uint16 id, String name, uint8 fieldCount, (Modifiers, String, Type)[] fields
112 kStructType_Command,
113 // bool isStatic, SymbolTable symbols, Expression value, uint8 caseCount,
114 // (Expression value, uint8 statementCount, Statement[] statements)[] cases
115 kSwitch_Command,
116 // Expression base, uint8 componentCount, uint8[] components
117 kSwizzle_Command,
118 // uint16 id
119 kSymbolRef_Command,
120 // uint16 owned symbol count, Symbol[] ownedSymbols, uint16 symbol count,
121 // (String, uint16/*index*/)[].
122 kSymbolTable_Command,
123 // uint16 id, String name
124 kSystemType_Command,
125 // Expression test, Expression ifTrue, Expression ifFalse
126 kTernary_Command,
127 // uint16 id, FunctionDeclaration[] functions
128 kUnresolvedFunction_Command,
129 // uint16 id, Modifiers modifiers, String name, Type type, uint8 storage
130 kVariable_Command,
131 // uint16 varId, uint8 sizeCount, Expression[] sizes, Expression? value
132 kVarDeclaration_Command,
133 // Type baseType, uint8 varCount, VarDeclaration vars
134 kVarDeclarations_Command,
135 // uint16 varId, uint8 refKind
136 kVariableReference_Command,
137 kVoid_Command,
138 // Expression test, Statement body
139 kWhile_Command,
140 };
141
142 // src must remain in memory as long as the objects created from it do
143 Rehydrator(Context* context, std::shared_ptr<SymbolTable> symbolTable,
144 ErrorReporter* errorReporter, const uint8_t* src, size_t length)
145 : fContext(*context)
146 , fSymbolTable(std::move(symbolTable))
147 , fStart(src)
148 SkDEBUGCODE(, fEnd(fStart + length)) {
149 SkASSERT(fSymbolTable);
150 // skip past string data
151 fIP = fStart;
152 fIP += this->readU16();
153 }
154
155 std::vector<std::unique_ptr<ProgramElement>> elements();
156
157 std::shared_ptr<SymbolTable> symbolTable();
158
159private:
160 int8_t readS8() {
161 SkASSERT(fIP < fEnd);
162 return *(fIP++);
163 }
164
165 uint8_t readU8() {
166 return this->readS8();
167 }
168
169 int16_t readS16() {
170 uint8_t b1 = this->readU8();
171 uint8_t b2 = this->readU8();
172 return (b2 << 8) + b1;
173 }
174
175 uint16_t readU16() {
176 return this->readS16();
177 }
178
179 int32_t readS32() {
180 uint8_t b1 = this->readU8();
181 uint8_t b2 = this->readU8();
182 uint8_t b3 = this->readU8();
183 uint8_t b4 = this->readU8();
184 return (b4 << 24) + (b3 << 16) + (b2 << 8) + b1;
185 }
186
187 uint32_t readU32() {
188 return this->readS32();
189 }
190
191 StringFragment readString() {
192 uint16_t offset = this->readU16();
193 uint8_t length = *(uint8_t*) (fStart + offset);
194 const char* chars = (const char*) fStart + offset + 1;
195 return StringFragment(chars, length);
196 }
197
198 void addSymbol(int id, const Symbol* symbol) {
199 while ((size_t) id >= fSymbols.size()) {
200 fSymbols.push_back(nullptr);
201 }
202 fSymbols[id] = symbol;
203 }
204
205 template<typename T>
206 T* symbolRef(Symbol::Kind kind) {
207 uint16_t result = this->readU16();
208 SkASSERT(fSymbols.size() > result);
209 return (T*) fSymbols[result];
210 }
211
212 Layout layout();
213
214 Modifiers modifiers();
215
216 const Symbol* symbol();
217
218 std::unique_ptr<ProgramElement> element();
219
220 std::unique_ptr<Statement> statement();
221
222 std::unique_ptr<Expression> expression();
223
224 const Type* type();
225
226 Context& fContext;
227 std::shared_ptr<SymbolTable> fSymbolTable;
228 std::vector<const Symbol*> fSymbols;
229
230 const uint8_t* fStart;
231 const uint8_t* fIP;
232 SkDEBUGCODE(const uint8_t* fEnd;)
233
234 friend class AutoRehydratorSymbolTable;
235};
236
237} // namespace SkSL
238
239#endif
240