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