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