blob: 57fead0f6e6c6ee594fcdaba9f7f25b3b6777e9f [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"
34#include "src/sksl/ir/SkSLNullLiteral.h"
35#include "src/sksl/ir/SkSLPostfixExpression.h"
36#include "src/sksl/ir/SkSLPrefixExpression.h"
37#include "src/sksl/ir/SkSLProgramElement.h"
38#include "src/sksl/ir/SkSLReturnStatement.h"
39#include "src/sksl/ir/SkSLSetting.h"
40#include "src/sksl/ir/SkSLStatement.h"
John Stilesdc75a972020-11-25 16:24:55 -050041#include "src/sksl/ir/SkSLStructDefinition.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040042#include "src/sksl/ir/SkSLSwitchCase.h"
43#include "src/sksl/ir/SkSLSwitchStatement.h"
44#include "src/sksl/ir/SkSLSwizzle.h"
John Stiles49a547f2020-10-06 16:14:37 -040045#include "src/sksl/ir/SkSLSymbolAlias.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040046#include "src/sksl/ir/SkSLSymbolTable.h"
47#include "src/sksl/ir/SkSLTernaryExpression.h"
48#include "src/sksl/ir/SkSLType.h"
49#include "src/sksl/ir/SkSLUnresolvedFunction.h"
50#include "src/sksl/ir/SkSLVarDeclarations.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040051#include "src/sksl/ir/SkSLVariable.h"
52#include "src/sksl/ir/SkSLWhileStatement.h"
53
54namespace SkSL {
55
56class AutoRehydratorSymbolTable {
57public:
58 AutoRehydratorSymbolTable(Rehydrator* rehydrator)
59 : fRehydrator(rehydrator)
60 , fOldSymbols(fRehydrator->fSymbolTable) {
61 fRehydrator->fSymbolTable = fRehydrator->symbolTable();
62 }
63
64 ~AutoRehydratorSymbolTable() {
65 fRehydrator->fSymbolTable = std::move(fOldSymbols);
66 }
67
68private:
69 Rehydrator* fRehydrator;
70 std::shared_ptr<SymbolTable> fOldSymbols;
71};
72
John Stiles7c3515b2020-10-16 18:38:39 -040073Rehydrator::Rehydrator(const Context* context, ModifiersPool* modifiers,
74 std::shared_ptr<SymbolTable> symbolTable, ErrorReporter* errorReporter,
75 const uint8_t* src, size_t length)
76 : fContext(*context)
77 , fModifiers(*modifiers)
78 , fErrors(errorReporter)
79 , fSymbolTable(std::move(symbolTable))
80 , fStart(src)
81 SkDEBUGCODE(, fEnd(fStart + length)) {
82 SkASSERT(fSymbolTable);
83 SkASSERT(fSymbolTable->isBuiltin());
84 // skip past string data
85 fIP = fStart;
86 fIP += this->readU16();
87}
88
Ethan Nicholasc18bb512020-07-28 14:46:53 -040089Layout Rehydrator::layout() {
90 switch (this->readU8()) {
91 case kBuiltinLayout_Command: {
92 Layout result;
93 result.fBuiltin = this->readS16();
94 return result;
95 }
96 case kDefaultLayout_Command:
97 return Layout();
98 case kLayout_Command: {
99 int flags = this->readU32();
100 int location = this->readS8();
101 int offset = this->readS8();
102 int binding = this->readS8();
103 int index = this->readS8();
104 int set = this->readS8();
105 int builtin = this->readS16();
106 int inputAttachmentIndex = this->readS8();
107 int format = this->readS8();
108 int primitive = this->readS8();
109 int maxVertices = this->readS8();
110 int invocations = this->readS8();
111 StringFragment marker = this->readString();
112 StringFragment when = this->readString();
113 int key = this->readS8();
114 int ctype = this->readS8();
115 return Layout(flags, location, offset, binding, index, set, builtin,
116 inputAttachmentIndex, (Layout::Format) format,
117 (Layout::Primitive) primitive, maxVertices, invocations, marker, when,
118 (Layout::Key) key, (Layout::CType) ctype);
119 }
120 default:
121 SkASSERT(false);
122 return Layout();
123 }
124}
125
126Modifiers 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
Brian Osman5bf3e202020-10-13 10:34:18 -0400146const Symbol* Rehydrator::symbol() {
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400147 int kind = this->readU8();
148 switch (kind) {
149 case kArrayType_Command: {
150 uint16_t id = this->readU16();
151 const Type* componentType = this->type();
Brian Osmane8c26082020-10-01 17:22:45 -0400152 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 }
Brian Osman5bf3e202020-10-13 10:34:18 -0400159 const Type* result = fSymbolTable->takeOwnershipOfSymbol(
Brian Osmane8c26082020-10-01 17:22:45 -0400160 std::make_unique<Type>(name, Type::TypeKind::kArray, *componentType, count));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400161 this->addSymbol(id, result);
162 return result;
163 }
164 case kEnumType_Command: {
165 uint16_t id = this->readU16();
166 StringFragment name = this->readString();
Brian Osman5bf3e202020-10-13 10:34:18 -0400167 const Type* result = fSymbolTable->takeOwnershipOfSymbol(
Ethan Nicholase6592142020-09-08 10:22:09 -0400168 std::make_unique<Type>(name, Type::TypeKind::kEnum));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400169 this->addSymbol(id, result);
170 return result;
171 }
172 case kFunctionDeclaration_Command: {
173 uint16_t id = this->readU16();
174 Modifiers modifiers = this->modifiers();
175 StringFragment name = this->readString();
176 int parameterCount = this->readU8();
Brian Osman5bf3e202020-10-13 10:34:18 -0400177 std::vector<const Variable*> parameters;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400178 parameters.reserve(parameterCount);
179 for (int i = 0; i < parameterCount; ++i) {
Ethan Nicholase6592142020-09-08 10:22:09 -0400180 parameters.push_back(this->symbolRef<Variable>(Symbol::Kind::kVariable));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400181 }
182 const Type* returnType = this->type();
Brian Osman5bf3e202020-10-13 10:34:18 -0400183 const FunctionDeclaration* result =
John Stiles3ae071e2020-08-05 15:29:29 -0400184 fSymbolTable->takeOwnershipOfSymbol(std::make_unique<FunctionDeclaration>(
John Stiles586df952020-11-12 18:27:13 -0500185 /*offset=*/-1, fModifiers.addToPool(modifiers), name,
Ethan Nicholased84b732020-10-08 11:45:44 -0400186 std::move(parameters), returnType, /*builtin=*/true));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400187 this->addSymbol(id, result);
188 return result;
189 }
190 case kField_Command: {
Ethan Nicholase6592142020-09-08 10:22:09 -0400191 const Variable* owner = this->symbolRef<Variable>(Symbol::Kind::kVariable);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400192 uint8_t index = this->readU8();
Brian Osman5bf3e202020-10-13 10:34:18 -0400193 const Field* result = fSymbolTable->takeOwnershipOfSymbol(
Ethan Nicholase2c49992020-10-05 11:49:11 -0400194 std::make_unique<Field>(/*offset=*/-1, owner, index));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400195 return result;
196 }
197 case kNullableType_Command: {
198 uint16_t id = this->readU16();
199 const Type* base = this->type();
Brian Osman5bf3e202020-10-13 10:34:18 -0400200 const Type* result = fSymbolTable->takeOwnershipOfSymbol(
Ethan Nicholase6592142020-09-08 10:22:09 -0400201 std::make_unique<Type>(base->name() + "?", Type::TypeKind::kNullable, *base));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400202 this->addSymbol(id, result);
203 return result;
204 }
205 case kStructType_Command: {
206 uint16_t id = this->readU16();
207 StringFragment name = this->readString();
208 uint8_t fieldCount = this->readU8();
209 std::vector<Type::Field> fields;
210 fields.reserve(fieldCount);
211 for (int i = 0; i < fieldCount; ++i) {
212 Modifiers m = this->modifiers();
John Stilesf621e232020-08-25 13:33:02 -0400213 StringFragment fieldName = this->readString();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400214 const Type* type = this->type();
John Stilesf621e232020-08-25 13:33:02 -0400215 fields.emplace_back(m, fieldName, type);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400216 }
Brian Osman5bf3e202020-10-13 10:34:18 -0400217 const Type* result = fSymbolTable->takeOwnershipOfSymbol(
John Stiles3ae071e2020-08-05 15:29:29 -0400218 std::make_unique<Type>(/*offset=*/-1, name, std::move(fields)));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400219 this->addSymbol(id, result);
220 return result;
221 }
222 case kSymbolRef_Command: {
223 uint16_t id = this->readU16();
224 SkASSERT(fSymbols.size() > id);
225 return fSymbols[id];
226 }
John Stiles49a547f2020-10-06 16:14:37 -0400227 case kSymbolAlias_Command: {
228 uint16_t id = this->readU16();
229 StringFragment name = this->readString();
Brian Osman5bf3e202020-10-13 10:34:18 -0400230 const Symbol* origSymbol = this->symbol();
231 const SymbolAlias* symbolAlias = fSymbolTable->takeOwnershipOfSymbol(
John Stiles49a547f2020-10-06 16:14:37 -0400232 std::make_unique<SymbolAlias>(/*offset=*/-1, name, origSymbol));
233 this->addSymbol(id, symbolAlias);
234 return symbolAlias;
235 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400236 case kSystemType_Command: {
237 uint16_t id = this->readU16();
238 StringFragment name = this->readString();
Brian Osman5bf3e202020-10-13 10:34:18 -0400239 const Symbol* result = (*fSymbolTable)[name];
Ethan Nicholase6592142020-09-08 10:22:09 -0400240 SkASSERT(result && result->kind() == Symbol::Kind::kType);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400241 this->addSymbol(id, result);
242 return result;
243 }
244 case kUnresolvedFunction_Command: {
245 uint16_t id = this->readU16();
246 int length = this->readU8();
247 std::vector<const FunctionDeclaration*> functions;
248 functions.reserve(length);
249 for (int i = 0; i < length; ++i) {
250 const Symbol* f = this->symbol();
Ethan Nicholase6592142020-09-08 10:22:09 -0400251 SkASSERT(f && f->kind() == Symbol::Kind::kFunctionDeclaration);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400252 functions.push_back((const FunctionDeclaration*) f);
253 }
Brian Osman5bf3e202020-10-13 10:34:18 -0400254 const UnresolvedFunction* result = fSymbolTable->takeOwnershipOfSymbol(
John Stiles3ae071e2020-08-05 15:29:29 -0400255 std::make_unique<UnresolvedFunction>(std::move(functions)));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400256 this->addSymbol(id, result);
257 return result;
258 }
259 case kVariable_Command: {
260 uint16_t id = this->readU16();
John Stiles586df952020-11-12 18:27:13 -0500261 const Modifiers* m = fModifiers.addToPool(this->modifiers());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400262 StringFragment name = this->readString();
263 const Type* type = this->type();
264 Variable::Storage storage = (Variable::Storage) this->readU8();
Brian Osman5bf3e202020-10-13 10:34:18 -0400265 const Variable* result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Variable>(
Brian Osman3887a012020-09-30 13:22:27 -0400266 /*offset=*/-1, m, name, type, /*builtin=*/true, storage));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400267 this->addSymbol(id, result);
268 return result;
269 }
270 default:
271 printf("unsupported symbol %d\n", kind);
272 SkASSERT(false);
273 return nullptr;
274 }
275}
276
277const Type* Rehydrator::type() {
278 const Symbol* result = this->symbol();
Ethan Nicholase6592142020-09-08 10:22:09 -0400279 SkASSERT(result->kind() == Symbol::Kind::kType);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400280 return (const Type*) result;
281}
282
283std::vector<std::unique_ptr<ProgramElement>> Rehydrator::elements() {
284 SkDEBUGCODE(uint8_t command = )this->readU8();
285 SkASSERT(command == kElements_Command);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400286 std::vector<std::unique_ptr<ProgramElement>> result;
John Stiles1ea7f542020-11-02 13:07:23 -0500287 while (std::unique_ptr<ProgramElement> elem = this->element()) {
288 result.push_back(std::move(elem));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400289 }
290 return result;
291}
292
293std::unique_ptr<ProgramElement> Rehydrator::element() {
294 int kind = this->readU8();
295 switch (kind) {
296 case Rehydrator::kEnum_Command: {
297 StringFragment typeName = this->readString();
Brian Osman1313d1a2020-09-08 10:34:30 -0400298 std::shared_ptr<SymbolTable> symbols = this->symbolTable(/*inherit=*/false);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400299 for (auto& s : symbols->fOwnedSymbols) {
Ethan Nicholase6592142020-09-08 10:22:09 -0400300 SkASSERT(s->kind() == Symbol::Kind::kVariable);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400301 Variable& v = (Variable&) *s;
302 int value = this->readS32();
Ethan Nicholas041fd0a2020-10-07 16:42:04 -0400303 v.setInitialValue(symbols->takeOwnershipOfIRNode(
304 std::make_unique<IntLiteral>(fContext, /*offset=*/-1, value)));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400305 }
John Stiles1c823672020-10-20 10:23:50 -0400306 return std::make_unique<Enum>(/*offset=*/-1, typeName, std::move(symbols),
307 /*isSharedWithCpp=*/true, /*isBuiltin=*/true);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400308 }
309 case Rehydrator::kFunctionDefinition_Command: {
310 const FunctionDeclaration* decl = this->symbolRef<FunctionDeclaration>(
Ethan Nicholase6592142020-09-08 10:22:09 -0400311 Symbol::Kind::kFunctionDeclaration);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400312 std::unique_ptr<Statement> body = this->statement();
John Stilesb8e010c2020-08-11 18:05:39 -0400313 std::unordered_set<const FunctionDeclaration*> refs;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400314 uint8_t refCount = this->readU8();
315 for (int i = 0; i < refCount; ++i) {
316 refs.insert(this->symbolRef<FunctionDeclaration>(
Ethan Nicholase6592142020-09-08 10:22:09 -0400317 Symbol::Kind::kFunctionDeclaration));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400318 }
John Stiles607d36b2020-10-19 15:00:01 -0400319 auto result = std::make_unique<FunctionDefinition>(/*offset=*/-1, decl,
320 /*builtin=*/true, std::move(body),
321 std::move(refs));
322 decl->setDefinition(result.get());
323 return std::move(result);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400324 }
325 case Rehydrator::kInterfaceBlock_Command: {
326 const Symbol* var = this->symbol();
John Stiles87ae34e2020-10-13 12:50:11 -0400327 SkASSERT(var && var->is<Variable>());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400328 StringFragment typeName = this->readString();
329 StringFragment instanceName = this->readString();
330 uint8_t sizeCount = this->readU8();
John Stiles87ae34e2020-10-13 12:50:11 -0400331 ExpressionArray sizes;
John Stilesf4bda742020-10-14 16:57:41 -0400332 sizes.reserve_back(sizeCount);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400333 for (int i = 0; i < sizeCount; ++i) {
334 sizes.push_back(this->expression());
335 }
John Stiles87ae34e2020-10-13 12:50:11 -0400336 return std::make_unique<InterfaceBlock>(/*offset=*/-1, &var->as<Variable>(), typeName,
337 instanceName, std::move(sizes), nullptr);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400338 }
339 case Rehydrator::kVarDeclarations_Command: {
Brian Osmanc0213602020-10-06 14:43:32 -0400340 std::unique_ptr<Statement> decl = this->statement();
John Stiles1ea7f542020-11-02 13:07:23 -0500341 return std::make_unique<GlobalVarDeclaration>(/*offset=*/-1, std::move(decl));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400342 }
John Stilesdc75a972020-11-25 16:24:55 -0500343 case Rehydrator::kStructDefinition_Command: {
344 const Symbol* type = this->symbol();
345 SkASSERT(type && type->is<Type>());
346 return std::make_unique<StructDefinition>(/*offset=*/-1, type->as<Type>());
347 }
John Stiles1ea7f542020-11-02 13:07:23 -0500348 case Rehydrator::kElementsComplete_Command:
349 return nullptr;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400350 default:
John Stiles1ea7f542020-11-02 13:07:23 -0500351 SkDEBUGFAILF("unsupported element %d\n", kind);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400352 return nullptr;
353 }
354}
355
356std::unique_ptr<Statement> Rehydrator::statement() {
357 int kind = this->readU8();
358 switch (kind) {
359 case Rehydrator::kBlock_Command: {
360 AutoRehydratorSymbolTable symbols(this);
361 int count = this->readU8();
John Stiles8f2a0cf2020-10-13 12:48:21 -0400362 StatementArray statements;
John Stilesf4bda742020-10-14 16:57:41 -0400363 statements.reserve_back(count);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400364 for (int i = 0; i < count; ++i) {
365 statements.push_back(this->statement());
366 }
367 bool isScope = this->readU8();
John Stiles8f2a0cf2020-10-13 12:48:21 -0400368 return std::make_unique<Block>(/*offset=*/-1, std::move(statements), fSymbolTable,
369 isScope);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400370 }
371 case Rehydrator::kBreak_Command:
372 return std::unique_ptr<Statement>(new BreakStatement(-1));
373 case Rehydrator::kContinue_Command:
374 return std::unique_ptr<Statement>(new ContinueStatement(-1));
375 case Rehydrator::kDiscard_Command:
376 return std::unique_ptr<Statement>(new DiscardStatement(-1));
377 case Rehydrator::kDo_Command: {
378 std::unique_ptr<Statement> stmt = this->statement();
379 std::unique_ptr<Expression> expr = this->expression();
380 return std::unique_ptr<Statement>(new DoStatement(-1, std::move(stmt),
381 std::move(expr)));
382 }
383 case Rehydrator::kExpressionStatement_Command: {
384 std::unique_ptr<Expression> expr = this->expression();
385 return std::unique_ptr<Statement>(new ExpressionStatement(std::move(expr)));
386 }
387 case Rehydrator::kFor_Command: {
388 std::unique_ptr<Statement> initializer = this->statement();
389 std::unique_ptr<Expression> test = this->expression();
390 std::unique_ptr<Expression> next = this->expression();
391 std::unique_ptr<Statement> body = this->statement();
392 std::shared_ptr<SymbolTable> symbols = this->symbolTable();
393 return std::unique_ptr<Statement>(new ForStatement(-1, std::move(initializer),
394 std::move(test), std::move(next),
395 std::move(body),
396 std::move(symbols)));
397 }
398 case Rehydrator::kIf_Command: {
399 bool isStatic = this->readU8();
400 std::unique_ptr<Expression> test = this->expression();
401 std::unique_ptr<Statement> ifTrue = this->statement();
402 std::unique_ptr<Statement> ifFalse = this->statement();
403 return std::unique_ptr<Statement>(new IfStatement(-1, isStatic, std::move(test),
404 std::move(ifTrue),
405 std::move(ifFalse)));
406 }
John Stiles98c1f822020-09-09 14:18:53 -0400407 case Rehydrator::kInlineMarker_Command: {
408 const FunctionDeclaration* funcDecl = this->symbolRef<FunctionDeclaration>(
409 Symbol::Kind::kFunctionDeclaration);
Ethan Nicholasceb62142020-10-09 16:51:18 -0400410 return std::make_unique<InlineMarker>(funcDecl);
John Stiles98c1f822020-09-09 14:18:53 -0400411 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400412 case Rehydrator::kReturn_Command: {
413 std::unique_ptr<Expression> expr = this->expression();
414 if (expr) {
415 return std::unique_ptr<Statement>(new ReturnStatement(std::move(expr)));
416 } else {
417 return std::unique_ptr<Statement>(new ReturnStatement(-1));
418 }
419 }
420 case Rehydrator::kSwitch_Command: {
421 bool isStatic = this->readU8();
422 AutoRehydratorSymbolTable symbols(this);
423 std::unique_ptr<Expression> expr = this->expression();
424 int caseCount = this->readU8();
425 std::vector<std::unique_ptr<SwitchCase>> cases;
426 cases.reserve(caseCount);
427 for (int i = 0; i < caseCount; ++i) {
428 std::unique_ptr<Expression> value = this->expression();
429 int statementCount = this->readU8();
John Stiles8f2a0cf2020-10-13 12:48:21 -0400430 StatementArray statements;
John Stilesf4bda742020-10-14 16:57:41 -0400431 statements.reserve_back(statementCount);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400432 for (int j = 0; j < statementCount; ++j) {
433 statements.push_back(this->statement());
434 }
John Stiles8f2a0cf2020-10-13 12:48:21 -0400435 cases.push_back(std::make_unique<SwitchCase>(/*offset=*/-1, std::move(value),
436 std::move(statements)));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400437 }
John Stiles8f2a0cf2020-10-13 12:48:21 -0400438 return std::make_unique<SwitchStatement>(-1, isStatic, std::move(expr),
439 std::move(cases), fSymbolTable);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400440 }
441 case Rehydrator::kVarDeclaration_Command: {
Ethan Nicholase6592142020-09-08 10:22:09 -0400442 Variable* var = this->symbolRef<Variable>(Symbol::Kind::kVariable);
Brian Osmanc0213602020-10-06 14:43:32 -0400443 const Type* baseType = this->type();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400444 uint8_t sizeCount = this->readU8();
John Stiles87ae34e2020-10-13 12:50:11 -0400445 ExpressionArray sizes;
John Stilesf4bda742020-10-14 16:57:41 -0400446 sizes.reserve_back(sizeCount);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400447 for (int i = 0; i < sizeCount; ++i) {
448 sizes.push_back(this->expression());
449 }
450 std::unique_ptr<Expression> value = this->expression();
451 if (value) {
Ethan Nicholas041fd0a2020-10-07 16:42:04 -0400452 var->setInitialValue(value.get());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400453 }
John Stiles87ae34e2020-10-13 12:50:11 -0400454 return std::make_unique<VarDeclaration>(var, baseType, std::move(sizes),
455 std::move(value));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400456 }
457 case Rehydrator::kVoid_Command:
458 return nullptr;
459 case Rehydrator::kWhile_Command: {
460 std::unique_ptr<Expression> expr = this->expression();
461 std::unique_ptr<Statement> stmt = this->statement();
462 return std::unique_ptr<Statement>(new WhileStatement(-1, std::move(expr),
463 std::move(stmt)));
464 }
465 default:
466 printf("unsupported statement %d\n", kind);
467 SkASSERT(false);
468 return nullptr;
469 }
470}
471
472std::unique_ptr<Expression> Rehydrator::expression() {
473 int kind = this->readU8();
474 switch (kind) {
475 case Rehydrator::kBinary_Command: {
476 std::unique_ptr<Expression> left = this->expression();
477 Token::Kind op = (Token::Kind) this->readU8();
478 std::unique_ptr<Expression> right = this->expression();
479 const Type* type = this->type();
Ethan Nicholas30d30222020-09-11 12:27:26 -0400480 return std::make_unique<BinaryExpression>(-1, std::move(left), op, std::move(right),
481 type);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400482 }
483 case Rehydrator::kBoolLiteral_Command: {
484 bool value = this->readU8();
Ethan Nicholas30d30222020-09-11 12:27:26 -0400485 return std::make_unique<BoolLiteral>(fContext, -1, value);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400486 }
487 case Rehydrator::kConstructor_Command: {
488 const Type* type = this->type();
489 uint8_t argCount = this->readU8();
John Stiles8e3b6be2020-10-13 11:14:08 -0400490 ExpressionArray args;
John Stilesf4bda742020-10-14 16:57:41 -0400491 args.reserve_back(argCount);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400492 for (int i = 0; i < argCount; ++i) {
493 args.push_back(this->expression());
494 }
Ethan Nicholas30d30222020-09-11 12:27:26 -0400495 return std::make_unique<Constructor>(-1, type, std::move(args));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400496 }
497 case Rehydrator::kFieldAccess_Command: {
498 std::unique_ptr<Expression> base = this->expression();
499 int index = this->readU8();
500 FieldAccess::OwnerKind ownerKind = (FieldAccess::OwnerKind) this->readU8();
Ethan Nicholas30d30222020-09-11 12:27:26 -0400501 return std::make_unique<FieldAccess>(std::move(base), index, ownerKind);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400502 }
503 case Rehydrator::kFloatLiteral_Command: {
Brian Osmanfb964a42020-11-18 10:45:52 -0500504 const Type* type = this->type();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400505 FloatIntUnion u;
506 u.fInt = this->readS32();
Brian Osmanfb964a42020-11-18 10:45:52 -0500507 return std::make_unique<FloatLiteral>(-1, u.fFloat, type);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400508 }
509 case Rehydrator::kFunctionCall_Command: {
Ethan Nicholas30d30222020-09-11 12:27:26 -0400510 const Type* type = this->type();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400511 const FunctionDeclaration* f = this->symbolRef<FunctionDeclaration>(
Ethan Nicholase6592142020-09-08 10:22:09 -0400512 Symbol::Kind::kFunctionDeclaration);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400513 uint8_t argCount = this->readU8();
John Stiles8e3b6be2020-10-13 11:14:08 -0400514 ExpressionArray args;
John Stilesf4bda742020-10-14 16:57:41 -0400515 args.reserve_back(argCount);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400516 for (int i = 0; i < argCount; ++i) {
517 args.push_back(this->expression());
518 }
Ethan Nicholas0dec9922020-10-05 15:51:52 -0400519 return std::make_unique<FunctionCall>(-1, type, f, std::move(args));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400520 }
521 case Rehydrator::kIndex_Command: {
522 std::unique_ptr<Expression> base = this->expression();
523 std::unique_ptr<Expression> index = this->expression();
Ethan Nicholas30d30222020-09-11 12:27:26 -0400524 return std::make_unique<IndexExpression>(fContext, std::move(base), std::move(index));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400525 }
526 case Rehydrator::kIntLiteral_Command: {
Brian Osmanfb964a42020-11-18 10:45:52 -0500527 const Type* type = this->type();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400528 int value = this->readS32();
Brian Osmanfb964a42020-11-18 10:45:52 -0500529 return std::make_unique<IntLiteral>(-1, value, type);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400530 }
531 case Rehydrator::kNullLiteral_Command:
Ethan Nicholas30d30222020-09-11 12:27:26 -0400532 return std::make_unique<NullLiteral>(fContext, -1);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400533 case Rehydrator::kPostfix_Command: {
534 Token::Kind op = (Token::Kind) this->readU8();
535 std::unique_ptr<Expression> operand = this->expression();
Ethan Nicholas30d30222020-09-11 12:27:26 -0400536 return std::make_unique<PostfixExpression>(std::move(operand), op);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400537 }
538 case Rehydrator::kPrefix_Command: {
539 Token::Kind op = (Token::Kind) this->readU8();
540 std::unique_ptr<Expression> operand = this->expression();
Ethan Nicholas30d30222020-09-11 12:27:26 -0400541 return std::make_unique<PrefixExpression>(op, std::move(operand));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400542 }
543 case Rehydrator::kSetting_Command: {
544 StringFragment name = this->readString();
Ethan Nicholas01ec7e82020-10-08 12:10:12 -0400545 const Type* type = this->type();
546 return std::make_unique<Setting>(-1, name, type);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400547 }
548 case Rehydrator::kSwizzle_Command: {
549 std::unique_ptr<Expression> base = this->expression();
550 int count = this->readU8();
John Stiles750109b2020-10-30 13:45:46 -0400551 ComponentArray components;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400552 for (int i = 0; i < count; ++i) {
553 components.push_back(this->readU8());
554 }
John Stiles750109b2020-10-30 13:45:46 -0400555 return std::make_unique<Swizzle>(fContext, std::move(base), components);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400556 }
557 case Rehydrator::kTernary_Command: {
558 std::unique_ptr<Expression> test = this->expression();
559 std::unique_ptr<Expression> ifTrue = this->expression();
560 std::unique_ptr<Expression> ifFalse = this->expression();
Ethan Nicholasa02ce0c2020-09-21 12:37:02 -0400561 return std::make_unique<TernaryExpression>(-1, std::move(test), std::move(ifTrue),
562 std::move(ifFalse));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400563 }
564 case Rehydrator::kVariableReference_Command: {
Ethan Nicholase6592142020-09-08 10:22:09 -0400565 const Variable* var = this->symbolRef<Variable>(Symbol::Kind::kVariable);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400566 VariableReference::RefKind refKind = (VariableReference::RefKind) this->readU8();
Brian Osman79457ef2020-09-24 15:01:27 -0400567 return std::make_unique<VariableReference>(-1, var, refKind);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400568 }
569 case Rehydrator::kVoid_Command:
570 return nullptr;
571 default:
572 printf("unsupported expression %d\n", kind);
573 SkASSERT(false);
574 return nullptr;
575 }
576}
577
Brian Osman1313d1a2020-09-08 10:34:30 -0400578std::shared_ptr<SymbolTable> Rehydrator::symbolTable(bool inherit) {
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400579 int command = this->readU8();
580 if (command == kVoid_Command) {
581 return nullptr;
582 }
583 SkASSERT(command == kSymbolTable_Command);
584 uint16_t ownedCount = this->readU16();
Brian Osman1313d1a2020-09-08 10:34:30 -0400585 std::shared_ptr<SymbolTable> oldTable = fSymbolTable;
John Stiles7c3515b2020-10-16 18:38:39 -0400586 std::shared_ptr<SymbolTable> result =
587 inherit ? std::make_shared<SymbolTable>(fSymbolTable, /*builtin=*/true)
588 : std::make_shared<SymbolTable>(fErrors, /*builtin=*/true);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400589 fSymbolTable = result;
Brian Osman5bf3e202020-10-13 10:34:18 -0400590 std::vector<const Symbol*> ownedSymbols;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400591 ownedSymbols.reserve(ownedCount);
592 for (int i = 0; i < ownedCount; ++i) {
593 ownedSymbols.push_back(this->symbol());
594 }
595 uint16_t symbolCount = this->readU16();
596 std::vector<std::pair<StringFragment, int>> symbols;
597 symbols.reserve(symbolCount);
598 for (int i = 0; i < symbolCount; ++i) {
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400599 int index = this->readU16();
John Stilesb8cc6652020-10-08 09:12:07 -0400600 fSymbolTable->addWithoutOwnership(ownedSymbols[index]);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400601 }
Brian Osman1313d1a2020-09-08 10:34:30 -0400602 fSymbolTable = oldTable;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400603 return result;
604}
605
John Stilesa6841be2020-08-06 14:11:56 -0400606} // namespace SkSL