blob: 23d8943b39a5435f1fe6c5b581025d33f4880142 [file] [log] [blame]
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001/*
2 * Copyright 2019 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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/sksl/SkSLByteCodeGenerator.h"
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04009
10namespace SkSL {
11
12static int slot_count(const Type& type) {
13 return type.columns() * type.rows();
14}
15
16bool ByteCodeGenerator::generateCode() {
17 for (const auto& e : fProgram) {
18 switch (e.fKind) {
19 case ProgramElement::kFunction_Kind: {
20 std::unique_ptr<ByteCodeFunction> f = this->writeFunction((FunctionDefinition&) e);
21 if (!f) {
22 return false;
23 }
24 fOutput->fFunctions.push_back(std::move(f));
25 break;
26 }
27 case ProgramElement::kVar_Kind: {
28 VarDeclarations& decl = (VarDeclarations&) e;
29 for (const auto& v : decl.fVars) {
30 const Variable* declVar = ((VarDeclaration&) *v).fVar;
31 if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
32 continue;
33 }
34 if (declVar->fModifiers.fFlags & Modifiers::kIn_Flag) {
35 for (int i = slot_count(declVar->fType); i > 0; --i) {
36 fOutput->fInputSlots.push_back(fOutput->fGlobalCount++);
37 }
38 } else {
39 fOutput->fGlobalCount += slot_count(declVar->fType);
40 }
41 }
42 break;
43 }
44 default:
45 ; // ignore
46 }
47 }
48 return true;
49}
50
51std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
52 fFunction = &f;
53 std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(fOutput, &f.fDeclaration));
54 fParameterCount = 0;
55 for (const auto& p : f.fDeclaration.fParameters) {
56 fParameterCount += p->fType.columns() * p->fType.rows();
57 }
58 fCode = &result->fCode;
59 this->writeStatement(*f.fBody);
Ethan Nicholas7e603db2019-05-03 12:57:47 -040060 this->write(ByteCodeInstruction::kReturn);
61 this->write8(0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040062 result->fParameterCount = fParameterCount;
63 result->fLocalCount = fLocals.size();
64 fLocals.clear();
65 fFunction = nullptr;
66 return result;
67}
68
69enum class TypeCategory {
70 kBool,
71 kSigned,
72 kUnsigned,
73 kFloat,
74};
75
76static TypeCategory type_category(const Type& type) {
77 switch (type.kind()) {
78 case Type::Kind::kVector_Kind:
79 case Type::Kind::kMatrix_Kind:
80 return type_category(type.componentType());
81 default:
82 if (type.fName == "bool") {
83 return TypeCategory::kBool;
84 } else if (type.fName == "int" || type.fName == "short") {
85 return TypeCategory::kSigned;
86 } else if (type.fName == "uint" || type.fName == "ushort") {
87 return TypeCategory::kUnsigned;
88 } else {
89 SkASSERT(type.fName == "float" || type.fName == "half");
90 return TypeCategory::kFloat;
91 }
92 ABORT("unsupported type: %s\n", type.description().c_str());
93 }
94}
95
96int ByteCodeGenerator::getLocation(const Variable& var) {
97 // given that we seldom have more than a couple of variables, linear search is probably the most
98 // efficient way to handle lookups
99 switch (var.fStorage) {
100 case Variable::kLocal_Storage: {
101 for (int i = fLocals.size() - 1; i >= 0; --i) {
102 if (fLocals[i] == &var) {
103 return fParameterCount + i;
104 }
105 }
106 int result = fParameterCount + fLocals.size();
107 fLocals.push_back(&var);
108 for (int i = 0; i < slot_count(var.fType) - 1; ++i) {
109 fLocals.push_back(nullptr);
110 }
111 return result;
112 }
113 case Variable::kParameter_Storage: {
114 int offset = 0;
115 for (const auto& p : fFunction->fDeclaration.fParameters) {
116 if (p == &var) {
117 return offset;
118 }
119 offset += slot_count(p->fType);
120 }
121 SkASSERT(false);
122 return -1;
123 }
124 case Variable::kGlobal_Storage: {
125 int offset = 0;
126 for (const auto& e : fProgram) {
127 if (e.fKind == ProgramElement::kVar_Kind) {
128 VarDeclarations& decl = (VarDeclarations&) e;
129 for (const auto& v : decl.fVars) {
130 const Variable* declVar = ((VarDeclaration&) *v).fVar;
131 if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
132 continue;
133 }
134 if (declVar == &var) {
135 return offset;
136 }
137 offset += slot_count(declVar->fType);
138 }
139 }
140 }
141 SkASSERT(false);
142 return -1;
143 }
144 default:
145 SkASSERT(false);
146 return 0;
147 }
148}
149
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400150void ByteCodeGenerator::align(int divisor, int remainder) {
151 while ((int) fCode->size() % divisor != remainder) {
152 this->write(ByteCodeInstruction::kNop);
153 }
154}
155
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400156void ByteCodeGenerator::write8(uint8_t b) {
157 fCode->push_back(b);
158}
159
160void ByteCodeGenerator::write16(uint16_t i) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400161 SkASSERT(fCode->size() % 2 == 0);
162 this->write8(i >> 0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400163 this->write8(i >> 8);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400164}
165
166void ByteCodeGenerator::write32(uint32_t i) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400167 SkASSERT(fCode->size() % 4 == 0);
Brian Osmane1e988d2019-03-21 14:06:24 -0400168 this->write8((i >> 0) & 0xFF);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400169 this->write8((i >> 8) & 0xFF);
170 this->write8((i >> 16) & 0xFF);
171 this->write8((i >> 24) & 0xFF);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400172}
173
174void ByteCodeGenerator::write(ByteCodeInstruction i) {
175 this->write8((uint8_t) i);
176}
177
178void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
179 ByteCodeInstruction u, ByteCodeInstruction f) {
180 switch (type_category(type)) {
181 case TypeCategory::kSigned:
182 this->write(s);
183 break;
184 case TypeCategory::kUnsigned:
185 this->write(u);
186 break;
187 case TypeCategory::kFloat:
188 this->write(f);
189 break;
190 default:
191 SkASSERT(false);
192 }
193}
194
195void ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b) {
196 if (b.fOperator == Token::Kind::EQ) {
197 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
198 this->writeExpression(*b.fRight);
199 this->write(ByteCodeInstruction::kDupDown);
200 this->write8(slot_count(b.fRight->fType));
201 lvalue->store();
202 return;
203 }
204 Token::Kind op;
205 std::unique_ptr<LValue> lvalue;
206 if (is_assignment(b.fOperator)) {
207 lvalue = this->getLValue(*b.fLeft);
208 lvalue->load();
209 op = remove_assignment(b.fOperator);
210 } else {
211 this->writeExpression(*b.fLeft);
212 op = b.fOperator;
213 if (b.fLeft->fType.kind() == Type::kScalar_Kind &&
214 b.fRight->fType.kind() == Type::kVector_Kind) {
215 for (int i = b.fRight->fType.columns(); i > 1; --i) {
216 this->write(ByteCodeInstruction::kDup);
217 }
218 }
219 }
220 this->writeExpression(*b.fRight);
221 if (b.fLeft->fType.kind() == Type::kVector_Kind &&
222 b.fRight->fType.kind() == Type::kScalar_Kind) {
223 for (int i = b.fLeft->fType.columns(); i > 1; --i) {
224 this->write(ByteCodeInstruction::kDup);
225 }
226 }
227 int count = slot_count(b.fType);
228 if (count > 1) {
229 this->write(ByteCodeInstruction::kVector);
230 this->write8(count);
231 }
232 switch (op) {
233 case Token::Kind::EQEQ:
234 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareIEQ,
235 ByteCodeInstruction::kCompareIEQ,
236 ByteCodeInstruction::kCompareFEQ);
237 break;
238 case Token::Kind::GT:
239 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGT,
240 ByteCodeInstruction::kCompareUGT,
241 ByteCodeInstruction::kCompareFGT);
242 break;
243 case Token::Kind::GTEQ:
244 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGTEQ,
245 ByteCodeInstruction::kCompareUGTEQ,
246 ByteCodeInstruction::kCompareFGTEQ);
247 break;
248 case Token::Kind::LT:
249 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLT,
250 ByteCodeInstruction::kCompareULT,
251 ByteCodeInstruction::kCompareFLT);
252 break;
253 case Token::Kind::LTEQ:
254 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLTEQ,
255 ByteCodeInstruction::kCompareULTEQ,
256 ByteCodeInstruction::kCompareFLTEQ);
257 break;
258 case Token::Kind::MINUS:
259 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kSubtractI,
260 ByteCodeInstruction::kSubtractI,
261 ByteCodeInstruction::kSubtractF);
262 break;
263 case Token::Kind::NEQ:
264 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareINEQ,
265 ByteCodeInstruction::kCompareINEQ,
266 ByteCodeInstruction::kCompareFNEQ);
267 break;
268 case Token::Kind::PERCENT:
269 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kRemainderS,
270 ByteCodeInstruction::kRemainderU,
271 ByteCodeInstruction::kInvalid);
272 break;
273 case Token::Kind::PLUS:
274 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kAddI,
275 ByteCodeInstruction::kAddI,
276 ByteCodeInstruction::kAddF);
277 break;
278 case Token::Kind::SLASH:
279 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kDivideS,
280 ByteCodeInstruction::kDivideU,
281 ByteCodeInstruction::kDivideF);
282 break;
283 case Token::Kind::STAR:
284 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kMultiplyS,
285 ByteCodeInstruction::kMultiplyU,
286 ByteCodeInstruction::kMultiplyF);
287 break;
288 default:
289 SkASSERT(false);
290 }
291 if (lvalue) {
292 this->write(ByteCodeInstruction::kDupDown);
293 this->write8(slot_count(b.fType));
294 lvalue->store();
295 }
296}
297
298void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400299 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400300 this->write(ByteCodeInstruction::kPushImmediate);
301 this->write32(1);
302}
303
304void ByteCodeGenerator::writeConstructor(const Constructor& c) {
305 if (c.fArguments.size() == 1 &&
306 type_category(c.fType) == type_category(c.fArguments[0]->fType)) {
307 // cast from float to half or similar no-op
308 this->writeExpression(*c.fArguments[0]);
309 return;
310 }
311 for (const auto& arg : c.fArguments) {
312 this->writeExpression(*arg);
313 }
314 if (c.fArguments.size() == 1) {
315 TypeCategory inCategory = type_category(c.fArguments[0]->fType);
316 TypeCategory outCategory = type_category(c.fType);
317 if (inCategory != outCategory) {
318 int count = c.fType.columns();
319 if (count > 1) {
320 this->write(ByteCodeInstruction::kVector);
321 this->write8(count);
322 }
323 if (inCategory == TypeCategory::kFloat) {
324 SkASSERT(outCategory == TypeCategory::kSigned ||
325 outCategory == TypeCategory::kUnsigned);
326 this->write(ByteCodeInstruction::kFloatToInt);
327 } else if (outCategory == TypeCategory::kFloat) {
328 if (inCategory == TypeCategory::kSigned) {
329 this->write(ByteCodeInstruction::kSignedToFloat);
330 } else {
331 SkASSERT(inCategory == TypeCategory::kUnsigned);
332 this->write(ByteCodeInstruction::kUnsignedToFloat);
333 }
334 } else {
335 SkASSERT(false);
336 }
337 }
338 }
339}
340
341void ByteCodeGenerator::writeFieldAccess(const FieldAccess& f) {
342 // not yet implemented
343 abort();
344}
345
346void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400347 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400348 this->write(ByteCodeInstruction::kPushImmediate);
349 union { float f; uint32_t u; } pun = { (float) f.fValue };
350 this->write32(pun.u);
351}
352
353void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
354 // not yet implemented
355 abort();
356}
357
358void ByteCodeGenerator::writeIndexExpression(const IndexExpression& i) {
359 // not yet implemented
360 abort();
361}
362
363void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400364 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400365 this->write(ByteCodeInstruction::kPushImmediate);
366 this->write32(i.fValue);
367}
368
369void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
370 // not yet implemented
371 abort();
372}
373
374void ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p) {
375 switch (p.fOperator) {
376 case Token::Kind::PLUSPLUS: // fall through
377 case Token::Kind::MINUSMINUS: {
378 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
379 lvalue->load();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400380 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400381 this->write(ByteCodeInstruction::kPushImmediate);
382 this->write32(1);
383 if (p.fOperator == Token::Kind::PLUSPLUS) {
384 this->writeTypedInstruction(p.fType,
385 ByteCodeInstruction::kAddI,
386 ByteCodeInstruction::kAddI,
387 ByteCodeInstruction::kAddF);
388 } else {
389 this->writeTypedInstruction(p.fType,
390 ByteCodeInstruction::kSubtractI,
391 ByteCodeInstruction::kSubtractI,
392 ByteCodeInstruction::kSubtractF);
393 }
394 this->write(ByteCodeInstruction::kDupDown);
395 this->write8(slot_count(p.fType));
396 lvalue->store();
397 break;
398 }
399 case Token::Kind::MINUS:
400 this->writeTypedInstruction(p.fType,
401 ByteCodeInstruction::kNegateS,
402 ByteCodeInstruction::kInvalid,
403 ByteCodeInstruction::kNegateF);
404 break;
405 default:
406 SkASSERT(false);
407 }
408}
409
410void ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p) {
411 // not yet implemented
412 abort();
413}
414
415void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
416 switch (s.fBase->fKind) {
417 case Expression::kVariableReference_Kind: {
418 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
419 int location = this->getLocation(var);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400420 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400421 this->write(ByteCodeInstruction::kPushImmediate);
422 this->write32(location);
423 this->write(ByteCodeInstruction::kLoadSwizzle);
424 this->write8(s.fComponents.size());
425 for (int c : s.fComponents) {
426 this->write8(c);
427 }
428 break;
429 }
430 default:
431 this->writeExpression(*s.fBase);
432 this->write(ByteCodeInstruction::kSwizzle);
433 this->write8(s.fBase->fType.columns());
434 this->write8(s.fComponents.size());
435 for (int c : s.fComponents) {
436 this->write8(c);
437 }
438 }
439}
440
441void ByteCodeGenerator::writeVariableReference(const VariableReference& v) {
442 if (v.fVariable.fStorage == Variable::kGlobal_Storage) {
443 this->write(ByteCodeInstruction::kLoadGlobal);
444 int location = this->getLocation(v.fVariable);
445 SkASSERT(location <= 255);
446 this->write8(location);
447 } else {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400448 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400449 this->write(ByteCodeInstruction::kPushImmediate);
450 this->write32(this->getLocation(v.fVariable));
451 int count = slot_count(v.fType);
452 if (count > 1) {
453 this->write(ByteCodeInstruction::kVector);
454 this->write8(count);
455 }
456 this->write(ByteCodeInstruction::kLoad);
457 }
458}
459
460void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
461 // not yet implemented
462 abort();
463}
464
465void ByteCodeGenerator::writeExpression(const Expression& e) {
466 switch (e.fKind) {
467 case Expression::kBinary_Kind:
468 this->writeBinaryExpression((BinaryExpression&) e);
469 break;
470 case Expression::kBoolLiteral_Kind:
471 this->writeBoolLiteral((BoolLiteral&) e);
472 break;
473 case Expression::kConstructor_Kind:
474 this->writeConstructor((Constructor&) e);
475 break;
476 case Expression::kFieldAccess_Kind:
477 this->writeFieldAccess((FieldAccess&) e);
478 break;
479 case Expression::kFloatLiteral_Kind:
480 this->writeFloatLiteral((FloatLiteral&) e);
481 break;
482 case Expression::kFunctionCall_Kind:
483 this->writeFunctionCall((FunctionCall&) e);
484 break;
485 case Expression::kIndex_Kind:
486 this->writeIndexExpression((IndexExpression&) e);
487 break;
488 case Expression::kIntLiteral_Kind:
489 this->writeIntLiteral((IntLiteral&) e);
490 break;
491 case Expression::kNullLiteral_Kind:
492 this->writeNullLiteral((NullLiteral&) e);
493 break;
494 case Expression::kPrefix_Kind:
495 this->writePrefixExpression((PrefixExpression&) e);
496 break;
497 case Expression::kPostfix_Kind:
498 this->writePostfixExpression((PostfixExpression&) e);
499 break;
500 case Expression::kSwizzle_Kind:
501 this->writeSwizzle((Swizzle&) e);
502 break;
503 case Expression::kVariableReference_Kind:
504 this->writeVariableReference((VariableReference&) e);
505 break;
506 case Expression::kTernary_Kind:
507 this->writeTernaryExpression((TernaryExpression&) e);
508 break;
509 default:
510 printf("unsupported expression %s\n", e.description().c_str());
511 SkASSERT(false);
512 }
513}
514
515void ByteCodeGenerator::writeTarget(const Expression& e) {
516 switch (e.fKind) {
517 case Expression::kVariableReference_Kind:
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400518 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400519 this->write(ByteCodeInstruction::kPushImmediate);
520 this->write32(this->getLocation(((VariableReference&) e).fVariable));
521 break;
522 case Expression::kIndex_Kind:
523 case Expression::kTernary_Kind:
524 default:
525 printf("unsupported target %s\n", e.description().c_str());
526 SkASSERT(false);
527 }
528}
529
530class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
531public:
532 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
533 : INHERITED(*generator)
534 , fSwizzle(swizzle) {
535 fGenerator.writeTarget(*swizzle.fBase);
536 }
537
538 void load() override {
539 fGenerator.write(ByteCodeInstruction::kDup);
540 fGenerator.write(ByteCodeInstruction::kLoadSwizzle);
541 fGenerator.write8(fSwizzle.fComponents.size());
542 for (int c : fSwizzle.fComponents) {
543 fGenerator.write8(c);
544 }
545 }
546
547 void store() override {
548 fGenerator.write(ByteCodeInstruction::kStoreSwizzle);
549 fGenerator.write8(fSwizzle.fComponents.size());
550 for (int c : fSwizzle.fComponents) {
551 fGenerator.write8(c);
552 }
553 }
554
555private:
556 const Swizzle& fSwizzle;
557
558 typedef LValue INHERITED;
559};
560
561class ByteCodeVariableLValue : public ByteCodeGenerator::LValue {
562public:
563 ByteCodeVariableLValue(ByteCodeGenerator* generator, const Variable& var)
564 : INHERITED(*generator)
565 , fCount(slot_count(var.fType))
566 , fIsGlobal(var.fStorage == Variable::kGlobal_Storage) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400567 fGenerator.align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400568 fGenerator.write(ByteCodeInstruction::kPushImmediate);
569 fGenerator.write32(generator->getLocation(var));
570 }
571
572 void load() override {
573 fGenerator.write(ByteCodeInstruction::kDup);
574 if (fCount > 1) {
575 fGenerator.write(ByteCodeInstruction::kVector);
576 fGenerator.write8(fCount);
577 }
578 fGenerator.write(fIsGlobal ? ByteCodeInstruction::kLoadGlobal : ByteCodeInstruction::kLoad);
579 }
580
581 void store() override {
582 if (fCount > 1) {
583 fGenerator.write(ByteCodeInstruction::kVector);
584 fGenerator.write8(fCount);
585 }
586 fGenerator.write(fIsGlobal ? ByteCodeInstruction::kStoreGlobal
587 : ByteCodeInstruction::kStore);
588 }
589
590private:
591 typedef LValue INHERITED;
592
593 int fCount;
594
595 bool fIsGlobal;
596};
597
598std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
599 switch (e.fKind) {
600 case Expression::kIndex_Kind:
601 // not yet implemented
602 abort();
603 case Expression::kVariableReference_Kind:
604 return std::unique_ptr<LValue>(new ByteCodeVariableLValue(this,
605 ((VariableReference&) e).fVariable));
606 case Expression::kSwizzle_Kind:
607 return std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, (Swizzle&) e));
608 case Expression::kTernary_Kind:
609 default:
610 printf("unsupported lvalue %s\n", e.description().c_str());
611 return nullptr;
612 }
613}
614
615void ByteCodeGenerator::writeBlock(const Block& b) {
616 for (const auto& s : b.fStatements) {
617 this->writeStatement(*s);
618 }
619}
620
621void ByteCodeGenerator::setBreakTargets() {
622 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
623 for (DeferredLocation& b : breaks) {
624 b.set();
625 }
626 fBreakTargets.pop();
627}
628
629void ByteCodeGenerator::setContinueTargets() {
630 std::vector<DeferredLocation>& continues = fContinueTargets.top();
631 for (DeferredLocation& c : continues) {
632 c.set();
633 }
634 fContinueTargets.pop();
635}
636
637void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400638 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400639 this->write(ByteCodeInstruction::kBranch);
640 fBreakTargets.top().emplace_back(this);
641}
642
643void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400644 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400645 this->write(ByteCodeInstruction::kBranch);
646 fContinueTargets.top().emplace_back(this);
647}
648
649void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
650 fContinueTargets.emplace();
651 fBreakTargets.emplace();
652 size_t start = fCode->size();
653 this->writeStatement(*d.fStatement);
654 this->setContinueTargets();
655 this->writeExpression(*d.fTest);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400656 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400657 this->write(ByteCodeInstruction::kConditionalBranch);
658 this->write16(start);
659 this->setBreakTargets();
660}
661
662void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
663 fContinueTargets.emplace();
664 fBreakTargets.emplace();
665 if (f.fInitializer) {
666 this->writeStatement(*f.fInitializer);
667 }
668 size_t start = fCode->size();
669 if (f.fTest) {
670 this->writeExpression(*f.fTest);
671 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400672 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400673 this->write(ByteCodeInstruction::kConditionalBranch);
674 DeferredLocation endLocation(this);
675 this->writeStatement(*f.fStatement);
676 this->setContinueTargets();
677 if (f.fNext) {
678 this->writeExpression(*f.fNext);
679 this->write(ByteCodeInstruction::kPop);
680 this->write8(slot_count(f.fNext->fType));
681 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400682 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400683 this->write(ByteCodeInstruction::kBranch);
684 this->write16(start);
685 endLocation.set();
686 } else {
687 this->writeStatement(*f.fStatement);
688 this->setContinueTargets();
689 if (f.fNext) {
690 this->writeExpression(*f.fNext);
691 this->write(ByteCodeInstruction::kPop);
692 this->write8(slot_count(f.fNext->fType));
693 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400694 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400695 this->write(ByteCodeInstruction::kBranch);
696 this->write16(start);
697 }
698 this->setBreakTargets();
699}
700
701void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
702 this->writeExpression(*i.fTest);
703 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400704 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400705 this->write(ByteCodeInstruction::kConditionalBranch);
706 DeferredLocation elseLocation(this);
707 this->writeStatement(*i.fIfTrue);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400708 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400709 this->write(ByteCodeInstruction::kBranch);
710 DeferredLocation endLocation(this);
711 elseLocation.set();
712 if (i.fIfFalse) {
713 this->writeStatement(*i.fIfFalse);
714 }
715 endLocation.set();
716}
717
718void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -0400719 this->writeExpression(*r.fExpression);
720 this->write(ByteCodeInstruction::kReturn);
721 this->write8(r.fExpression->fType.columns() * r.fExpression->fType.rows());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400722}
723
724void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
725 // not yet implemented
726 abort();
727}
728
729void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
730 for (const auto& declStatement : v.fVars) {
731 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
732 // we need to grab the location even if we don't use it, to ensure it
733 // has been allocated
734 int location = getLocation(*decl.fVar);
735 if (decl.fValue) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400736 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400737 this->write(ByteCodeInstruction::kPushImmediate);
738 this->write32(location);
739 this->writeExpression(*decl.fValue);
740 int count = slot_count(decl.fValue->fType);
741 if (count > 1) {
742 this->write(ByteCodeInstruction::kVector);
743 this->write8(count);
744 }
745 this->write(ByteCodeInstruction::kStore);
746 }
747 }
748}
749
750void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
751 fContinueTargets.emplace();
752 fBreakTargets.emplace();
753 size_t start = fCode->size();
754 this->writeExpression(*w.fTest);
755 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400756 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400757 this->write(ByteCodeInstruction::kConditionalBranch);
758 DeferredLocation endLocation(this);
759 this->writeStatement(*w.fStatement);
760 this->setContinueTargets();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400761 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400762 this->write(ByteCodeInstruction::kBranch);
763 this->write16(start);
764 endLocation.set();
765 this->setBreakTargets();
766}
767
768void ByteCodeGenerator::writeStatement(const Statement& s) {
769 switch (s.fKind) {
770 case Statement::kBlock_Kind:
771 this->writeBlock((Block&) s);
772 break;
773 case Statement::kBreak_Kind:
774 this->writeBreakStatement((BreakStatement&) s);
775 break;
776 case Statement::kContinue_Kind:
777 this->writeContinueStatement((ContinueStatement&) s);
778 break;
779 case Statement::kDiscard_Kind:
780 // not yet implemented
781 abort();
782 case Statement::kDo_Kind:
783 this->writeDoStatement((DoStatement&) s);
784 break;
785 case Statement::kExpression_Kind: {
786 const Expression& expr = *((ExpressionStatement&) s).fExpression;
787 this->writeExpression(expr);
788 this->write(ByteCodeInstruction::kPop);
789 this->write8(slot_count(expr.fType));
790 break;
791 }
792 case Statement::kFor_Kind:
793 this->writeForStatement((ForStatement&) s);
794 break;
795 case Statement::kIf_Kind:
796 this->writeIfStatement((IfStatement&) s);
797 break;
798 case Statement::kNop_Kind:
799 break;
800 case Statement::kReturn_Kind:
801 this->writeReturnStatement((ReturnStatement&) s);
802 break;
803 case Statement::kSwitch_Kind:
804 this->writeSwitchStatement((SwitchStatement&) s);
805 break;
806 case Statement::kVarDeclarations_Kind:
807 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
808 break;
809 case Statement::kWhile_Kind:
810 this->writeWhileStatement((WhileStatement&) s);
811 break;
812 default:
813 SkASSERT(false);
814 }
815}
816
817}