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 #include "src/sksl/SkSLRehydrator.h"
9
10 #include <memory>
11 #include <unordered_set>
12
13 #include "include/private/SkSLModifiers.h"
14 #include "include/private/SkSLProgramElement.h"
15 #include "include/private/SkSLStatement.h"
16 #include "src/sksl/ir/SkSLBinaryExpression.h"
17 #include "src/sksl/ir/SkSLBreakStatement.h"
18 #include "src/sksl/ir/SkSLConstructor.h"
19 #include "src/sksl/ir/SkSLConstructorArray.h"
20 #include "src/sksl/ir/SkSLConstructorCompound.h"
21 #include "src/sksl/ir/SkSLConstructorCompoundCast.h"
22 #include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
23 #include "src/sksl/ir/SkSLConstructorMatrixResize.h"
24 #include "src/sksl/ir/SkSLConstructorScalarCast.h"
25 #include "src/sksl/ir/SkSLConstructorSplat.h"
26 #include "src/sksl/ir/SkSLConstructorStruct.h"
27 #include "src/sksl/ir/SkSLContinueStatement.h"
28 #include "src/sksl/ir/SkSLDiscardStatement.h"
29 #include "src/sksl/ir/SkSLDoStatement.h"
30 #include "src/sksl/ir/SkSLEnum.h"
31 #include "src/sksl/ir/SkSLExpression.h"
32 #include "src/sksl/ir/SkSLExpressionStatement.h"
33 #include "src/sksl/ir/SkSLField.h"
34 #include "src/sksl/ir/SkSLFieldAccess.h"
35 #include "src/sksl/ir/SkSLFloatLiteral.h"
36 #include "src/sksl/ir/SkSLForStatement.h"
37 #include "src/sksl/ir/SkSLFunctionCall.h"
38 #include "src/sksl/ir/SkSLFunctionDeclaration.h"
39 #include "src/sksl/ir/SkSLFunctionDefinition.h"
40 #include "src/sksl/ir/SkSLIfStatement.h"
41 #include "src/sksl/ir/SkSLIndexExpression.h"
42 #include "src/sksl/ir/SkSLInlineMarker.h"
43 #include "src/sksl/ir/SkSLIntLiteral.h"
44 #include "src/sksl/ir/SkSLInterfaceBlock.h"
45 #include "src/sksl/ir/SkSLPostfixExpression.h"
46 #include "src/sksl/ir/SkSLPrefixExpression.h"
47 #include "src/sksl/ir/SkSLReturnStatement.h"
48 #include "src/sksl/ir/SkSLSetting.h"
49 #include "src/sksl/ir/SkSLStructDefinition.h"
50 #include "src/sksl/ir/SkSLSwitchCase.h"
51 #include "src/sksl/ir/SkSLSwitchStatement.h"
52 #include "src/sksl/ir/SkSLSwizzle.h"
53 #include "src/sksl/ir/SkSLSymbolAlias.h"
54 #include "src/sksl/ir/SkSLSymbolTable.h"
55 #include "src/sksl/ir/SkSLTernaryExpression.h"
56 #include "src/sksl/ir/SkSLType.h"
57 #include "src/sksl/ir/SkSLUnresolvedFunction.h"
58 #include "src/sksl/ir/SkSLVarDeclarations.h"
59 #include "src/sksl/ir/SkSLVariable.h"
60
61 namespace SkSL {
62
63 class AutoRehydratorSymbolTable {
64 public:
AutoRehydratorSymbolTable(Rehydrator * rehydrator)65 AutoRehydratorSymbolTable(Rehydrator* rehydrator)
66 : fRehydrator(rehydrator)
67 , fOldSymbols(fRehydrator->fSymbolTable) {
68 fRehydrator->fSymbolTable = fRehydrator->symbolTable();
69 }
70
~AutoRehydratorSymbolTable()71 ~AutoRehydratorSymbolTable() {
72 fRehydrator->fSymbolTable = std::move(fOldSymbols);
73 }
74
75 private:
76 Rehydrator* fRehydrator;
77 std::shared_ptr<SymbolTable> fOldSymbols;
78 };
79
Rehydrator(const Context * context,std::shared_ptr<SymbolTable> symbolTable,const uint8_t * src,size_t length)80 Rehydrator::Rehydrator(const Context* context, std::shared_ptr<SymbolTable> symbolTable,
81 const uint8_t* src, size_t length)
82 : fContext(*context)
83 , fSymbolTable(std::move(symbolTable))
84 , fStart(src)
85 SkDEBUGCODE(, fEnd(fStart + length)) {
86 SkASSERT(fSymbolTable);
87 SkASSERT(fSymbolTable->isBuiltin());
88 // skip past string data
89 fIP = fStart;
90 fIP += this->readU16();
91 }
92
layout()93 Layout Rehydrator::layout() {
94 switch (this->readU8()) {
95 case kBuiltinLayout_Command: {
96 Layout result;
97 result.fBuiltin = this->readS16();
98 return result;
99 }
100 case kDefaultLayout_Command:
101 return Layout();
102 case kLayout_Command: {
103 int flags = this->readU32();
104 int location = this->readS8();
105 int offset = this->readS8();
106 int binding = this->readS8();
107 int index = this->readS8();
108 int set = this->readS8();
109 int builtin = this->readS16();
110 int inputAttachmentIndex = this->readS8();
111 int primitive = this->readS8();
112 int maxVertices = this->readS8();
113 int invocations = this->readS8();
114 StringFragment when = this->readString();
115 int ctype = this->readS8();
116 return Layout(flags, location, offset, binding, index, set, builtin,
117 inputAttachmentIndex, (Layout::Primitive)primitive, maxVertices,
118 invocations, when, (Layout::CType)ctype);
119 }
120 default:
121 SkASSERT(false);
122 return Layout();
123 }
124 }
125
modifiers()126 Modifiers Rehydrator::modifiers() {
127 switch (this->readU8()) {
128 case kDefaultModifiers_Command:
129 return Modifiers();
130 case kModifiers8Bit_Command: {
131 Layout l = this->layout();
132 int flags = this->readU8();
133 return Modifiers(l, flags);
134 }
135 case kModifiers_Command: {
136 Layout l = this->layout();
137 int flags = this->readS32();
138 return Modifiers(l, flags);
139 }
140 default:
141 SkASSERT(false);
142 return Modifiers();
143 }
144 }
145
symbol()146 const Symbol* Rehydrator::symbol() {
147 int kind = this->readU8();
148 switch (kind) {
149 case kArrayType_Command: {
150 uint16_t id = this->readU16();
151 const Type* componentType = this->type();
152 int8_t count = this->readS8();
153 String name = componentType->name();
154 if (count == Type::kUnsizedArray) {
155 name += "[]";
156 } else {
157 name += "[" + to_string(count) + "]";
158 }
159 const Type* result = fSymbolTable->takeOwnershipOfSymbol(
160 Type::MakeArrayType(name, *componentType, count));
161 this->addSymbol(id, result);
162 return result;
163 }
164 case kEnumType_Command: {
165 uint16_t id = this->readU16();
166 StringFragment name = this->readString();
167 const Type* result = fSymbolTable->takeOwnershipOfSymbol(Type::MakeEnumType(name));
168 this->addSymbol(id, result);
169 return result;
170 }
171 case kFunctionDeclaration_Command: {
172 uint16_t id = this->readU16();
173 Modifiers modifiers = this->modifiers();
174 StringFragment name = this->readString();
175 int parameterCount = this->readU8();
176 std::vector<const Variable*> parameters;
177 parameters.reserve(parameterCount);
178 for (int i = 0; i < parameterCount; ++i) {
179 parameters.push_back(this->symbolRef<Variable>(Symbol::Kind::kVariable));
180 }
181 const Type* returnType = this->type();
182 const FunctionDeclaration* result =
183 fSymbolTable->takeOwnershipOfSymbol(std::make_unique<FunctionDeclaration>(
184 /*offset=*/-1,
185 this->modifiersPool().add(modifiers),
186 name,
187 std::move(parameters),
188 returnType,
189 /*builtin=*/true));
190 this->addSymbol(id, result);
191 return result;
192 }
193 case kField_Command: {
194 const Variable* owner = this->symbolRef<Variable>(Symbol::Kind::kVariable);
195 uint8_t index = this->readU8();
196 const Field* result = fSymbolTable->takeOwnershipOfSymbol(
197 std::make_unique<Field>(/*offset=*/-1, owner, index));
198 return result;
199 }
200 case kStructType_Command: {
201 uint16_t id = this->readU16();
202 StringFragment name = this->readString();
203 uint8_t fieldCount = this->readU8();
204 std::vector<Type::Field> fields;
205 fields.reserve(fieldCount);
206 for (int i = 0; i < fieldCount; ++i) {
207 Modifiers m = this->modifiers();
208 StringFragment fieldName = this->readString();
209 const Type* type = this->type();
210 fields.emplace_back(m, fieldName, type);
211 }
212 const Type* result = fSymbolTable->takeOwnershipOfSymbol(
213 Type::MakeStructType(/*offset=*/-1, name, std::move(fields)));
214 this->addSymbol(id, result);
215 return result;
216 }
217 case kSymbolRef_Command: {
218 uint16_t id = this->readU16();
219 SkASSERT(fSymbols.size() > id);
220 return fSymbols[id];
221 }
222 case kSymbolAlias_Command: {
223 uint16_t id = this->readU16();
224 StringFragment name = this->readString();
225 const Symbol* origSymbol = this->symbol();
226 const SymbolAlias* symbolAlias = fSymbolTable->takeOwnershipOfSymbol(
227 std::make_unique<SymbolAlias>(/*offset=*/-1, name, origSymbol));
228 this->addSymbol(id, symbolAlias);
229 return symbolAlias;
230 }
231 case kSystemType_Command: {
232 uint16_t id = this->readU16();
233 StringFragment name = this->readString();
234 const Symbol* result = (*fSymbolTable)[name];
235 SkASSERT(result && result->kind() == Symbol::Kind::kType);
236 this->addSymbol(id, result);
237 return result;
238 }
239 case kUnresolvedFunction_Command: {
240 uint16_t id = this->readU16();
241 int length = this->readU8();
242 std::vector<const FunctionDeclaration*> functions;
243 functions.reserve(length);
244 for (int i = 0; i < length; ++i) {
245 const Symbol* f = this->symbol();
246 SkASSERT(f && f->kind() == Symbol::Kind::kFunctionDeclaration);
247 functions.push_back((const FunctionDeclaration*) f);
248 }
249 const UnresolvedFunction* result = fSymbolTable->takeOwnershipOfSymbol(
250 std::make_unique<UnresolvedFunction>(std::move(functions)));
251 this->addSymbol(id, result);
252 return result;
253 }
254 case kVariable_Command: {
255 uint16_t id = this->readU16();
256 const Modifiers* m = this->modifiersPool().add(this->modifiers());
257 StringFragment name = this->readString();
258 const Type* type = this->type();
259 Variable::Storage storage = (Variable::Storage) this->readU8();
260 const Variable* result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Variable>(
261 /*offset=*/-1, m, name, type, /*builtin=*/true, storage));
262 this->addSymbol(id, result);
263 return result;
264 }
265 default:
266 printf("unsupported symbol %d\n", kind);
267 SkASSERT(false);
268 return nullptr;
269 }
270 }
271
type()272 const Type* Rehydrator::type() {
273 const Symbol* result = this->symbol();
274 SkASSERT(result->kind() == Symbol::Kind::kType);
275 return (const Type*) result;
276 }
277
elements()278 std::vector<std::unique_ptr<ProgramElement>> Rehydrator::elements() {
279 SkDEBUGCODE(uint8_t command = )this->readU8();
280 SkASSERT(command == kElements_Command);
281 std::vector<std::unique_ptr<ProgramElement>> result;
282 while (std::unique_ptr<ProgramElement> elem = this->element()) {
283 result.push_back(std::move(elem));
284 }
285 return result;
286 }
287
element()288 std::unique_ptr<ProgramElement> Rehydrator::element() {
289 int kind = this->readU8();
290 switch (kind) {
291 case Rehydrator::kEnum_Command: {
292 StringFragment typeName = this->readString();
293 std::shared_ptr<SymbolTable> symbols = this->symbolTable(/*inherit=*/false);
294 for (auto& s : symbols->fOwnedSymbols) {
295 SkASSERT(s->kind() == Symbol::Kind::kVariable);
296 Variable& v = (Variable&) *s;
297 int value = this->readS32();
298 // enum variables aren't really 'declared', but we have to create a declaration to
299 // store the value
300 auto valueLiteral = IntLiteral::Make(fContext, /*offset=*/-1, value);
301 auto declaration = VarDeclaration::Make(fContext, &v, &v.type(), /*arraySize=*/0,
302 std::move(valueLiteral));
303 symbols->takeOwnershipOfIRNode(std::move(declaration));
304 }
305 return std::make_unique<Enum>(/*offset=*/-1, typeName, std::move(symbols),
306 /*isSharedWithCpp=*/true, /*isBuiltin=*/true);
307 }
308 case Rehydrator::kFunctionDefinition_Command: {
309 const FunctionDeclaration* decl = this->symbolRef<FunctionDeclaration>(
310 Symbol::Kind::kFunctionDeclaration);
311 std::unique_ptr<Statement> body = this->statement();
312 std::unordered_set<const FunctionDeclaration*> refs;
313 uint8_t refCount = this->readU8();
314 for (int i = 0; i < refCount; ++i) {
315 refs.insert(this->symbolRef<FunctionDeclaration>(
316 Symbol::Kind::kFunctionDeclaration));
317 }
318 auto result = std::make_unique<FunctionDefinition>(/*offset=*/-1, decl,
319 /*builtin=*/true, std::move(body),
320 std::move(refs));
321 decl->setDefinition(result.get());
322 return std::move(result);
323 }
324 case Rehydrator::kInterfaceBlock_Command: {
325 const Symbol* var = this->symbol();
326 SkASSERT(var && var->is<Variable>());
327 StringFragment typeName = this->readString();
328 StringFragment instanceName = this->readString();
329 int arraySize = this->readS8();
330 return std::make_unique<InterfaceBlock>(/*offset=*/-1, &var->as<Variable>(), typeName,
331 instanceName, arraySize, nullptr);
332 }
333 case Rehydrator::kVarDeclarations_Command: {
334 std::unique_ptr<Statement> decl = this->statement();
335 return std::make_unique<GlobalVarDeclaration>(std::move(decl));
336 }
337 case Rehydrator::kStructDefinition_Command: {
338 const Symbol* type = this->symbol();
339 SkASSERT(type && type->is<Type>());
340 return std::make_unique<StructDefinition>(/*offset=*/-1, type->as<Type>());
341 }
342 case Rehydrator::kElementsComplete_Command:
343 return nullptr;
344 default:
345 SkDEBUGFAILF("unsupported element %d\n", kind);
346 return nullptr;
347 }
348 }
349
statement()350 std::unique_ptr<Statement> Rehydrator::statement() {
351 int kind = this->readU8();
352 switch (kind) {
353 case Rehydrator::kBlock_Command: {
354 AutoRehydratorSymbolTable symbols(this);
355 int count = this->readU8();
356 StatementArray statements;
357 statements.reserve_back(count);
358 for (int i = 0; i < count; ++i) {
359 statements.push_back(this->statement());
360 }
361 bool isScope = this->readU8();
362 return Block::Make(/*offset=*/-1, std::move(statements), fSymbolTable, isScope);
363 }
364 case Rehydrator::kBreak_Command:
365 return BreakStatement::Make(/*offset=*/-1);
366 case Rehydrator::kContinue_Command:
367 return ContinueStatement::Make(/*offset=*/-1);
368 case Rehydrator::kDiscard_Command:
369 return DiscardStatement::Make(/*offset=*/-1);
370 case Rehydrator::kDo_Command: {
371 std::unique_ptr<Statement> stmt = this->statement();
372 std::unique_ptr<Expression> expr = this->expression();
373 return DoStatement::Make(fContext, std::move(stmt), std::move(expr));
374 }
375 case Rehydrator::kExpressionStatement_Command: {
376 std::unique_ptr<Expression> expr = this->expression();
377 return ExpressionStatement::Make(fContext, std::move(expr));
378 }
379 case Rehydrator::kFor_Command: {
380 std::unique_ptr<Statement> initializer = this->statement();
381 std::unique_ptr<Expression> test = this->expression();
382 std::unique_ptr<Expression> next = this->expression();
383 std::unique_ptr<Statement> body = this->statement();
384 std::shared_ptr<SymbolTable> symbols = this->symbolTable();
385 return ForStatement::Make(fContext, /*offset=*/-1, std::move(initializer),
386 std::move(test), std::move(next), std::move(body),
387 std::move(symbols));
388 }
389 case Rehydrator::kIf_Command: {
390 bool isStatic = this->readU8();
391 std::unique_ptr<Expression> test = this->expression();
392 std::unique_ptr<Statement> ifTrue = this->statement();
393 std::unique_ptr<Statement> ifFalse = this->statement();
394 return IfStatement::Make(fContext, /*offset=*/-1, isStatic, std::move(test),
395 std::move(ifTrue), std::move(ifFalse));
396 }
397 case Rehydrator::kInlineMarker_Command: {
398 const FunctionDeclaration* funcDecl = this->symbolRef<FunctionDeclaration>(
399 Symbol::Kind::kFunctionDeclaration);
400 return InlineMarker::Make(funcDecl);
401 }
402 case Rehydrator::kReturn_Command: {
403 std::unique_ptr<Expression> expr = this->expression();
404 return ReturnStatement::Make(/*offset=*/-1, std::move(expr));
405 }
406 case Rehydrator::kSwitch_Command: {
407 bool isStatic = this->readU8();
408 AutoRehydratorSymbolTable symbols(this);
409 std::unique_ptr<Expression> expr = this->expression();
410 int caseCount = this->readU8();
411 StatementArray cases;
412 cases.reserve_back(caseCount);
413 for (int i = 0; i < caseCount; ++i) {
414 std::unique_ptr<Expression> value = this->expression();
415 std::unique_ptr<Statement> statement = this->statement();
416 cases.push_back(std::make_unique<SwitchCase>(/*offset=*/-1, std::move(value),
417 std::move(statement)));
418 }
419 return SwitchStatement::Make(fContext, /*offset=*/-1, isStatic, std::move(expr),
420 std::move(cases), fSymbolTable);
421 }
422 case Rehydrator::kVarDeclaration_Command: {
423 Variable* var = this->symbolRef<Variable>(Symbol::Kind::kVariable);
424 const Type* baseType = this->type();
425 int arraySize = this->readS8();
426 std::unique_ptr<Expression> value = this->expression();
427 return VarDeclaration::Make(fContext, var, baseType, arraySize, std::move(value));
428 }
429 case Rehydrator::kVoid_Command:
430 return nullptr;
431 default:
432 printf("unsupported statement %d\n", kind);
433 SkASSERT(false);
434 return nullptr;
435 }
436 }
437
expressionArray()438 ExpressionArray Rehydrator::expressionArray() {
439 uint8_t count = this->readU8();
440 ExpressionArray array;
441 array.reserve_back(count);
442 for (int i = 0; i < count; ++i) {
443 array.push_back(this->expression());
444 }
445 return array;
446 }
447
expression()448 std::unique_ptr<Expression> Rehydrator::expression() {
449 int kind = this->readU8();
450 switch (kind) {
451 case Rehydrator::kBinary_Command: {
452 std::unique_ptr<Expression> left = this->expression();
453 Token::Kind op = (Token::Kind) this->readU8();
454 std::unique_ptr<Expression> right = this->expression();
455 return BinaryExpression::Make(fContext, std::move(left), op, std::move(right));
456 }
457 case Rehydrator::kBoolLiteral_Command: {
458 bool value = this->readU8();
459 return BoolLiteral::Make(fContext, /*offset=*/-1, value);
460 }
461 case Rehydrator::kConstructorArray_Command: {
462 const Type* type = this->type();
463 return ConstructorArray::Make(fContext, /*offset=*/-1, *type, this->expressionArray());
464 }
465 case Rehydrator::kConstructorCompound_Command: {
466 const Type* type = this->type();
467 return ConstructorCompound::Make(fContext, /*offset=*/-1, *type,
468 this->expressionArray());
469 }
470 case Rehydrator::kConstructorDiagonalMatrix_Command: {
471 const Type* type = this->type();
472 ExpressionArray args = this->expressionArray();
473 SkASSERT(args.size() == 1);
474 return ConstructorDiagonalMatrix::Make(fContext, /*offset=*/-1, *type,
475 std::move(args[0]));
476 }
477 case Rehydrator::kConstructorMatrixResize_Command: {
478 const Type* type = this->type();
479 ExpressionArray args = this->expressionArray();
480 SkASSERT(args.size() == 1);
481 return ConstructorMatrixResize::Make(fContext, /*offset=*/-1, *type,
482 std::move(args[0]));
483 }
484 case Rehydrator::kConstructorScalarCast_Command: {
485 const Type* type = this->type();
486 ExpressionArray args = this->expressionArray();
487 SkASSERT(args.size() == 1);
488 return ConstructorScalarCast::Make(fContext, /*offset=*/-1, *type, std::move(args[0]));
489 }
490 case Rehydrator::kConstructorSplat_Command: {
491 const Type* type = this->type();
492 ExpressionArray args = this->expressionArray();
493 SkASSERT(args.size() == 1);
494 return ConstructorSplat::Make(fContext, /*offset=*/-1, *type, std::move(args[0]));
495 }
496 case Rehydrator::kConstructorStruct_Command: {
497 const Type* type = this->type();
498 return ConstructorStruct::Make(fContext, /*offset=*/-1, *type, this->expressionArray());
499 }
500 case Rehydrator::kConstructorCompoundCast_Command: {
501 const Type* type = this->type();
502 ExpressionArray args = this->expressionArray();
503 SkASSERT(args.size() == 1);
504 return ConstructorCompoundCast::Make(fContext,/*offset=*/-1, *type, std::move(args[0]));
505 }
506 case Rehydrator::kFieldAccess_Command: {
507 std::unique_ptr<Expression> base = this->expression();
508 int index = this->readU8();
509 FieldAccess::OwnerKind ownerKind = (FieldAccess::OwnerKind) this->readU8();
510 return FieldAccess::Make(fContext, std::move(base), index, ownerKind);
511 }
512 case Rehydrator::kFloatLiteral_Command: {
513 const Type* type = this->type();
514 FloatIntUnion u;
515 u.fInt = this->readS32();
516 return FloatLiteral::Make(/*offset=*/-1, u.fFloat, type);
517 }
518 case Rehydrator::kFunctionCall_Command: {
519 const Type* type = this->type();
520 const FunctionDeclaration* f = this->symbolRef<FunctionDeclaration>(
521 Symbol::Kind::kFunctionDeclaration);
522 ExpressionArray args = this->expressionArray();
523 return FunctionCall::Make(fContext, /*offset=*/-1, type, *f, std::move(args));
524 }
525 case Rehydrator::kIndex_Command: {
526 std::unique_ptr<Expression> base = this->expression();
527 std::unique_ptr<Expression> index = this->expression();
528 return IndexExpression::Make(fContext, std::move(base), std::move(index));
529 }
530 case Rehydrator::kIntLiteral_Command: {
531 const Type* type = this->type();
532 int value = this->readS32();
533 return IntLiteral::Make(/*offset=*/-1, value, type);
534 }
535 case Rehydrator::kPostfix_Command: {
536 Token::Kind op = (Token::Kind) this->readU8();
537 std::unique_ptr<Expression> operand = this->expression();
538 return PostfixExpression::Make(fContext, std::move(operand), op);
539 }
540 case Rehydrator::kPrefix_Command: {
541 Token::Kind op = (Token::Kind) this->readU8();
542 std::unique_ptr<Expression> operand = this->expression();
543 return PrefixExpression::Make(fContext, op, std::move(operand));
544 }
545 case Rehydrator::kSetting_Command: {
546 StringFragment name = this->readString();
547 return Setting::Convert(fContext, /*offset=*/-1, name);
548 }
549 case Rehydrator::kSwizzle_Command: {
550 std::unique_ptr<Expression> base = this->expression();
551 int count = this->readU8();
552 ComponentArray components;
553 for (int i = 0; i < count; ++i) {
554 components.push_back(this->readU8());
555 }
556 return Swizzle::Make(fContext, std::move(base), components);
557 }
558 case Rehydrator::kTernary_Command: {
559 std::unique_ptr<Expression> test = this->expression();
560 std::unique_ptr<Expression> ifTrue = this->expression();
561 std::unique_ptr<Expression> ifFalse = this->expression();
562 return TernaryExpression::Make(fContext, std::move(test),
563 std::move(ifTrue), std::move(ifFalse));
564 }
565 case Rehydrator::kVariableReference_Command: {
566 const Variable* var = this->symbolRef<Variable>(Symbol::Kind::kVariable);
567 VariableReference::RefKind refKind = (VariableReference::RefKind) this->readU8();
568 return VariableReference::Make(/*offset=*/-1, var, refKind);
569 }
570 case Rehydrator::kVoid_Command:
571 return nullptr;
572 default:
573 printf("unsupported expression %d\n", kind);
574 SkASSERT(false);
575 return nullptr;
576 }
577 }
578
symbolTable(bool inherit)579 std::shared_ptr<SymbolTable> Rehydrator::symbolTable(bool inherit) {
580 int command = this->readU8();
581 if (command == kVoid_Command) {
582 return nullptr;
583 }
584 SkASSERT(command == kSymbolTable_Command);
585 uint16_t ownedCount = this->readU16();
586 std::shared_ptr<SymbolTable> oldTable = fSymbolTable;
587 std::shared_ptr<SymbolTable> result =
588 inherit ? std::make_shared<SymbolTable>(fSymbolTable, /*builtin=*/true)
589 : std::make_shared<SymbolTable>(this->errorReporter(), /*builtin=*/true);
590 fSymbolTable = result;
591 std::vector<const Symbol*> ownedSymbols;
592 ownedSymbols.reserve(ownedCount);
593 for (int i = 0; i < ownedCount; ++i) {
594 ownedSymbols.push_back(this->symbol());
595 }
596 uint16_t symbolCount = this->readU16();
597 std::vector<std::pair<StringFragment, int>> symbols;
598 symbols.reserve(symbolCount);
599 for (int i = 0; i < symbolCount; ++i) {
600 int index = this->readU16();
601 fSymbolTable->addWithoutOwnership(ownedSymbols[index]);
602 }
603 fSymbolTable = oldTable;
604 return result;
605 }
606
607 } // namespace SkSL
608