blob: 78b79c45808ef3242c6bec7689ec38f332b19b51 [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"
41#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"
51#include "src/sksl/ir/SkSLWhileStatement.h"
52
53namespace SkSL {
54
55class AutoRehydratorSymbolTable {
56public:
57 AutoRehydratorSymbolTable(Rehydrator* rehydrator)
58 : fRehydrator(rehydrator)
59 , fOldSymbols(fRehydrator->fSymbolTable) {
60 fRehydrator->fSymbolTable = fRehydrator->symbolTable();
61 }
62
63 ~AutoRehydratorSymbolTable() {
64 fRehydrator->fSymbolTable = std::move(fOldSymbols);
65 }
66
67private:
68 Rehydrator* fRehydrator;
69 std::shared_ptr<SymbolTable> fOldSymbols;
70};
71
John Stiles7c3515b2020-10-16 18:38:39 -040072Rehydrator::Rehydrator(const Context* context, ModifiersPool* modifiers,
73 std::shared_ptr<SymbolTable> symbolTable, ErrorReporter* errorReporter,
74 const uint8_t* src, size_t length)
75 : fContext(*context)
76 , fModifiers(*modifiers)
77 , fErrors(errorReporter)
78 , fSymbolTable(std::move(symbolTable))
79 , fStart(src)
80 SkDEBUGCODE(, fEnd(fStart + length)) {
81 SkASSERT(fSymbolTable);
82 SkASSERT(fSymbolTable->isBuiltin());
83 // skip past string data
84 fIP = fStart;
85 fIP += this->readU16();
86}
87
Ethan Nicholasc18bb512020-07-28 14:46:53 -040088Layout Rehydrator::layout() {
89 switch (this->readU8()) {
90 case kBuiltinLayout_Command: {
91 Layout result;
92 result.fBuiltin = this->readS16();
93 return result;
94 }
95 case kDefaultLayout_Command:
96 return Layout();
97 case kLayout_Command: {
98 int flags = this->readU32();
99 int location = this->readS8();
100 int offset = this->readS8();
101 int binding = this->readS8();
102 int index = this->readS8();
103 int set = this->readS8();
104 int builtin = this->readS16();
105 int inputAttachmentIndex = this->readS8();
106 int format = this->readS8();
107 int primitive = this->readS8();
108 int maxVertices = this->readS8();
109 int invocations = this->readS8();
110 StringFragment marker = this->readString();
111 StringFragment when = this->readString();
112 int key = this->readS8();
113 int ctype = this->readS8();
114 return Layout(flags, location, offset, binding, index, set, builtin,
115 inputAttachmentIndex, (Layout::Format) format,
116 (Layout::Primitive) primitive, maxVertices, invocations, marker, when,
117 (Layout::Key) key, (Layout::CType) ctype);
118 }
119 default:
120 SkASSERT(false);
121 return Layout();
122 }
123}
124
125Modifiers Rehydrator::modifiers() {
126 switch (this->readU8()) {
127 case kDefaultModifiers_Command:
128 return Modifiers();
129 case kModifiers8Bit_Command: {
130 Layout l = this->layout();
131 int flags = this->readU8();
132 return Modifiers(l, flags);
133 }
134 case kModifiers_Command: {
135 Layout l = this->layout();
136 int flags = this->readS32();
137 return Modifiers(l, flags);
138 }
139 default:
140 SkASSERT(false);
141 return Modifiers();
142 }
143}
144
Brian Osman5bf3e202020-10-13 10:34:18 -0400145const Symbol* Rehydrator::symbol() {
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400146 int kind = this->readU8();
147 switch (kind) {
148 case kArrayType_Command: {
149 uint16_t id = this->readU16();
150 const Type* componentType = this->type();
Brian Osmane8c26082020-10-01 17:22:45 -0400151 int8_t count = this->readS8();
152 String name = componentType->name();
153 if (count == Type::kUnsizedArray) {
154 name += "[]";
155 } else {
156 name += "[" + to_string(count) + "]";
157 }
Brian Osman5bf3e202020-10-13 10:34:18 -0400158 const Type* result = fSymbolTable->takeOwnershipOfSymbol(
Brian Osmane8c26082020-10-01 17:22:45 -0400159 std::make_unique<Type>(name, Type::TypeKind::kArray, *componentType, count));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400160 this->addSymbol(id, result);
161 return result;
162 }
163 case kEnumType_Command: {
164 uint16_t id = this->readU16();
165 StringFragment name = this->readString();
Brian Osman5bf3e202020-10-13 10:34:18 -0400166 const Type* result = fSymbolTable->takeOwnershipOfSymbol(
Ethan Nicholase6592142020-09-08 10:22:09 -0400167 std::make_unique<Type>(name, Type::TypeKind::kEnum));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400168 this->addSymbol(id, result);
169 return result;
170 }
171 case kFunctionDeclaration_Command: {
172 uint16_t id = this->readU16();
173 Modifiers modifiers = this->modifiers();
174 StringFragment name = this->readString();
175 int parameterCount = this->readU8();
Brian Osman5bf3e202020-10-13 10:34:18 -0400176 std::vector<const Variable*> parameters;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400177 parameters.reserve(parameterCount);
178 for (int i = 0; i < parameterCount; ++i) {
Ethan Nicholase6592142020-09-08 10:22:09 -0400179 parameters.push_back(this->symbolRef<Variable>(Symbol::Kind::kVariable));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400180 }
181 const Type* returnType = this->type();
Brian Osman5bf3e202020-10-13 10:34:18 -0400182 const FunctionDeclaration* result =
John Stiles3ae071e2020-08-05 15:29:29 -0400183 fSymbolTable->takeOwnershipOfSymbol(std::make_unique<FunctionDeclaration>(
Ethan Nicholased84b732020-10-08 11:45:44 -0400184 /*offset=*/-1, fModifiers.handle(modifiers), name,
185 std::move(parameters), returnType, /*builtin=*/true));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400186 this->addSymbol(id, result);
187 return result;
188 }
189 case kField_Command: {
Ethan Nicholase6592142020-09-08 10:22:09 -0400190 const Variable* owner = this->symbolRef<Variable>(Symbol::Kind::kVariable);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400191 uint8_t index = this->readU8();
Brian Osman5bf3e202020-10-13 10:34:18 -0400192 const Field* result = fSymbolTable->takeOwnershipOfSymbol(
Ethan Nicholase2c49992020-10-05 11:49:11 -0400193 std::make_unique<Field>(/*offset=*/-1, owner, index));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400194 return result;
195 }
196 case kNullableType_Command: {
197 uint16_t id = this->readU16();
198 const Type* base = this->type();
Brian Osman5bf3e202020-10-13 10:34:18 -0400199 const Type* result = fSymbolTable->takeOwnershipOfSymbol(
Ethan Nicholase6592142020-09-08 10:22:09 -0400200 std::make_unique<Type>(base->name() + "?", Type::TypeKind::kNullable, *base));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400201 this->addSymbol(id, result);
202 return result;
203 }
204 case kStructType_Command: {
205 uint16_t id = this->readU16();
206 StringFragment 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();
John Stilesf621e232020-08-25 13:33:02 -0400212 StringFragment fieldName = this->readString();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400213 const Type* type = this->type();
John Stilesf621e232020-08-25 13:33:02 -0400214 fields.emplace_back(m, fieldName, type);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400215 }
Brian Osman5bf3e202020-10-13 10:34:18 -0400216 const Type* result = fSymbolTable->takeOwnershipOfSymbol(
John Stiles3ae071e2020-08-05 15:29:29 -0400217 std::make_unique<Type>(/*offset=*/-1, name, std::move(fields)));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400218 this->addSymbol(id, result);
219 return result;
220 }
221 case kSymbolRef_Command: {
222 uint16_t id = this->readU16();
223 SkASSERT(fSymbols.size() > id);
224 return fSymbols[id];
225 }
John Stiles49a547f2020-10-06 16:14:37 -0400226 case kSymbolAlias_Command: {
227 uint16_t id = this->readU16();
228 StringFragment name = this->readString();
Brian Osman5bf3e202020-10-13 10:34:18 -0400229 const Symbol* origSymbol = this->symbol();
230 const SymbolAlias* symbolAlias = fSymbolTable->takeOwnershipOfSymbol(
John Stiles49a547f2020-10-06 16:14:37 -0400231 std::make_unique<SymbolAlias>(/*offset=*/-1, name, origSymbol));
232 this->addSymbol(id, symbolAlias);
233 return symbolAlias;
234 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400235 case kSystemType_Command: {
236 uint16_t id = this->readU16();
237 StringFragment name = this->readString();
Brian Osman5bf3e202020-10-13 10:34:18 -0400238 const Symbol* result = (*fSymbolTable)[name];
Ethan Nicholase6592142020-09-08 10:22:09 -0400239 SkASSERT(result && result->kind() == Symbol::Kind::kType);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400240 this->addSymbol(id, result);
241 return result;
242 }
243 case kUnresolvedFunction_Command: {
244 uint16_t id = this->readU16();
245 int length = this->readU8();
246 std::vector<const FunctionDeclaration*> functions;
247 functions.reserve(length);
248 for (int i = 0; i < length; ++i) {
249 const Symbol* f = this->symbol();
Ethan Nicholase6592142020-09-08 10:22:09 -0400250 SkASSERT(f && f->kind() == Symbol::Kind::kFunctionDeclaration);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400251 functions.push_back((const FunctionDeclaration*) f);
252 }
Brian Osman5bf3e202020-10-13 10:34:18 -0400253 const UnresolvedFunction* result = fSymbolTable->takeOwnershipOfSymbol(
John Stiles3ae071e2020-08-05 15:29:29 -0400254 std::make_unique<UnresolvedFunction>(std::move(functions)));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400255 this->addSymbol(id, result);
256 return result;
257 }
258 case kVariable_Command: {
259 uint16_t id = this->readU16();
Ethan Nicholas041fd0a2020-10-07 16:42:04 -0400260 ModifiersPool::Handle m = fModifiers.handle(this->modifiers());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400261 StringFragment name = this->readString();
262 const Type* type = this->type();
263 Variable::Storage storage = (Variable::Storage) this->readU8();
Brian Osman5bf3e202020-10-13 10:34:18 -0400264 const Variable* result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Variable>(
Brian Osman3887a012020-09-30 13:22:27 -0400265 /*offset=*/-1, m, name, type, /*builtin=*/true, storage));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400266 this->addSymbol(id, result);
267 return result;
268 }
269 default:
270 printf("unsupported symbol %d\n", kind);
271 SkASSERT(false);
272 return nullptr;
273 }
274}
275
276const Type* Rehydrator::type() {
277 const Symbol* result = this->symbol();
Ethan Nicholase6592142020-09-08 10:22:09 -0400278 SkASSERT(result->kind() == Symbol::Kind::kType);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400279 return (const Type*) result;
280}
281
282std::vector<std::unique_ptr<ProgramElement>> Rehydrator::elements() {
283 SkDEBUGCODE(uint8_t command = )this->readU8();
284 SkASSERT(command == kElements_Command);
285 uint8_t count = this->readU8();
286 std::vector<std::unique_ptr<ProgramElement>> result;
287 result.reserve(count);
288 for (int i = 0; i < count; ++i) {
289 result.push_back(this->element());
290 }
291 return result;
292}
293
294std::unique_ptr<ProgramElement> Rehydrator::element() {
295 int kind = this->readU8();
296 switch (kind) {
297 case Rehydrator::kEnum_Command: {
298 StringFragment typeName = this->readString();
Brian Osman1313d1a2020-09-08 10:34:30 -0400299 std::shared_ptr<SymbolTable> symbols = this->symbolTable(/*inherit=*/false);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400300 for (auto& s : symbols->fOwnedSymbols) {
Ethan Nicholase6592142020-09-08 10:22:09 -0400301 SkASSERT(s->kind() == Symbol::Kind::kVariable);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400302 Variable& v = (Variable&) *s;
303 int value = this->readS32();
Ethan Nicholas041fd0a2020-10-07 16:42:04 -0400304 v.setInitialValue(symbols->takeOwnershipOfIRNode(
305 std::make_unique<IntLiteral>(fContext, /*offset=*/-1, value)));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400306 }
John Stiles1c823672020-10-20 10:23:50 -0400307 return std::make_unique<Enum>(/*offset=*/-1, typeName, std::move(symbols),
308 /*isSharedWithCpp=*/true, /*isBuiltin=*/true);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400309 }
310 case Rehydrator::kFunctionDefinition_Command: {
311 const FunctionDeclaration* decl = this->symbolRef<FunctionDeclaration>(
Ethan Nicholase6592142020-09-08 10:22:09 -0400312 Symbol::Kind::kFunctionDeclaration);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400313 std::unique_ptr<Statement> body = this->statement();
John Stilesb8e010c2020-08-11 18:05:39 -0400314 std::unordered_set<const FunctionDeclaration*> refs;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400315 uint8_t refCount = this->readU8();
316 for (int i = 0; i < refCount; ++i) {
317 refs.insert(this->symbolRef<FunctionDeclaration>(
Ethan Nicholase6592142020-09-08 10:22:09 -0400318 Symbol::Kind::kFunctionDeclaration));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400319 }
John Stiles607d36b2020-10-19 15:00:01 -0400320 auto result = std::make_unique<FunctionDefinition>(/*offset=*/-1, decl,
321 /*builtin=*/true, std::move(body),
322 std::move(refs));
323 decl->setDefinition(result.get());
324 return std::move(result);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400325 }
326 case Rehydrator::kInterfaceBlock_Command: {
327 const Symbol* var = this->symbol();
John Stiles87ae34e2020-10-13 12:50:11 -0400328 SkASSERT(var && var->is<Variable>());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400329 StringFragment typeName = this->readString();
330 StringFragment instanceName = this->readString();
331 uint8_t sizeCount = this->readU8();
John Stiles87ae34e2020-10-13 12:50:11 -0400332 ExpressionArray sizes;
John Stilesf4bda742020-10-14 16:57:41 -0400333 sizes.reserve_back(sizeCount);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400334 for (int i = 0; i < sizeCount; ++i) {
335 sizes.push_back(this->expression());
336 }
John Stiles87ae34e2020-10-13 12:50:11 -0400337 return std::make_unique<InterfaceBlock>(/*offset=*/-1, &var->as<Variable>(), typeName,
338 instanceName, std::move(sizes), nullptr);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400339 }
340 case Rehydrator::kVarDeclarations_Command: {
Brian Osmanc0213602020-10-06 14:43:32 -0400341 std::unique_ptr<Statement> decl = this->statement();
342 return std::unique_ptr<ProgramElement>(
343 new GlobalVarDeclaration(/*offset=*/-1, std::move(decl)));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400344 }
345 default:
346 printf("unsupported element %d\n", kind);
347 SkASSERT(false);
348 return nullptr;
349 }
350}
351
352std::unique_ptr<Statement> Rehydrator::statement() {
353 int kind = this->readU8();
354 switch (kind) {
355 case Rehydrator::kBlock_Command: {
356 AutoRehydratorSymbolTable symbols(this);
357 int count = this->readU8();
John Stiles8f2a0cf2020-10-13 12:48:21 -0400358 StatementArray statements;
John Stilesf4bda742020-10-14 16:57:41 -0400359 statements.reserve_back(count);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400360 for (int i = 0; i < count; ++i) {
361 statements.push_back(this->statement());
362 }
363 bool isScope = this->readU8();
John Stiles8f2a0cf2020-10-13 12:48:21 -0400364 return std::make_unique<Block>(/*offset=*/-1, std::move(statements), fSymbolTable,
365 isScope);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400366 }
367 case Rehydrator::kBreak_Command:
368 return std::unique_ptr<Statement>(new BreakStatement(-1));
369 case Rehydrator::kContinue_Command:
370 return std::unique_ptr<Statement>(new ContinueStatement(-1));
371 case Rehydrator::kDiscard_Command:
372 return std::unique_ptr<Statement>(new DiscardStatement(-1));
373 case Rehydrator::kDo_Command: {
374 std::unique_ptr<Statement> stmt = this->statement();
375 std::unique_ptr<Expression> expr = this->expression();
376 return std::unique_ptr<Statement>(new DoStatement(-1, std::move(stmt),
377 std::move(expr)));
378 }
379 case Rehydrator::kExpressionStatement_Command: {
380 std::unique_ptr<Expression> expr = this->expression();
381 return std::unique_ptr<Statement>(new ExpressionStatement(std::move(expr)));
382 }
383 case Rehydrator::kFor_Command: {
384 std::unique_ptr<Statement> initializer = this->statement();
385 std::unique_ptr<Expression> test = this->expression();
386 std::unique_ptr<Expression> next = this->expression();
387 std::unique_ptr<Statement> body = this->statement();
388 std::shared_ptr<SymbolTable> symbols = this->symbolTable();
389 return std::unique_ptr<Statement>(new ForStatement(-1, std::move(initializer),
390 std::move(test), std::move(next),
391 std::move(body),
392 std::move(symbols)));
393 }
394 case Rehydrator::kIf_Command: {
395 bool isStatic = this->readU8();
396 std::unique_ptr<Expression> test = this->expression();
397 std::unique_ptr<Statement> ifTrue = this->statement();
398 std::unique_ptr<Statement> ifFalse = this->statement();
399 return std::unique_ptr<Statement>(new IfStatement(-1, isStatic, std::move(test),
400 std::move(ifTrue),
401 std::move(ifFalse)));
402 }
John Stiles98c1f822020-09-09 14:18:53 -0400403 case Rehydrator::kInlineMarker_Command: {
404 const FunctionDeclaration* funcDecl = this->symbolRef<FunctionDeclaration>(
405 Symbol::Kind::kFunctionDeclaration);
Ethan Nicholasceb62142020-10-09 16:51:18 -0400406 return std::make_unique<InlineMarker>(funcDecl);
John Stiles98c1f822020-09-09 14:18:53 -0400407 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400408 case Rehydrator::kReturn_Command: {
409 std::unique_ptr<Expression> expr = this->expression();
410 if (expr) {
411 return std::unique_ptr<Statement>(new ReturnStatement(std::move(expr)));
412 } else {
413 return std::unique_ptr<Statement>(new ReturnStatement(-1));
414 }
415 }
416 case Rehydrator::kSwitch_Command: {
417 bool isStatic = this->readU8();
418 AutoRehydratorSymbolTable symbols(this);
419 std::unique_ptr<Expression> expr = this->expression();
420 int caseCount = this->readU8();
421 std::vector<std::unique_ptr<SwitchCase>> cases;
422 cases.reserve(caseCount);
423 for (int i = 0; i < caseCount; ++i) {
424 std::unique_ptr<Expression> value = this->expression();
425 int statementCount = this->readU8();
John Stiles8f2a0cf2020-10-13 12:48:21 -0400426 StatementArray statements;
John Stilesf4bda742020-10-14 16:57:41 -0400427 statements.reserve_back(statementCount);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400428 for (int j = 0; j < statementCount; ++j) {
429 statements.push_back(this->statement());
430 }
John Stiles8f2a0cf2020-10-13 12:48:21 -0400431 cases.push_back(std::make_unique<SwitchCase>(/*offset=*/-1, std::move(value),
432 std::move(statements)));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400433 }
John Stiles8f2a0cf2020-10-13 12:48:21 -0400434 return std::make_unique<SwitchStatement>(-1, isStatic, std::move(expr),
435 std::move(cases), fSymbolTable);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400436 }
437 case Rehydrator::kVarDeclaration_Command: {
Ethan Nicholase6592142020-09-08 10:22:09 -0400438 Variable* var = this->symbolRef<Variable>(Symbol::Kind::kVariable);
Brian Osmanc0213602020-10-06 14:43:32 -0400439 const Type* baseType = this->type();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400440 uint8_t sizeCount = this->readU8();
John Stiles87ae34e2020-10-13 12:50:11 -0400441 ExpressionArray sizes;
John Stilesf4bda742020-10-14 16:57:41 -0400442 sizes.reserve_back(sizeCount);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400443 for (int i = 0; i < sizeCount; ++i) {
444 sizes.push_back(this->expression());
445 }
446 std::unique_ptr<Expression> value = this->expression();
447 if (value) {
Ethan Nicholas041fd0a2020-10-07 16:42:04 -0400448 var->setInitialValue(value.get());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400449 }
John Stiles87ae34e2020-10-13 12:50:11 -0400450 return std::make_unique<VarDeclaration>(var, baseType, std::move(sizes),
451 std::move(value));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400452 }
453 case Rehydrator::kVoid_Command:
454 return nullptr;
455 case Rehydrator::kWhile_Command: {
456 std::unique_ptr<Expression> expr = this->expression();
457 std::unique_ptr<Statement> stmt = this->statement();
458 return std::unique_ptr<Statement>(new WhileStatement(-1, std::move(expr),
459 std::move(stmt)));
460 }
461 default:
462 printf("unsupported statement %d\n", kind);
463 SkASSERT(false);
464 return nullptr;
465 }
466}
467
468std::unique_ptr<Expression> Rehydrator::expression() {
469 int kind = this->readU8();
470 switch (kind) {
471 case Rehydrator::kBinary_Command: {
472 std::unique_ptr<Expression> left = this->expression();
473 Token::Kind op = (Token::Kind) this->readU8();
474 std::unique_ptr<Expression> right = this->expression();
475 const Type* type = this->type();
Ethan Nicholas30d30222020-09-11 12:27:26 -0400476 return std::make_unique<BinaryExpression>(-1, std::move(left), op, std::move(right),
477 type);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400478 }
479 case Rehydrator::kBoolLiteral_Command: {
480 bool value = this->readU8();
Ethan Nicholas30d30222020-09-11 12:27:26 -0400481 return std::make_unique<BoolLiteral>(fContext, -1, value);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400482 }
483 case Rehydrator::kConstructor_Command: {
484 const Type* type = this->type();
485 uint8_t argCount = this->readU8();
John Stiles8e3b6be2020-10-13 11:14:08 -0400486 ExpressionArray args;
John Stilesf4bda742020-10-14 16:57:41 -0400487 args.reserve_back(argCount);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400488 for (int i = 0; i < argCount; ++i) {
489 args.push_back(this->expression());
490 }
Ethan Nicholas30d30222020-09-11 12:27:26 -0400491 return std::make_unique<Constructor>(-1, type, std::move(args));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400492 }
493 case Rehydrator::kFieldAccess_Command: {
494 std::unique_ptr<Expression> base = this->expression();
495 int index = this->readU8();
496 FieldAccess::OwnerKind ownerKind = (FieldAccess::OwnerKind) this->readU8();
Ethan Nicholas30d30222020-09-11 12:27:26 -0400497 return std::make_unique<FieldAccess>(std::move(base), index, ownerKind);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400498 }
499 case Rehydrator::kFloatLiteral_Command: {
500 FloatIntUnion u;
501 u.fInt = this->readS32();
Ethan Nicholas30d30222020-09-11 12:27:26 -0400502 return std::make_unique<FloatLiteral>(fContext, -1, u.fFloat);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400503 }
504 case Rehydrator::kFunctionCall_Command: {
Ethan Nicholas30d30222020-09-11 12:27:26 -0400505 const Type* type = this->type();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400506 const FunctionDeclaration* f = this->symbolRef<FunctionDeclaration>(
Ethan Nicholase6592142020-09-08 10:22:09 -0400507 Symbol::Kind::kFunctionDeclaration);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400508 uint8_t argCount = this->readU8();
John Stiles8e3b6be2020-10-13 11:14:08 -0400509 ExpressionArray args;
John Stilesf4bda742020-10-14 16:57:41 -0400510 args.reserve_back(argCount);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400511 for (int i = 0; i < argCount; ++i) {
512 args.push_back(this->expression());
513 }
Ethan Nicholas0dec9922020-10-05 15:51:52 -0400514 return std::make_unique<FunctionCall>(-1, type, f, std::move(args));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400515 }
516 case Rehydrator::kIndex_Command: {
517 std::unique_ptr<Expression> base = this->expression();
518 std::unique_ptr<Expression> index = this->expression();
Ethan Nicholas30d30222020-09-11 12:27:26 -0400519 return std::make_unique<IndexExpression>(fContext, std::move(base), std::move(index));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400520 }
521 case Rehydrator::kIntLiteral_Command: {
522 int value = this->readS32();
Ethan Nicholas30d30222020-09-11 12:27:26 -0400523 return std::make_unique<IntLiteral>(fContext, -1, value);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400524 }
525 case Rehydrator::kNullLiteral_Command:
Ethan Nicholas30d30222020-09-11 12:27:26 -0400526 return std::make_unique<NullLiteral>(fContext, -1);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400527 case Rehydrator::kPostfix_Command: {
528 Token::Kind op = (Token::Kind) this->readU8();
529 std::unique_ptr<Expression> operand = this->expression();
Ethan Nicholas30d30222020-09-11 12:27:26 -0400530 return std::make_unique<PostfixExpression>(std::move(operand), op);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400531 }
532 case Rehydrator::kPrefix_Command: {
533 Token::Kind op = (Token::Kind) this->readU8();
534 std::unique_ptr<Expression> operand = this->expression();
Ethan Nicholas30d30222020-09-11 12:27:26 -0400535 return std::make_unique<PrefixExpression>(op, std::move(operand));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400536 }
537 case Rehydrator::kSetting_Command: {
538 StringFragment name = this->readString();
Ethan Nicholas01ec7e82020-10-08 12:10:12 -0400539 const Type* type = this->type();
540 return std::make_unique<Setting>(-1, name, type);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400541 }
542 case Rehydrator::kSwizzle_Command: {
543 std::unique_ptr<Expression> base = this->expression();
544 int count = this->readU8();
545 std::vector<int> components;
546 components.reserve(count);
547 for (int i = 0; i < count; ++i) {
548 components.push_back(this->readU8());
549 }
Ethan Nicholas30d30222020-09-11 12:27:26 -0400550 return std::make_unique<Swizzle>(fContext, std::move(base), std::move(components));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400551 }
552 case Rehydrator::kTernary_Command: {
553 std::unique_ptr<Expression> test = this->expression();
554 std::unique_ptr<Expression> ifTrue = this->expression();
555 std::unique_ptr<Expression> ifFalse = this->expression();
Ethan Nicholasa02ce0c2020-09-21 12:37:02 -0400556 return std::make_unique<TernaryExpression>(-1, std::move(test), std::move(ifTrue),
557 std::move(ifFalse));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400558 }
559 case Rehydrator::kVariableReference_Command: {
Ethan Nicholase6592142020-09-08 10:22:09 -0400560 const Variable* var = this->symbolRef<Variable>(Symbol::Kind::kVariable);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400561 VariableReference::RefKind refKind = (VariableReference::RefKind) this->readU8();
Brian Osman79457ef2020-09-24 15:01:27 -0400562 return std::make_unique<VariableReference>(-1, var, refKind);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400563 }
564 case Rehydrator::kVoid_Command:
565 return nullptr;
566 default:
567 printf("unsupported expression %d\n", kind);
568 SkASSERT(false);
569 return nullptr;
570 }
571}
572
Brian Osman1313d1a2020-09-08 10:34:30 -0400573std::shared_ptr<SymbolTable> Rehydrator::symbolTable(bool inherit) {
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400574 int command = this->readU8();
575 if (command == kVoid_Command) {
576 return nullptr;
577 }
578 SkASSERT(command == kSymbolTable_Command);
579 uint16_t ownedCount = this->readU16();
Brian Osman1313d1a2020-09-08 10:34:30 -0400580 std::shared_ptr<SymbolTable> oldTable = fSymbolTable;
John Stiles7c3515b2020-10-16 18:38:39 -0400581 std::shared_ptr<SymbolTable> result =
582 inherit ? std::make_shared<SymbolTable>(fSymbolTable, /*builtin=*/true)
583 : std::make_shared<SymbolTable>(fErrors, /*builtin=*/true);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400584 fSymbolTable = result;
Brian Osman5bf3e202020-10-13 10:34:18 -0400585 std::vector<const Symbol*> ownedSymbols;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400586 ownedSymbols.reserve(ownedCount);
587 for (int i = 0; i < ownedCount; ++i) {
588 ownedSymbols.push_back(this->symbol());
589 }
590 uint16_t symbolCount = this->readU16();
591 std::vector<std::pair<StringFragment, int>> symbols;
592 symbols.reserve(symbolCount);
593 for (int i = 0; i < symbolCount; ++i) {
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400594 int index = this->readU16();
John Stilesb8cc6652020-10-08 09:12:07 -0400595 fSymbolTable->addWithoutOwnership(ownedSymbols[index]);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400596 }
Brian Osman1313d1a2020-09-08 10:34:30 -0400597 fSymbolTable = oldTable;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400598 return result;
599}
600
John Stilesa6841be2020-08-06 14:11:56 -0400601} // namespace SkSL