blob: 9b7842e234f95634ea3426f719bed3debe2b061c [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 Nicholasdaed2592021-03-04 14:30:25 -050013#include "include/private/SkSLModifiers.h"
Ethan Nicholas24c17722021-03-09 13:10:59 -050014#include "include/private/SkSLProgramElement.h"
15#include "include/private/SkSLStatement.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040016#include "src/sksl/ir/SkSLBinaryExpression.h"
17#include "src/sksl/ir/SkSLBreakStatement.h"
John Stilese1182782021-03-30 22:09:37 -040018#include "src/sksl/ir/SkSLConstructor.h"
19#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040020#include "src/sksl/ir/SkSLContinueStatement.h"
21#include "src/sksl/ir/SkSLDiscardStatement.h"
22#include "src/sksl/ir/SkSLDoStatement.h"
23#include "src/sksl/ir/SkSLEnum.h"
24#include "src/sksl/ir/SkSLExpression.h"
25#include "src/sksl/ir/SkSLExpressionStatement.h"
26#include "src/sksl/ir/SkSLField.h"
27#include "src/sksl/ir/SkSLFieldAccess.h"
28#include "src/sksl/ir/SkSLFloatLiteral.h"
29#include "src/sksl/ir/SkSLForStatement.h"
30#include "src/sksl/ir/SkSLFunctionCall.h"
31#include "src/sksl/ir/SkSLFunctionDeclaration.h"
32#include "src/sksl/ir/SkSLFunctionDefinition.h"
33#include "src/sksl/ir/SkSLIfStatement.h"
34#include "src/sksl/ir/SkSLIndexExpression.h"
John Stiles98c1f822020-09-09 14:18:53 -040035#include "src/sksl/ir/SkSLInlineMarker.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040036#include "src/sksl/ir/SkSLIntLiteral.h"
37#include "src/sksl/ir/SkSLInterfaceBlock.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040038#include "src/sksl/ir/SkSLPostfixExpression.h"
39#include "src/sksl/ir/SkSLPrefixExpression.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040040#include "src/sksl/ir/SkSLReturnStatement.h"
41#include "src/sksl/ir/SkSLSetting.h"
John Stilesdc75a972020-11-25 16:24:55 -050042#include "src/sksl/ir/SkSLStructDefinition.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040043#include "src/sksl/ir/SkSLSwitchCase.h"
44#include "src/sksl/ir/SkSLSwitchStatement.h"
45#include "src/sksl/ir/SkSLSwizzle.h"
John Stiles49a547f2020-10-06 16:14:37 -040046#include "src/sksl/ir/SkSLSymbolAlias.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040047#include "src/sksl/ir/SkSLSymbolTable.h"
48#include "src/sksl/ir/SkSLTernaryExpression.h"
49#include "src/sksl/ir/SkSLType.h"
50#include "src/sksl/ir/SkSLUnresolvedFunction.h"
51#include "src/sksl/ir/SkSLVarDeclarations.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040052#include "src/sksl/ir/SkSLVariable.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040053
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();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400107 int primitive = this->readS8();
108 int maxVertices = this->readS8();
109 int invocations = this->readS8();
110 StringFragment marker = this->readString();
111 StringFragment when = this->readString();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400112 int ctype = this->readS8();
113 return Layout(flags, location, offset, binding, index, set, builtin,
Brian Osman4717fbb2021-02-23 13:12:09 -0500114 inputAttachmentIndex, (Layout::Primitive)primitive, maxVertices,
Brian Osmanba7ef322021-02-23 13:37:22 -0500115 invocations, marker, when, (Layout::CType)ctype);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400116 }
117 default:
118 SkASSERT(false);
119 return Layout();
120 }
121}
122
123Modifiers Rehydrator::modifiers() {
124 switch (this->readU8()) {
125 case kDefaultModifiers_Command:
126 return Modifiers();
127 case kModifiers8Bit_Command: {
128 Layout l = this->layout();
129 int flags = this->readU8();
130 return Modifiers(l, flags);
131 }
132 case kModifiers_Command: {
133 Layout l = this->layout();
134 int flags = this->readS32();
135 return Modifiers(l, flags);
136 }
137 default:
138 SkASSERT(false);
139 return Modifiers();
140 }
141}
142
Brian Osman5bf3e202020-10-13 10:34:18 -0400143const Symbol* Rehydrator::symbol() {
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400144 int kind = this->readU8();
145 switch (kind) {
146 case kArrayType_Command: {
147 uint16_t id = this->readU16();
148 const Type* componentType = this->type();
Brian Osmane8c26082020-10-01 17:22:45 -0400149 int8_t count = this->readS8();
150 String name = componentType->name();
151 if (count == Type::kUnsizedArray) {
152 name += "[]";
153 } else {
154 name += "[" + to_string(count) + "]";
155 }
Brian Osman5bf3e202020-10-13 10:34:18 -0400156 const Type* result = fSymbolTable->takeOwnershipOfSymbol(
John Stilesad2d4942020-12-11 16:55:58 -0500157 Type::MakeArrayType(name, *componentType, count));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400158 this->addSymbol(id, result);
159 return result;
160 }
161 case kEnumType_Command: {
162 uint16_t id = this->readU16();
163 StringFragment name = this->readString();
John Stilese6c67c52021-01-15 12:01:00 -0500164 const Type* result = fSymbolTable->takeOwnershipOfSymbol(Type::MakeEnumType(name));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400165 this->addSymbol(id, result);
166 return result;
167 }
168 case kFunctionDeclaration_Command: {
169 uint16_t id = this->readU16();
170 Modifiers modifiers = this->modifiers();
171 StringFragment name = this->readString();
172 int parameterCount = this->readU8();
Brian Osman5bf3e202020-10-13 10:34:18 -0400173 std::vector<const Variable*> parameters;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400174 parameters.reserve(parameterCount);
175 for (int i = 0; i < parameterCount; ++i) {
Ethan Nicholase6592142020-09-08 10:22:09 -0400176 parameters.push_back(this->symbolRef<Variable>(Symbol::Kind::kVariable));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400177 }
178 const Type* returnType = this->type();
Brian Osman5bf3e202020-10-13 10:34:18 -0400179 const FunctionDeclaration* result =
John Stiles3ae071e2020-08-05 15:29:29 -0400180 fSymbolTable->takeOwnershipOfSymbol(std::make_unique<FunctionDeclaration>(
John Stiles586df952020-11-12 18:27:13 -0500181 /*offset=*/-1, fModifiers.addToPool(modifiers), name,
Ethan Nicholased84b732020-10-08 11:45:44 -0400182 std::move(parameters), returnType, /*builtin=*/true));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400183 this->addSymbol(id, result);
184 return result;
185 }
186 case kField_Command: {
Ethan Nicholase6592142020-09-08 10:22:09 -0400187 const Variable* owner = this->symbolRef<Variable>(Symbol::Kind::kVariable);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400188 uint8_t index = this->readU8();
Brian Osman5bf3e202020-10-13 10:34:18 -0400189 const Field* result = fSymbolTable->takeOwnershipOfSymbol(
Ethan Nicholase2c49992020-10-05 11:49:11 -0400190 std::make_unique<Field>(/*offset=*/-1, owner, index));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400191 return result;
192 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400193 case kStructType_Command: {
194 uint16_t id = this->readU16();
195 StringFragment name = this->readString();
196 uint8_t fieldCount = this->readU8();
197 std::vector<Type::Field> fields;
198 fields.reserve(fieldCount);
199 for (int i = 0; i < fieldCount; ++i) {
200 Modifiers m = this->modifiers();
John Stilesf621e232020-08-25 13:33:02 -0400201 StringFragment fieldName = this->readString();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400202 const Type* type = this->type();
John Stilesf621e232020-08-25 13:33:02 -0400203 fields.emplace_back(m, fieldName, type);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400204 }
Brian Osman5bf3e202020-10-13 10:34:18 -0400205 const Type* result = fSymbolTable->takeOwnershipOfSymbol(
John Stilesad2d4942020-12-11 16:55:58 -0500206 Type::MakeStructType(/*offset=*/-1, name, std::move(fields)));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400207 this->addSymbol(id, result);
208 return result;
209 }
210 case kSymbolRef_Command: {
211 uint16_t id = this->readU16();
212 SkASSERT(fSymbols.size() > id);
213 return fSymbols[id];
214 }
John Stiles49a547f2020-10-06 16:14:37 -0400215 case kSymbolAlias_Command: {
216 uint16_t id = this->readU16();
217 StringFragment name = this->readString();
Brian Osman5bf3e202020-10-13 10:34:18 -0400218 const Symbol* origSymbol = this->symbol();
219 const SymbolAlias* symbolAlias = fSymbolTable->takeOwnershipOfSymbol(
John Stiles49a547f2020-10-06 16:14:37 -0400220 std::make_unique<SymbolAlias>(/*offset=*/-1, name, origSymbol));
221 this->addSymbol(id, symbolAlias);
222 return symbolAlias;
223 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400224 case kSystemType_Command: {
225 uint16_t id = this->readU16();
226 StringFragment name = this->readString();
Brian Osman5bf3e202020-10-13 10:34:18 -0400227 const Symbol* result = (*fSymbolTable)[name];
Ethan Nicholase6592142020-09-08 10:22:09 -0400228 SkASSERT(result && result->kind() == Symbol::Kind::kType);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400229 this->addSymbol(id, result);
230 return result;
231 }
232 case kUnresolvedFunction_Command: {
233 uint16_t id = this->readU16();
234 int length = this->readU8();
235 std::vector<const FunctionDeclaration*> functions;
236 functions.reserve(length);
237 for (int i = 0; i < length; ++i) {
238 const Symbol* f = this->symbol();
Ethan Nicholase6592142020-09-08 10:22:09 -0400239 SkASSERT(f && f->kind() == Symbol::Kind::kFunctionDeclaration);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400240 functions.push_back((const FunctionDeclaration*) f);
241 }
Brian Osman5bf3e202020-10-13 10:34:18 -0400242 const UnresolvedFunction* result = fSymbolTable->takeOwnershipOfSymbol(
John Stiles3ae071e2020-08-05 15:29:29 -0400243 std::make_unique<UnresolvedFunction>(std::move(functions)));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400244 this->addSymbol(id, result);
245 return result;
246 }
247 case kVariable_Command: {
248 uint16_t id = this->readU16();
John Stiles586df952020-11-12 18:27:13 -0500249 const Modifiers* m = fModifiers.addToPool(this->modifiers());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400250 StringFragment name = this->readString();
251 const Type* type = this->type();
252 Variable::Storage storage = (Variable::Storage) this->readU8();
Brian Osman5bf3e202020-10-13 10:34:18 -0400253 const Variable* result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Variable>(
Brian Osman3887a012020-09-30 13:22:27 -0400254 /*offset=*/-1, m, name, type, /*builtin=*/true, storage));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400255 this->addSymbol(id, result);
256 return result;
257 }
258 default:
259 printf("unsupported symbol %d\n", kind);
260 SkASSERT(false);
261 return nullptr;
262 }
263}
264
265const Type* Rehydrator::type() {
266 const Symbol* result = this->symbol();
Ethan Nicholase6592142020-09-08 10:22:09 -0400267 SkASSERT(result->kind() == Symbol::Kind::kType);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400268 return (const Type*) result;
269}
270
271std::vector<std::unique_ptr<ProgramElement>> Rehydrator::elements() {
272 SkDEBUGCODE(uint8_t command = )this->readU8();
273 SkASSERT(command == kElements_Command);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400274 std::vector<std::unique_ptr<ProgramElement>> result;
John Stiles1ea7f542020-11-02 13:07:23 -0500275 while (std::unique_ptr<ProgramElement> elem = this->element()) {
276 result.push_back(std::move(elem));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400277 }
278 return result;
279}
280
281std::unique_ptr<ProgramElement> Rehydrator::element() {
282 int kind = this->readU8();
283 switch (kind) {
284 case Rehydrator::kEnum_Command: {
285 StringFragment typeName = this->readString();
Brian Osman1313d1a2020-09-08 10:34:30 -0400286 std::shared_ptr<SymbolTable> symbols = this->symbolTable(/*inherit=*/false);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400287 for (auto& s : symbols->fOwnedSymbols) {
Ethan Nicholase6592142020-09-08 10:22:09 -0400288 SkASSERT(s->kind() == Symbol::Kind::kVariable);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400289 Variable& v = (Variable&) *s;
290 int value = this->readS32();
Ethan Nicholas5b9b0db2021-01-21 13:12:01 -0500291 // enum variables aren't really 'declared', but we have to create a declaration to
292 // store the value
John Stiles9ce80f72021-03-11 22:35:19 -0500293 auto valueLiteral = IntLiteral::Make(fContext, /*offset=*/-1, value);
John Stilese67bd132021-03-19 18:39:25 -0400294 auto declaration = VarDeclaration::Make(fContext, &v, &v.type(), /*arraySize=*/0,
295 std::move(valueLiteral));
Ethan Nicholas5b9b0db2021-01-21 13:12:01 -0500296 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 Stilesbf16b6c2021-03-12 19:24:31 -0500355 return Block::Make(/*offset=*/-1, std::move(statements), fSymbolTable, isScope);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400356 }
357 case Rehydrator::kBreak_Command:
John Stilesa0c04d62021-03-11 23:07:24 -0500358 return BreakStatement::Make(/*offset=*/-1);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400359 case Rehydrator::kContinue_Command:
John Stilesa0c04d62021-03-11 23:07:24 -0500360 return ContinueStatement::Make(/*offset=*/-1);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400361 case Rehydrator::kDiscard_Command:
John Stilesa0c04d62021-03-11 23:07:24 -0500362 return DiscardStatement::Make(/*offset=*/-1);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400363 case Rehydrator::kDo_Command: {
364 std::unique_ptr<Statement> stmt = this->statement();
365 std::unique_ptr<Expression> expr = this->expression();
John Stilesea5822e2021-02-26 11:18:20 -0500366 return DoStatement::Make(fContext, std::move(stmt), std::move(expr));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400367 }
368 case Rehydrator::kExpressionStatement_Command: {
369 std::unique_ptr<Expression> expr = this->expression();
John Stiles3e5871c2021-02-25 20:52:03 -0500370 return ExpressionStatement::Make(fContext, std::move(expr));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400371 }
372 case Rehydrator::kFor_Command: {
373 std::unique_ptr<Statement> initializer = this->statement();
374 std::unique_ptr<Expression> test = this->expression();
375 std::unique_ptr<Expression> next = this->expression();
376 std::unique_ptr<Statement> body = this->statement();
377 std::shared_ptr<SymbolTable> symbols = this->symbolTable();
John Stiles23521a82021-03-02 17:02:51 -0500378 return ForStatement::Make(fContext, /*offset=*/-1, std::move(initializer),
379 std::move(test), std::move(next), std::move(body),
380 std::move(symbols));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400381 }
382 case Rehydrator::kIf_Command: {
383 bool isStatic = this->readU8();
384 std::unique_ptr<Expression> test = this->expression();
385 std::unique_ptr<Statement> ifTrue = this->statement();
386 std::unique_ptr<Statement> ifFalse = this->statement();
John Stilescf3059e2021-02-25 14:27:02 -0500387 return IfStatement::Make(fContext, /*offset=*/-1, isStatic, std::move(test),
388 std::move(ifTrue), std::move(ifFalse));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400389 }
John Stiles98c1f822020-09-09 14:18:53 -0400390 case Rehydrator::kInlineMarker_Command: {
391 const FunctionDeclaration* funcDecl = this->symbolRef<FunctionDeclaration>(
392 Symbol::Kind::kFunctionDeclaration);
John Stilesa0c04d62021-03-11 23:07:24 -0500393 return InlineMarker::Make(funcDecl);
John Stiles98c1f822020-09-09 14:18:53 -0400394 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400395 case Rehydrator::kReturn_Command: {
396 std::unique_ptr<Expression> expr = this->expression();
John Stilesa0c04d62021-03-11 23:07:24 -0500397 return ReturnStatement::Make(/*offset=*/-1, std::move(expr));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400398 }
399 case Rehydrator::kSwitch_Command: {
400 bool isStatic = this->readU8();
401 AutoRehydratorSymbolTable symbols(this);
402 std::unique_ptr<Expression> expr = this->expression();
403 int caseCount = this->readU8();
John Stilesb23a64b2021-03-11 08:27:59 -0500404 StatementArray cases;
405 cases.reserve_back(caseCount);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400406 for (int i = 0; i < caseCount; ++i) {
407 std::unique_ptr<Expression> value = this->expression();
John Stilesc3ce43b2021-03-09 15:37:01 -0500408 std::unique_ptr<Statement> statement = this->statement();
John Stiles8f2a0cf2020-10-13 12:48:21 -0400409 cases.push_back(std::make_unique<SwitchCase>(/*offset=*/-1, std::move(value),
John Stilesc3ce43b2021-03-09 15:37:01 -0500410 std::move(statement)));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400411 }
John Stiles23521a82021-03-02 17:02:51 -0500412 return SwitchStatement::Make(fContext, /*offset=*/-1, isStatic, std::move(expr),
413 std::move(cases), fSymbolTable);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400414 }
415 case Rehydrator::kVarDeclaration_Command: {
Ethan Nicholase6592142020-09-08 10:22:09 -0400416 Variable* var = this->symbolRef<Variable>(Symbol::Kind::kVariable);
Brian Osmanc0213602020-10-06 14:43:32 -0400417 const Type* baseType = this->type();
John Stiles62a56462020-12-03 10:41:58 -0500418 int arraySize = this->readS8();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400419 std::unique_ptr<Expression> value = this->expression();
John Stilese67bd132021-03-19 18:39:25 -0400420 return VarDeclaration::Make(fContext, var, baseType, arraySize, std::move(value));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400421 }
422 case Rehydrator::kVoid_Command:
423 return nullptr;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400424 default:
425 printf("unsupported statement %d\n", kind);
426 SkASSERT(false);
427 return nullptr;
428 }
429}
430
John Stilesd8eb8752021-04-01 11:49:10 -0400431ExpressionArray Rehydrator::expressionArray() {
432 uint8_t count = this->readU8();
433 ExpressionArray array;
434 array.reserve_back(count);
435 for (int i = 0; i < count; ++i) {
436 array.push_back(this->expression());
437 }
438 return array;
439}
440
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400441std::unique_ptr<Expression> Rehydrator::expression() {
442 int kind = this->readU8();
443 switch (kind) {
444 case Rehydrator::kBinary_Command: {
445 std::unique_ptr<Expression> left = this->expression();
446 Token::Kind op = (Token::Kind) this->readU8();
447 std::unique_ptr<Expression> right = this->expression();
John Stilese2aec432021-03-01 09:27:48 -0500448 return BinaryExpression::Make(fContext, std::move(left), op, std::move(right));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400449 }
450 case Rehydrator::kBoolLiteral_Command: {
451 bool value = this->readU8();
John Stiles9ce80f72021-03-11 22:35:19 -0500452 return BoolLiteral::Make(fContext, /*offset=*/-1, value);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400453 }
454 case Rehydrator::kConstructor_Command: {
455 const Type* type = this->type();
John Stilesd8eb8752021-04-01 11:49:10 -0400456 ExpressionArray args = this->expressionArray();
John Stiles23521a82021-03-02 17:02:51 -0500457 auto ctor = Constructor::Convert(fContext, /*offset=*/-1, *type, std::move(args));
458 SkASSERT(ctor);
459 return ctor;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400460 }
John Stilese1182782021-03-30 22:09:37 -0400461 case Rehydrator::kConstructorDiagonalMatrix_Command: {
462 const Type* type = this->type();
John Stilesd8eb8752021-04-01 11:49:10 -0400463 ExpressionArray args = this->expressionArray();
464 SkASSERT(args.size() == 1);
John Stilese1182782021-03-30 22:09:37 -0400465 return ConstructorDiagonalMatrix::Make(fContext, /*offset=*/-1, *type,
John Stilesd8eb8752021-04-01 11:49:10 -0400466 std::move(args[0]));
John Stilese1182782021-03-30 22:09:37 -0400467 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400468 case Rehydrator::kFieldAccess_Command: {
469 std::unique_ptr<Expression> base = this->expression();
470 int index = this->readU8();
471 FieldAccess::OwnerKind ownerKind = (FieldAccess::OwnerKind) this->readU8();
John Stiles06d600f2021-03-08 09:18:21 -0500472 return FieldAccess::Make(fContext, std::move(base), index, ownerKind);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400473 }
474 case Rehydrator::kFloatLiteral_Command: {
Brian Osmanfb964a42020-11-18 10:45:52 -0500475 const Type* type = this->type();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400476 FloatIntUnion u;
477 u.fInt = this->readS32();
John Stiles9ce80f72021-03-11 22:35:19 -0500478 return FloatLiteral::Make(/*offset=*/-1, u.fFloat, type);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400479 }
480 case Rehydrator::kFunctionCall_Command: {
Ethan Nicholas30d30222020-09-11 12:27:26 -0400481 const Type* type = this->type();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400482 const FunctionDeclaration* f = this->symbolRef<FunctionDeclaration>(
Ethan Nicholase6592142020-09-08 10:22:09 -0400483 Symbol::Kind::kFunctionDeclaration);
John Stilesd8eb8752021-04-01 11:49:10 -0400484 ExpressionArray args = this->expressionArray();
John Stilescd7ba502021-03-19 10:54:59 -0400485 return FunctionCall::Make(fContext, /*offset=*/-1, type, *f, std::move(args));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400486 }
487 case Rehydrator::kIndex_Command: {
488 std::unique_ptr<Expression> base = this->expression();
489 std::unique_ptr<Expression> index = this->expression();
John Stiles51d33982021-03-08 09:18:07 -0500490 return IndexExpression::Make(fContext, std::move(base), std::move(index));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400491 }
492 case Rehydrator::kIntLiteral_Command: {
Brian Osmanfb964a42020-11-18 10:45:52 -0500493 const Type* type = this->type();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400494 int value = this->readS32();
John Stiles9ce80f72021-03-11 22:35:19 -0500495 return IntLiteral::Make(/*offset=*/-1, value, type);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400496 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400497 case Rehydrator::kPostfix_Command: {
498 Token::Kind op = (Token::Kind) this->readU8();
499 std::unique_ptr<Expression> operand = this->expression();
John Stiles52d3b012021-02-26 15:56:48 -0500500 return PostfixExpression::Make(fContext, std::move(operand), op);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400501 }
502 case Rehydrator::kPrefix_Command: {
503 Token::Kind op = (Token::Kind) this->readU8();
504 std::unique_ptr<Expression> operand = this->expression();
John Stilesb0eb20f2021-02-26 15:29:33 -0500505 return PrefixExpression::Make(fContext, op, std::move(operand));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400506 }
507 case Rehydrator::kSetting_Command: {
508 StringFragment name = this->readString();
John Stiles23521a82021-03-02 17:02:51 -0500509 return Setting::Convert(fContext, /*offset=*/-1, name);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400510 }
511 case Rehydrator::kSwizzle_Command: {
512 std::unique_ptr<Expression> base = this->expression();
513 int count = this->readU8();
John Stiles750109b2020-10-30 13:45:46 -0400514 ComponentArray components;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400515 for (int i = 0; i < count; ++i) {
516 components.push_back(this->readU8());
517 }
John Stiles23521a82021-03-02 17:02:51 -0500518 return Swizzle::Make(fContext, std::move(base), components);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400519 }
520 case Rehydrator::kTernary_Command: {
521 std::unique_ptr<Expression> test = this->expression();
522 std::unique_ptr<Expression> ifTrue = this->expression();
523 std::unique_ptr<Expression> ifFalse = this->expression();
John Stiles90518f72021-02-26 20:44:54 -0500524 return TernaryExpression::Make(fContext, std::move(test),
525 std::move(ifTrue), std::move(ifFalse));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400526 }
527 case Rehydrator::kVariableReference_Command: {
Ethan Nicholase6592142020-09-08 10:22:09 -0400528 const Variable* var = this->symbolRef<Variable>(Symbol::Kind::kVariable);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400529 VariableReference::RefKind refKind = (VariableReference::RefKind) this->readU8();
Brian Osman79457ef2020-09-24 15:01:27 -0400530 return std::make_unique<VariableReference>(-1, var, refKind);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400531 }
532 case Rehydrator::kVoid_Command:
533 return nullptr;
534 default:
535 printf("unsupported expression %d\n", kind);
536 SkASSERT(false);
537 return nullptr;
538 }
539}
540
Brian Osman1313d1a2020-09-08 10:34:30 -0400541std::shared_ptr<SymbolTable> Rehydrator::symbolTable(bool inherit) {
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400542 int command = this->readU8();
543 if (command == kVoid_Command) {
544 return nullptr;
545 }
546 SkASSERT(command == kSymbolTable_Command);
547 uint16_t ownedCount = this->readU16();
Brian Osman1313d1a2020-09-08 10:34:30 -0400548 std::shared_ptr<SymbolTable> oldTable = fSymbolTable;
John Stiles7c3515b2020-10-16 18:38:39 -0400549 std::shared_ptr<SymbolTable> result =
550 inherit ? std::make_shared<SymbolTable>(fSymbolTable, /*builtin=*/true)
551 : std::make_shared<SymbolTable>(fErrors, /*builtin=*/true);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400552 fSymbolTable = result;
Brian Osman5bf3e202020-10-13 10:34:18 -0400553 std::vector<const Symbol*> ownedSymbols;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400554 ownedSymbols.reserve(ownedCount);
555 for (int i = 0; i < ownedCount; ++i) {
556 ownedSymbols.push_back(this->symbol());
557 }
558 uint16_t symbolCount = this->readU16();
559 std::vector<std::pair<StringFragment, int>> symbols;
560 symbols.reserve(symbolCount);
561 for (int i = 0; i < symbolCount; ++i) {
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400562 int index = this->readU16();
John Stilesb8cc6652020-10-08 09:12:07 -0400563 fSymbolTable->addWithoutOwnership(ownedSymbols[index]);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400564 }
Brian Osman1313d1a2020-09-08 10:34:30 -0400565 fSymbolTable = oldTable;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400566 return result;
567}
568
John Stilesa6841be2020-08-06 14:11:56 -0400569} // namespace SkSL