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