blob: b7bf3944e83103cbe72c5214e4470059d78f9b24 [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 }
Brian Osman226668a2019-05-14 16:47:30 -040048 for (auto& call : fCallTargets) {
49 if (!call.set()) {
50 return false;
51 }
52 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040053 return true;
54}
55
56std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
57 fFunction = &f;
Brian Osman226668a2019-05-14 16:47:30 -040058 std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040059 fParameterCount = 0;
60 for (const auto& p : f.fDeclaration.fParameters) {
61 fParameterCount += p->fType.columns() * p->fType.rows();
62 }
63 fCode = &result->fCode;
64 this->writeStatement(*f.fBody);
Ethan Nicholas7e603db2019-05-03 12:57:47 -040065 this->write(ByteCodeInstruction::kReturn);
66 this->write8(0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040067 result->fParameterCount = fParameterCount;
68 result->fLocalCount = fLocals.size();
Ethan Nicholasdfcad062019-05-07 12:53:34 -040069 const Type& returnType = f.fDeclaration.fReturnType;
70 if (returnType != *fContext.fVoid_Type) {
71 result->fReturnCount = returnType.columns() * returnType.rows();
72 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040073 fLocals.clear();
74 fFunction = nullptr;
75 return result;
76}
77
78enum class TypeCategory {
79 kBool,
80 kSigned,
81 kUnsigned,
82 kFloat,
83};
84
85static TypeCategory type_category(const Type& type) {
86 switch (type.kind()) {
87 case Type::Kind::kVector_Kind:
88 case Type::Kind::kMatrix_Kind:
89 return type_category(type.componentType());
90 default:
91 if (type.fName == "bool") {
92 return TypeCategory::kBool;
93 } else if (type.fName == "int" || type.fName == "short") {
94 return TypeCategory::kSigned;
95 } else if (type.fName == "uint" || type.fName == "ushort") {
96 return TypeCategory::kUnsigned;
97 } else {
98 SkASSERT(type.fName == "float" || type.fName == "half");
99 return TypeCategory::kFloat;
100 }
101 ABORT("unsupported type: %s\n", type.description().c_str());
102 }
103}
104
105int ByteCodeGenerator::getLocation(const Variable& var) {
106 // given that we seldom have more than a couple of variables, linear search is probably the most
107 // efficient way to handle lookups
108 switch (var.fStorage) {
109 case Variable::kLocal_Storage: {
110 for (int i = fLocals.size() - 1; i >= 0; --i) {
111 if (fLocals[i] == &var) {
112 return fParameterCount + i;
113 }
114 }
115 int result = fParameterCount + fLocals.size();
116 fLocals.push_back(&var);
117 for (int i = 0; i < slot_count(var.fType) - 1; ++i) {
118 fLocals.push_back(nullptr);
119 }
120 return result;
121 }
122 case Variable::kParameter_Storage: {
123 int offset = 0;
124 for (const auto& p : fFunction->fDeclaration.fParameters) {
125 if (p == &var) {
126 return offset;
127 }
128 offset += slot_count(p->fType);
129 }
130 SkASSERT(false);
131 return -1;
132 }
133 case Variable::kGlobal_Storage: {
134 int offset = 0;
135 for (const auto& e : fProgram) {
136 if (e.fKind == ProgramElement::kVar_Kind) {
137 VarDeclarations& decl = (VarDeclarations&) e;
138 for (const auto& v : decl.fVars) {
139 const Variable* declVar = ((VarDeclaration&) *v).fVar;
140 if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
141 continue;
142 }
143 if (declVar == &var) {
Brian Osmanb7451292019-05-15 13:02:13 -0400144 SkASSERT(offset <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400145 return offset;
146 }
147 offset += slot_count(declVar->fType);
148 }
149 }
150 }
151 SkASSERT(false);
152 return -1;
153 }
154 default:
155 SkASSERT(false);
156 return 0;
157 }
158}
159
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400160void ByteCodeGenerator::align(int divisor, int remainder) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400161 switch (remainder - (int) fCode->size() % divisor) {
162 case 0: return;
163 case 3: this->write(ByteCodeInstruction::kNop3); // fall through
164 case 2: this->write(ByteCodeInstruction::kNop2); // fall through
165 case 1: this->write(ByteCodeInstruction::kNop1);
166 break;
167 default: SkASSERT(false);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400168 }
169}
170
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400171void ByteCodeGenerator::write8(uint8_t b) {
172 fCode->push_back(b);
173}
174
175void ByteCodeGenerator::write16(uint16_t i) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400176 SkASSERT(fCode->size() % 2 == 0);
177 this->write8(i >> 0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400178 this->write8(i >> 8);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400179}
180
181void ByteCodeGenerator::write32(uint32_t i) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400182 SkASSERT(fCode->size() % 4 == 0);
Brian Osmane1e988d2019-03-21 14:06:24 -0400183 this->write8((i >> 0) & 0xFF);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400184 this->write8((i >> 8) & 0xFF);
185 this->write8((i >> 16) & 0xFF);
186 this->write8((i >> 24) & 0xFF);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400187}
188
189void ByteCodeGenerator::write(ByteCodeInstruction i) {
190 this->write8((uint8_t) i);
191}
192
193void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
194 ByteCodeInstruction u, ByteCodeInstruction f) {
195 switch (type_category(type)) {
196 case TypeCategory::kSigned:
197 this->write(s);
198 break;
199 case TypeCategory::kUnsigned:
200 this->write(u);
201 break;
202 case TypeCategory::kFloat:
203 this->write(f);
204 break;
205 default:
206 SkASSERT(false);
207 }
208}
209
210void ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b) {
211 if (b.fOperator == Token::Kind::EQ) {
212 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
213 this->writeExpression(*b.fRight);
214 this->write(ByteCodeInstruction::kDupDown);
215 this->write8(slot_count(b.fRight->fType));
216 lvalue->store();
217 return;
218 }
219 Token::Kind op;
220 std::unique_ptr<LValue> lvalue;
221 if (is_assignment(b.fOperator)) {
222 lvalue = this->getLValue(*b.fLeft);
223 lvalue->load();
224 op = remove_assignment(b.fOperator);
225 } else {
226 this->writeExpression(*b.fLeft);
227 op = b.fOperator;
228 if (b.fLeft->fType.kind() == Type::kScalar_Kind &&
229 b.fRight->fType.kind() == Type::kVector_Kind) {
230 for (int i = b.fRight->fType.columns(); i > 1; --i) {
231 this->write(ByteCodeInstruction::kDup);
232 }
233 }
234 }
235 this->writeExpression(*b.fRight);
236 if (b.fLeft->fType.kind() == Type::kVector_Kind &&
237 b.fRight->fType.kind() == Type::kScalar_Kind) {
238 for (int i = b.fLeft->fType.columns(); i > 1; --i) {
239 this->write(ByteCodeInstruction::kDup);
240 }
241 }
242 int count = slot_count(b.fType);
243 if (count > 1) {
244 this->write(ByteCodeInstruction::kVector);
245 this->write8(count);
246 }
247 switch (op) {
248 case Token::Kind::EQEQ:
249 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareIEQ,
250 ByteCodeInstruction::kCompareIEQ,
251 ByteCodeInstruction::kCompareFEQ);
252 break;
253 case Token::Kind::GT:
254 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGT,
255 ByteCodeInstruction::kCompareUGT,
256 ByteCodeInstruction::kCompareFGT);
257 break;
258 case Token::Kind::GTEQ:
259 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGTEQ,
260 ByteCodeInstruction::kCompareUGTEQ,
261 ByteCodeInstruction::kCompareFGTEQ);
262 break;
263 case Token::Kind::LT:
264 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLT,
265 ByteCodeInstruction::kCompareULT,
266 ByteCodeInstruction::kCompareFLT);
267 break;
268 case Token::Kind::LTEQ:
269 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLTEQ,
270 ByteCodeInstruction::kCompareULTEQ,
271 ByteCodeInstruction::kCompareFLTEQ);
272 break;
273 case Token::Kind::MINUS:
274 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kSubtractI,
275 ByteCodeInstruction::kSubtractI,
276 ByteCodeInstruction::kSubtractF);
277 break;
278 case Token::Kind::NEQ:
279 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareINEQ,
280 ByteCodeInstruction::kCompareINEQ,
281 ByteCodeInstruction::kCompareFNEQ);
282 break;
283 case Token::Kind::PERCENT:
284 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kRemainderS,
285 ByteCodeInstruction::kRemainderU,
Brian Osman3b41baf2019-05-08 09:24:46 -0400286 ByteCodeInstruction::kRemainderF);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400287 break;
288 case Token::Kind::PLUS:
289 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kAddI,
290 ByteCodeInstruction::kAddI,
291 ByteCodeInstruction::kAddF);
292 break;
293 case Token::Kind::SLASH:
294 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kDivideS,
295 ByteCodeInstruction::kDivideU,
296 ByteCodeInstruction::kDivideF);
297 break;
298 case Token::Kind::STAR:
299 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kMultiplyS,
300 ByteCodeInstruction::kMultiplyU,
301 ByteCodeInstruction::kMultiplyF);
302 break;
303 default:
304 SkASSERT(false);
305 }
306 if (lvalue) {
307 this->write(ByteCodeInstruction::kDupDown);
308 this->write8(slot_count(b.fType));
309 lvalue->store();
310 }
311}
312
313void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400314 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400315 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osman44d44762019-05-13 14:19:12 -0400316 this->write32(b.fValue ? 1 : 0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400317}
318
319void ByteCodeGenerator::writeConstructor(const Constructor& c) {
320 if (c.fArguments.size() == 1 &&
321 type_category(c.fType) == type_category(c.fArguments[0]->fType)) {
322 // cast from float to half or similar no-op
323 this->writeExpression(*c.fArguments[0]);
324 return;
325 }
326 for (const auto& arg : c.fArguments) {
327 this->writeExpression(*arg);
328 }
329 if (c.fArguments.size() == 1) {
330 TypeCategory inCategory = type_category(c.fArguments[0]->fType);
331 TypeCategory outCategory = type_category(c.fType);
332 if (inCategory != outCategory) {
333 int count = c.fType.columns();
334 if (count > 1) {
335 this->write(ByteCodeInstruction::kVector);
336 this->write8(count);
337 }
338 if (inCategory == TypeCategory::kFloat) {
339 SkASSERT(outCategory == TypeCategory::kSigned ||
340 outCategory == TypeCategory::kUnsigned);
341 this->write(ByteCodeInstruction::kFloatToInt);
342 } else if (outCategory == TypeCategory::kFloat) {
343 if (inCategory == TypeCategory::kSigned) {
344 this->write(ByteCodeInstruction::kSignedToFloat);
345 } else {
346 SkASSERT(inCategory == TypeCategory::kUnsigned);
347 this->write(ByteCodeInstruction::kUnsignedToFloat);
348 }
349 } else {
350 SkASSERT(false);
351 }
352 }
353 }
354}
355
356void ByteCodeGenerator::writeFieldAccess(const FieldAccess& f) {
357 // not yet implemented
358 abort();
359}
360
361void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
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 union { float f; uint32_t u; } pun = { (float) f.fValue };
365 this->write32(pun.u);
366}
367
368void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Brian Osman226668a2019-05-14 16:47:30 -0400369 for (const auto& arg : f.fArguments) {
370 this->writeExpression(*arg);
371 }
372 this->write(ByteCodeInstruction::kCall);
373 fCallTargets.emplace_back(this, f.fFunction);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400374}
375
376void ByteCodeGenerator::writeIndexExpression(const IndexExpression& i) {
377 // not yet implemented
378 abort();
379}
380
381void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400382 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400383 this->write(ByteCodeInstruction::kPushImmediate);
384 this->write32(i.fValue);
385}
386
387void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
388 // not yet implemented
389 abort();
390}
391
392void ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p) {
393 switch (p.fOperator) {
394 case Token::Kind::PLUSPLUS: // fall through
395 case Token::Kind::MINUSMINUS: {
396 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
397 lvalue->load();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400398 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400399 this->write(ByteCodeInstruction::kPushImmediate);
400 this->write32(1);
401 if (p.fOperator == Token::Kind::PLUSPLUS) {
402 this->writeTypedInstruction(p.fType,
403 ByteCodeInstruction::kAddI,
404 ByteCodeInstruction::kAddI,
405 ByteCodeInstruction::kAddF);
406 } else {
407 this->writeTypedInstruction(p.fType,
408 ByteCodeInstruction::kSubtractI,
409 ByteCodeInstruction::kSubtractI,
410 ByteCodeInstruction::kSubtractF);
411 }
412 this->write(ByteCodeInstruction::kDupDown);
413 this->write8(slot_count(p.fType));
414 lvalue->store();
415 break;
416 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400417 case Token::Kind::MINUS: {
418 this->writeExpression(*p.fOperand);
419 int count = slot_count(p.fOperand->fType);
420 if (count > 1) {
421 this->write(ByteCodeInstruction::kVector);
422 this->write8(count);
423 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400424 this->writeTypedInstruction(p.fType,
425 ByteCodeInstruction::kNegateS,
426 ByteCodeInstruction::kInvalid,
427 ByteCodeInstruction::kNegateF);
428 break;
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400429 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400430 default:
431 SkASSERT(false);
432 }
433}
434
435void ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p) {
436 // not yet implemented
437 abort();
438}
439
440void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
441 switch (s.fBase->fKind) {
442 case Expression::kVariableReference_Kind: {
443 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
Brian Osmanb7451292019-05-15 13:02:13 -0400444 if (var.fStorage == Variable::kGlobal_Storage) {
445 this->write(ByteCodeInstruction::kLoadSwizzleGlobal);
446 this->write8(this->getLocation(var));
447 } else {
448 this->align(4, 3);
449 this->write(ByteCodeInstruction::kPushImmediate);
450 this->write32(this->getLocation(var));
451 this->write(ByteCodeInstruction::kLoadSwizzle);
452 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400453 this->write8(s.fComponents.size());
454 for (int c : s.fComponents) {
455 this->write8(c);
456 }
457 break;
458 }
459 default:
460 this->writeExpression(*s.fBase);
461 this->write(ByteCodeInstruction::kSwizzle);
462 this->write8(s.fBase->fType.columns());
463 this->write8(s.fComponents.size());
464 for (int c : s.fComponents) {
465 this->write8(c);
466 }
467 }
468}
469
470void ByteCodeGenerator::writeVariableReference(const VariableReference& v) {
471 if (v.fVariable.fStorage == Variable::kGlobal_Storage) {
Brian Osmanb7451292019-05-15 13:02:13 -0400472 int count = slot_count(v.fType);
473 if (count > 1) {
474 this->write(ByteCodeInstruction::kVector);
475 this->write8(count);
476 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400477 this->write(ByteCodeInstruction::kLoadGlobal);
Brian Osmanb7451292019-05-15 13:02:13 -0400478 this->write8(this->getLocation(v.fVariable));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400479 } else {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400480 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400481 this->write(ByteCodeInstruction::kPushImmediate);
482 this->write32(this->getLocation(v.fVariable));
483 int count = slot_count(v.fType);
484 if (count > 1) {
485 this->write(ByteCodeInstruction::kVector);
486 this->write8(count);
487 }
488 this->write(ByteCodeInstruction::kLoad);
489 }
490}
491
492void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
493 // not yet implemented
494 abort();
495}
496
497void ByteCodeGenerator::writeExpression(const Expression& e) {
498 switch (e.fKind) {
499 case Expression::kBinary_Kind:
500 this->writeBinaryExpression((BinaryExpression&) e);
501 break;
502 case Expression::kBoolLiteral_Kind:
503 this->writeBoolLiteral((BoolLiteral&) e);
504 break;
505 case Expression::kConstructor_Kind:
506 this->writeConstructor((Constructor&) e);
507 break;
508 case Expression::kFieldAccess_Kind:
509 this->writeFieldAccess((FieldAccess&) e);
510 break;
511 case Expression::kFloatLiteral_Kind:
512 this->writeFloatLiteral((FloatLiteral&) e);
513 break;
514 case Expression::kFunctionCall_Kind:
515 this->writeFunctionCall((FunctionCall&) e);
516 break;
517 case Expression::kIndex_Kind:
518 this->writeIndexExpression((IndexExpression&) e);
519 break;
520 case Expression::kIntLiteral_Kind:
521 this->writeIntLiteral((IntLiteral&) e);
522 break;
523 case Expression::kNullLiteral_Kind:
524 this->writeNullLiteral((NullLiteral&) e);
525 break;
526 case Expression::kPrefix_Kind:
527 this->writePrefixExpression((PrefixExpression&) e);
528 break;
529 case Expression::kPostfix_Kind:
530 this->writePostfixExpression((PostfixExpression&) e);
531 break;
532 case Expression::kSwizzle_Kind:
533 this->writeSwizzle((Swizzle&) e);
534 break;
535 case Expression::kVariableReference_Kind:
536 this->writeVariableReference((VariableReference&) e);
537 break;
538 case Expression::kTernary_Kind:
539 this->writeTernaryExpression((TernaryExpression&) e);
540 break;
541 default:
542 printf("unsupported expression %s\n", e.description().c_str());
543 SkASSERT(false);
544 }
545}
546
547void ByteCodeGenerator::writeTarget(const Expression& e) {
548 switch (e.fKind) {
549 case Expression::kVariableReference_Kind:
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400550 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400551 this->write(ByteCodeInstruction::kPushImmediate);
552 this->write32(this->getLocation(((VariableReference&) e).fVariable));
553 break;
554 case Expression::kIndex_Kind:
555 case Expression::kTernary_Kind:
556 default:
557 printf("unsupported target %s\n", e.description().c_str());
558 SkASSERT(false);
559 }
560}
561
562class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
563public:
564 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
565 : INHERITED(*generator)
566 , fSwizzle(swizzle) {
567 fGenerator.writeTarget(*swizzle.fBase);
568 }
569
570 void load() override {
571 fGenerator.write(ByteCodeInstruction::kDup);
572 fGenerator.write(ByteCodeInstruction::kLoadSwizzle);
573 fGenerator.write8(fSwizzle.fComponents.size());
574 for (int c : fSwizzle.fComponents) {
575 fGenerator.write8(c);
576 }
577 }
578
579 void store() override {
580 fGenerator.write(ByteCodeInstruction::kStoreSwizzle);
581 fGenerator.write8(fSwizzle.fComponents.size());
582 for (int c : fSwizzle.fComponents) {
583 fGenerator.write8(c);
584 }
585 }
586
587private:
588 const Swizzle& fSwizzle;
589
590 typedef LValue INHERITED;
591};
592
593class ByteCodeVariableLValue : public ByteCodeGenerator::LValue {
594public:
595 ByteCodeVariableLValue(ByteCodeGenerator* generator, const Variable& var)
596 : INHERITED(*generator)
597 , fCount(slot_count(var.fType))
598 , fIsGlobal(var.fStorage == Variable::kGlobal_Storage) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400599 fGenerator.align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400600 fGenerator.write(ByteCodeInstruction::kPushImmediate);
601 fGenerator.write32(generator->getLocation(var));
602 }
603
604 void load() override {
605 fGenerator.write(ByteCodeInstruction::kDup);
606 if (fCount > 1) {
607 fGenerator.write(ByteCodeInstruction::kVector);
608 fGenerator.write8(fCount);
609 }
610 fGenerator.write(fIsGlobal ? ByteCodeInstruction::kLoadGlobal : ByteCodeInstruction::kLoad);
611 }
612
613 void store() override {
614 if (fCount > 1) {
615 fGenerator.write(ByteCodeInstruction::kVector);
616 fGenerator.write8(fCount);
617 }
618 fGenerator.write(fIsGlobal ? ByteCodeInstruction::kStoreGlobal
619 : ByteCodeInstruction::kStore);
620 }
621
622private:
623 typedef LValue INHERITED;
624
625 int fCount;
626
627 bool fIsGlobal;
628};
629
630std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
631 switch (e.fKind) {
632 case Expression::kIndex_Kind:
633 // not yet implemented
634 abort();
635 case Expression::kVariableReference_Kind:
636 return std::unique_ptr<LValue>(new ByteCodeVariableLValue(this,
637 ((VariableReference&) e).fVariable));
638 case Expression::kSwizzle_Kind:
639 return std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, (Swizzle&) e));
640 case Expression::kTernary_Kind:
641 default:
642 printf("unsupported lvalue %s\n", e.description().c_str());
643 return nullptr;
644 }
645}
646
647void ByteCodeGenerator::writeBlock(const Block& b) {
648 for (const auto& s : b.fStatements) {
649 this->writeStatement(*s);
650 }
651}
652
653void ByteCodeGenerator::setBreakTargets() {
654 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
655 for (DeferredLocation& b : breaks) {
656 b.set();
657 }
658 fBreakTargets.pop();
659}
660
661void ByteCodeGenerator::setContinueTargets() {
662 std::vector<DeferredLocation>& continues = fContinueTargets.top();
663 for (DeferredLocation& c : continues) {
664 c.set();
665 }
666 fContinueTargets.pop();
667}
668
669void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400670 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400671 this->write(ByteCodeInstruction::kBranch);
672 fBreakTargets.top().emplace_back(this);
673}
674
675void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400676 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400677 this->write(ByteCodeInstruction::kBranch);
678 fContinueTargets.top().emplace_back(this);
679}
680
681void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
682 fContinueTargets.emplace();
683 fBreakTargets.emplace();
684 size_t start = fCode->size();
685 this->writeStatement(*d.fStatement);
686 this->setContinueTargets();
687 this->writeExpression(*d.fTest);
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 this->write16(start);
691 this->setBreakTargets();
692}
693
694void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
695 fContinueTargets.emplace();
696 fBreakTargets.emplace();
697 if (f.fInitializer) {
698 this->writeStatement(*f.fInitializer);
699 }
700 size_t start = fCode->size();
701 if (f.fTest) {
702 this->writeExpression(*f.fTest);
703 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400704 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400705 this->write(ByteCodeInstruction::kConditionalBranch);
706 DeferredLocation endLocation(this);
707 this->writeStatement(*f.fStatement);
708 this->setContinueTargets();
709 if (f.fNext) {
710 this->writeExpression(*f.fNext);
711 this->write(ByteCodeInstruction::kPop);
712 this->write8(slot_count(f.fNext->fType));
713 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400714 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400715 this->write(ByteCodeInstruction::kBranch);
716 this->write16(start);
717 endLocation.set();
718 } else {
719 this->writeStatement(*f.fStatement);
720 this->setContinueTargets();
721 if (f.fNext) {
722 this->writeExpression(*f.fNext);
723 this->write(ByteCodeInstruction::kPop);
724 this->write8(slot_count(f.fNext->fType));
725 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400726 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400727 this->write(ByteCodeInstruction::kBranch);
728 this->write16(start);
729 }
730 this->setBreakTargets();
731}
732
733void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
734 this->writeExpression(*i.fTest);
735 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400736 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400737 this->write(ByteCodeInstruction::kConditionalBranch);
738 DeferredLocation elseLocation(this);
739 this->writeStatement(*i.fIfTrue);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400740 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400741 this->write(ByteCodeInstruction::kBranch);
742 DeferredLocation endLocation(this);
743 elseLocation.set();
744 if (i.fIfFalse) {
745 this->writeStatement(*i.fIfFalse);
746 }
747 endLocation.set();
748}
749
750void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -0400751 this->writeExpression(*r.fExpression);
752 this->write(ByteCodeInstruction::kReturn);
753 this->write8(r.fExpression->fType.columns() * r.fExpression->fType.rows());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400754}
755
756void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
757 // not yet implemented
758 abort();
759}
760
761void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
762 for (const auto& declStatement : v.fVars) {
763 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
764 // we need to grab the location even if we don't use it, to ensure it
765 // has been allocated
766 int location = getLocation(*decl.fVar);
767 if (decl.fValue) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400768 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400769 this->write(ByteCodeInstruction::kPushImmediate);
770 this->write32(location);
771 this->writeExpression(*decl.fValue);
772 int count = slot_count(decl.fValue->fType);
773 if (count > 1) {
774 this->write(ByteCodeInstruction::kVector);
775 this->write8(count);
776 }
777 this->write(ByteCodeInstruction::kStore);
778 }
779 }
780}
781
782void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
783 fContinueTargets.emplace();
784 fBreakTargets.emplace();
785 size_t start = fCode->size();
786 this->writeExpression(*w.fTest);
787 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400788 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400789 this->write(ByteCodeInstruction::kConditionalBranch);
790 DeferredLocation endLocation(this);
791 this->writeStatement(*w.fStatement);
792 this->setContinueTargets();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400793 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400794 this->write(ByteCodeInstruction::kBranch);
795 this->write16(start);
796 endLocation.set();
797 this->setBreakTargets();
798}
799
800void ByteCodeGenerator::writeStatement(const Statement& s) {
801 switch (s.fKind) {
802 case Statement::kBlock_Kind:
803 this->writeBlock((Block&) s);
804 break;
805 case Statement::kBreak_Kind:
806 this->writeBreakStatement((BreakStatement&) s);
807 break;
808 case Statement::kContinue_Kind:
809 this->writeContinueStatement((ContinueStatement&) s);
810 break;
811 case Statement::kDiscard_Kind:
812 // not yet implemented
813 abort();
814 case Statement::kDo_Kind:
815 this->writeDoStatement((DoStatement&) s);
816 break;
817 case Statement::kExpression_Kind: {
818 const Expression& expr = *((ExpressionStatement&) s).fExpression;
819 this->writeExpression(expr);
820 this->write(ByteCodeInstruction::kPop);
821 this->write8(slot_count(expr.fType));
822 break;
823 }
824 case Statement::kFor_Kind:
825 this->writeForStatement((ForStatement&) s);
826 break;
827 case Statement::kIf_Kind:
828 this->writeIfStatement((IfStatement&) s);
829 break;
830 case Statement::kNop_Kind:
831 break;
832 case Statement::kReturn_Kind:
833 this->writeReturnStatement((ReturnStatement&) s);
834 break;
835 case Statement::kSwitch_Kind:
836 this->writeSwitchStatement((SwitchStatement&) s);
837 break;
838 case Statement::kVarDeclarations_Kind:
839 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
840 break;
841 case Statement::kWhile_Kind:
842 this->writeWhileStatement((WhileStatement&) s);
843 break;
844 default:
845 SkASSERT(false);
846 }
847}
848
849}