• 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 #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 "include/sksl/DSLCore.h"
17 #include "src/sksl/SkSLAnalysis.h"
18 #include "src/sksl/SkSLCompiler.h"
19 #include "src/sksl/SkSLThreadContext.h"
20 #include "src/sksl/ir/SkSLBinaryExpression.h"
21 #include "src/sksl/ir/SkSLBreakStatement.h"
22 #include "src/sksl/ir/SkSLConstructor.h"
23 #include "src/sksl/ir/SkSLConstructorArray.h"
24 #include "src/sksl/ir/SkSLConstructorArrayCast.h"
25 #include "src/sksl/ir/SkSLConstructorCompound.h"
26 #include "src/sksl/ir/SkSLConstructorCompoundCast.h"
27 #include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
28 #include "src/sksl/ir/SkSLConstructorMatrixResize.h"
29 #include "src/sksl/ir/SkSLConstructorScalarCast.h"
30 #include "src/sksl/ir/SkSLConstructorSplat.h"
31 #include "src/sksl/ir/SkSLConstructorStruct.h"
32 #include "src/sksl/ir/SkSLContinueStatement.h"
33 #include "src/sksl/ir/SkSLDiscardStatement.h"
34 #include "src/sksl/ir/SkSLDoStatement.h"
35 #include "src/sksl/ir/SkSLExpression.h"
36 #include "src/sksl/ir/SkSLExpressionStatement.h"
37 #include "src/sksl/ir/SkSLField.h"
38 #include "src/sksl/ir/SkSLFieldAccess.h"
39 #include "src/sksl/ir/SkSLForStatement.h"
40 #include "src/sksl/ir/SkSLFunctionCall.h"
41 #include "src/sksl/ir/SkSLFunctionDeclaration.h"
42 #include "src/sksl/ir/SkSLFunctionDefinition.h"
43 #include "src/sksl/ir/SkSLFunctionPrototype.h"
44 #include "src/sksl/ir/SkSLIfStatement.h"
45 #include "src/sksl/ir/SkSLIndexExpression.h"
46 #include "src/sksl/ir/SkSLInlineMarker.h"
47 #include "src/sksl/ir/SkSLInterfaceBlock.h"
48 #include "src/sksl/ir/SkSLLiteral.h"
49 #include "src/sksl/ir/SkSLNop.h"
50 #include "src/sksl/ir/SkSLPostfixExpression.h"
51 #include "src/sksl/ir/SkSLPrefixExpression.h"
52 #include "src/sksl/ir/SkSLReturnStatement.h"
53 #include "src/sksl/ir/SkSLSetting.h"
54 #include "src/sksl/ir/SkSLStructDefinition.h"
55 #include "src/sksl/ir/SkSLSwitchCase.h"
56 #include "src/sksl/ir/SkSLSwitchStatement.h"
57 #include "src/sksl/ir/SkSLSwizzle.h"
58 #include "src/sksl/ir/SkSLSymbolTable.h"
59 #include "src/sksl/ir/SkSLTernaryExpression.h"
60 #include "src/sksl/ir/SkSLType.h"
61 #include "src/sksl/ir/SkSLUnresolvedFunction.h"
62 #include "src/sksl/ir/SkSLVarDeclarations.h"
63 #include "src/sksl/ir/SkSLVariable.h"
64 
65 namespace SkSL {
66 
67 class AutoRehydratorSymbolTable {
68 public:
AutoRehydratorSymbolTable(Rehydrator * rehydrator)69     AutoRehydratorSymbolTable(Rehydrator* rehydrator)
70         : fRehydrator(rehydrator)
71         , fOldSymbols(fRehydrator->fSymbolTable) {
72         std::shared_ptr<SymbolTable> symbols = fRehydrator->symbolTable();
73         if (symbols) {
74             fRehydrator->fSymbolTable = std::move(symbols);
75         }
76     }
77 
~AutoRehydratorSymbolTable()78     ~AutoRehydratorSymbolTable() {
79         fRehydrator->fSymbolTable = std::move(fOldSymbols);
80     }
81 
82 private:
83     Rehydrator* fRehydrator;
84     std::shared_ptr<SymbolTable> fOldSymbols;
85 };
86 
Rehydrator(Compiler & compiler,const uint8_t * src,size_t length,std::shared_ptr<SymbolTable> symbols)87 Rehydrator::Rehydrator(Compiler& compiler, const uint8_t* src, size_t length,
88         std::shared_ptr<SymbolTable> symbols)
89     : fCompiler(compiler)
90     , fSymbolTable(symbols ? std::move(symbols) : compiler.makeGLSLRootSymbolTable())
91     SkDEBUGCODE(, fEnd(src + length)) {
92     SkASSERT(fSymbolTable);
93     SkASSERT(fSymbolTable->isBuiltin());
94     fIP = src;
95     [[maybe_unused]] uint16_t version = this->readU16();
96     SkASSERTF(version == kVersion, "Dehydrated file is an unsupported version (current version is "
97             "%d, found version %d)", kVersion, version);
98     fStringStart = fIP;
99     // skip over string data
100     fIP += this->readU16();
101 }
102 
103 #ifdef SK_DEBUG
~Rehydrator()104 Rehydrator::~Rehydrator() {
105     // ensure that we have read the expected number of bytes
106     SkASSERT(fIP == fEnd);
107 }
108 #endif
109 
context() const110 Context& Rehydrator::context() const {
111     return fCompiler.context();
112 }
113 
layout()114 Layout Rehydrator::layout() {
115     switch (this->readU8()) {
116         case kBuiltinLayout_Command: {
117             Layout result;
118             result.fBuiltin = this->readS16();
119             return result;
120         }
121         case kDefaultLayout_Command:
122             return Layout();
123         case kLayout_Command: {
124             int flags = this->readU32();
125             int location = this->readS8();
126             int offset = this->readS16();
127             int binding = this->readS16();
128             int index = this->readS8();
129             int set = this->readS8();
130             int builtin = this->readS16();
131             int inputAttachmentIndex = this->readS8();
132             return Layout(
133                     flags, location, offset, binding, index, set, builtin, inputAttachmentIndex);
134         }
135         default:
136             SkASSERT(false);
137             return Layout();
138     }
139 }
140 
modifiers()141 Modifiers Rehydrator::modifiers() {
142     switch (this->readU8()) {
143         case kDefaultModifiers_Command:
144             return Modifiers();
145         case kModifiers8Bit_Command: {
146             Layout l = this->layout();
147             int flags = this->readU8();
148             return Modifiers(l, flags);
149         }
150         case kModifiers_Command: {
151             Layout l = this->layout();
152             int flags = this->readS32();
153             return Modifiers(l, flags);
154         }
155         default:
156             SkASSERT(false);
157             return Modifiers();
158     }
159 }
160 
symbol()161 const Symbol* Rehydrator::symbol() {
162     int kind = this->readU8();
163     switch (kind) {
164         case kArrayType_Command: {
165             uint16_t id = this->readU16();
166             const Type* componentType = this->type();
167             int8_t count = this->readS8();
168             const std::string* arrayName =
169                     fSymbolTable->takeOwnershipOfString(componentType->getArrayName(count));
170             const Type* result = fSymbolTable->takeOwnershipOfSymbol(
171                     Type::MakeArrayType(*arrayName, *componentType, count));
172             this->addSymbol(id, result);
173             return result;
174         }
175         case kFunctionDeclaration_Command: {
176             uint16_t id = this->readU16();
177             Modifiers modifiers = this->modifiers();
178             std::string_view name = this->readString();
179             int parameterCount = this->readU8();
180             std::vector<const Variable*> parameters;
181             parameters.reserve(parameterCount);
182             for (int i = 0; i < parameterCount; ++i) {
183                 parameters.push_back(this->symbolRef<Variable>(Symbol::Kind::kVariable));
184             }
185             const Type* returnType = this->type();
186             const FunctionDeclaration* result =
187                     fSymbolTable->takeOwnershipOfSymbol(std::make_unique<FunctionDeclaration>(
188                             /*line=*/-1,
189                             this->modifiersPool().add(modifiers),
190                             name,
191                             std::move(parameters),
192                             returnType,
193                             fSymbolTable->isBuiltin()));
194             this->addSymbol(id, result);
195             return result;
196         }
197         case kField_Command: {
198             const Variable* owner = this->symbolRef<Variable>(Symbol::Kind::kVariable);
199             uint8_t index = this->readU8();
200             const Field* result = fSymbolTable->takeOwnershipOfSymbol(
201                     std::make_unique<Field>(/*line=*/-1, owner, index));
202             return result;
203         }
204         case kStructType_Command: {
205             uint16_t id = this->readU16();
206             std::string name(this->readString());
207             uint8_t fieldCount = this->readU8();
208             std::vector<Type::Field> fields;
209             fields.reserve(fieldCount);
210             for (int i = 0; i < fieldCount; ++i) {
211                 Modifiers m = this->modifiers();
212                 std::string_view fieldName = this->readString();
213                 const Type* type = this->type();
214                 fields.emplace_back(m, fieldName, type);
215             }
216             bool interfaceBlock = this->readU8();
217             std::string_view nameChars(*fSymbolTable->takeOwnershipOfString(std::move(name)));
218             const Type* result = fSymbolTable->takeOwnershipOfSymbol(Type::MakeStructType(
219                     /*line=*/-1, nameChars, std::move(fields), interfaceBlock));
220             this->addSymbol(id, result);
221             return result;
222         }
223         case kSymbolRef_Command: {
224             uint16_t id = this->readU16();
225             if (id == kBuiltin_Symbol) {
226                 return (*fSymbolTable)[this->readString()];
227             }
228             SkASSERT(fSymbols.size() > id);
229             return fSymbols[id];
230         }
231         case kUnresolvedFunction_Command: {
232             uint16_t id = this->readU16();
233             int length = this->readU8();
234             std::vector<const FunctionDeclaration*> functions;
235             functions.reserve(length);
236             for (int i = 0; i < length; ++i) {
237                 const Symbol* f = this->symbol();
238                 SkASSERT(f && f->kind() == Symbol::Kind::kFunctionDeclaration);
239                 functions.push_back((const FunctionDeclaration*) f);
240             }
241             const UnresolvedFunction* result = fSymbolTable->takeOwnershipOfSymbol(
242                     std::make_unique<UnresolvedFunction>(std::move(functions)));
243             this->addSymbol(id, result);
244             return result;
245         }
246         case kVariable_Command: {
247             uint16_t id = this->readU16();
248             const Modifiers* m = this->modifiersPool().add(this->modifiers());
249             std::string_view name = this->readString();
250             const Type* type = this->type();
251             Variable::Storage storage = (Variable::Storage) this->readU8();
252             const Variable* result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Variable>(
253                     /*line=*/-1, m, name, type, fSymbolTable->isBuiltin(), storage));
254             this->addSymbol(id, result);
255             return result;
256         }
257         default:
258             printf("unsupported symbol %d\n", kind);
259             SkASSERT(false);
260             return nullptr;
261     }
262 }
263 
type()264 const Type* Rehydrator::type() {
265     const Symbol* result = this->symbol();
266     SkASSERT(result->kind() == Symbol::Kind::kType);
267     return (const Type*) result;
268 }
269 
program()270 std::unique_ptr<Program> Rehydrator::program() {
271     [[maybe_unused]] uint8_t command = this->readU8();
272     SkASSERT(command == kProgram_Command);
273 
274     // Initialize the temporary config used to generate the complete program. We explicitly avoid
275     // enforcing ES2 restrictions when rehydrating a program, which we assume to be already
276     // well-formed when dehydrated.
277     auto config = std::make_unique<ProgramConfig>();
278     config->fKind = (ProgramKind)this->readU8();
279     config->fSettings.fEnforceES2Restrictions = false;
280 
281     Context& context = this->context();
282     ProgramConfig* oldConfig = context.fConfig;
283     ModifiersPool* oldModifiersPool = context.fModifiersPool;
284     context.fConfig = config.get();
285     fSymbolTable = fCompiler.moduleForProgramKind(config->fKind).fSymbols;
286     dsl::Start(&fCompiler, config->fKind, config->fSettings);
287     auto modifiers = std::make_unique<ModifiersPool>();
288     context.fModifiersPool = modifiers.get();
289     this->symbolTable();
290     std::vector<std::unique_ptr<ProgramElement>> elements = this->elements();
291     context.fConfig = oldConfig;
292     context.fModifiersPool = oldModifiersPool;
293     Program::Inputs inputs;
294     inputs.fUseFlipRTUniform = this->readU8();
295     std::unique_ptr<Pool> pool = std::move(ThreadContext::MemoryPool());
296     pool->detachFromThread();
297     std::unique_ptr<Program> result = std::make_unique<Program>(nullptr, std::move(config),
298             fCompiler.fContext, std::move(elements),
299             /*sharedElements=*/std::vector<const ProgramElement*>(), std::move(modifiers),
300             fSymbolTable, std::move(pool), inputs);
301     fSymbolTable = fSymbolTable->fParent;
302     dsl::End();
303     return result;
304 }
305 
elements()306 std::vector<std::unique_ptr<ProgramElement>> Rehydrator::elements() {
307     SkDEBUGCODE(uint8_t command = )this->readU8();
308     SkASSERT(command == kElements_Command);
309     std::vector<std::unique_ptr<ProgramElement>> result;
310     while (std::unique_ptr<ProgramElement> elem = this->element()) {
311         result.push_back(std::move(elem));
312     }
313     return result;
314 }
315 
element()316 std::unique_ptr<ProgramElement> Rehydrator::element() {
317     int kind = this->readU8();
318     switch (kind) {
319         case Rehydrator::kFunctionDefinition_Command: {
320             const FunctionDeclaration* decl = this->symbolRef<FunctionDeclaration>(
321                                                                 Symbol::Kind::kFunctionDeclaration);
322             std::unique_ptr<Statement> body = this->statement();
323             auto result = FunctionDefinition::Convert(this->context(), /*line=*/-1, *decl,
324                                                       std::move(body), fSymbolTable->isBuiltin());
325             decl->setDefinition(result.get());
326             return std::move(result);
327         }
328         case Rehydrator::kFunctionPrototype_Command: {
329             const FunctionDeclaration* decl = this->symbolRef<FunctionDeclaration>(
330                                                                 Symbol::Kind::kFunctionDeclaration);
331             // since we skip over builtin prototypes when dehydrating, we know that this
332             // builtin=false
333             return std::make_unique<FunctionPrototype>(/*line=*/-1, decl, /*builtin=*/false);
334         }
335         case Rehydrator::kGlobalVar_Command: {
336             std::unique_ptr<Statement> decl = this->statement();
337             return std::make_unique<GlobalVarDeclaration>(std::move(decl));
338         }
339         case Rehydrator::kInterfaceBlock_Command: {
340             const Symbol* var = this->symbol();
341             SkASSERT(var && var->is<Variable>());
342             std::string_view typeName = this->readString();
343             std::string_view instanceName = this->readString();
344             int arraySize = this->readU8();
345             return std::make_unique<InterfaceBlock>(/*line=*/-1, var->as<Variable>(), typeName,
346                                                     instanceName, arraySize, nullptr);
347         }
348         case Rehydrator::kStructDefinition_Command: {
349             const Symbol* type = this->symbol();
350             SkASSERT(type && type->is<Type>());
351             return std::make_unique<StructDefinition>(/*line=*/-1, type->as<Type>());
352         }
353         case Rehydrator::kSharedFunction_Command: {
354             int count = this->readU8();
355             for (int i = 0; i < count; ++i) {
356                 [[maybe_unused]] const Symbol* param = this->symbol();
357                 SkASSERT(param->is<Variable>());
358             }
359             [[maybe_unused]] const Symbol* decl = this->symbol();
360             SkASSERT(decl->is<FunctionDeclaration>());
361             std::unique_ptr<ProgramElement> result = this->element();
362             SkASSERT(result->is<FunctionDefinition>());
363             return result;
364         }
365         case Rehydrator::kElementsComplete_Command:
366             return nullptr;
367         default:
368             SkDEBUGFAILF("unsupported element %d\n", kind);
369             return nullptr;
370     }
371 }
372 
statement()373 std::unique_ptr<Statement> Rehydrator::statement() {
374     int kind = this->readU8();
375     switch (kind) {
376         case Rehydrator::kBlock_Command: {
377             AutoRehydratorSymbolTable symbols(this);
378             int count = this->readU8();
379             StatementArray statements;
380             statements.reserve_back(count);
381             for (int i = 0; i < count; ++i) {
382                 statements.push_back(this->statement());
383             }
384             bool isScope = this->readU8();
385             return Block::Make(/*line=*/-1, std::move(statements), fSymbolTable, isScope);
386         }
387         case Rehydrator::kBreak_Command:
388             return BreakStatement::Make(/*line=*/-1);
389         case Rehydrator::kContinue_Command:
390             return ContinueStatement::Make(/*line=*/-1);
391         case Rehydrator::kDiscard_Command:
392             return DiscardStatement::Make(/*line=*/-1);
393         case Rehydrator::kDo_Command: {
394             std::unique_ptr<Statement> stmt = this->statement();
395             std::unique_ptr<Expression> expr = this->expression();
396             return DoStatement::Make(this->context(), std::move(stmt), std::move(expr));
397         }
398         case Rehydrator::kExpressionStatement_Command: {
399             std::unique_ptr<Expression> expr = this->expression();
400             return ExpressionStatement::Make(this->context(), std::move(expr));
401         }
402         case Rehydrator::kFor_Command: {
403             AutoRehydratorSymbolTable symbols(this);
404             std::unique_ptr<Statement> initializer = this->statement();
405             std::unique_ptr<Expression> test = this->expression();
406             std::unique_ptr<Expression> next = this->expression();
407             std::unique_ptr<Statement> body = this->statement();
408             std::unique_ptr<LoopUnrollInfo> unrollInfo =
409                     Analysis::GetLoopUnrollInfo(/*line=*/-1, initializer.get(), test.get(),
410                                                 next.get(), body.get(), /*errors=*/nullptr);
411             return ForStatement::Make(this->context(), /*line=*/-1, std::move(initializer),
412                                       std::move(test), std::move(next), std::move(body),
413                                       std::move(unrollInfo), fSymbolTable);
414         }
415         case Rehydrator::kIf_Command: {
416             bool isStatic = this->readU8();
417             std::unique_ptr<Expression> test = this->expression();
418             std::unique_ptr<Statement> ifTrue = this->statement();
419             std::unique_ptr<Statement> ifFalse = this->statement();
420             return IfStatement::Make(this->context(), /*line=*/-1, isStatic, std::move(test),
421                                      std::move(ifTrue), std::move(ifFalse));
422         }
423         case Rehydrator::kInlineMarker_Command: {
424             const FunctionDeclaration* funcDecl = this->symbolRef<FunctionDeclaration>(
425                                                           Symbol::Kind::kFunctionDeclaration);
426             return InlineMarker::Make(funcDecl);
427         }
428         case Rehydrator::kNop_Command:
429             return std::make_unique<SkSL::Nop>();
430         case Rehydrator::kReturn_Command: {
431             std::unique_ptr<Expression> expr = this->expression();
432             return ReturnStatement::Make(/*line=*/-1, std::move(expr));
433         }
434         case Rehydrator::kSwitch_Command: {
435             bool isStatic = this->readU8();
436             AutoRehydratorSymbolTable symbols(this);
437             std::unique_ptr<Expression> expr = this->expression();
438             int caseCount = this->readU8();
439             StatementArray cases;
440             cases.reserve_back(caseCount);
441             for (int i = 0; i < caseCount; ++i) {
442                 bool isDefault = this->readU8();
443                 if (isDefault) {
444                     std::unique_ptr<Statement> statement = this->statement();
445                     cases.push_back(SwitchCase::MakeDefault(/*line=*/-1, std::move(statement)));
446                 } else {
447                     SKSL_INT value = this->readS32();
448                     std::unique_ptr<Statement> statement = this->statement();
449                     cases.push_back(SwitchCase::Make(/*line=*/-1, std::move(value),
450                             std::move(statement)));
451                 }
452             }
453             return SwitchStatement::Make(this->context(), /*line=*/-1, isStatic, std::move(expr),
454                                          std::move(cases), fSymbolTable);
455         }
456         case Rehydrator::kVarDeclaration_Command: {
457             Variable* var = this->symbolRef<Variable>(Symbol::Kind::kVariable);
458             const Type* baseType = this->type();
459             int arraySize = this->readU8();
460             std::unique_ptr<Expression> value = this->expression();
461             return VarDeclaration::Make(this->context(), var, baseType, arraySize,
462                     std::move(value));
463         }
464         case Rehydrator::kVoid_Command:
465             return nullptr;
466         default:
467             printf("unsupported statement %d\n", kind);
468             SkASSERT(false);
469             return nullptr;
470     }
471 }
472 
expressionArray()473 ExpressionArray Rehydrator::expressionArray() {
474     uint8_t count = this->readU8();
475     ExpressionArray array;
476     array.reserve_back(count);
477     for (int i = 0; i < count; ++i) {
478         array.push_back(this->expression());
479     }
480     return array;
481 }
482 
expression()483 std::unique_ptr<Expression> Rehydrator::expression() {
484     int kind = this->readU8();
485     switch (kind) {
486         case Rehydrator::kBinary_Command: {
487             std::unique_ptr<Expression> left = this->expression();
488             Token::Kind op = (Token::Kind) this->readU8();
489             std::unique_ptr<Expression> right = this->expression();
490             return BinaryExpression::Make(this->context(), std::move(left), op, std::move(right));
491         }
492         case Rehydrator::kBoolLiteral_Command: {
493             bool value = this->readU8();
494             return Literal::MakeBool(this->context(), /*line=*/-1, value);
495         }
496         case Rehydrator::kConstructorArray_Command: {
497             const Type* type = this->type();
498             return ConstructorArray::Make(this->context(), /*line=*/-1, *type,
499                     this->expressionArray());
500         }
501         case Rehydrator::kConstructorArrayCast_Command: {
502             const Type* type = this->type();
503             ExpressionArray args = this->expressionArray();
504             SkASSERT(args.size() == 1);
505             return ConstructorArrayCast::Make(this->context(), /*line=*/-1, *type,
506                                               std::move(args[0]));
507         }
508         case Rehydrator::kConstructorCompound_Command: {
509             const Type* type = this->type();
510             return ConstructorCompound::Make(this->context(), /*line=*/-1, *type,
511                                              this->expressionArray());
512         }
513         case Rehydrator::kConstructorDiagonalMatrix_Command: {
514             const Type* type = this->type();
515             ExpressionArray args = this->expressionArray();
516             SkASSERT(args.size() == 1);
517             return ConstructorDiagonalMatrix::Make(this->context(), /*line=*/-1, *type,
518                                                    std::move(args[0]));
519         }
520         case Rehydrator::kConstructorMatrixResize_Command: {
521             const Type* type = this->type();
522             ExpressionArray args = this->expressionArray();
523             SkASSERT(args.size() == 1);
524             return ConstructorMatrixResize::Make(this->context(), /*line=*/-1, *type,
525                                                  std::move(args[0]));
526         }
527         case Rehydrator::kConstructorScalarCast_Command: {
528             const Type* type = this->type();
529             ExpressionArray args = this->expressionArray();
530             SkASSERT(args.size() == 1);
531             return ConstructorScalarCast::Make(this->context(), /*line=*/-1, *type,
532                     std::move(args[0]));
533         }
534         case Rehydrator::kConstructorSplat_Command: {
535             const Type* type = this->type();
536             ExpressionArray args = this->expressionArray();
537             SkASSERT(args.size() == 1);
538             return ConstructorSplat::Make(this->context(), /*line=*/-1, *type, std::move(args[0]));
539         }
540         case Rehydrator::kConstructorStruct_Command: {
541             const Type* type = this->type();
542             return ConstructorStruct::Make(this->context(), /*line=*/-1, *type,
543                     this->expressionArray());
544         }
545         case Rehydrator::kConstructorCompoundCast_Command: {
546             const Type* type = this->type();
547             ExpressionArray args = this->expressionArray();
548             SkASSERT(args.size() == 1);
549             return ConstructorCompoundCast::Make(this->context(), /*line=*/-1, *type,
550                     std::move(args[0]));
551         }
552         case Rehydrator::kFieldAccess_Command: {
553             std::unique_ptr<Expression> base = this->expression();
554             int index = this->readU8();
555             FieldAccess::OwnerKind ownerKind = (FieldAccess::OwnerKind) this->readU8();
556             return FieldAccess::Make(this->context(), std::move(base), index, ownerKind);
557         }
558         case Rehydrator::kFloatLiteral_Command: {
559             const Type* type = this->type();
560             int32_t floatBits = this->readS32();
561             float value;
562             memcpy(&value, &floatBits, sizeof(value));
563             return Literal::MakeFloat(/*line=*/-1, value, type);
564         }
565         case Rehydrator::kFunctionCall_Command: {
566             const Type* type = this->type();
567             const Symbol* symbol = this->possiblyBuiltinSymbolRef();
568             ExpressionArray args = this->expressionArray();
569             const FunctionDeclaration* f;
570             if (symbol->is<FunctionDeclaration>()) {
571                 f = &symbol->as<FunctionDeclaration>();
572             } else if (symbol->is<UnresolvedFunction>()) {
573                 const UnresolvedFunction& unresolved = symbol->as<UnresolvedFunction>();
574                 f = FunctionCall::FindBestFunctionForCall(this->context(), unresolved.functions(),
575                         args);
576                 SkASSERT(f);
577             } else {
578                 SkASSERT(false);
579                 return nullptr;
580             }
581             return FunctionCall::Make(this->context(), /*line=*/-1, type, *f, std::move(args));
582         }
583         case Rehydrator::kIndex_Command: {
584             std::unique_ptr<Expression> base = this->expression();
585             std::unique_ptr<Expression> index = this->expression();
586             return IndexExpression::Make(this->context(), std::move(base), std::move(index));
587         }
588         case Rehydrator::kIntLiteral_Command: {
589             const Type* type = this->type();
590             if (type->isUnsigned()) {
591                 unsigned int value = this->readU32();
592                 return Literal::MakeInt(/*line=*/-1, value, type);
593             } else {
594                 int value = this->readS32();
595                 return Literal::MakeInt(/*line=*/-1, value, type);
596             }
597         }
598         case Rehydrator::kPostfix_Command: {
599             Token::Kind op = (Token::Kind) this->readU8();
600             std::unique_ptr<Expression> operand = this->expression();
601             return PostfixExpression::Make(this->context(), std::move(operand), op);
602         }
603         case Rehydrator::kPrefix_Command: {
604             Token::Kind op = (Token::Kind) this->readU8();
605             std::unique_ptr<Expression> operand = this->expression();
606             return PrefixExpression::Make(this->context(), op, std::move(operand));
607         }
608         case Rehydrator::kSetting_Command: {
609             std::string name(this->readString());
610             return Setting::Convert(this->context(), /*line=*/-1, name);
611         }
612         case Rehydrator::kSwizzle_Command: {
613             std::unique_ptr<Expression> base = this->expression();
614             int count = this->readU8();
615             ComponentArray components;
616             for (int i = 0; i < count; ++i) {
617                 components.push_back(this->readU8());
618             }
619             return Swizzle::Make(this->context(), std::move(base), components);
620         }
621         case Rehydrator::kTernary_Command: {
622             std::unique_ptr<Expression> test = this->expression();
623             std::unique_ptr<Expression> ifTrue = this->expression();
624             std::unique_ptr<Expression> ifFalse = this->expression();
625             return TernaryExpression::Make(this->context(), std::move(test),
626                                            std::move(ifTrue), std::move(ifFalse));
627         }
628         case Rehydrator::kVariableReference_Command: {
629             const Variable* var = this->symbolRef<Variable>(Symbol::Kind::kVariable);
630             VariableReference::RefKind refKind = (VariableReference::RefKind) this->readU8();
631             return VariableReference::Make(/*line=*/-1, var, refKind);
632         }
633         case Rehydrator::kVoid_Command:
634             return nullptr;
635         default:
636             printf("unsupported expression %d\n", kind);
637             SkASSERT(false);
638             return nullptr;
639     }
640 }
641 
symbolTable()642 std::shared_ptr<SymbolTable> Rehydrator::symbolTable() {
643     int command = this->readU8();
644     if (command == kVoid_Command) {
645         return nullptr;
646     }
647     SkASSERT(command == kSymbolTable_Command);
648     bool builtin = this->readU8();
649     uint16_t ownedCount = this->readU16();
650     fSymbolTable = std::make_shared<SymbolTable>(std::move(fSymbolTable), builtin);
651     std::vector<const Symbol*> ownedSymbols;
652     ownedSymbols.reserve(ownedCount);
653     for (int i = 0; i < ownedCount; ++i) {
654         ownedSymbols.push_back(this->symbol());
655     }
656     uint16_t symbolCount = this->readU16();
657     std::vector<std::pair<std::string_view, int>> symbols;
658     symbols.reserve(symbolCount);
659     for (int i = 0; i < symbolCount; ++i) {
660         int index = this->readU16();
661         if (index != kBuiltin_Symbol) {
662             fSymbolTable->addWithoutOwnership(ownedSymbols[index]);
663         } else {
664             std::string_view name = this->readString();
665             SymbolTable* root = fSymbolTable.get();
666             while (root->fParent) {
667                 root = root->fParent.get();
668             }
669             const Symbol* s = (*root)[name];
670             SkASSERT(s);
671             fSymbolTable->addWithoutOwnership(s);
672         }
673     }
674     return fSymbolTable;
675 }
676 
677 }  // namespace SkSL
678