blob: 1125c05d749ae558ed7523c89387e383f96ff597 [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) {
144 return offset;
145 }
146 offset += slot_count(declVar->fType);
147 }
148 }
149 }
150 SkASSERT(false);
151 return -1;
152 }
153 default:
154 SkASSERT(false);
155 return 0;
156 }
157}
158
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400159void ByteCodeGenerator::align(int divisor, int remainder) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400160 switch (remainder - (int) fCode->size() % divisor) {
161 case 0: return;
162 case 3: this->write(ByteCodeInstruction::kNop3); // fall through
163 case 2: this->write(ByteCodeInstruction::kNop2); // fall through
164 case 1: this->write(ByteCodeInstruction::kNop1);
165 break;
166 default: SkASSERT(false);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400167 }
168}
169
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400170void ByteCodeGenerator::write8(uint8_t b) {
171 fCode->push_back(b);
172}
173
174void ByteCodeGenerator::write16(uint16_t i) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400175 SkASSERT(fCode->size() % 2 == 0);
176 this->write8(i >> 0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400177 this->write8(i >> 8);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400178}
179
180void ByteCodeGenerator::write32(uint32_t i) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400181 SkASSERT(fCode->size() % 4 == 0);
Brian Osmane1e988d2019-03-21 14:06:24 -0400182 this->write8((i >> 0) & 0xFF);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400183 this->write8((i >> 8) & 0xFF);
184 this->write8((i >> 16) & 0xFF);
185 this->write8((i >> 24) & 0xFF);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400186}
187
188void ByteCodeGenerator::write(ByteCodeInstruction i) {
189 this->write8((uint8_t) i);
190}
191
192void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
193 ByteCodeInstruction u, ByteCodeInstruction f) {
194 switch (type_category(type)) {
195 case TypeCategory::kSigned:
196 this->write(s);
197 break;
198 case TypeCategory::kUnsigned:
199 this->write(u);
200 break;
201 case TypeCategory::kFloat:
202 this->write(f);
203 break;
204 default:
205 SkASSERT(false);
206 }
207}
208
209void ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b) {
210 if (b.fOperator == Token::Kind::EQ) {
211 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
212 this->writeExpression(*b.fRight);
213 this->write(ByteCodeInstruction::kDupDown);
214 this->write8(slot_count(b.fRight->fType));
215 lvalue->store();
216 return;
217 }
218 Token::Kind op;
219 std::unique_ptr<LValue> lvalue;
220 if (is_assignment(b.fOperator)) {
221 lvalue = this->getLValue(*b.fLeft);
222 lvalue->load();
223 op = remove_assignment(b.fOperator);
224 } else {
225 this->writeExpression(*b.fLeft);
226 op = b.fOperator;
227 if (b.fLeft->fType.kind() == Type::kScalar_Kind &&
228 b.fRight->fType.kind() == Type::kVector_Kind) {
229 for (int i = b.fRight->fType.columns(); i > 1; --i) {
230 this->write(ByteCodeInstruction::kDup);
231 }
232 }
233 }
234 this->writeExpression(*b.fRight);
235 if (b.fLeft->fType.kind() == Type::kVector_Kind &&
236 b.fRight->fType.kind() == Type::kScalar_Kind) {
237 for (int i = b.fLeft->fType.columns(); i > 1; --i) {
238 this->write(ByteCodeInstruction::kDup);
239 }
240 }
241 int count = slot_count(b.fType);
242 if (count > 1) {
243 this->write(ByteCodeInstruction::kVector);
244 this->write8(count);
245 }
246 switch (op) {
247 case Token::Kind::EQEQ:
248 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareIEQ,
249 ByteCodeInstruction::kCompareIEQ,
250 ByteCodeInstruction::kCompareFEQ);
251 break;
252 case Token::Kind::GT:
253 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGT,
254 ByteCodeInstruction::kCompareUGT,
255 ByteCodeInstruction::kCompareFGT);
256 break;
257 case Token::Kind::GTEQ:
258 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGTEQ,
259 ByteCodeInstruction::kCompareUGTEQ,
260 ByteCodeInstruction::kCompareFGTEQ);
261 break;
262 case Token::Kind::LT:
263 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLT,
264 ByteCodeInstruction::kCompareULT,
265 ByteCodeInstruction::kCompareFLT);
266 break;
267 case Token::Kind::LTEQ:
268 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLTEQ,
269 ByteCodeInstruction::kCompareULTEQ,
270 ByteCodeInstruction::kCompareFLTEQ);
271 break;
272 case Token::Kind::MINUS:
273 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kSubtractI,
274 ByteCodeInstruction::kSubtractI,
275 ByteCodeInstruction::kSubtractF);
276 break;
277 case Token::Kind::NEQ:
278 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareINEQ,
279 ByteCodeInstruction::kCompareINEQ,
280 ByteCodeInstruction::kCompareFNEQ);
281 break;
282 case Token::Kind::PERCENT:
283 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kRemainderS,
284 ByteCodeInstruction::kRemainderU,
Brian Osman3b41baf2019-05-08 09:24:46 -0400285 ByteCodeInstruction::kRemainderF);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400286 break;
287 case Token::Kind::PLUS:
288 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kAddI,
289 ByteCodeInstruction::kAddI,
290 ByteCodeInstruction::kAddF);
291 break;
292 case Token::Kind::SLASH:
293 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kDivideS,
294 ByteCodeInstruction::kDivideU,
295 ByteCodeInstruction::kDivideF);
296 break;
297 case Token::Kind::STAR:
298 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kMultiplyS,
299 ByteCodeInstruction::kMultiplyU,
300 ByteCodeInstruction::kMultiplyF);
301 break;
302 default:
303 SkASSERT(false);
304 }
305 if (lvalue) {
306 this->write(ByteCodeInstruction::kDupDown);
307 this->write8(slot_count(b.fType));
308 lvalue->store();
309 }
310}
311
312void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400313 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400314 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osman44d44762019-05-13 14:19:12 -0400315 this->write32(b.fValue ? 1 : 0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400316}
317
318void ByteCodeGenerator::writeConstructor(const Constructor& c) {
319 if (c.fArguments.size() == 1 &&
320 type_category(c.fType) == type_category(c.fArguments[0]->fType)) {
321 // cast from float to half or similar no-op
322 this->writeExpression(*c.fArguments[0]);
323 return;
324 }
325 for (const auto& arg : c.fArguments) {
326 this->writeExpression(*arg);
327 }
328 if (c.fArguments.size() == 1) {
329 TypeCategory inCategory = type_category(c.fArguments[0]->fType);
330 TypeCategory outCategory = type_category(c.fType);
331 if (inCategory != outCategory) {
332 int count = c.fType.columns();
333 if (count > 1) {
334 this->write(ByteCodeInstruction::kVector);
335 this->write8(count);
336 }
337 if (inCategory == TypeCategory::kFloat) {
338 SkASSERT(outCategory == TypeCategory::kSigned ||
339 outCategory == TypeCategory::kUnsigned);
340 this->write(ByteCodeInstruction::kFloatToInt);
341 } else if (outCategory == TypeCategory::kFloat) {
342 if (inCategory == TypeCategory::kSigned) {
343 this->write(ByteCodeInstruction::kSignedToFloat);
344 } else {
345 SkASSERT(inCategory == TypeCategory::kUnsigned);
346 this->write(ByteCodeInstruction::kUnsignedToFloat);
347 }
348 } else {
349 SkASSERT(false);
350 }
351 }
352 }
353}
354
355void ByteCodeGenerator::writeFieldAccess(const FieldAccess& f) {
356 // not yet implemented
357 abort();
358}
359
360void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400361 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400362 this->write(ByteCodeInstruction::kPushImmediate);
363 union { float f; uint32_t u; } pun = { (float) f.fValue };
364 this->write32(pun.u);
365}
366
367void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Brian Osman226668a2019-05-14 16:47:30 -0400368 for (const auto& arg : f.fArguments) {
369 this->writeExpression(*arg);
370 }
371 this->write(ByteCodeInstruction::kCall);
372 fCallTargets.emplace_back(this, f.fFunction);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400373}
374
375void ByteCodeGenerator::writeIndexExpression(const IndexExpression& i) {
376 // not yet implemented
377 abort();
378}
379
380void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400381 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400382 this->write(ByteCodeInstruction::kPushImmediate);
383 this->write32(i.fValue);
384}
385
386void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
387 // not yet implemented
388 abort();
389}
390
391void ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p) {
392 switch (p.fOperator) {
393 case Token::Kind::PLUSPLUS: // fall through
394 case Token::Kind::MINUSMINUS: {
395 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
396 lvalue->load();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400397 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400398 this->write(ByteCodeInstruction::kPushImmediate);
399 this->write32(1);
400 if (p.fOperator == Token::Kind::PLUSPLUS) {
401 this->writeTypedInstruction(p.fType,
402 ByteCodeInstruction::kAddI,
403 ByteCodeInstruction::kAddI,
404 ByteCodeInstruction::kAddF);
405 } else {
406 this->writeTypedInstruction(p.fType,
407 ByteCodeInstruction::kSubtractI,
408 ByteCodeInstruction::kSubtractI,
409 ByteCodeInstruction::kSubtractF);
410 }
411 this->write(ByteCodeInstruction::kDupDown);
412 this->write8(slot_count(p.fType));
413 lvalue->store();
414 break;
415 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400416 case Token::Kind::MINUS: {
417 this->writeExpression(*p.fOperand);
418 int count = slot_count(p.fOperand->fType);
419 if (count > 1) {
420 this->write(ByteCodeInstruction::kVector);
421 this->write8(count);
422 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400423 this->writeTypedInstruction(p.fType,
424 ByteCodeInstruction::kNegateS,
425 ByteCodeInstruction::kInvalid,
426 ByteCodeInstruction::kNegateF);
427 break;
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400428 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400429 default:
430 SkASSERT(false);
431 }
432}
433
434void ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p) {
435 // not yet implemented
436 abort();
437}
438
439void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
440 switch (s.fBase->fKind) {
441 case Expression::kVariableReference_Kind: {
442 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
443 int location = this->getLocation(var);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400444 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400445 this->write(ByteCodeInstruction::kPushImmediate);
446 this->write32(location);
447 this->write(ByteCodeInstruction::kLoadSwizzle);
448 this->write8(s.fComponents.size());
449 for (int c : s.fComponents) {
450 this->write8(c);
451 }
452 break;
453 }
454 default:
455 this->writeExpression(*s.fBase);
456 this->write(ByteCodeInstruction::kSwizzle);
457 this->write8(s.fBase->fType.columns());
458 this->write8(s.fComponents.size());
459 for (int c : s.fComponents) {
460 this->write8(c);
461 }
462 }
463}
464
465void ByteCodeGenerator::writeVariableReference(const VariableReference& v) {
466 if (v.fVariable.fStorage == Variable::kGlobal_Storage) {
467 this->write(ByteCodeInstruction::kLoadGlobal);
468 int location = this->getLocation(v.fVariable);
469 SkASSERT(location <= 255);
470 this->write8(location);
471 } else {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400472 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400473 this->write(ByteCodeInstruction::kPushImmediate);
474 this->write32(this->getLocation(v.fVariable));
475 int count = slot_count(v.fType);
476 if (count > 1) {
477 this->write(ByteCodeInstruction::kVector);
478 this->write8(count);
479 }
480 this->write(ByteCodeInstruction::kLoad);
481 }
482}
483
484void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
485 // not yet implemented
486 abort();
487}
488
489void ByteCodeGenerator::writeExpression(const Expression& e) {
490 switch (e.fKind) {
491 case Expression::kBinary_Kind:
492 this->writeBinaryExpression((BinaryExpression&) e);
493 break;
494 case Expression::kBoolLiteral_Kind:
495 this->writeBoolLiteral((BoolLiteral&) e);
496 break;
497 case Expression::kConstructor_Kind:
498 this->writeConstructor((Constructor&) e);
499 break;
500 case Expression::kFieldAccess_Kind:
501 this->writeFieldAccess((FieldAccess&) e);
502 break;
503 case Expression::kFloatLiteral_Kind:
504 this->writeFloatLiteral((FloatLiteral&) e);
505 break;
506 case Expression::kFunctionCall_Kind:
507 this->writeFunctionCall((FunctionCall&) e);
508 break;
509 case Expression::kIndex_Kind:
510 this->writeIndexExpression((IndexExpression&) e);
511 break;
512 case Expression::kIntLiteral_Kind:
513 this->writeIntLiteral((IntLiteral&) e);
514 break;
515 case Expression::kNullLiteral_Kind:
516 this->writeNullLiteral((NullLiteral&) e);
517 break;
518 case Expression::kPrefix_Kind:
519 this->writePrefixExpression((PrefixExpression&) e);
520 break;
521 case Expression::kPostfix_Kind:
522 this->writePostfixExpression((PostfixExpression&) e);
523 break;
524 case Expression::kSwizzle_Kind:
525 this->writeSwizzle((Swizzle&) e);
526 break;
527 case Expression::kVariableReference_Kind:
528 this->writeVariableReference((VariableReference&) e);
529 break;
530 case Expression::kTernary_Kind:
531 this->writeTernaryExpression((TernaryExpression&) e);
532 break;
533 default:
534 printf("unsupported expression %s\n", e.description().c_str());
535 SkASSERT(false);
536 }
537}
538
539void ByteCodeGenerator::writeTarget(const Expression& e) {
540 switch (e.fKind) {
541 case Expression::kVariableReference_Kind:
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400542 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400543 this->write(ByteCodeInstruction::kPushImmediate);
544 this->write32(this->getLocation(((VariableReference&) e).fVariable));
545 break;
546 case Expression::kIndex_Kind:
547 case Expression::kTernary_Kind:
548 default:
549 printf("unsupported target %s\n", e.description().c_str());
550 SkASSERT(false);
551 }
552}
553
554class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
555public:
556 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
557 : INHERITED(*generator)
558 , fSwizzle(swizzle) {
559 fGenerator.writeTarget(*swizzle.fBase);
560 }
561
562 void load() override {
563 fGenerator.write(ByteCodeInstruction::kDup);
564 fGenerator.write(ByteCodeInstruction::kLoadSwizzle);
565 fGenerator.write8(fSwizzle.fComponents.size());
566 for (int c : fSwizzle.fComponents) {
567 fGenerator.write8(c);
568 }
569 }
570
571 void store() override {
572 fGenerator.write(ByteCodeInstruction::kStoreSwizzle);
573 fGenerator.write8(fSwizzle.fComponents.size());
574 for (int c : fSwizzle.fComponents) {
575 fGenerator.write8(c);
576 }
577 }
578
579private:
580 const Swizzle& fSwizzle;
581
582 typedef LValue INHERITED;
583};
584
585class ByteCodeVariableLValue : public ByteCodeGenerator::LValue {
586public:
587 ByteCodeVariableLValue(ByteCodeGenerator* generator, const Variable& var)
588 : INHERITED(*generator)
589 , fCount(slot_count(var.fType))
590 , fIsGlobal(var.fStorage == Variable::kGlobal_Storage) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400591 fGenerator.align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400592 fGenerator.write(ByteCodeInstruction::kPushImmediate);
593 fGenerator.write32(generator->getLocation(var));
594 }
595
596 void load() override {
597 fGenerator.write(ByteCodeInstruction::kDup);
598 if (fCount > 1) {
599 fGenerator.write(ByteCodeInstruction::kVector);
600 fGenerator.write8(fCount);
601 }
602 fGenerator.write(fIsGlobal ? ByteCodeInstruction::kLoadGlobal : ByteCodeInstruction::kLoad);
603 }
604
605 void store() override {
606 if (fCount > 1) {
607 fGenerator.write(ByteCodeInstruction::kVector);
608 fGenerator.write8(fCount);
609 }
610 fGenerator.write(fIsGlobal ? ByteCodeInstruction::kStoreGlobal
611 : ByteCodeInstruction::kStore);
612 }
613
614private:
615 typedef LValue INHERITED;
616
617 int fCount;
618
619 bool fIsGlobal;
620};
621
622std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
623 switch (e.fKind) {
624 case Expression::kIndex_Kind:
625 // not yet implemented
626 abort();
627 case Expression::kVariableReference_Kind:
628 return std::unique_ptr<LValue>(new ByteCodeVariableLValue(this,
629 ((VariableReference&) e).fVariable));
630 case Expression::kSwizzle_Kind:
631 return std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, (Swizzle&) e));
632 case Expression::kTernary_Kind:
633 default:
634 printf("unsupported lvalue %s\n", e.description().c_str());
635 return nullptr;
636 }
637}
638
639void ByteCodeGenerator::writeBlock(const Block& b) {
640 for (const auto& s : b.fStatements) {
641 this->writeStatement(*s);
642 }
643}
644
645void ByteCodeGenerator::setBreakTargets() {
646 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
647 for (DeferredLocation& b : breaks) {
648 b.set();
649 }
650 fBreakTargets.pop();
651}
652
653void ByteCodeGenerator::setContinueTargets() {
654 std::vector<DeferredLocation>& continues = fContinueTargets.top();
655 for (DeferredLocation& c : continues) {
656 c.set();
657 }
658 fContinueTargets.pop();
659}
660
661void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400662 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400663 this->write(ByteCodeInstruction::kBranch);
664 fBreakTargets.top().emplace_back(this);
665}
666
667void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400668 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400669 this->write(ByteCodeInstruction::kBranch);
670 fContinueTargets.top().emplace_back(this);
671}
672
673void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
674 fContinueTargets.emplace();
675 fBreakTargets.emplace();
676 size_t start = fCode->size();
677 this->writeStatement(*d.fStatement);
678 this->setContinueTargets();
679 this->writeExpression(*d.fTest);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400680 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400681 this->write(ByteCodeInstruction::kConditionalBranch);
682 this->write16(start);
683 this->setBreakTargets();
684}
685
686void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
687 fContinueTargets.emplace();
688 fBreakTargets.emplace();
689 if (f.fInitializer) {
690 this->writeStatement(*f.fInitializer);
691 }
692 size_t start = fCode->size();
693 if (f.fTest) {
694 this->writeExpression(*f.fTest);
695 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400696 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400697 this->write(ByteCodeInstruction::kConditionalBranch);
698 DeferredLocation endLocation(this);
699 this->writeStatement(*f.fStatement);
700 this->setContinueTargets();
701 if (f.fNext) {
702 this->writeExpression(*f.fNext);
703 this->write(ByteCodeInstruction::kPop);
704 this->write8(slot_count(f.fNext->fType));
705 }
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 this->write16(start);
709 endLocation.set();
710 } else {
711 this->writeStatement(*f.fStatement);
712 this->setContinueTargets();
713 if (f.fNext) {
714 this->writeExpression(*f.fNext);
715 this->write(ByteCodeInstruction::kPop);
716 this->write8(slot_count(f.fNext->fType));
717 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400718 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400719 this->write(ByteCodeInstruction::kBranch);
720 this->write16(start);
721 }
722 this->setBreakTargets();
723}
724
725void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
726 this->writeExpression(*i.fTest);
727 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400728 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400729 this->write(ByteCodeInstruction::kConditionalBranch);
730 DeferredLocation elseLocation(this);
731 this->writeStatement(*i.fIfTrue);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400732 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400733 this->write(ByteCodeInstruction::kBranch);
734 DeferredLocation endLocation(this);
735 elseLocation.set();
736 if (i.fIfFalse) {
737 this->writeStatement(*i.fIfFalse);
738 }
739 endLocation.set();
740}
741
742void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -0400743 this->writeExpression(*r.fExpression);
744 this->write(ByteCodeInstruction::kReturn);
745 this->write8(r.fExpression->fType.columns() * r.fExpression->fType.rows());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400746}
747
748void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
749 // not yet implemented
750 abort();
751}
752
753void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
754 for (const auto& declStatement : v.fVars) {
755 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
756 // we need to grab the location even if we don't use it, to ensure it
757 // has been allocated
758 int location = getLocation(*decl.fVar);
759 if (decl.fValue) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400760 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400761 this->write(ByteCodeInstruction::kPushImmediate);
762 this->write32(location);
763 this->writeExpression(*decl.fValue);
764 int count = slot_count(decl.fValue->fType);
765 if (count > 1) {
766 this->write(ByteCodeInstruction::kVector);
767 this->write8(count);
768 }
769 this->write(ByteCodeInstruction::kStore);
770 }
771 }
772}
773
774void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
775 fContinueTargets.emplace();
776 fBreakTargets.emplace();
777 size_t start = fCode->size();
778 this->writeExpression(*w.fTest);
779 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400780 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400781 this->write(ByteCodeInstruction::kConditionalBranch);
782 DeferredLocation endLocation(this);
783 this->writeStatement(*w.fStatement);
784 this->setContinueTargets();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400785 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400786 this->write(ByteCodeInstruction::kBranch);
787 this->write16(start);
788 endLocation.set();
789 this->setBreakTargets();
790}
791
792void ByteCodeGenerator::writeStatement(const Statement& s) {
793 switch (s.fKind) {
794 case Statement::kBlock_Kind:
795 this->writeBlock((Block&) s);
796 break;
797 case Statement::kBreak_Kind:
798 this->writeBreakStatement((BreakStatement&) s);
799 break;
800 case Statement::kContinue_Kind:
801 this->writeContinueStatement((ContinueStatement&) s);
802 break;
803 case Statement::kDiscard_Kind:
804 // not yet implemented
805 abort();
806 case Statement::kDo_Kind:
807 this->writeDoStatement((DoStatement&) s);
808 break;
809 case Statement::kExpression_Kind: {
810 const Expression& expr = *((ExpressionStatement&) s).fExpression;
811 this->writeExpression(expr);
812 this->write(ByteCodeInstruction::kPop);
813 this->write8(slot_count(expr.fType));
814 break;
815 }
816 case Statement::kFor_Kind:
817 this->writeForStatement((ForStatement&) s);
818 break;
819 case Statement::kIf_Kind:
820 this->writeIfStatement((IfStatement&) s);
821 break;
822 case Statement::kNop_Kind:
823 break;
824 case Statement::kReturn_Kind:
825 this->writeReturnStatement((ReturnStatement&) s);
826 break;
827 case Statement::kSwitch_Kind:
828 this->writeSwitchStatement((SwitchStatement&) s);
829 break;
830 case Statement::kVarDeclarations_Kind:
831 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
832 break;
833 case Statement::kWhile_Kind:
834 this->writeWhileStatement((WhileStatement&) s);
835 break;
836 default:
837 SkASSERT(false);
838 }
839}
840
841}