blob: 699fda23e90cbbf2260b81dd0693155838da9f9d [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,
Brian Osman3b41baf2019-05-08 09:24:46 -0400280 ByteCodeInstruction::kRemainderF);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400281 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 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400408 case Token::Kind::MINUS: {
409 this->writeExpression(*p.fOperand);
410 int count = slot_count(p.fOperand->fType);
411 if (count > 1) {
412 this->write(ByteCodeInstruction::kVector);
413 this->write8(count);
414 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400415 this->writeTypedInstruction(p.fType,
416 ByteCodeInstruction::kNegateS,
417 ByteCodeInstruction::kInvalid,
418 ByteCodeInstruction::kNegateF);
419 break;
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400420 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400421 default:
422 SkASSERT(false);
423 }
424}
425
426void ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p) {
427 // not yet implemented
428 abort();
429}
430
431void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
432 switch (s.fBase->fKind) {
433 case Expression::kVariableReference_Kind: {
434 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
435 int location = this->getLocation(var);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400436 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400437 this->write(ByteCodeInstruction::kPushImmediate);
438 this->write32(location);
439 this->write(ByteCodeInstruction::kLoadSwizzle);
440 this->write8(s.fComponents.size());
441 for (int c : s.fComponents) {
442 this->write8(c);
443 }
444 break;
445 }
446 default:
447 this->writeExpression(*s.fBase);
448 this->write(ByteCodeInstruction::kSwizzle);
449 this->write8(s.fBase->fType.columns());
450 this->write8(s.fComponents.size());
451 for (int c : s.fComponents) {
452 this->write8(c);
453 }
454 }
455}
456
457void ByteCodeGenerator::writeVariableReference(const VariableReference& v) {
458 if (v.fVariable.fStorage == Variable::kGlobal_Storage) {
459 this->write(ByteCodeInstruction::kLoadGlobal);
460 int location = this->getLocation(v.fVariable);
461 SkASSERT(location <= 255);
462 this->write8(location);
463 } else {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400464 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400465 this->write(ByteCodeInstruction::kPushImmediate);
466 this->write32(this->getLocation(v.fVariable));
467 int count = slot_count(v.fType);
468 if (count > 1) {
469 this->write(ByteCodeInstruction::kVector);
470 this->write8(count);
471 }
472 this->write(ByteCodeInstruction::kLoad);
473 }
474}
475
476void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
477 // not yet implemented
478 abort();
479}
480
481void ByteCodeGenerator::writeExpression(const Expression& e) {
482 switch (e.fKind) {
483 case Expression::kBinary_Kind:
484 this->writeBinaryExpression((BinaryExpression&) e);
485 break;
486 case Expression::kBoolLiteral_Kind:
487 this->writeBoolLiteral((BoolLiteral&) e);
488 break;
489 case Expression::kConstructor_Kind:
490 this->writeConstructor((Constructor&) e);
491 break;
492 case Expression::kFieldAccess_Kind:
493 this->writeFieldAccess((FieldAccess&) e);
494 break;
495 case Expression::kFloatLiteral_Kind:
496 this->writeFloatLiteral((FloatLiteral&) e);
497 break;
498 case Expression::kFunctionCall_Kind:
499 this->writeFunctionCall((FunctionCall&) e);
500 break;
501 case Expression::kIndex_Kind:
502 this->writeIndexExpression((IndexExpression&) e);
503 break;
504 case Expression::kIntLiteral_Kind:
505 this->writeIntLiteral((IntLiteral&) e);
506 break;
507 case Expression::kNullLiteral_Kind:
508 this->writeNullLiteral((NullLiteral&) e);
509 break;
510 case Expression::kPrefix_Kind:
511 this->writePrefixExpression((PrefixExpression&) e);
512 break;
513 case Expression::kPostfix_Kind:
514 this->writePostfixExpression((PostfixExpression&) e);
515 break;
516 case Expression::kSwizzle_Kind:
517 this->writeSwizzle((Swizzle&) e);
518 break;
519 case Expression::kVariableReference_Kind:
520 this->writeVariableReference((VariableReference&) e);
521 break;
522 case Expression::kTernary_Kind:
523 this->writeTernaryExpression((TernaryExpression&) e);
524 break;
525 default:
526 printf("unsupported expression %s\n", e.description().c_str());
527 SkASSERT(false);
528 }
529}
530
531void ByteCodeGenerator::writeTarget(const Expression& e) {
532 switch (e.fKind) {
533 case Expression::kVariableReference_Kind:
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400534 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400535 this->write(ByteCodeInstruction::kPushImmediate);
536 this->write32(this->getLocation(((VariableReference&) e).fVariable));
537 break;
538 case Expression::kIndex_Kind:
539 case Expression::kTernary_Kind:
540 default:
541 printf("unsupported target %s\n", e.description().c_str());
542 SkASSERT(false);
543 }
544}
545
546class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
547public:
548 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
549 : INHERITED(*generator)
550 , fSwizzle(swizzle) {
551 fGenerator.writeTarget(*swizzle.fBase);
552 }
553
554 void load() override {
555 fGenerator.write(ByteCodeInstruction::kDup);
556 fGenerator.write(ByteCodeInstruction::kLoadSwizzle);
557 fGenerator.write8(fSwizzle.fComponents.size());
558 for (int c : fSwizzle.fComponents) {
559 fGenerator.write8(c);
560 }
561 }
562
563 void store() override {
564 fGenerator.write(ByteCodeInstruction::kStoreSwizzle);
565 fGenerator.write8(fSwizzle.fComponents.size());
566 for (int c : fSwizzle.fComponents) {
567 fGenerator.write8(c);
568 }
569 }
570
571private:
572 const Swizzle& fSwizzle;
573
574 typedef LValue INHERITED;
575};
576
577class ByteCodeVariableLValue : public ByteCodeGenerator::LValue {
578public:
579 ByteCodeVariableLValue(ByteCodeGenerator* generator, const Variable& var)
580 : INHERITED(*generator)
581 , fCount(slot_count(var.fType))
582 , fIsGlobal(var.fStorage == Variable::kGlobal_Storage) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400583 fGenerator.align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400584 fGenerator.write(ByteCodeInstruction::kPushImmediate);
585 fGenerator.write32(generator->getLocation(var));
586 }
587
588 void load() override {
589 fGenerator.write(ByteCodeInstruction::kDup);
590 if (fCount > 1) {
591 fGenerator.write(ByteCodeInstruction::kVector);
592 fGenerator.write8(fCount);
593 }
594 fGenerator.write(fIsGlobal ? ByteCodeInstruction::kLoadGlobal : ByteCodeInstruction::kLoad);
595 }
596
597 void store() override {
598 if (fCount > 1) {
599 fGenerator.write(ByteCodeInstruction::kVector);
600 fGenerator.write8(fCount);
601 }
602 fGenerator.write(fIsGlobal ? ByteCodeInstruction::kStoreGlobal
603 : ByteCodeInstruction::kStore);
604 }
605
606private:
607 typedef LValue INHERITED;
608
609 int fCount;
610
611 bool fIsGlobal;
612};
613
614std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
615 switch (e.fKind) {
616 case Expression::kIndex_Kind:
617 // not yet implemented
618 abort();
619 case Expression::kVariableReference_Kind:
620 return std::unique_ptr<LValue>(new ByteCodeVariableLValue(this,
621 ((VariableReference&) e).fVariable));
622 case Expression::kSwizzle_Kind:
623 return std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, (Swizzle&) e));
624 case Expression::kTernary_Kind:
625 default:
626 printf("unsupported lvalue %s\n", e.description().c_str());
627 return nullptr;
628 }
629}
630
631void ByteCodeGenerator::writeBlock(const Block& b) {
632 for (const auto& s : b.fStatements) {
633 this->writeStatement(*s);
634 }
635}
636
637void ByteCodeGenerator::setBreakTargets() {
638 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
639 for (DeferredLocation& b : breaks) {
640 b.set();
641 }
642 fBreakTargets.pop();
643}
644
645void ByteCodeGenerator::setContinueTargets() {
646 std::vector<DeferredLocation>& continues = fContinueTargets.top();
647 for (DeferredLocation& c : continues) {
648 c.set();
649 }
650 fContinueTargets.pop();
651}
652
653void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400654 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400655 this->write(ByteCodeInstruction::kBranch);
656 fBreakTargets.top().emplace_back(this);
657}
658
659void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400660 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400661 this->write(ByteCodeInstruction::kBranch);
662 fContinueTargets.top().emplace_back(this);
663}
664
665void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
666 fContinueTargets.emplace();
667 fBreakTargets.emplace();
668 size_t start = fCode->size();
669 this->writeStatement(*d.fStatement);
670 this->setContinueTargets();
671 this->writeExpression(*d.fTest);
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 this->write16(start);
675 this->setBreakTargets();
676}
677
678void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
679 fContinueTargets.emplace();
680 fBreakTargets.emplace();
681 if (f.fInitializer) {
682 this->writeStatement(*f.fInitializer);
683 }
684 size_t start = fCode->size();
685 if (f.fTest) {
686 this->writeExpression(*f.fTest);
687 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400688 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400689 this->write(ByteCodeInstruction::kConditionalBranch);
690 DeferredLocation endLocation(this);
691 this->writeStatement(*f.fStatement);
692 this->setContinueTargets();
693 if (f.fNext) {
694 this->writeExpression(*f.fNext);
695 this->write(ByteCodeInstruction::kPop);
696 this->write8(slot_count(f.fNext->fType));
697 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400698 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400699 this->write(ByteCodeInstruction::kBranch);
700 this->write16(start);
701 endLocation.set();
702 } else {
703 this->writeStatement(*f.fStatement);
704 this->setContinueTargets();
705 if (f.fNext) {
706 this->writeExpression(*f.fNext);
707 this->write(ByteCodeInstruction::kPop);
708 this->write8(slot_count(f.fNext->fType));
709 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400710 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400711 this->write(ByteCodeInstruction::kBranch);
712 this->write16(start);
713 }
714 this->setBreakTargets();
715}
716
717void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
718 this->writeExpression(*i.fTest);
719 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400720 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400721 this->write(ByteCodeInstruction::kConditionalBranch);
722 DeferredLocation elseLocation(this);
723 this->writeStatement(*i.fIfTrue);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400724 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400725 this->write(ByteCodeInstruction::kBranch);
726 DeferredLocation endLocation(this);
727 elseLocation.set();
728 if (i.fIfFalse) {
729 this->writeStatement(*i.fIfFalse);
730 }
731 endLocation.set();
732}
733
734void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -0400735 this->writeExpression(*r.fExpression);
736 this->write(ByteCodeInstruction::kReturn);
737 this->write8(r.fExpression->fType.columns() * r.fExpression->fType.rows());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400738}
739
740void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
741 // not yet implemented
742 abort();
743}
744
745void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
746 for (const auto& declStatement : v.fVars) {
747 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
748 // we need to grab the location even if we don't use it, to ensure it
749 // has been allocated
750 int location = getLocation(*decl.fVar);
751 if (decl.fValue) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400752 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400753 this->write(ByteCodeInstruction::kPushImmediate);
754 this->write32(location);
755 this->writeExpression(*decl.fValue);
756 int count = slot_count(decl.fValue->fType);
757 if (count > 1) {
758 this->write(ByteCodeInstruction::kVector);
759 this->write8(count);
760 }
761 this->write(ByteCodeInstruction::kStore);
762 }
763 }
764}
765
766void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
767 fContinueTargets.emplace();
768 fBreakTargets.emplace();
769 size_t start = fCode->size();
770 this->writeExpression(*w.fTest);
771 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400772 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400773 this->write(ByteCodeInstruction::kConditionalBranch);
774 DeferredLocation endLocation(this);
775 this->writeStatement(*w.fStatement);
776 this->setContinueTargets();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400777 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400778 this->write(ByteCodeInstruction::kBranch);
779 this->write16(start);
780 endLocation.set();
781 this->setBreakTargets();
782}
783
784void ByteCodeGenerator::writeStatement(const Statement& s) {
785 switch (s.fKind) {
786 case Statement::kBlock_Kind:
787 this->writeBlock((Block&) s);
788 break;
789 case Statement::kBreak_Kind:
790 this->writeBreakStatement((BreakStatement&) s);
791 break;
792 case Statement::kContinue_Kind:
793 this->writeContinueStatement((ContinueStatement&) s);
794 break;
795 case Statement::kDiscard_Kind:
796 // not yet implemented
797 abort();
798 case Statement::kDo_Kind:
799 this->writeDoStatement((DoStatement&) s);
800 break;
801 case Statement::kExpression_Kind: {
802 const Expression& expr = *((ExpressionStatement&) s).fExpression;
803 this->writeExpression(expr);
804 this->write(ByteCodeInstruction::kPop);
805 this->write8(slot_count(expr.fType));
806 break;
807 }
808 case Statement::kFor_Kind:
809 this->writeForStatement((ForStatement&) s);
810 break;
811 case Statement::kIf_Kind:
812 this->writeIfStatement((IfStatement&) s);
813 break;
814 case Statement::kNop_Kind:
815 break;
816 case Statement::kReturn_Kind:
817 this->writeReturnStatement((ReturnStatement&) s);
818 break;
819 case Statement::kSwitch_Kind:
820 this->writeSwitchStatement((SwitchStatement&) s);
821 break;
822 case Statement::kVarDeclarations_Kind:
823 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
824 break;
825 case Statement::kWhile_Kind:
826 this->writeWhileStatement((WhileStatement&) s);
827 break;
828 default:
829 SkASSERT(false);
830 }
831}
832
833}