blob: 5d10c829dcaeba4f4491bd573221d7e4a65cd6f8 [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"
John Stiles4118f142021-04-01 16:42:35 -040019#include "src/sksl/ir/SkSLConstructorArray.h"
John Stiles8cad6372021-04-07 12:31:13 -040020#include "src/sksl/ir/SkSLConstructorCompound.h"
21#include "src/sksl/ir/SkSLConstructorCompoundCast.h"
John Stilese1182782021-03-30 22:09:37 -040022#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
John Stiles5abb9e12021-04-06 13:47:19 -040023#include "src/sksl/ir/SkSLConstructorMatrixResize.h"
John Stilesfd7252f2021-04-04 22:24:40 -040024#include "src/sksl/ir/SkSLConstructorScalarCast.h"
John Stiles2938eea2021-04-01 18:58:25 -040025#include "src/sksl/ir/SkSLConstructorSplat.h"
John Stilesd47330f2021-04-08 23:25:52 -040026#include "src/sksl/ir/SkSLConstructorStruct.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040027#include "src/sksl/ir/SkSLContinueStatement.h"
28#include "src/sksl/ir/SkSLDiscardStatement.h"
29#include "src/sksl/ir/SkSLDoStatement.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040030#include "src/sksl/ir/SkSLExpression.h"
31#include "src/sksl/ir/SkSLExpressionStatement.h"
32#include "src/sksl/ir/SkSLField.h"
33#include "src/sksl/ir/SkSLFieldAccess.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040034#include "src/sksl/ir/SkSLForStatement.h"
35#include "src/sksl/ir/SkSLFunctionCall.h"
36#include "src/sksl/ir/SkSLFunctionDeclaration.h"
37#include "src/sksl/ir/SkSLFunctionDefinition.h"
38#include "src/sksl/ir/SkSLIfStatement.h"
39#include "src/sksl/ir/SkSLIndexExpression.h"
John Stiles98c1f822020-09-09 14:18:53 -040040#include "src/sksl/ir/SkSLInlineMarker.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040041#include "src/sksl/ir/SkSLInterfaceBlock.h"
John Stiles7591d4b2021-09-13 13:32:06 -040042#include "src/sksl/ir/SkSLLiteral.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040043#include "src/sksl/ir/SkSLPostfixExpression.h"
44#include "src/sksl/ir/SkSLPrefixExpression.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040045#include "src/sksl/ir/SkSLReturnStatement.h"
46#include "src/sksl/ir/SkSLSetting.h"
John Stilesdc75a972020-11-25 16:24:55 -050047#include "src/sksl/ir/SkSLStructDefinition.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040048#include "src/sksl/ir/SkSLSwitchCase.h"
49#include "src/sksl/ir/SkSLSwitchStatement.h"
50#include "src/sksl/ir/SkSLSwizzle.h"
John Stiles49a547f2020-10-06 16:14:37 -040051#include "src/sksl/ir/SkSLSymbolAlias.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040052#include "src/sksl/ir/SkSLSymbolTable.h"
53#include "src/sksl/ir/SkSLTernaryExpression.h"
54#include "src/sksl/ir/SkSLType.h"
55#include "src/sksl/ir/SkSLUnresolvedFunction.h"
56#include "src/sksl/ir/SkSLVarDeclarations.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040057#include "src/sksl/ir/SkSLVariable.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040058
59namespace SkSL {
60
61class AutoRehydratorSymbolTable {
62public:
63 AutoRehydratorSymbolTable(Rehydrator* rehydrator)
64 : fRehydrator(rehydrator)
65 , fOldSymbols(fRehydrator->fSymbolTable) {
66 fRehydrator->fSymbolTable = fRehydrator->symbolTable();
67 }
68
69 ~AutoRehydratorSymbolTable() {
70 fRehydrator->fSymbolTable = std::move(fOldSymbols);
71 }
72
73private:
74 Rehydrator* fRehydrator;
75 std::shared_ptr<SymbolTable> fOldSymbols;
76};
77
John Stiles10d39d92021-05-04 16:13:14 -040078Rehydrator::Rehydrator(const Context* context, std::shared_ptr<SymbolTable> symbolTable,
John Stiles7c3515b2020-10-16 18:38:39 -040079 const uint8_t* src, size_t length)
80 : fContext(*context)
John Stiles7c3515b2020-10-16 18:38:39 -040081 , fSymbolTable(std::move(symbolTable))
82 , fStart(src)
83 SkDEBUGCODE(, fEnd(fStart + length)) {
84 SkASSERT(fSymbolTable);
85 SkASSERT(fSymbolTable->isBuiltin());
86 // skip past string data
87 fIP = fStart;
88 fIP += this->readU16();
89}
90
Ethan Nicholasc18bb512020-07-28 14:46:53 -040091Layout Rehydrator::layout() {
92 switch (this->readU8()) {
93 case kBuiltinLayout_Command: {
94 Layout result;
95 result.fBuiltin = this->readS16();
96 return result;
97 }
98 case kDefaultLayout_Command:
99 return Layout();
100 case kLayout_Command: {
101 int flags = this->readU32();
102 int location = this->readS8();
103 int offset = this->readS8();
104 int binding = this->readS8();
105 int index = this->readS8();
106 int set = this->readS8();
107 int builtin = this->readS16();
108 int inputAttachmentIndex = this->readS8();
Brian Osman99ddd2a2021-08-27 11:21:12 -0400109 return Layout(
110 flags, location, offset, binding, index, set, builtin, inputAttachmentIndex);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400111 }
112 default:
113 SkASSERT(false);
114 return Layout();
115 }
116}
117
118Modifiers Rehydrator::modifiers() {
119 switch (this->readU8()) {
120 case kDefaultModifiers_Command:
121 return Modifiers();
122 case kModifiers8Bit_Command: {
123 Layout l = this->layout();
124 int flags = this->readU8();
125 return Modifiers(l, flags);
126 }
127 case kModifiers_Command: {
128 Layout l = this->layout();
129 int flags = this->readS32();
130 return Modifiers(l, flags);
131 }
132 default:
133 SkASSERT(false);
134 return Modifiers();
135 }
136}
137
Brian Osman5bf3e202020-10-13 10:34:18 -0400138const Symbol* Rehydrator::symbol() {
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400139 int kind = this->readU8();
140 switch (kind) {
141 case kArrayType_Command: {
142 uint16_t id = this->readU16();
143 const Type* componentType = this->type();
Brian Osmane8c26082020-10-01 17:22:45 -0400144 int8_t count = this->readS8();
John Stiles9506c342021-08-09 14:19:01 -0400145 const String* arrayName =
146 fSymbolTable->takeOwnershipOfString(componentType->getArrayName(count));
Brian Osman5bf3e202020-10-13 10:34:18 -0400147 const Type* result = fSymbolTable->takeOwnershipOfSymbol(
John Stiles9506c342021-08-09 14:19:01 -0400148 Type::MakeArrayType(*arrayName, *componentType, count));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400149 this->addSymbol(id, result);
150 return result;
151 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400152 case kFunctionDeclaration_Command: {
153 uint16_t id = this->readU16();
154 Modifiers modifiers = this->modifiers();
Ethan Nicholas962dec42021-06-10 13:06:39 -0400155 skstd::string_view name = this->readString();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400156 int parameterCount = this->readU8();
Brian Osman5bf3e202020-10-13 10:34:18 -0400157 std::vector<const Variable*> parameters;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400158 parameters.reserve(parameterCount);
159 for (int i = 0; i < parameterCount; ++i) {
Ethan Nicholase6592142020-09-08 10:22:09 -0400160 parameters.push_back(this->symbolRef<Variable>(Symbol::Kind::kVariable));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400161 }
162 const Type* returnType = this->type();
Brian Osman5bf3e202020-10-13 10:34:18 -0400163 const FunctionDeclaration* result =
John Stiles3ae071e2020-08-05 15:29:29 -0400164 fSymbolTable->takeOwnershipOfSymbol(std::make_unique<FunctionDeclaration>(
John Stilesf2872e62021-05-04 11:38:43 -0400165 /*offset=*/-1,
166 this->modifiersPool().add(modifiers),
167 name,
168 std::move(parameters),
169 returnType,
170 /*builtin=*/true));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400171 this->addSymbol(id, result);
172 return result;
173 }
174 case kField_Command: {
Ethan Nicholase6592142020-09-08 10:22:09 -0400175 const Variable* owner = this->symbolRef<Variable>(Symbol::Kind::kVariable);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400176 uint8_t index = this->readU8();
Brian Osman5bf3e202020-10-13 10:34:18 -0400177 const Field* result = fSymbolTable->takeOwnershipOfSymbol(
Ethan Nicholase2c49992020-10-05 11:49:11 -0400178 std::make_unique<Field>(/*offset=*/-1, owner, index));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400179 return result;
180 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400181 case kStructType_Command: {
182 uint16_t id = this->readU16();
Ethan Nicholasd2e09602021-06-10 11:21:59 -0400183 String name(this->readString());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400184 uint8_t fieldCount = this->readU8();
185 std::vector<Type::Field> fields;
186 fields.reserve(fieldCount);
187 for (int i = 0; i < fieldCount; ++i) {
188 Modifiers m = this->modifiers();
Ethan Nicholas962dec42021-06-10 13:06:39 -0400189 skstd::string_view fieldName = this->readString();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400190 const Type* type = this->type();
John Stilesf621e232020-08-25 13:33:02 -0400191 fields.emplace_back(m, fieldName, type);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400192 }
Ethan Nicholas27f06eb2021-07-26 16:39:40 -0400193 skstd::string_view nameChars(*fSymbolTable->takeOwnershipOfString(std::move(name)));
Brian Osman5bf3e202020-10-13 10:34:18 -0400194 const Type* result = fSymbolTable->takeOwnershipOfSymbol(
Ethan Nicholas27f06eb2021-07-26 16:39:40 -0400195 Type::MakeStructType(/*offset=*/-1, nameChars, std::move(fields)));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400196 this->addSymbol(id, result);
197 return result;
198 }
199 case kSymbolRef_Command: {
200 uint16_t id = this->readU16();
201 SkASSERT(fSymbols.size() > id);
202 return fSymbols[id];
203 }
John Stiles49a547f2020-10-06 16:14:37 -0400204 case kSymbolAlias_Command: {
205 uint16_t id = this->readU16();
Ethan Nicholas962dec42021-06-10 13:06:39 -0400206 skstd::string_view name = this->readString();
Brian Osman5bf3e202020-10-13 10:34:18 -0400207 const Symbol* origSymbol = this->symbol();
208 const SymbolAlias* symbolAlias = fSymbolTable->takeOwnershipOfSymbol(
John Stiles49a547f2020-10-06 16:14:37 -0400209 std::make_unique<SymbolAlias>(/*offset=*/-1, name, origSymbol));
210 this->addSymbol(id, symbolAlias);
211 return symbolAlias;
212 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400213 case kSystemType_Command: {
214 uint16_t id = this->readU16();
Ethan Nicholas962dec42021-06-10 13:06:39 -0400215 skstd::string_view name = this->readString();
Brian Osman5bf3e202020-10-13 10:34:18 -0400216 const Symbol* result = (*fSymbolTable)[name];
Ethan Nicholase6592142020-09-08 10:22:09 -0400217 SkASSERT(result && result->kind() == Symbol::Kind::kType);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400218 this->addSymbol(id, result);
219 return result;
220 }
221 case kUnresolvedFunction_Command: {
222 uint16_t id = this->readU16();
223 int length = this->readU8();
224 std::vector<const FunctionDeclaration*> functions;
225 functions.reserve(length);
226 for (int i = 0; i < length; ++i) {
227 const Symbol* f = this->symbol();
Ethan Nicholase6592142020-09-08 10:22:09 -0400228 SkASSERT(f && f->kind() == Symbol::Kind::kFunctionDeclaration);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400229 functions.push_back((const FunctionDeclaration*) f);
230 }
Brian Osman5bf3e202020-10-13 10:34:18 -0400231 const UnresolvedFunction* result = fSymbolTable->takeOwnershipOfSymbol(
John Stiles3ae071e2020-08-05 15:29:29 -0400232 std::make_unique<UnresolvedFunction>(std::move(functions)));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400233 this->addSymbol(id, result);
234 return result;
235 }
236 case kVariable_Command: {
237 uint16_t id = this->readU16();
John Stilesf2872e62021-05-04 11:38:43 -0400238 const Modifiers* m = this->modifiersPool().add(this->modifiers());
Ethan Nicholas962dec42021-06-10 13:06:39 -0400239 skstd::string_view name = this->readString();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400240 const Type* type = this->type();
241 Variable::Storage storage = (Variable::Storage) this->readU8();
Brian Osman5bf3e202020-10-13 10:34:18 -0400242 const Variable* result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Variable>(
Brian Osman3887a012020-09-30 13:22:27 -0400243 /*offset=*/-1, m, name, type, /*builtin=*/true, storage));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400244 this->addSymbol(id, result);
245 return result;
246 }
247 default:
248 printf("unsupported symbol %d\n", kind);
249 SkASSERT(false);
250 return nullptr;
251 }
252}
253
254const Type* Rehydrator::type() {
255 const Symbol* result = this->symbol();
Ethan Nicholase6592142020-09-08 10:22:09 -0400256 SkASSERT(result->kind() == Symbol::Kind::kType);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400257 return (const Type*) result;
258}
259
260std::vector<std::unique_ptr<ProgramElement>> Rehydrator::elements() {
261 SkDEBUGCODE(uint8_t command = )this->readU8();
262 SkASSERT(command == kElements_Command);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400263 std::vector<std::unique_ptr<ProgramElement>> result;
John Stiles1ea7f542020-11-02 13:07:23 -0500264 while (std::unique_ptr<ProgramElement> elem = this->element()) {
265 result.push_back(std::move(elem));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400266 }
267 return result;
268}
269
270std::unique_ptr<ProgramElement> Rehydrator::element() {
271 int kind = this->readU8();
272 switch (kind) {
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400273 case Rehydrator::kFunctionDefinition_Command: {
274 const FunctionDeclaration* decl = this->symbolRef<FunctionDeclaration>(
Ethan Nicholase6592142020-09-08 10:22:09 -0400275 Symbol::Kind::kFunctionDeclaration);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400276 std::unique_ptr<Statement> body = this->statement();
John Stiles3b204892021-08-27 17:35:35 -0400277 auto result = FunctionDefinition::Convert(fContext, /*offset=*/-1, *decl,
278 std::move(body), /*builtin=*/true);
John Stiles607d36b2020-10-19 15:00:01 -0400279 decl->setDefinition(result.get());
280 return std::move(result);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400281 }
282 case Rehydrator::kInterfaceBlock_Command: {
283 const Symbol* var = this->symbol();
John Stiles87ae34e2020-10-13 12:50:11 -0400284 SkASSERT(var && var->is<Variable>());
Ethan Nicholas3533ff12021-08-02 12:53:29 -0400285 skstd::string_view typeName = this->readString();
286 skstd::string_view instanceName = this->readString();
John Stilesd39aec02020-12-03 10:42:26 -0500287 int arraySize = this->readS8();
Ethan Nicholas3533ff12021-08-02 12:53:29 -0400288 return std::make_unique<InterfaceBlock>(/*offset=*/-1, &var->as<Variable>(), typeName,
289 instanceName, arraySize, nullptr);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400290 }
291 case Rehydrator::kVarDeclarations_Command: {
Brian Osmanc0213602020-10-06 14:43:32 -0400292 std::unique_ptr<Statement> decl = this->statement();
Ethan Nicholas624a5292021-04-16 14:54:43 -0400293 return std::make_unique<GlobalVarDeclaration>(std::move(decl));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400294 }
John Stilesdc75a972020-11-25 16:24:55 -0500295 case Rehydrator::kStructDefinition_Command: {
296 const Symbol* type = this->symbol();
297 SkASSERT(type && type->is<Type>());
298 return std::make_unique<StructDefinition>(/*offset=*/-1, type->as<Type>());
299 }
John Stiles1ea7f542020-11-02 13:07:23 -0500300 case Rehydrator::kElementsComplete_Command:
301 return nullptr;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400302 default:
John Stiles1ea7f542020-11-02 13:07:23 -0500303 SkDEBUGFAILF("unsupported element %d\n", kind);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400304 return nullptr;
305 }
306}
307
308std::unique_ptr<Statement> Rehydrator::statement() {
309 int kind = this->readU8();
310 switch (kind) {
311 case Rehydrator::kBlock_Command: {
312 AutoRehydratorSymbolTable symbols(this);
313 int count = this->readU8();
John Stiles8f2a0cf2020-10-13 12:48:21 -0400314 StatementArray statements;
John Stilesf4bda742020-10-14 16:57:41 -0400315 statements.reserve_back(count);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400316 for (int i = 0; i < count; ++i) {
317 statements.push_back(this->statement());
318 }
319 bool isScope = this->readU8();
John Stilesbf16b6c2021-03-12 19:24:31 -0500320 return Block::Make(/*offset=*/-1, std::move(statements), fSymbolTable, isScope);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400321 }
322 case Rehydrator::kBreak_Command:
John Stilesa0c04d62021-03-11 23:07:24 -0500323 return BreakStatement::Make(/*offset=*/-1);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400324 case Rehydrator::kContinue_Command:
John Stilesa0c04d62021-03-11 23:07:24 -0500325 return ContinueStatement::Make(/*offset=*/-1);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400326 case Rehydrator::kDiscard_Command:
John Stilesa0c04d62021-03-11 23:07:24 -0500327 return DiscardStatement::Make(/*offset=*/-1);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400328 case Rehydrator::kDo_Command: {
329 std::unique_ptr<Statement> stmt = this->statement();
330 std::unique_ptr<Expression> expr = this->expression();
John Stilesea5822e2021-02-26 11:18:20 -0500331 return DoStatement::Make(fContext, std::move(stmt), std::move(expr));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400332 }
333 case Rehydrator::kExpressionStatement_Command: {
334 std::unique_ptr<Expression> expr = this->expression();
John Stiles3e5871c2021-02-25 20:52:03 -0500335 return ExpressionStatement::Make(fContext, std::move(expr));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400336 }
337 case Rehydrator::kFor_Command: {
338 std::unique_ptr<Statement> initializer = this->statement();
339 std::unique_ptr<Expression> test = this->expression();
340 std::unique_ptr<Expression> next = this->expression();
341 std::unique_ptr<Statement> body = this->statement();
342 std::shared_ptr<SymbolTable> symbols = this->symbolTable();
John Stiles23521a82021-03-02 17:02:51 -0500343 return ForStatement::Make(fContext, /*offset=*/-1, std::move(initializer),
344 std::move(test), std::move(next), std::move(body),
John Stiles9c975c52021-08-31 10:18:57 -0400345 /*unrollInfo=*/nullptr, std::move(symbols));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400346 }
347 case Rehydrator::kIf_Command: {
348 bool isStatic = this->readU8();
349 std::unique_ptr<Expression> test = this->expression();
350 std::unique_ptr<Statement> ifTrue = this->statement();
351 std::unique_ptr<Statement> ifFalse = this->statement();
John Stilescf3059e2021-02-25 14:27:02 -0500352 return IfStatement::Make(fContext, /*offset=*/-1, isStatic, std::move(test),
353 std::move(ifTrue), std::move(ifFalse));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400354 }
John Stiles98c1f822020-09-09 14:18:53 -0400355 case Rehydrator::kInlineMarker_Command: {
356 const FunctionDeclaration* funcDecl = this->symbolRef<FunctionDeclaration>(
357 Symbol::Kind::kFunctionDeclaration);
John Stilesa0c04d62021-03-11 23:07:24 -0500358 return InlineMarker::Make(funcDecl);
John Stiles98c1f822020-09-09 14:18:53 -0400359 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400360 case Rehydrator::kReturn_Command: {
361 std::unique_ptr<Expression> expr = this->expression();
John Stilesa0c04d62021-03-11 23:07:24 -0500362 return ReturnStatement::Make(/*offset=*/-1, std::move(expr));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400363 }
364 case Rehydrator::kSwitch_Command: {
365 bool isStatic = this->readU8();
366 AutoRehydratorSymbolTable symbols(this);
367 std::unique_ptr<Expression> expr = this->expression();
368 int caseCount = this->readU8();
John Stilesb23a64b2021-03-11 08:27:59 -0500369 StatementArray cases;
370 cases.reserve_back(caseCount);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400371 for (int i = 0; i < caseCount; ++i) {
372 std::unique_ptr<Expression> value = this->expression();
John Stilesc3ce43b2021-03-09 15:37:01 -0500373 std::unique_ptr<Statement> statement = this->statement();
John Stiles8f2a0cf2020-10-13 12:48:21 -0400374 cases.push_back(std::make_unique<SwitchCase>(/*offset=*/-1, std::move(value),
John Stilesc3ce43b2021-03-09 15:37:01 -0500375 std::move(statement)));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400376 }
John Stiles23521a82021-03-02 17:02:51 -0500377 return SwitchStatement::Make(fContext, /*offset=*/-1, isStatic, std::move(expr),
378 std::move(cases), fSymbolTable);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400379 }
380 case Rehydrator::kVarDeclaration_Command: {
Ethan Nicholase6592142020-09-08 10:22:09 -0400381 Variable* var = this->symbolRef<Variable>(Symbol::Kind::kVariable);
Brian Osmanc0213602020-10-06 14:43:32 -0400382 const Type* baseType = this->type();
John Stiles62a56462020-12-03 10:41:58 -0500383 int arraySize = this->readS8();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400384 std::unique_ptr<Expression> value = this->expression();
John Stilese67bd132021-03-19 18:39:25 -0400385 return VarDeclaration::Make(fContext, var, baseType, arraySize, std::move(value));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400386 }
387 case Rehydrator::kVoid_Command:
388 return nullptr;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400389 default:
390 printf("unsupported statement %d\n", kind);
391 SkASSERT(false);
392 return nullptr;
393 }
394}
395
John Stilesd8eb8752021-04-01 11:49:10 -0400396ExpressionArray Rehydrator::expressionArray() {
397 uint8_t count = this->readU8();
398 ExpressionArray array;
399 array.reserve_back(count);
400 for (int i = 0; i < count; ++i) {
401 array.push_back(this->expression());
402 }
403 return array;
404}
405
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400406std::unique_ptr<Expression> Rehydrator::expression() {
407 int kind = this->readU8();
408 switch (kind) {
409 case Rehydrator::kBinary_Command: {
410 std::unique_ptr<Expression> left = this->expression();
411 Token::Kind op = (Token::Kind) this->readU8();
412 std::unique_ptr<Expression> right = this->expression();
John Stilese2aec432021-03-01 09:27:48 -0500413 return BinaryExpression::Make(fContext, std::move(left), op, std::move(right));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400414 }
415 case Rehydrator::kBoolLiteral_Command: {
416 bool value = this->readU8();
John Stiles7591d4b2021-09-13 13:32:06 -0400417 return Literal::MakeBool(fContext, /*offset=*/-1, value);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400418 }
John Stiles4118f142021-04-01 16:42:35 -0400419 case Rehydrator::kConstructorArray_Command: {
420 const Type* type = this->type();
421 return ConstructorArray::Make(fContext, /*offset=*/-1, *type, this->expressionArray());
422 }
John Stiles8cad6372021-04-07 12:31:13 -0400423 case Rehydrator::kConstructorCompound_Command: {
John Stiles2bec8ab2021-04-06 18:40:04 -0400424 const Type* type = this->type();
John Stiles8cad6372021-04-07 12:31:13 -0400425 return ConstructorCompound::Make(fContext, /*offset=*/-1, *type,
John Stiles2bec8ab2021-04-06 18:40:04 -0400426 this->expressionArray());
427 }
John Stilese1182782021-03-30 22:09:37 -0400428 case Rehydrator::kConstructorDiagonalMatrix_Command: {
429 const Type* type = this->type();
John Stilesd8eb8752021-04-01 11:49:10 -0400430 ExpressionArray args = this->expressionArray();
431 SkASSERT(args.size() == 1);
John Stilese1182782021-03-30 22:09:37 -0400432 return ConstructorDiagonalMatrix::Make(fContext, /*offset=*/-1, *type,
John Stilesd8eb8752021-04-01 11:49:10 -0400433 std::move(args[0]));
John Stilese1182782021-03-30 22:09:37 -0400434 }
John Stiles5abb9e12021-04-06 13:47:19 -0400435 case Rehydrator::kConstructorMatrixResize_Command: {
436 const Type* type = this->type();
437 ExpressionArray args = this->expressionArray();
438 SkASSERT(args.size() == 1);
439 return ConstructorMatrixResize::Make(fContext, /*offset=*/-1, *type,
440 std::move(args[0]));
441 }
John Stilesfd7252f2021-04-04 22:24:40 -0400442 case Rehydrator::kConstructorScalarCast_Command: {
443 const Type* type = this->type();
444 ExpressionArray args = this->expressionArray();
445 SkASSERT(args.size() == 1);
446 return ConstructorScalarCast::Make(fContext, /*offset=*/-1, *type, std::move(args[0]));
447 }
John Stiles2938eea2021-04-01 18:58:25 -0400448 case Rehydrator::kConstructorSplat_Command: {
449 const Type* type = this->type();
450 ExpressionArray args = this->expressionArray();
451 SkASSERT(args.size() == 1);
452 return ConstructorSplat::Make(fContext, /*offset=*/-1, *type, std::move(args[0]));
453 }
John Stilesd47330f2021-04-08 23:25:52 -0400454 case Rehydrator::kConstructorStruct_Command: {
455 const Type* type = this->type();
456 return ConstructorStruct::Make(fContext, /*offset=*/-1, *type, this->expressionArray());
457 }
John Stiles8cad6372021-04-07 12:31:13 -0400458 case Rehydrator::kConstructorCompoundCast_Command: {
John Stilesb14a8192021-04-05 11:40:46 -0400459 const Type* type = this->type();
460 ExpressionArray args = this->expressionArray();
461 SkASSERT(args.size() == 1);
John Stiles8cad6372021-04-07 12:31:13 -0400462 return ConstructorCompoundCast::Make(fContext,/*offset=*/-1, *type, std::move(args[0]));
John Stilesb14a8192021-04-05 11:40:46 -0400463 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400464 case Rehydrator::kFieldAccess_Command: {
465 std::unique_ptr<Expression> base = this->expression();
466 int index = this->readU8();
467 FieldAccess::OwnerKind ownerKind = (FieldAccess::OwnerKind) this->readU8();
John Stiles06d600f2021-03-08 09:18:21 -0500468 return FieldAccess::Make(fContext, std::move(base), index, ownerKind);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400469 }
470 case Rehydrator::kFloatLiteral_Command: {
Brian Osmanfb964a42020-11-18 10:45:52 -0500471 const Type* type = this->type();
John Stiles7591d4b2021-09-13 13:32:06 -0400472 int32_t floatBits = this->readS32();
473 float value;
474 memcpy(&value, &floatBits, sizeof(value));
475 return Literal::MakeFloat(/*offset=*/-1, value, type);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400476 }
477 case Rehydrator::kFunctionCall_Command: {
Ethan Nicholas30d30222020-09-11 12:27:26 -0400478 const Type* type = this->type();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400479 const FunctionDeclaration* f = this->symbolRef<FunctionDeclaration>(
Ethan Nicholase6592142020-09-08 10:22:09 -0400480 Symbol::Kind::kFunctionDeclaration);
John Stilesd8eb8752021-04-01 11:49:10 -0400481 ExpressionArray args = this->expressionArray();
John Stilescd7ba502021-03-19 10:54:59 -0400482 return FunctionCall::Make(fContext, /*offset=*/-1, type, *f, std::move(args));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400483 }
484 case Rehydrator::kIndex_Command: {
485 std::unique_ptr<Expression> base = this->expression();
486 std::unique_ptr<Expression> index = this->expression();
John Stiles51d33982021-03-08 09:18:07 -0500487 return IndexExpression::Make(fContext, std::move(base), std::move(index));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400488 }
489 case Rehydrator::kIntLiteral_Command: {
Brian Osmanfb964a42020-11-18 10:45:52 -0500490 const Type* type = this->type();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400491 int value = this->readS32();
John Stiles7591d4b2021-09-13 13:32:06 -0400492 return Literal::MakeInt(/*offset=*/-1, value, type);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400493 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400494 case Rehydrator::kPostfix_Command: {
495 Token::Kind op = (Token::Kind) this->readU8();
496 std::unique_ptr<Expression> operand = this->expression();
John Stiles52d3b012021-02-26 15:56:48 -0500497 return PostfixExpression::Make(fContext, std::move(operand), op);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400498 }
499 case Rehydrator::kPrefix_Command: {
500 Token::Kind op = (Token::Kind) this->readU8();
501 std::unique_ptr<Expression> operand = this->expression();
John Stilesb0eb20f2021-02-26 15:29:33 -0500502 return PrefixExpression::Make(fContext, op, std::move(operand));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400503 }
504 case Rehydrator::kSetting_Command: {
Ethan Nicholasd2e09602021-06-10 11:21:59 -0400505 String name(this->readString());
John Stiles23521a82021-03-02 17:02:51 -0500506 return Setting::Convert(fContext, /*offset=*/-1, name);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400507 }
508 case Rehydrator::kSwizzle_Command: {
509 std::unique_ptr<Expression> base = this->expression();
510 int count = this->readU8();
John Stiles750109b2020-10-30 13:45:46 -0400511 ComponentArray components;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400512 for (int i = 0; i < count; ++i) {
513 components.push_back(this->readU8());
514 }
John Stiles23521a82021-03-02 17:02:51 -0500515 return Swizzle::Make(fContext, std::move(base), components);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400516 }
517 case Rehydrator::kTernary_Command: {
518 std::unique_ptr<Expression> test = this->expression();
519 std::unique_ptr<Expression> ifTrue = this->expression();
520 std::unique_ptr<Expression> ifFalse = this->expression();
John Stiles90518f72021-02-26 20:44:54 -0500521 return TernaryExpression::Make(fContext, std::move(test),
522 std::move(ifTrue), std::move(ifFalse));
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400523 }
524 case Rehydrator::kVariableReference_Command: {
Ethan Nicholase6592142020-09-08 10:22:09 -0400525 const Variable* var = this->symbolRef<Variable>(Symbol::Kind::kVariable);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400526 VariableReference::RefKind refKind = (VariableReference::RefKind) this->readU8();
John Stilesa94e0262021-04-27 17:29:59 -0400527 return VariableReference::Make(/*offset=*/-1, var, refKind);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400528 }
529 case Rehydrator::kVoid_Command:
530 return nullptr;
531 default:
532 printf("unsupported expression %d\n", kind);
533 SkASSERT(false);
534 return nullptr;
535 }
536}
537
Brian Osman1313d1a2020-09-08 10:34:30 -0400538std::shared_ptr<SymbolTable> Rehydrator::symbolTable(bool inherit) {
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400539 int command = this->readU8();
540 if (command == kVoid_Command) {
541 return nullptr;
542 }
543 SkASSERT(command == kSymbolTable_Command);
544 uint16_t ownedCount = this->readU16();
Brian Osman1313d1a2020-09-08 10:34:30 -0400545 std::shared_ptr<SymbolTable> oldTable = fSymbolTable;
John Stiles7c3515b2020-10-16 18:38:39 -0400546 std::shared_ptr<SymbolTable> result =
547 inherit ? std::make_shared<SymbolTable>(fSymbolTable, /*builtin=*/true)
Ethan Nicholasc7774a72021-08-27 15:34:05 -0400548 : std::make_shared<SymbolTable>(fContext, /*builtin=*/true);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400549 fSymbolTable = result;
Brian Osman5bf3e202020-10-13 10:34:18 -0400550 std::vector<const Symbol*> ownedSymbols;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400551 ownedSymbols.reserve(ownedCount);
552 for (int i = 0; i < ownedCount; ++i) {
553 ownedSymbols.push_back(this->symbol());
554 }
555 uint16_t symbolCount = this->readU16();
Ethan Nicholas962dec42021-06-10 13:06:39 -0400556 std::vector<std::pair<skstd::string_view, int>> symbols;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400557 symbols.reserve(symbolCount);
558 for (int i = 0; i < symbolCount; ++i) {
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400559 int index = this->readU16();
John Stilesb8cc6652020-10-08 09:12:07 -0400560 fSymbolTable->addWithoutOwnership(ownedSymbols[index]);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400561 }
Brian Osman1313d1a2020-09-08 10:34:30 -0400562 fSymbolTable = oldTable;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400563 return result;
564}
565
John Stilesa6841be2020-08-06 14:11:56 -0400566} // namespace SkSL