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