blob: 6c4c6b3f6f52fec35b98613f49ae7a19d5500be8 [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/SkSLDehydrator.h"
9
John Stiles810c8cf2020-08-26 19:46:27 -040010#include <map>
11
Ethan Nicholasc18bb512020-07-28 14:46:53 -040012#include "src/sksl/SkSLRehydrator.h"
13#include "src/sksl/ir/SkSLBinaryExpression.h"
14#include "src/sksl/ir/SkSLBreakStatement.h"
15#include "src/sksl/ir/SkSLConstructor.h"
16#include "src/sksl/ir/SkSLContinueStatement.h"
17#include "src/sksl/ir/SkSLDiscardStatement.h"
18#include "src/sksl/ir/SkSLDoStatement.h"
19#include "src/sksl/ir/SkSLEnum.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/SkSLForStatement.h"
24#include "src/sksl/ir/SkSLFunctionCall.h"
25#include "src/sksl/ir/SkSLFunctionDeclaration.h"
26#include "src/sksl/ir/SkSLFunctionDefinition.h"
27#include "src/sksl/ir/SkSLIfStatement.h"
28#include "src/sksl/ir/SkSLIndexExpression.h"
John Stiles98c1f822020-09-09 14:18:53 -040029#include "src/sksl/ir/SkSLInlineMarker.h"
Ethan Nicholasc18bb512020-07-28 14:46:53 -040030#include "src/sksl/ir/SkSLIntLiteral.h"
31#include "src/sksl/ir/SkSLInterfaceBlock.h"
32#include "src/sksl/ir/SkSLNullLiteral.h"
33#include "src/sksl/ir/SkSLPostfixExpression.h"
34#include "src/sksl/ir/SkSLPrefixExpression.h"
35#include "src/sksl/ir/SkSLProgramElement.h"
36#include "src/sksl/ir/SkSLReturnStatement.h"
37#include "src/sksl/ir/SkSLSetting.h"
38#include "src/sksl/ir/SkSLStatement.h"
39#include "src/sksl/ir/SkSLSwitchCase.h"
40#include "src/sksl/ir/SkSLSwitchStatement.h"
41#include "src/sksl/ir/SkSLSwizzle.h"
42#include "src/sksl/ir/SkSLSymbol.h"
43#include "src/sksl/ir/SkSLSymbolTable.h"
44#include "src/sksl/ir/SkSLTernaryExpression.h"
45#include "src/sksl/ir/SkSLUnresolvedFunction.h"
46#include "src/sksl/ir/SkSLVarDeclarations.h"
47#include "src/sksl/ir/SkSLVarDeclarationsStatement.h"
48#include "src/sksl/ir/SkSLVariable.h"
49#include "src/sksl/ir/SkSLWhileStatement.h"
50
51#ifdef SKSL_STANDALONE
52
53namespace SkSL {
54
55static constexpr int HEADER_SIZE = 2;
56
57class AutoDehydratorSymbolTable {
58public:
59 AutoDehydratorSymbolTable(Dehydrator* dehydrator, const std::shared_ptr<SymbolTable>& symbols)
60 : fDehydrator(dehydrator) {
61 dehydrator->fSymbolMap.emplace_back();
62 if (symbols) {
63 dehydrator->write(*symbols);
64 } else {
65 dehydrator->writeU8(Rehydrator::kVoid_Command);
66 }
67 }
68
69 ~AutoDehydratorSymbolTable() {
70 fDehydrator->fSymbolMap.pop_back();
71 }
72
73private:
74 Dehydrator* fDehydrator;
75};
76
77void Dehydrator::write(Layout l) {
78 if (l == Layout()) {
79 this->writeU8(Rehydrator::kDefaultLayout_Command);
80 } else if (l == Layout::builtin(l.fBuiltin)) {
81 this->writeS8(Rehydrator::kBuiltinLayout_Command);
82 this->writeS16(l.fBuiltin);
83 } else {
84 this->writeS8(Rehydrator::kLayout_Command);
85 fBody.write32(l.fFlags);
86 this->writeS8(l.fLocation);
87 this->writeS8(l.fOffset);
88 this->writeS8(l.fBinding);
89 this->writeS8(l.fIndex);
90 this->writeS8(l.fSet);
91 this->writeS16(l.fBuiltin);
92 this->writeS8(l.fInputAttachmentIndex);
93 this->writeS8((int) l.fFormat);
94 this->writeS8(l.fPrimitive);
95 this->writeS8(l.fMaxVertices);
96 this->writeS8(l.fInvocations);
97 this->write(l.fMarker);
98 this->write(l.fWhen);
99 this->writeS8(l.fKey);
100 this->writeS8((int) l.fCType);
101 }
102}
103
104void Dehydrator::write(Modifiers m) {
105 if (m == Modifiers()) {
106 this->writeU8(Rehydrator::kDefaultModifiers_Command);
107 } else {
108 if (m.fFlags <= 255) {
109 this->writeU8(Rehydrator::kModifiers8Bit_Command);
110 this->write(m.fLayout);
111 this->writeU8(m.fFlags);
112 } else {
113 this->writeU8(Rehydrator::kModifiers_Command);
114 this->write(m.fLayout);
115 this->writeS32(m.fFlags);
116 }
117 }
118}
119
120void Dehydrator::write(StringFragment s) {
121 this->write(String(s));
122}
123
124void Dehydrator::write(String s) {
125 auto found = fStrings.find(s);
126 int offset;
127 if (found == fStrings.end()) {
128 offset = fStringBuffer.str().length() + HEADER_SIZE;
129 fStrings.insert({ s, offset });
130 SkASSERT(s.length() <= 255);
131 fStringBuffer.write8(s.length());
132 fStringBuffer.writeString(s);
133 } else {
134 offset = found->second;
135 }
136 this->writeU16(offset);
137}
138
139void Dehydrator::write(const Symbol& s) {
140 uint16_t id = this->symbolId(&s, false);
141 if (id) {
142 this->writeU8(Rehydrator::kSymbolRef_Command);
143 this->writeU16(id);
144 return;
145 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400146 switch (s.kind()) {
147 case Symbol::Kind::kFunctionDeclaration: {
John Stiles17c5b702020-08-18 10:40:03 -0400148 const FunctionDeclaration& f = s.as<FunctionDeclaration>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400149 this->writeU8(Rehydrator::kFunctionDeclaration_Command);
150 this->writeId(&f);
151 this->write(f.fModifiers);
Ethan Nicholase2c49992020-10-05 11:49:11 -0400152 this->write(f.name());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400153 this->writeU8(f.fParameters.size());
154 for (const Variable* p : f.fParameters) {
155 this->writeU16(this->symbolId(p));
156 }
157 this->write(f.fReturnType);
158 break;
159 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400160 case Symbol::Kind::kUnresolvedFunction: {
John Stiles17c5b702020-08-18 10:40:03 -0400161 const UnresolvedFunction& f = s.as<UnresolvedFunction>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400162 this->writeU8(Rehydrator::kUnresolvedFunction_Command);
163 this->writeId(&f);
164 this->writeU8(f.fFunctions.size());
John Stilesf621e232020-08-25 13:33:02 -0400165 for (const FunctionDeclaration* funcDecl : f.fFunctions) {
166 this->write(*funcDecl);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400167 }
168 break;
169 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400170 case Symbol::Kind::kType: {
John Stiles17c5b702020-08-18 10:40:03 -0400171 const Type& t = s.as<Type>();
Ethan Nicholase6592142020-09-08 10:22:09 -0400172 switch (t.typeKind()) {
173 case Type::TypeKind::kArray:
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400174 this->writeU8(Rehydrator::kArrayType_Command);
175 this->writeId(&t);
176 this->write(t.componentType());
Brian Osmane8c26082020-10-01 17:22:45 -0400177 this->writeS8(t.columns());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400178 break;
Ethan Nicholase6592142020-09-08 10:22:09 -0400179 case Type::TypeKind::kEnum:
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400180 this->writeU8(Rehydrator::kEnumType_Command);
181 this->writeId(&t);
Ethan Nicholase2c49992020-10-05 11:49:11 -0400182 this->write(t.name());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400183 break;
Ethan Nicholase6592142020-09-08 10:22:09 -0400184 case Type::TypeKind::kNullable:
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400185 this->writeU8(Rehydrator::kNullableType_Command);
186 this->writeId(&t);
187 this->write(t.componentType());
188 break;
Ethan Nicholase6592142020-09-08 10:22:09 -0400189 case Type::TypeKind::kStruct:
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400190 this->writeU8(Rehydrator::kStructType_Command);
191 this->writeId(&t);
Ethan Nicholase2c49992020-10-05 11:49:11 -0400192 this->write(t.name());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400193 this->writeU8(t.fields().size());
194 for (const Type::Field& f : t.fields()) {
195 this->write(f.fModifiers);
196 this->write(f.fName);
197 this->write(*f.fType);
198 }
199 break;
200 default:
201 this->writeU8(Rehydrator::kSystemType_Command);
202 this->writeId(&t);
Ethan Nicholase2c49992020-10-05 11:49:11 -0400203 this->write(t.name());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400204 }
205 break;
206 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400207 case Symbol::Kind::kVariable: {
John Stiles17c5b702020-08-18 10:40:03 -0400208 const Variable& v = s.as<Variable>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400209 this->writeU8(Rehydrator::kVariable_Command);
210 this->writeId(&v);
211 this->write(v.fModifiers);
Ethan Nicholase2c49992020-10-05 11:49:11 -0400212 this->write(v.name());
Ethan Nicholas30d30222020-09-11 12:27:26 -0400213 this->write(v.type());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400214 this->writeU8(v.fStorage);
215 break;
216 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400217 case Symbol::Kind::kField: {
John Stiles17c5b702020-08-18 10:40:03 -0400218 const Field& f = s.as<Field>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400219 this->writeU8(Rehydrator::kField_Command);
Ethan Nicholase2c49992020-10-05 11:49:11 -0400220 this->writeU16(this->symbolId(&f.owner()));
221 this->writeU8(f.fieldIndex());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400222 break;
223 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400224 case Symbol::Kind::kExternal:
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400225 SkASSERT(false);
226 break;
227 }
228}
229
230void Dehydrator::write(const SymbolTable& symbols) {
231 this->writeU8(Rehydrator::kSymbolTable_Command);
232 this->writeU16(symbols.fOwnedSymbols.size());
233 for (const std::unique_ptr<const Symbol>& s : symbols.fOwnedSymbols) {
234 this->write(*s);
235 }
236 this->writeU16(symbols.fSymbols.size());
Ethan Nicholas7154b742020-07-31 13:18:02 -0400237 std::map<StringFragment, const Symbol*> ordered;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400238 for (std::pair<StringFragment, const Symbol*> p : symbols.fSymbols) {
Ethan Nicholas7154b742020-07-31 13:18:02 -0400239 ordered.insert(p);
240 }
241 for (std::pair<StringFragment, const Symbol*> p : ordered) {
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400242 this->write(p.first);
243 bool found = false;
244 for (size_t i = 0; i < symbols.fOwnedSymbols.size(); ++i) {
245 if (symbols.fOwnedSymbols[i].get() == p.second) {
246 this->writeU16(i);
247 found = true;
248 break;
249 }
250 }
251 SkASSERT(found);
252 }
253}
254
255void Dehydrator::write(const Expression* e) {
256 if (e) {
Ethan Nicholase6592142020-09-08 10:22:09 -0400257 switch (e->kind()) {
258 case Expression::Kind::kBinary: {
John Stiles81365af2020-08-18 09:24:00 -0400259 const BinaryExpression& b = e->as<BinaryExpression>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400260 this->writeU8(Rehydrator::kBinary_Command);
Ethan Nicholasc8d9c8e2020-09-22 15:05:37 -0400261 this->write(&b.left());
262 this->writeU8((int) b.getOperator());
263 this->write(&b.right());
Ethan Nicholas30d30222020-09-11 12:27:26 -0400264 this->write(b.type());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400265 break;
266 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400267 case Expression::Kind::kBoolLiteral: {
John Stiles81365af2020-08-18 09:24:00 -0400268 const BoolLiteral& b = e->as<BoolLiteral>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400269 this->writeU8(Rehydrator::kBoolLiteral_Command);
Ethan Nicholas59d660c2020-09-28 09:18:15 -0400270 this->writeU8(b.value());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400271 break;
272 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400273 case Expression::Kind::kConstructor: {
John Stiles81365af2020-08-18 09:24:00 -0400274 const Constructor& c = e->as<Constructor>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400275 this->writeU8(Rehydrator::kConstructor_Command);
Ethan Nicholas30d30222020-09-11 12:27:26 -0400276 this->write(c.type());
Ethan Nicholasf70f0442020-09-29 12:41:35 -0400277 this->writeU8(c.arguments().size());
278 for (const auto& a : c.arguments()) {
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400279 this->write(a.get());
280 }
281 break;
282 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400283 case Expression::Kind::kExternalFunctionCall:
284 case Expression::Kind::kExternalValue:
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400285 // not implemented; doesn't seem like we'll ever need them from within an include
286 // file
287 SkASSERT(false);
288 break;
Ethan Nicholase6592142020-09-08 10:22:09 -0400289 case Expression::Kind::kFieldAccess: {
John Stiles81365af2020-08-18 09:24:00 -0400290 const FieldAccess& f = e->as<FieldAccess>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400291 this->writeU8(Rehydrator::kFieldAccess_Command);
292 this->write(f.fBase.get());
293 this->writeU8(f.fFieldIndex);
294 this->writeU8(f.fOwnerKind);
295 break;
296 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400297 case Expression::Kind::kFloatLiteral: {
John Stiles81365af2020-08-18 09:24:00 -0400298 const FloatLiteral& f = e->as<FloatLiteral>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400299 this->writeU8(Rehydrator::kFloatLiteral_Command);
300 FloatIntUnion u;
Ethan Nicholasa3f22f12020-10-01 12:13:17 -0400301 u.fFloat = f.value();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400302 this->writeS32(u.fInt);
303 break;
304 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400305 case Expression::Kind::kFunctionCall: {
John Stiles81365af2020-08-18 09:24:00 -0400306 const FunctionCall& f = e->as<FunctionCall>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400307 this->writeU8(Rehydrator::kFunctionCall_Command);
Ethan Nicholas30d30222020-09-11 12:27:26 -0400308 this->write(f.type());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400309 this->writeId(&f.fFunction);
310 this->writeU8(f.fArguments.size());
311 for (const auto& a : f.fArguments) {
312 this->write(a.get());
313 }
314 break;
315 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400316 case Expression::Kind::kIndex: {
John Stiles81365af2020-08-18 09:24:00 -0400317 const IndexExpression& i = e->as<IndexExpression>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400318 this->writeU8(Rehydrator::kIndex_Command);
319 this->write(i.fBase.get());
320 this->write(i.fIndex.get());
321 break;
322 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400323 case Expression::Kind::kIntLiteral: {
John Stiles81365af2020-08-18 09:24:00 -0400324 const IntLiteral& i = e->as<IntLiteral>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400325 this->writeU8(Rehydrator::kIntLiteral_Command);
Ethan Nicholase96cdd12020-09-28 16:27:18 -0400326 this->writeS32(i.value());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400327 break;
328 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400329 case Expression::Kind::kNullLiteral:
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400330 this->writeU8(Rehydrator::kNullLiteral_Command);
331 break;
Ethan Nicholase6592142020-09-08 10:22:09 -0400332 case Expression::Kind::kPostfix: {
John Stiles81365af2020-08-18 09:24:00 -0400333 const PostfixExpression& p = e->as<PostfixExpression>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400334 this->writeU8(Rehydrator::kPostfix_Command);
335 this->writeU8((int) p.fOperator);
336 this->write(p.fOperand.get());
337 break;
338 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400339 case Expression::Kind::kPrefix: {
John Stiles81365af2020-08-18 09:24:00 -0400340 const PrefixExpression& p = e->as<PrefixExpression>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400341 this->writeU8(Rehydrator::kPrefix_Command);
342 this->writeU8((int) p.fOperator);
343 this->write(p.fOperand.get());
344 break;
345 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400346 case Expression::Kind::kSetting: {
John Stiles81365af2020-08-18 09:24:00 -0400347 const Setting& s = e->as<Setting>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400348 this->writeU8(Rehydrator::kSetting_Command);
349 this->write(s.fName);
350 this->write(s.fValue.get());
351 break;
352 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400353 case Expression::Kind::kSwizzle: {
John Stiles81365af2020-08-18 09:24:00 -0400354 const Swizzle& s = e->as<Swizzle>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400355 this->writeU8(Rehydrator::kSwizzle_Command);
356 this->write(s.fBase.get());
357 this->writeU8(s.fComponents.size());
358 for (int c : s.fComponents) {
359 this->writeU8(c);
360 }
361 break;
362 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400363 case Expression::Kind::kTernary: {
John Stiles81365af2020-08-18 09:24:00 -0400364 const TernaryExpression& t = e->as<TernaryExpression>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400365 this->writeU8(Rehydrator::kTernary_Command);
366 this->write(t.fTest.get());
367 this->write(t.fIfTrue.get());
368 this->write(t.fIfFalse.get());
369 break;
370 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400371 case Expression::Kind::kVariableReference: {
John Stiles81365af2020-08-18 09:24:00 -0400372 const VariableReference& v = e->as<VariableReference>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400373 this->writeU8(Rehydrator::kVariableReference_Command);
Brian Osman79457ef2020-09-24 15:01:27 -0400374 this->writeId(v.fVariable);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400375 this->writeU8(v.fRefKind);
376 break;
377 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400378 case Expression::Kind::kFunctionReference:
379 case Expression::Kind::kTypeReference:
380 case Expression::Kind::kDefined:
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400381 // shouldn't appear in finished code
382 SkASSERT(false);
383 break;
384 }
385 } else {
386 this->writeU8(Rehydrator::kVoid_Command);
387 }
388}
389
390void Dehydrator::write(const Statement* s) {
391 if (s) {
Ethan Nicholase6592142020-09-08 10:22:09 -0400392 switch (s->kind()) {
393 case Statement::Kind::kBlock: {
John Stiles26f98502020-08-18 09:30:51 -0400394 const Block& b = s->as<Block>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400395 this->writeU8(Rehydrator::kBlock_Command);
Ethan Nicholas7bd60432020-09-25 14:31:59 -0400396 AutoDehydratorSymbolTable symbols(this, b.symbolTable());
397 this->writeU8(b.children().size());
398 for (const std::unique_ptr<Statement>& blockStmt : b.children()) {
John Stilesf621e232020-08-25 13:33:02 -0400399 this->write(blockStmt.get());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400400 }
Ethan Nicholas7bd60432020-09-25 14:31:59 -0400401 this->writeU8(b.isScope());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400402 break;
403 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400404 case Statement::Kind::kBreak:
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400405 this->writeU8(Rehydrator::kBreak_Command);
406 break;
Ethan Nicholase6592142020-09-08 10:22:09 -0400407 case Statement::Kind::kContinue:
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400408 this->writeU8(Rehydrator::kContinue_Command);
409 break;
Ethan Nicholase6592142020-09-08 10:22:09 -0400410 case Statement::Kind::kDiscard:
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400411 this->writeU8(Rehydrator::kDiscard_Command);
412 break;
Ethan Nicholase6592142020-09-08 10:22:09 -0400413 case Statement::Kind::kDo: {
John Stiles26f98502020-08-18 09:30:51 -0400414 const DoStatement& d = s->as<DoStatement>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400415 this->writeU8(Rehydrator::kDo_Command);
Ethan Nicholas1fd61162020-09-28 13:14:19 -0400416 this->write(d.statement().get());
417 this->write(d.test().get());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400418 break;
419 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400420 case Statement::Kind::kExpression: {
John Stiles26f98502020-08-18 09:30:51 -0400421 const ExpressionStatement& e = s->as<ExpressionStatement>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400422 this->writeU8(Rehydrator::kExpressionStatement_Command);
Ethan Nicholasd503a5a2020-09-30 09:29:55 -0400423 this->write(e.expression().get());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400424 break;
425 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400426 case Statement::Kind::kFor: {
John Stiles26f98502020-08-18 09:30:51 -0400427 const ForStatement& f = s->as<ForStatement>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400428 this->writeU8(Rehydrator::kFor_Command);
Ethan Nicholas0d31ed52020-10-05 14:47:09 -0400429 this->write(f.initializer().get());
430 this->write(f.test().get());
431 this->write(f.next().get());
432 this->write(f.statement().get());
433 this->write(f.symbols());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400434 break;
435 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400436 case Statement::Kind::kIf: {
John Stiles26f98502020-08-18 09:30:51 -0400437 const IfStatement& i = s->as<IfStatement>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400438 this->writeU8(Rehydrator::kIf_Command);
439 this->writeU8(i.fIsStatic);
440 this->write(i.fTest.get());
441 this->write(i.fIfTrue.get());
442 this->write(i.fIfFalse.get());
443 break;
444 }
John Stiles98c1f822020-09-09 14:18:53 -0400445 case Statement::Kind::kInlineMarker: {
446 const InlineMarker& i = s->as<InlineMarker>();
447 this->writeU8(Rehydrator::kInlineMarker_Command);
448 this->writeId(i.fFuncDecl);
449 break;
450 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400451 case Statement::Kind::kNop:
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400452 SkASSERT(false);
453 break;
Ethan Nicholase6592142020-09-08 10:22:09 -0400454 case Statement::Kind::kReturn: {
John Stiles26f98502020-08-18 09:30:51 -0400455 const ReturnStatement& r = s->as<ReturnStatement>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400456 this->writeU8(Rehydrator::kReturn_Command);
457 this->write(r.fExpression.get());
458 break;
459 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400460 case Statement::Kind::kSwitch: {
John Stiles26f98502020-08-18 09:30:51 -0400461 const SwitchStatement& ss = s->as<SwitchStatement>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400462 this->writeU8(Rehydrator::kSwitch_Command);
463 this->writeU8(ss.fIsStatic);
464 AutoDehydratorSymbolTable symbols(this, ss.fSymbols);
465 this->write(ss.fValue.get());
466 this->writeU8(ss.fCases.size());
John Stilesf621e232020-08-25 13:33:02 -0400467 for (const std::unique_ptr<SwitchCase>& sc : ss.fCases) {
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400468 this->write(sc->fValue.get());
469 this->writeU8(sc->fStatements.size());
John Stilesf621e232020-08-25 13:33:02 -0400470 for (const std::unique_ptr<Statement>& stmt : sc->fStatements) {
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400471 this->write(stmt.get());
472 }
473 }
474 break;
475 }
Brian Osman9eb848a2020-09-11 15:53:40 -0400476 case Statement::Kind::kSwitchCase:
477 SkASSERT(false);
478 break;
Ethan Nicholase6592142020-09-08 10:22:09 -0400479 case Statement::Kind::kVarDeclaration: {
John Stiles26f98502020-08-18 09:30:51 -0400480 const VarDeclaration& v = s->as<VarDeclaration>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400481 this->writeU8(Rehydrator::kVarDeclaration_Command);
482 this->writeU16(this->symbolId(v.fVar));
483 this->writeU8(v.fSizes.size());
John Stilesf621e232020-08-25 13:33:02 -0400484 for (const std::unique_ptr<Expression>& sizeExpr : v.fSizes) {
485 this->write(sizeExpr.get());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400486 }
487 this->write(v.fValue.get());
488 break;
489 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400490 case Statement::Kind::kVarDeclarations: {
John Stiles26f98502020-08-18 09:30:51 -0400491 const VarDeclarationsStatement& v = s->as<VarDeclarationsStatement>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400492 this->write(*v.fDeclaration);
493 break;
494 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400495 case Statement::Kind::kWhile: {
John Stiles26f98502020-08-18 09:30:51 -0400496 const WhileStatement& w = s->as<WhileStatement>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400497 this->writeU8(Rehydrator::kWhile_Command);
498 this->write(w.fTest.get());
499 this->write(w.fStatement.get());
500 break;
501 }
502 }
503 } else {
504 this->writeU8(Rehydrator::kVoid_Command);
505 }
506}
507
508void Dehydrator::write(const ProgramElement& e) {
Ethan Nicholase6592142020-09-08 10:22:09 -0400509 switch (e.kind()) {
510 case ProgramElement::Kind::kEnum: {
John Stiles3dc0da62020-08-19 17:48:31 -0400511 const Enum& en = e.as<Enum>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400512 this->writeU8(Rehydrator::kEnum_Command);
Ethan Nicholasd83ded82020-09-29 17:05:54 -0400513 this->write(en.typeName());
514 AutoDehydratorSymbolTable symbols(this, en.symbols());
515 for (const std::unique_ptr<const Symbol>& s : en.symbols()->fOwnedSymbols) {
Ethan Nicholase6592142020-09-08 10:22:09 -0400516 SkASSERT(s->kind() == Symbol::Kind::kVariable);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400517 Variable& v = (Variable&) *s;
John Stiles81365af2020-08-18 09:24:00 -0400518 SkASSERT(v.fInitialValue);
519 const IntLiteral& i = v.fInitialValue->as<IntLiteral>();
Ethan Nicholase96cdd12020-09-28 16:27:18 -0400520 this->writeS32(i.value());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400521 }
522 break;
523 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400524 case ProgramElement::Kind::kExtension:
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400525 SkASSERT(false);
526 break;
Ethan Nicholase6592142020-09-08 10:22:09 -0400527 case ProgramElement::Kind::kFunction: {
John Stiles3dc0da62020-08-19 17:48:31 -0400528 const FunctionDefinition& f = e.as<FunctionDefinition>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400529 this->writeU8(Rehydrator::kFunctionDefinition_Command);
530 this->writeU16(this->symbolId(&f.fDeclaration));
531 this->write(f.fBody.get());
532 this->writeU8(f.fReferencedIntrinsics.size());
Ethan Nicholas7154b742020-07-31 13:18:02 -0400533 std::set<uint16_t> ordered;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400534 for (const FunctionDeclaration* ref : f.fReferencedIntrinsics) {
Ethan Nicholas7154b742020-07-31 13:18:02 -0400535 ordered.insert(this->symbolId(ref));
536 }
537 for (uint16_t ref : ordered) {
538 this->writeU16(ref);
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400539 }
540 break;
541 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400542 case ProgramElement::Kind::kInterfaceBlock: {
John Stiles3dc0da62020-08-19 17:48:31 -0400543 const InterfaceBlock& i = e.as<InterfaceBlock>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400544 this->writeU8(Rehydrator::kInterfaceBlock_Command);
545 this->write(i.fVariable);
546 this->write(i.fTypeName);
547 this->write(i.fInstanceName);
548 this->writeU8(i.fSizes.size());
549 for (const auto& s : i.fSizes) {
550 this->write(s.get());
551 }
552 break;
553 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400554 case ProgramElement::Kind::kModifiers:
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400555 SkASSERT(false);
556 break;
Ethan Nicholase6592142020-09-08 10:22:09 -0400557 case ProgramElement::Kind::kSection:
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400558 SkASSERT(false);
559 break;
Ethan Nicholase6592142020-09-08 10:22:09 -0400560 case ProgramElement::Kind::kVar: {
John Stiles3dc0da62020-08-19 17:48:31 -0400561 const VarDeclarations& v = e.as<VarDeclarations>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400562 this->writeU8(Rehydrator::kVarDeclarations_Command);
563 this->write(v.fBaseType);
564 this->writeU8(v.fVars.size());
John Stilesf621e232020-08-25 13:33:02 -0400565 for (const auto& var : v.fVars) {
566 this->write(var.get());
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400567 }
568 break;
569 }
570 }
571}
572
573void Dehydrator::write(const std::vector<std::unique_ptr<ProgramElement>>& elements) {
574 this->writeU8(Rehydrator::kElements_Command);
575 this->writeU8(elements.size());
576 for (const auto& e : elements) {
577 this->write(*e);
578 }
579}
580
581void Dehydrator::finish(OutputStream& out) {
582 out.write16(fStringBuffer.str().size());
583 out.writeString(fStringBuffer.str());
584 out.writeString(fBody.str());
585}
586
587} // namespace
588
589#endif