blob: 5bf18aa89b8618e1950eb25a8d1d25a027f46694 [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);
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
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400148void ByteCodeGenerator::align(int divisor, int remainder) {
149 while ((int) fCode->size() % divisor != remainder) {
150 this->write(ByteCodeInstruction::kNop);
151 }
152}
153
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400154void ByteCodeGenerator::write8(uint8_t b) {
155 fCode->push_back(b);
156}
157
158void ByteCodeGenerator::write16(uint16_t i) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400159 SkASSERT(fCode->size() % 2 == 0);
160 this->write8(i >> 0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400161 this->write8(i >> 8);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400162}
163
164void ByteCodeGenerator::write32(uint32_t i) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400165 SkASSERT(fCode->size() % 4 == 0);
Brian Osmane1e988d2019-03-21 14:06:24 -0400166 this->write8((i >> 0) & 0xFF);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400167 this->write8((i >> 8) & 0xFF);
168 this->write8((i >> 16) & 0xFF);
169 this->write8((i >> 24) & 0xFF);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400170}
171
172void ByteCodeGenerator::write(ByteCodeInstruction i) {
173 this->write8((uint8_t) i);
174}
175
176void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
177 ByteCodeInstruction u, ByteCodeInstruction f) {
178 switch (type_category(type)) {
179 case TypeCategory::kSigned:
180 this->write(s);
181 break;
182 case TypeCategory::kUnsigned:
183 this->write(u);
184 break;
185 case TypeCategory::kFloat:
186 this->write(f);
187 break;
188 default:
189 SkASSERT(false);
190 }
191}
192
193void ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b) {
194 if (b.fOperator == Token::Kind::EQ) {
195 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
196 this->writeExpression(*b.fRight);
197 this->write(ByteCodeInstruction::kDupDown);
198 this->write8(slot_count(b.fRight->fType));
199 lvalue->store();
200 return;
201 }
202 Token::Kind op;
203 std::unique_ptr<LValue> lvalue;
204 if (is_assignment(b.fOperator)) {
205 lvalue = this->getLValue(*b.fLeft);
206 lvalue->load();
207 op = remove_assignment(b.fOperator);
208 } else {
209 this->writeExpression(*b.fLeft);
210 op = b.fOperator;
211 if (b.fLeft->fType.kind() == Type::kScalar_Kind &&
212 b.fRight->fType.kind() == Type::kVector_Kind) {
213 for (int i = b.fRight->fType.columns(); i > 1; --i) {
214 this->write(ByteCodeInstruction::kDup);
215 }
216 }
217 }
218 this->writeExpression(*b.fRight);
219 if (b.fLeft->fType.kind() == Type::kVector_Kind &&
220 b.fRight->fType.kind() == Type::kScalar_Kind) {
221 for (int i = b.fLeft->fType.columns(); i > 1; --i) {
222 this->write(ByteCodeInstruction::kDup);
223 }
224 }
225 int count = slot_count(b.fType);
226 if (count > 1) {
227 this->write(ByteCodeInstruction::kVector);
228 this->write8(count);
229 }
230 switch (op) {
231 case Token::Kind::EQEQ:
232 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareIEQ,
233 ByteCodeInstruction::kCompareIEQ,
234 ByteCodeInstruction::kCompareFEQ);
235 break;
236 case Token::Kind::GT:
237 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGT,
238 ByteCodeInstruction::kCompareUGT,
239 ByteCodeInstruction::kCompareFGT);
240 break;
241 case Token::Kind::GTEQ:
242 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGTEQ,
243 ByteCodeInstruction::kCompareUGTEQ,
244 ByteCodeInstruction::kCompareFGTEQ);
245 break;
246 case Token::Kind::LT:
247 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLT,
248 ByteCodeInstruction::kCompareULT,
249 ByteCodeInstruction::kCompareFLT);
250 break;
251 case Token::Kind::LTEQ:
252 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLTEQ,
253 ByteCodeInstruction::kCompareULTEQ,
254 ByteCodeInstruction::kCompareFLTEQ);
255 break;
256 case Token::Kind::MINUS:
257 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kSubtractI,
258 ByteCodeInstruction::kSubtractI,
259 ByteCodeInstruction::kSubtractF);
260 break;
261 case Token::Kind::NEQ:
262 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareINEQ,
263 ByteCodeInstruction::kCompareINEQ,
264 ByteCodeInstruction::kCompareFNEQ);
265 break;
266 case Token::Kind::PERCENT:
267 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kRemainderS,
268 ByteCodeInstruction::kRemainderU,
269 ByteCodeInstruction::kInvalid);
270 break;
271 case Token::Kind::PLUS:
272 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kAddI,
273 ByteCodeInstruction::kAddI,
274 ByteCodeInstruction::kAddF);
275 break;
276 case Token::Kind::SLASH:
277 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kDivideS,
278 ByteCodeInstruction::kDivideU,
279 ByteCodeInstruction::kDivideF);
280 break;
281 case Token::Kind::STAR:
282 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kMultiplyS,
283 ByteCodeInstruction::kMultiplyU,
284 ByteCodeInstruction::kMultiplyF);
285 break;
286 default:
287 SkASSERT(false);
288 }
289 if (lvalue) {
290 this->write(ByteCodeInstruction::kDupDown);
291 this->write8(slot_count(b.fType));
292 lvalue->store();
293 }
294}
295
296void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400297 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400298 this->write(ByteCodeInstruction::kPushImmediate);
299 this->write32(1);
300}
301
302void ByteCodeGenerator::writeConstructor(const Constructor& c) {
303 if (c.fArguments.size() == 1 &&
304 type_category(c.fType) == type_category(c.fArguments[0]->fType)) {
305 // cast from float to half or similar no-op
306 this->writeExpression(*c.fArguments[0]);
307 return;
308 }
309 for (const auto& arg : c.fArguments) {
310 this->writeExpression(*arg);
311 }
312 if (c.fArguments.size() == 1) {
313 TypeCategory inCategory = type_category(c.fArguments[0]->fType);
314 TypeCategory outCategory = type_category(c.fType);
315 if (inCategory != outCategory) {
316 int count = c.fType.columns();
317 if (count > 1) {
318 this->write(ByteCodeInstruction::kVector);
319 this->write8(count);
320 }
321 if (inCategory == TypeCategory::kFloat) {
322 SkASSERT(outCategory == TypeCategory::kSigned ||
323 outCategory == TypeCategory::kUnsigned);
324 this->write(ByteCodeInstruction::kFloatToInt);
325 } else if (outCategory == TypeCategory::kFloat) {
326 if (inCategory == TypeCategory::kSigned) {
327 this->write(ByteCodeInstruction::kSignedToFloat);
328 } else {
329 SkASSERT(inCategory == TypeCategory::kUnsigned);
330 this->write(ByteCodeInstruction::kUnsignedToFloat);
331 }
332 } else {
333 SkASSERT(false);
334 }
335 }
336 }
337}
338
339void ByteCodeGenerator::writeFieldAccess(const FieldAccess& f) {
340 // not yet implemented
341 abort();
342}
343
344void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400345 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400346 this->write(ByteCodeInstruction::kPushImmediate);
347 union { float f; uint32_t u; } pun = { (float) f.fValue };
348 this->write32(pun.u);
349}
350
351void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
352 // not yet implemented
353 abort();
354}
355
356void ByteCodeGenerator::writeIndexExpression(const IndexExpression& i) {
357 // not yet implemented
358 abort();
359}
360
361void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400362 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400363 this->write(ByteCodeInstruction::kPushImmediate);
364 this->write32(i.fValue);
365}
366
367void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
368 // not yet implemented
369 abort();
370}
371
372void ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p) {
373 switch (p.fOperator) {
374 case Token::Kind::PLUSPLUS: // fall through
375 case Token::Kind::MINUSMINUS: {
376 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
377 lvalue->load();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400378 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400379 this->write(ByteCodeInstruction::kPushImmediate);
380 this->write32(1);
381 if (p.fOperator == Token::Kind::PLUSPLUS) {
382 this->writeTypedInstruction(p.fType,
383 ByteCodeInstruction::kAddI,
384 ByteCodeInstruction::kAddI,
385 ByteCodeInstruction::kAddF);
386 } else {
387 this->writeTypedInstruction(p.fType,
388 ByteCodeInstruction::kSubtractI,
389 ByteCodeInstruction::kSubtractI,
390 ByteCodeInstruction::kSubtractF);
391 }
392 this->write(ByteCodeInstruction::kDupDown);
393 this->write8(slot_count(p.fType));
394 lvalue->store();
395 break;
396 }
397 case Token::Kind::MINUS:
398 this->writeTypedInstruction(p.fType,
399 ByteCodeInstruction::kNegateS,
400 ByteCodeInstruction::kInvalid,
401 ByteCodeInstruction::kNegateF);
402 break;
403 default:
404 SkASSERT(false);
405 }
406}
407
408void ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p) {
409 // not yet implemented
410 abort();
411}
412
413void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
414 switch (s.fBase->fKind) {
415 case Expression::kVariableReference_Kind: {
416 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
417 int location = this->getLocation(var);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400418 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400419 this->write(ByteCodeInstruction::kPushImmediate);
420 this->write32(location);
421 this->write(ByteCodeInstruction::kLoadSwizzle);
422 this->write8(s.fComponents.size());
423 for (int c : s.fComponents) {
424 this->write8(c);
425 }
426 break;
427 }
428 default:
429 this->writeExpression(*s.fBase);
430 this->write(ByteCodeInstruction::kSwizzle);
431 this->write8(s.fBase->fType.columns());
432 this->write8(s.fComponents.size());
433 for (int c : s.fComponents) {
434 this->write8(c);
435 }
436 }
437}
438
439void ByteCodeGenerator::writeVariableReference(const VariableReference& v) {
440 if (v.fVariable.fStorage == Variable::kGlobal_Storage) {
441 this->write(ByteCodeInstruction::kLoadGlobal);
442 int location = this->getLocation(v.fVariable);
443 SkASSERT(location <= 255);
444 this->write8(location);
445 } else {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400446 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400447 this->write(ByteCodeInstruction::kPushImmediate);
448 this->write32(this->getLocation(v.fVariable));
449 int count = slot_count(v.fType);
450 if (count > 1) {
451 this->write(ByteCodeInstruction::kVector);
452 this->write8(count);
453 }
454 this->write(ByteCodeInstruction::kLoad);
455 }
456}
457
458void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
459 // not yet implemented
460 abort();
461}
462
463void ByteCodeGenerator::writeExpression(const Expression& e) {
464 switch (e.fKind) {
465 case Expression::kBinary_Kind:
466 this->writeBinaryExpression((BinaryExpression&) e);
467 break;
468 case Expression::kBoolLiteral_Kind:
469 this->writeBoolLiteral((BoolLiteral&) e);
470 break;
471 case Expression::kConstructor_Kind:
472 this->writeConstructor((Constructor&) e);
473 break;
474 case Expression::kFieldAccess_Kind:
475 this->writeFieldAccess((FieldAccess&) e);
476 break;
477 case Expression::kFloatLiteral_Kind:
478 this->writeFloatLiteral((FloatLiteral&) e);
479 break;
480 case Expression::kFunctionCall_Kind:
481 this->writeFunctionCall((FunctionCall&) e);
482 break;
483 case Expression::kIndex_Kind:
484 this->writeIndexExpression((IndexExpression&) e);
485 break;
486 case Expression::kIntLiteral_Kind:
487 this->writeIntLiteral((IntLiteral&) e);
488 break;
489 case Expression::kNullLiteral_Kind:
490 this->writeNullLiteral((NullLiteral&) e);
491 break;
492 case Expression::kPrefix_Kind:
493 this->writePrefixExpression((PrefixExpression&) e);
494 break;
495 case Expression::kPostfix_Kind:
496 this->writePostfixExpression((PostfixExpression&) e);
497 break;
498 case Expression::kSwizzle_Kind:
499 this->writeSwizzle((Swizzle&) e);
500 break;
501 case Expression::kVariableReference_Kind:
502 this->writeVariableReference((VariableReference&) e);
503 break;
504 case Expression::kTernary_Kind:
505 this->writeTernaryExpression((TernaryExpression&) e);
506 break;
507 default:
508 printf("unsupported expression %s\n", e.description().c_str());
509 SkASSERT(false);
510 }
511}
512
513void ByteCodeGenerator::writeTarget(const Expression& e) {
514 switch (e.fKind) {
515 case Expression::kVariableReference_Kind:
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400516 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400517 this->write(ByteCodeInstruction::kPushImmediate);
518 this->write32(this->getLocation(((VariableReference&) e).fVariable));
519 break;
520 case Expression::kIndex_Kind:
521 case Expression::kTernary_Kind:
522 default:
523 printf("unsupported target %s\n", e.description().c_str());
524 SkASSERT(false);
525 }
526}
527
528class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
529public:
530 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
531 : INHERITED(*generator)
532 , fSwizzle(swizzle) {
533 fGenerator.writeTarget(*swizzle.fBase);
534 }
535
536 void load() override {
537 fGenerator.write(ByteCodeInstruction::kDup);
538 fGenerator.write(ByteCodeInstruction::kLoadSwizzle);
539 fGenerator.write8(fSwizzle.fComponents.size());
540 for (int c : fSwizzle.fComponents) {
541 fGenerator.write8(c);
542 }
543 }
544
545 void store() override {
546 fGenerator.write(ByteCodeInstruction::kStoreSwizzle);
547 fGenerator.write8(fSwizzle.fComponents.size());
548 for (int c : fSwizzle.fComponents) {
549 fGenerator.write8(c);
550 }
551 }
552
553private:
554 const Swizzle& fSwizzle;
555
556 typedef LValue INHERITED;
557};
558
559class ByteCodeVariableLValue : public ByteCodeGenerator::LValue {
560public:
561 ByteCodeVariableLValue(ByteCodeGenerator* generator, const Variable& var)
562 : INHERITED(*generator)
563 , fCount(slot_count(var.fType))
564 , fIsGlobal(var.fStorage == Variable::kGlobal_Storage) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400565 fGenerator.align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400566 fGenerator.write(ByteCodeInstruction::kPushImmediate);
567 fGenerator.write32(generator->getLocation(var));
568 }
569
570 void load() override {
571 fGenerator.write(ByteCodeInstruction::kDup);
572 if (fCount > 1) {
573 fGenerator.write(ByteCodeInstruction::kVector);
574 fGenerator.write8(fCount);
575 }
576 fGenerator.write(fIsGlobal ? ByteCodeInstruction::kLoadGlobal : ByteCodeInstruction::kLoad);
577 }
578
579 void store() override {
580 if (fCount > 1) {
581 fGenerator.write(ByteCodeInstruction::kVector);
582 fGenerator.write8(fCount);
583 }
584 fGenerator.write(fIsGlobal ? ByteCodeInstruction::kStoreGlobal
585 : ByteCodeInstruction::kStore);
586 }
587
588private:
589 typedef LValue INHERITED;
590
591 int fCount;
592
593 bool fIsGlobal;
594};
595
596std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
597 switch (e.fKind) {
598 case Expression::kIndex_Kind:
599 // not yet implemented
600 abort();
601 case Expression::kVariableReference_Kind:
602 return std::unique_ptr<LValue>(new ByteCodeVariableLValue(this,
603 ((VariableReference&) e).fVariable));
604 case Expression::kSwizzle_Kind:
605 return std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, (Swizzle&) e));
606 case Expression::kTernary_Kind:
607 default:
608 printf("unsupported lvalue %s\n", e.description().c_str());
609 return nullptr;
610 }
611}
612
613void ByteCodeGenerator::writeBlock(const Block& b) {
614 for (const auto& s : b.fStatements) {
615 this->writeStatement(*s);
616 }
617}
618
619void ByteCodeGenerator::setBreakTargets() {
620 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
621 for (DeferredLocation& b : breaks) {
622 b.set();
623 }
624 fBreakTargets.pop();
625}
626
627void ByteCodeGenerator::setContinueTargets() {
628 std::vector<DeferredLocation>& continues = fContinueTargets.top();
629 for (DeferredLocation& c : continues) {
630 c.set();
631 }
632 fContinueTargets.pop();
633}
634
635void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400636 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400637 this->write(ByteCodeInstruction::kBranch);
638 fBreakTargets.top().emplace_back(this);
639}
640
641void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400642 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400643 this->write(ByteCodeInstruction::kBranch);
644 fContinueTargets.top().emplace_back(this);
645}
646
647void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
648 fContinueTargets.emplace();
649 fBreakTargets.emplace();
650 size_t start = fCode->size();
651 this->writeStatement(*d.fStatement);
652 this->setContinueTargets();
653 this->writeExpression(*d.fTest);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400654 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400655 this->write(ByteCodeInstruction::kConditionalBranch);
656 this->write16(start);
657 this->setBreakTargets();
658}
659
660void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
661 fContinueTargets.emplace();
662 fBreakTargets.emplace();
663 if (f.fInitializer) {
664 this->writeStatement(*f.fInitializer);
665 }
666 size_t start = fCode->size();
667 if (f.fTest) {
668 this->writeExpression(*f.fTest);
669 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400670 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400671 this->write(ByteCodeInstruction::kConditionalBranch);
672 DeferredLocation endLocation(this);
673 this->writeStatement(*f.fStatement);
674 this->setContinueTargets();
675 if (f.fNext) {
676 this->writeExpression(*f.fNext);
677 this->write(ByteCodeInstruction::kPop);
678 this->write8(slot_count(f.fNext->fType));
679 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400680 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400681 this->write(ByteCodeInstruction::kBranch);
682 this->write16(start);
683 endLocation.set();
684 } else {
685 this->writeStatement(*f.fStatement);
686 this->setContinueTargets();
687 if (f.fNext) {
688 this->writeExpression(*f.fNext);
689 this->write(ByteCodeInstruction::kPop);
690 this->write8(slot_count(f.fNext->fType));
691 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400692 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400693 this->write(ByteCodeInstruction::kBranch);
694 this->write16(start);
695 }
696 this->setBreakTargets();
697}
698
699void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
700 this->writeExpression(*i.fTest);
701 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400702 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400703 this->write(ByteCodeInstruction::kConditionalBranch);
704 DeferredLocation elseLocation(this);
705 this->writeStatement(*i.fIfTrue);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400706 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400707 this->write(ByteCodeInstruction::kBranch);
708 DeferredLocation endLocation(this);
709 elseLocation.set();
710 if (i.fIfFalse) {
711 this->writeStatement(*i.fIfFalse);
712 }
713 endLocation.set();
714}
715
716void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -0400717 this->writeExpression(*r.fExpression);
718 this->write(ByteCodeInstruction::kReturn);
719 this->write8(r.fExpression->fType.columns() * r.fExpression->fType.rows());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400720}
721
722void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
723 // not yet implemented
724 abort();
725}
726
727void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
728 for (const auto& declStatement : v.fVars) {
729 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
730 // we need to grab the location even if we don't use it, to ensure it
731 // has been allocated
732 int location = getLocation(*decl.fVar);
733 if (decl.fValue) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400734 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400735 this->write(ByteCodeInstruction::kPushImmediate);
736 this->write32(location);
737 this->writeExpression(*decl.fValue);
738 int count = slot_count(decl.fValue->fType);
739 if (count > 1) {
740 this->write(ByteCodeInstruction::kVector);
741 this->write8(count);
742 }
743 this->write(ByteCodeInstruction::kStore);
744 }
745 }
746}
747
748void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
749 fContinueTargets.emplace();
750 fBreakTargets.emplace();
751 size_t start = fCode->size();
752 this->writeExpression(*w.fTest);
753 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400754 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400755 this->write(ByteCodeInstruction::kConditionalBranch);
756 DeferredLocation endLocation(this);
757 this->writeStatement(*w.fStatement);
758 this->setContinueTargets();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400759 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400760 this->write(ByteCodeInstruction::kBranch);
761 this->write16(start);
762 endLocation.set();
763 this->setBreakTargets();
764}
765
766void ByteCodeGenerator::writeStatement(const Statement& s) {
767 switch (s.fKind) {
768 case Statement::kBlock_Kind:
769 this->writeBlock((Block&) s);
770 break;
771 case Statement::kBreak_Kind:
772 this->writeBreakStatement((BreakStatement&) s);
773 break;
774 case Statement::kContinue_Kind:
775 this->writeContinueStatement((ContinueStatement&) s);
776 break;
777 case Statement::kDiscard_Kind:
778 // not yet implemented
779 abort();
780 case Statement::kDo_Kind:
781 this->writeDoStatement((DoStatement&) s);
782 break;
783 case Statement::kExpression_Kind: {
784 const Expression& expr = *((ExpressionStatement&) s).fExpression;
785 this->writeExpression(expr);
786 this->write(ByteCodeInstruction::kPop);
787 this->write8(slot_count(expr.fType));
788 break;
789 }
790 case Statement::kFor_Kind:
791 this->writeForStatement((ForStatement&) s);
792 break;
793 case Statement::kIf_Kind:
794 this->writeIfStatement((IfStatement&) s);
795 break;
796 case Statement::kNop_Kind:
797 break;
798 case Statement::kReturn_Kind:
799 this->writeReturnStatement((ReturnStatement&) s);
800 break;
801 case Statement::kSwitch_Kind:
802 this->writeSwitchStatement((SwitchStatement&) s);
803 break;
804 case Statement::kVarDeclarations_Kind:
805 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
806 break;
807 case Statement::kWhile_Kind:
808 this->writeWhileStatement((WhileStatement&) s);
809 break;
810 default:
811 SkASSERT(false);
812 }
813}
814
815}