blob: 9d916661d98d0ebf1eb8ecc81dae1455ff2943f1 [file] [log] [blame]
Ethan Nicholasc18bb512020-07-28 14:46:53 -04001/*
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"
John Stilesfbd050b2020-08-03 13:21:46 -04009
10#include <memory>
John Stilesb8e010c2020-08-11 18:05:39 -040011#include <unordered_set>
12
Ethan Nicholasc18bb512020-07-28 14:46:53 -040013#include "src/sksl/ir/SkSLBinaryExpression.h"
14#include "src/sksl/ir/SkSLBreakStatement.h"
15#include "src/sksl/ir/SkSLContinueStatement.h"
16#include "src/sksl/ir/SkSLDiscardStatement.h"
17#include "src/sksl/ir/SkSLDoStatement.h"
18#include "src/sksl/ir/SkSLEnum.h"
19#include "src/sksl/ir/SkSLExpression.h"
20#include "src/sksl/ir/SkSLExpressionStatement.h"
21#include "src/sksl/ir/SkSLField.h"
22#include "src/sksl/ir/SkSLFieldAccess.h"
23#include "src/sksl/ir/SkSLFloatLiteral.h"
24#include "src/sksl/ir/SkSLForStatement.h"
25#include "src/sksl/ir/SkSLFunctionCall.h"
26#include "src/sksl/ir/SkSLFunctionDeclaration.h"
27#include "src/sksl/ir/SkSLFunctionDefinition.h"
28#include "src/sksl/ir/SkSLIfStatement.h"
29#include "src/sksl/ir/SkSLIndexExpression.h"
John Stiles98c1f822020-09-09 14:18:53 -040030#include "src/sksl/ir/SkSLInlineMarker.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040031#include "src/sksl/ir/SkSLIntLiteral.h"
32#include "src/sksl/ir/SkSLInterfaceBlock.h"
33#include "src/sksl/ir/SkSLModifiers.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040034#include "src/sksl/ir/SkSLPostfixExpression.h"
35#include "src/sksl/ir/SkSLPrefixExpression.h"
36#include "src/sksl/ir/SkSLProgramElement.h"
37#include "src/sksl/ir/SkSLReturnStatement.h"
38#include "src/sksl/ir/SkSLSetting.h"
39#include "src/sksl/ir/SkSLStatement.h"
John Stilesdc75a972020-11-25 16:24:55 -050040#include "src/sksl/ir/SkSLStructDefinition.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040041#include "src/sksl/ir/SkSLSwitchCase.h"
42#include "src/sksl/ir/SkSLSwitchStatement.h"
43#include "src/sksl/ir/SkSLSwizzle.h"
John Stiles49a547f2020-10-06 16:14:37 -040044#include "src/sksl/ir/SkSLSymbolAlias.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040045#include "src/sksl/ir/SkSLSymbolTable.h"
46#include "src/sksl/ir/SkSLTernaryExpression.h"
47#include "src/sksl/ir/SkSLType.h"
48#include "src/sksl/ir/SkSLUnresolvedFunction.h"
49#include "src/sksl/ir/SkSLVarDeclarations.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040050#include "src/sksl/ir/SkSLVariable.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040051
52namespace SkSL {
53
54class AutoRehydratorSymbolTable {
55public:
56 AutoRehydratorSymbolTable(Rehydrator* rehydrator)
57 : fRehydrator(rehydrator)
58 , fOldSymbols(fRehydrator->fSymbolTable) {
59 fRehydrator->fSymbolTable = fRehydrator->symbolTable();
60 }
61
62 ~AutoRehydratorSymbolTable() {
63 fRehydrator->fSymbolTable = std::move(fOldSymbols);
64 }
65
66private:
67 Rehydrator* fRehydrator;
68 std::shared_ptr<SymbolTable> fOldSymbols;
69};
70
John Stiles7c3515b2020-10-16 18:38:39 -040071Rehydrator::Rehydrator(const Context* context, ModifiersPool* modifiers,
72 std::shared_ptr<SymbolTable> symbolTable, ErrorReporter* errorReporter,
73 const uint8_t* src, size_t length)
74 : fContext(*context)
75 , fModifiers(*modifiers)
76 , fErrors(errorReporter)
77 , fSymbolTable(std::move(symbolTable))
78 , fStart(src)
79 SkDEBUGCODE(, fEnd(fStart + length)) {
80 SkASSERT(fSymbolTable);
81 SkASSERT(fSymbolTable->isBuiltin());
82 // skip past string data
83 fIP = fStart;
84 fIP += this->readU16();
85}
86
Ethan Nicholasc18bb512020-07-28 14:46:53 -040087Layout Rehydrator::layout() {
88 switch (this->readU8()) {
89 case kBuiltinLayout_Command: {
90 Layout result;
91 result.fBuiltin = this->readS16();
92 return result;
93 }
94 case kDefaultLayout_Command:
95 return Layout();
96 case kLayout_Command: {
97 int flags = this->readU32();
98 int location = this->readS8();
99 int offset = this->readS8();
100 int binding = this->readS8();
101 int index = this->readS8();
102 int set = this->readS8();
103 int builtin = this->readS16();
104 int inputAttachmentIndex = this->readS8();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400105 int primitive = this->readS8();
106 int maxVertices = this->readS8();
107 int invocations = this->readS8();
108 StringFragment marker = this->readString();
109 StringFragment when = this->readString();
110 int key = this->readS8();
111 int ctype = this->readS8();
112 return Layout(flags, location, offset, binding, index, set, builtin,
Brian Osman4717fbb2021-02-23 13:12:09 -0500113 inputAttachmentIndex, (Layout::Primitive)primitive, maxVertices,
114 invocations, marker, when, (Layout::Key)key, (Layout::CType)ctype);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400115 }
116 default:
117 SkASSERT(false);
118 return Layout();
119 }
120}
121
122Modifiers Rehydrator::modifiers() {
123 switch (this->readU8()) {
124 case kDefaultModifiers_Command:
125 return Modifiers();
126 case kModifiers8Bit_Command: {
127 Layout l = this->layout();
128 int flags = this->readU8();
129 return Modifiers(l, flags);
130 }
131 case kModifiers_Command: {
132 Layout l = this->layout();
133 int flags = this->readS32();
134 return Modifiers(l, flags);
135 }
136 default:
137 SkASSERT(false);
138 return Modifiers();
139 }
140}
141
Brian Osman5bf3e202020-10-13 10:34:18 -0400142const Symbol* Rehydrator::symbol() {
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400143 int kind = this->readU8();
144 switch (kind) {
145 case kArrayType_Command: {
146 uint16_t id = this->readU16();
147 const Type* componentType = this->type();
Brian Osmane8c26082020-10-01 17:22:45 -0400148 int8_t count = this->readS8();
149 String name = componentType->name();
150 if (count == Type::kUnsizedArray) {
151 name += "[]";
152 } else {
153 name += "[" + to_string(count) + "]";
154 }
Brian Osman5bf3e202020-10-13 10:34:18 -0400155 const Type* result = fSymbolTable->takeOwnershipOfSymbol(
John Stilesad2d4942020-12-11 16:55:58 -0500156 Type::MakeArrayType(name, *componentType, count));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400157 this->addSymbol(id, result);
158 return result;
159 }
160 case kEnumType_Command: {
161 uint16_t id = this->readU16();
162 StringFragment name = this->readString();
John Stilese6c67c52021-01-15 12:01:00 -0500163 const Type* result = fSymbolTable->takeOwnershipOfSymbol(Type::MakeEnumType(name));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400164 this->addSymbol(id, result);
165 return result;
166 }
167 case kFunctionDeclaration_Command: {
168 uint16_t id = this->readU16();
169 Modifiers modifiers = this->modifiers();
170 StringFragment name = this->readString();
171 int parameterCount = this->readU8();
Brian Osman5bf3e202020-10-13 10:34:18 -0400172 std::vector<const Variable*> parameters;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400173 parameters.reserve(parameterCount);
174 for (int i = 0; i < parameterCount; ++i) {
Ethan Nicholase6592142020-09-08 10:22:09 -0400175 parameters.push_back(this->symbolRef<Variable>(Symbol::Kind::kVariable));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400176 }
177 const Type* returnType = this->type();
Brian Osman5bf3e202020-10-13 10:34:18 -0400178 const FunctionDeclaration* result =
John Stiles3ae071e2020-08-05 15:29:29 -0400179 fSymbolTable->takeOwnershipOfSymbol(std::make_unique<FunctionDeclaration>(
John Stiles586df952020-11-12 18:27:13 -0500180 /*offset=*/-1, fModifiers.addToPool(modifiers), name,
Ethan Nicholased84b732020-10-08 11:45:44 -0400181 std::move(parameters), returnType, /*builtin=*/true));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400182 this->addSymbol(id, result);
183 return result;
184 }
185 case kField_Command: {
Ethan Nicholase6592142020-09-08 10:22:09 -0400186 const Variable* owner = this->symbolRef<Variable>(Symbol::Kind::kVariable);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400187 uint8_t index = this->readU8();
Brian Osman5bf3e202020-10-13 10:34:18 -0400188 const Field* result = fSymbolTable->takeOwnershipOfSymbol(
Ethan Nicholase2c49992020-10-05 11:49:11 -0400189 std::make_unique<Field>(/*offset=*/-1, owner, index));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400190 return result;
191 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400192 case kStructType_Command: {
193 uint16_t id = this->readU16();
194 StringFragment name = this->readString();
195 uint8_t fieldCount = this->readU8();
196 std::vector<Type::Field> fields;
197 fields.reserve(fieldCount);
198 for (int i = 0; i < fieldCount; ++i) {
199 Modifiers m = this->modifiers();
John Stilesf621e232020-08-25 13:33:02 -0400200 StringFragment fieldName = this->readString();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400201 const Type* type = this->type();
John Stilesf621e232020-08-25 13:33:02 -0400202 fields.emplace_back(m, fieldName, type);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400203 }
Brian Osman5bf3e202020-10-13 10:34:18 -0400204 const Type* result = fSymbolTable->takeOwnershipOfSymbol(
John Stilesad2d4942020-12-11 16:55:58 -0500205 Type::MakeStructType(/*offset=*/-1, name, std::move(fields)));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400206 this->addSymbol(id, result);
207 return result;
208 }
209 case kSymbolRef_Command: {
210 uint16_t id = this->readU16();
211 SkASSERT(fSymbols.size() > id);
212 return fSymbols[id];
213 }
John Stiles49a547f2020-10-06 16:14:37 -0400214 case kSymbolAlias_Command: {
215 uint16_t id = this->readU16();
216 StringFragment name = this->readString();
Brian Osman5bf3e202020-10-13 10:34:18 -0400217 const Symbol* origSymbol = this->symbol();
218 const SymbolAlias* symbolAlias = fSymbolTable->takeOwnershipOfSymbol(
John Stiles49a547f2020-10-06 16:14:37 -0400219 std::make_unique<SymbolAlias>(/*offset=*/-1, name, origSymbol));
220 this->addSymbol(id, symbolAlias);
221 return symbolAlias;
222 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400223 case kSystemType_Command: {
224 uint16_t id = this->readU16();
225 StringFragment name = this->readString();
Brian Osman5bf3e202020-10-13 10:34:18 -0400226 const Symbol* result = (*fSymbolTable)[name];
Ethan Nicholase6592142020-09-08 10:22:09 -0400227 SkASSERT(result && result->kind() == Symbol::Kind::kType);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400228 this->addSymbol(id, result);
229 return result;
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();
Ethan Nicholase6592142020-09-08 10:22:09 -0400238 SkASSERT(f && f->kind() == Symbol::Kind::kFunctionDeclaration);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400239 functions.push_back((const FunctionDeclaration*) f);
240 }
Brian Osman5bf3e202020-10-13 10:34:18 -0400241 const UnresolvedFunction* result = fSymbolTable->takeOwnershipOfSymbol(
John Stiles3ae071e2020-08-05 15:29:29 -0400242 std::make_unique<UnresolvedFunction>(std::move(functions)));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400243 this->addSymbol(id, result);
244 return result;
245 }
246 case kVariable_Command: {
247 uint16_t id = this->readU16();
John Stiles586df952020-11-12 18:27:13 -0500248 const Modifiers* m = fModifiers.addToPool(this->modifiers());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400249 StringFragment name = this->readString();
250 const Type* type = this->type();
251 Variable::Storage storage = (Variable::Storage) this->readU8();
Brian Osman5bf3e202020-10-13 10:34:18 -0400252 const Variable* result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Variable>(
Brian Osman3887a012020-09-30 13:22:27 -0400253 /*offset=*/-1, m, name, type, /*builtin=*/true, storage));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400254 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
264const Type* Rehydrator::type() {
265 const Symbol* result = this->symbol();
Ethan Nicholase6592142020-09-08 10:22:09 -0400266 SkASSERT(result->kind() == Symbol::Kind::kType);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400267 return (const Type*) result;
268}
269
270std::vector<std::unique_ptr<ProgramElement>> Rehydrator::elements() {
271 SkDEBUGCODE(uint8_t command = )this->readU8();
272 SkASSERT(command == kElements_Command);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400273 std::vector<std::unique_ptr<ProgramElement>> result;
John Stiles1ea7f542020-11-02 13:07:23 -0500274 while (std::unique_ptr<ProgramElement> elem = this->element()) {
275 result.push_back(std::move(elem));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400276 }
277 return result;
278}
279
280std::unique_ptr<ProgramElement> Rehydrator::element() {
281 int kind = this->readU8();
282 switch (kind) {
283 case Rehydrator::kEnum_Command: {
284 StringFragment typeName = this->readString();
Brian Osman1313d1a2020-09-08 10:34:30 -0400285 std::shared_ptr<SymbolTable> symbols = this->symbolTable(/*inherit=*/false);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400286 for (auto& s : symbols->fOwnedSymbols) {
Ethan Nicholase6592142020-09-08 10:22:09 -0400287 SkASSERT(s->kind() == Symbol::Kind::kVariable);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400288 Variable& v = (Variable&) *s;
289 int value = this->readS32();
Ethan Nicholas5b9b0db2021-01-21 13:12:01 -0500290 // enum variables aren't really 'declared', but we have to create a declaration to
291 // store the value
292 auto valueLiteral = std::make_unique<IntLiteral>(fContext, /*offset=*/-1, value);
293 auto declaration = std::make_unique<VarDeclaration>(&v, &v.type(), /*arraySize=*/0,
294 std::move(valueLiteral));
295 v.setDeclaration(declaration.get());
296 symbols->takeOwnershipOfIRNode(std::move(declaration));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400297 }
John Stiles1c823672020-10-20 10:23:50 -0400298 return std::make_unique<Enum>(/*offset=*/-1, typeName, std::move(symbols),
299 /*isSharedWithCpp=*/true, /*isBuiltin=*/true);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400300 }
301 case Rehydrator::kFunctionDefinition_Command: {
302 const FunctionDeclaration* decl = this->symbolRef<FunctionDeclaration>(
Ethan Nicholase6592142020-09-08 10:22:09 -0400303 Symbol::Kind::kFunctionDeclaration);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400304 std::unique_ptr<Statement> body = this->statement();
John Stilesb8e010c2020-08-11 18:05:39 -0400305 std::unordered_set<const FunctionDeclaration*> refs;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400306 uint8_t refCount = this->readU8();
307 for (int i = 0; i < refCount; ++i) {
308 refs.insert(this->symbolRef<FunctionDeclaration>(
Ethan Nicholase6592142020-09-08 10:22:09 -0400309 Symbol::Kind::kFunctionDeclaration));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400310 }
John Stiles607d36b2020-10-19 15:00:01 -0400311 auto result = std::make_unique<FunctionDefinition>(/*offset=*/-1, decl,
312 /*builtin=*/true, std::move(body),
313 std::move(refs));
314 decl->setDefinition(result.get());
315 return std::move(result);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400316 }
317 case Rehydrator::kInterfaceBlock_Command: {
318 const Symbol* var = this->symbol();
John Stiles87ae34e2020-10-13 12:50:11 -0400319 SkASSERT(var && var->is<Variable>());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400320 StringFragment typeName = this->readString();
321 StringFragment instanceName = this->readString();
John Stilesd39aec02020-12-03 10:42:26 -0500322 int arraySize = this->readS8();
John Stiles87ae34e2020-10-13 12:50:11 -0400323 return std::make_unique<InterfaceBlock>(/*offset=*/-1, &var->as<Variable>(), typeName,
John Stilesd39aec02020-12-03 10:42:26 -0500324 instanceName, arraySize, nullptr);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400325 }
326 case Rehydrator::kVarDeclarations_Command: {
Brian Osmanc0213602020-10-06 14:43:32 -0400327 std::unique_ptr<Statement> decl = this->statement();
John Stiles1ea7f542020-11-02 13:07:23 -0500328 return std::make_unique<GlobalVarDeclaration>(/*offset=*/-1, std::move(decl));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400329 }
John Stilesdc75a972020-11-25 16:24:55 -0500330 case Rehydrator::kStructDefinition_Command: {
331 const Symbol* type = this->symbol();
332 SkASSERT(type && type->is<Type>());
333 return std::make_unique<StructDefinition>(/*offset=*/-1, type->as<Type>());
334 }
John Stiles1ea7f542020-11-02 13:07:23 -0500335 case Rehydrator::kElementsComplete_Command:
336 return nullptr;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400337 default:
John Stiles1ea7f542020-11-02 13:07:23 -0500338 SkDEBUGFAILF("unsupported element %d\n", kind);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400339 return nullptr;
340 }
341}
342
343std::unique_ptr<Statement> Rehydrator::statement() {
344 int kind = this->readU8();
345 switch (kind) {
346 case Rehydrator::kBlock_Command: {
347 AutoRehydratorSymbolTable symbols(this);
348 int count = this->readU8();
John Stiles8f2a0cf2020-10-13 12:48:21 -0400349 StatementArray statements;
John Stilesf4bda742020-10-14 16:57:41 -0400350 statements.reserve_back(count);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400351 for (int i = 0; i < count; ++i) {
352 statements.push_back(this->statement());
353 }
354 bool isScope = this->readU8();
John Stiles8f2a0cf2020-10-13 12:48:21 -0400355 return std::make_unique<Block>(/*offset=*/-1, std::move(statements), fSymbolTable,
356 isScope);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400357 }
358 case Rehydrator::kBreak_Command:
359 return std::unique_ptr<Statement>(new BreakStatement(-1));
360 case Rehydrator::kContinue_Command:
361 return std::unique_ptr<Statement>(new ContinueStatement(-1));
362 case Rehydrator::kDiscard_Command:
363 return std::unique_ptr<Statement>(new DiscardStatement(-1));
364 case Rehydrator::kDo_Command: {
365 std::unique_ptr<Statement> stmt = this->statement();
366 std::unique_ptr<Expression> expr = this->expression();
367 return std::unique_ptr<Statement>(new DoStatement(-1, std::move(stmt),
368 std::move(expr)));
369 }
370 case Rehydrator::kExpressionStatement_Command: {
371 std::unique_ptr<Expression> expr = this->expression();
372 return std::unique_ptr<Statement>(new ExpressionStatement(std::move(expr)));
373 }
374 case Rehydrator::kFor_Command: {
375 std::unique_ptr<Statement> initializer = this->statement();
376 std::unique_ptr<Expression> test = this->expression();
377 std::unique_ptr<Expression> next = this->expression();
378 std::unique_ptr<Statement> body = this->statement();
379 std::shared_ptr<SymbolTable> symbols = this->symbolTable();
380 return std::unique_ptr<Statement>(new ForStatement(-1, std::move(initializer),
381 std::move(test), std::move(next),
382 std::move(body),
383 std::move(symbols)));
384 }
385 case Rehydrator::kIf_Command: {
386 bool isStatic = this->readU8();
387 std::unique_ptr<Expression> test = this->expression();
388 std::unique_ptr<Statement> ifTrue = this->statement();
389 std::unique_ptr<Statement> ifFalse = this->statement();
390 return std::unique_ptr<Statement>(new IfStatement(-1, isStatic, std::move(test),
391 std::move(ifTrue),
392 std::move(ifFalse)));
393 }
John Stiles98c1f822020-09-09 14:18:53 -0400394 case Rehydrator::kInlineMarker_Command: {
395 const FunctionDeclaration* funcDecl = this->symbolRef<FunctionDeclaration>(
396 Symbol::Kind::kFunctionDeclaration);
Ethan Nicholasceb62142020-10-09 16:51:18 -0400397 return std::make_unique<InlineMarker>(funcDecl);
John Stiles98c1f822020-09-09 14:18:53 -0400398 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400399 case Rehydrator::kReturn_Command: {
400 std::unique_ptr<Expression> expr = this->expression();
401 if (expr) {
402 return std::unique_ptr<Statement>(new ReturnStatement(std::move(expr)));
403 } else {
404 return std::unique_ptr<Statement>(new ReturnStatement(-1));
405 }
406 }
407 case Rehydrator::kSwitch_Command: {
408 bool isStatic = this->readU8();
409 AutoRehydratorSymbolTable symbols(this);
410 std::unique_ptr<Expression> expr = this->expression();
411 int caseCount = this->readU8();
412 std::vector<std::unique_ptr<SwitchCase>> cases;
413 cases.reserve(caseCount);
414 for (int i = 0; i < caseCount; ++i) {
415 std::unique_ptr<Expression> value = this->expression();
416 int statementCount = this->readU8();
John Stiles8f2a0cf2020-10-13 12:48:21 -0400417 StatementArray statements;
John Stilesf4bda742020-10-14 16:57:41 -0400418 statements.reserve_back(statementCount);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400419 for (int j = 0; j < statementCount; ++j) {
420 statements.push_back(this->statement());
421 }
John Stiles8f2a0cf2020-10-13 12:48:21 -0400422 cases.push_back(std::make_unique<SwitchCase>(/*offset=*/-1, std::move(value),
423 std::move(statements)));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400424 }
John Stiles8f2a0cf2020-10-13 12:48:21 -0400425 return std::make_unique<SwitchStatement>(-1, isStatic, std::move(expr),
426 std::move(cases), fSymbolTable);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400427 }
428 case Rehydrator::kVarDeclaration_Command: {
Ethan Nicholase6592142020-09-08 10:22:09 -0400429 Variable* var = this->symbolRef<Variable>(Symbol::Kind::kVariable);
Brian Osmanc0213602020-10-06 14:43:32 -0400430 const Type* baseType = this->type();
John Stiles62a56462020-12-03 10:41:58 -0500431 int arraySize = this->readS8();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400432 std::unique_ptr<Expression> value = this->expression();
Ethan Nicholas5b9b0db2021-01-21 13:12:01 -0500433 auto result = std::make_unique<VarDeclaration>(var, baseType, arraySize,
434 std::move(value));
435 var->setDeclaration(result.get());
436 return std::move(result);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400437 }
438 case Rehydrator::kVoid_Command:
439 return nullptr;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400440 default:
441 printf("unsupported statement %d\n", kind);
442 SkASSERT(false);
443 return nullptr;
444 }
445}
446
447std::unique_ptr<Expression> Rehydrator::expression() {
448 int kind = this->readU8();
449 switch (kind) {
450 case Rehydrator::kBinary_Command: {
451 std::unique_ptr<Expression> left = this->expression();
452 Token::Kind op = (Token::Kind) this->readU8();
453 std::unique_ptr<Expression> right = this->expression();
454 const Type* type = this->type();
Ethan Nicholas30d30222020-09-11 12:27:26 -0400455 return std::make_unique<BinaryExpression>(-1, std::move(left), op, std::move(right),
456 type);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400457 }
458 case Rehydrator::kBoolLiteral_Command: {
459 bool value = this->readU8();
Ethan Nicholas30d30222020-09-11 12:27:26 -0400460 return std::make_unique<BoolLiteral>(fContext, -1, value);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400461 }
462 case Rehydrator::kConstructor_Command: {
463 const Type* type = this->type();
464 uint8_t argCount = this->readU8();
John Stiles8e3b6be2020-10-13 11:14:08 -0400465 ExpressionArray args;
John Stilesf4bda742020-10-14 16:57:41 -0400466 args.reserve_back(argCount);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400467 for (int i = 0; i < argCount; ++i) {
468 args.push_back(this->expression());
469 }
John Stiles54f00492021-02-19 11:46:10 -0500470 return std::make_unique<Constructor>(/*offset=*/-1, *type, std::move(args));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400471 }
472 case Rehydrator::kFieldAccess_Command: {
473 std::unique_ptr<Expression> base = this->expression();
474 int index = this->readU8();
475 FieldAccess::OwnerKind ownerKind = (FieldAccess::OwnerKind) this->readU8();
Ethan Nicholas30d30222020-09-11 12:27:26 -0400476 return std::make_unique<FieldAccess>(std::move(base), index, ownerKind);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400477 }
478 case Rehydrator::kFloatLiteral_Command: {
Brian Osmanfb964a42020-11-18 10:45:52 -0500479 const Type* type = this->type();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400480 FloatIntUnion u;
481 u.fInt = this->readS32();
Brian Osmanfb964a42020-11-18 10:45:52 -0500482 return std::make_unique<FloatLiteral>(-1, u.fFloat, type);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400483 }
484 case Rehydrator::kFunctionCall_Command: {
Ethan Nicholas30d30222020-09-11 12:27:26 -0400485 const Type* type = this->type();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400486 const FunctionDeclaration* f = this->symbolRef<FunctionDeclaration>(
Ethan Nicholase6592142020-09-08 10:22:09 -0400487 Symbol::Kind::kFunctionDeclaration);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400488 uint8_t argCount = this->readU8();
John Stiles8e3b6be2020-10-13 11:14:08 -0400489 ExpressionArray args;
John Stilesf4bda742020-10-14 16:57:41 -0400490 args.reserve_back(argCount);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400491 for (int i = 0; i < argCount; ++i) {
492 args.push_back(this->expression());
493 }
Ethan Nicholas0dec9922020-10-05 15:51:52 -0400494 return std::make_unique<FunctionCall>(-1, type, f, std::move(args));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400495 }
496 case Rehydrator::kIndex_Command: {
497 std::unique_ptr<Expression> base = this->expression();
498 std::unique_ptr<Expression> index = this->expression();
Ethan Nicholas30d30222020-09-11 12:27:26 -0400499 return std::make_unique<IndexExpression>(fContext, std::move(base), std::move(index));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400500 }
501 case Rehydrator::kIntLiteral_Command: {
Brian Osmanfb964a42020-11-18 10:45:52 -0500502 const Type* type = this->type();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400503 int value = this->readS32();
Brian Osmanfb964a42020-11-18 10:45:52 -0500504 return std::make_unique<IntLiteral>(-1, value, type);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400505 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400506 case Rehydrator::kPostfix_Command: {
507 Token::Kind op = (Token::Kind) this->readU8();
508 std::unique_ptr<Expression> operand = this->expression();
Ethan Nicholas30d30222020-09-11 12:27:26 -0400509 return std::make_unique<PostfixExpression>(std::move(operand), op);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400510 }
511 case Rehydrator::kPrefix_Command: {
512 Token::Kind op = (Token::Kind) this->readU8();
513 std::unique_ptr<Expression> operand = this->expression();
Ethan Nicholas30d30222020-09-11 12:27:26 -0400514 return std::make_unique<PrefixExpression>(op, std::move(operand));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400515 }
516 case Rehydrator::kSetting_Command: {
517 StringFragment name = this->readString();
Ethan Nicholas01ec7e82020-10-08 12:10:12 -0400518 const Type* type = this->type();
519 return std::make_unique<Setting>(-1, name, type);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400520 }
521 case Rehydrator::kSwizzle_Command: {
522 std::unique_ptr<Expression> base = this->expression();
523 int count = this->readU8();
John Stiles750109b2020-10-30 13:45:46 -0400524 ComponentArray components;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400525 for (int i = 0; i < count; ++i) {
526 components.push_back(this->readU8());
527 }
John Stiles750109b2020-10-30 13:45:46 -0400528 return std::make_unique<Swizzle>(fContext, std::move(base), components);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400529 }
530 case Rehydrator::kTernary_Command: {
531 std::unique_ptr<Expression> test = this->expression();
532 std::unique_ptr<Expression> ifTrue = this->expression();
533 std::unique_ptr<Expression> ifFalse = this->expression();
Ethan Nicholasa02ce0c2020-09-21 12:37:02 -0400534 return std::make_unique<TernaryExpression>(-1, std::move(test), std::move(ifTrue),
535 std::move(ifFalse));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400536 }
537 case Rehydrator::kVariableReference_Command: {
Ethan Nicholase6592142020-09-08 10:22:09 -0400538 const Variable* var = this->symbolRef<Variable>(Symbol::Kind::kVariable);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400539 VariableReference::RefKind refKind = (VariableReference::RefKind) this->readU8();
Brian Osman79457ef2020-09-24 15:01:27 -0400540 return std::make_unique<VariableReference>(-1, var, refKind);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400541 }
542 case Rehydrator::kVoid_Command:
543 return nullptr;
544 default:
545 printf("unsupported expression %d\n", kind);
546 SkASSERT(false);
547 return nullptr;
548 }
549}
550
Brian Osman1313d1a2020-09-08 10:34:30 -0400551std::shared_ptr<SymbolTable> Rehydrator::symbolTable(bool inherit) {
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400552 int command = this->readU8();
553 if (command == kVoid_Command) {
554 return nullptr;
555 }
556 SkASSERT(command == kSymbolTable_Command);
557 uint16_t ownedCount = this->readU16();
Brian Osman1313d1a2020-09-08 10:34:30 -0400558 std::shared_ptr<SymbolTable> oldTable = fSymbolTable;
John Stiles7c3515b2020-10-16 18:38:39 -0400559 std::shared_ptr<SymbolTable> result =
560 inherit ? std::make_shared<SymbolTable>(fSymbolTable, /*builtin=*/true)
561 : std::make_shared<SymbolTable>(fErrors, /*builtin=*/true);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400562 fSymbolTable = result;
Brian Osman5bf3e202020-10-13 10:34:18 -0400563 std::vector<const Symbol*> ownedSymbols;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400564 ownedSymbols.reserve(ownedCount);
565 for (int i = 0; i < ownedCount; ++i) {
566 ownedSymbols.push_back(this->symbol());
567 }
568 uint16_t symbolCount = this->readU16();
569 std::vector<std::pair<StringFragment, int>> symbols;
570 symbols.reserve(symbolCount);
571 for (int i = 0; i < symbolCount; ++i) {
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400572 int index = this->readU16();
John Stilesb8cc6652020-10-08 09:12:07 -0400573 fSymbolTable->addWithoutOwnership(ownedSymbols[index]);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400574 }
Brian Osman1313d1a2020-09-08 10:34:30 -0400575 fSymbolTable = oldTable;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400576 return result;
577}
578
John Stilesa6841be2020-08-06 14:11:56 -0400579} // namespace SkSL