blob: ed5ad3971a411678e6be1280b2c804983ef20488 [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);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400214 lvalue->store();
215 return;
216 }
217 Token::Kind op;
218 std::unique_ptr<LValue> lvalue;
219 if (is_assignment(b.fOperator)) {
220 lvalue = this->getLValue(*b.fLeft);
221 lvalue->load();
222 op = remove_assignment(b.fOperator);
223 } else {
224 this->writeExpression(*b.fLeft);
225 op = b.fOperator;
226 if (b.fLeft->fType.kind() == Type::kScalar_Kind &&
227 b.fRight->fType.kind() == Type::kVector_Kind) {
228 for (int i = b.fRight->fType.columns(); i > 1; --i) {
229 this->write(ByteCodeInstruction::kDup);
230 }
231 }
232 }
233 this->writeExpression(*b.fRight);
234 if (b.fLeft->fType.kind() == Type::kVector_Kind &&
235 b.fRight->fType.kind() == Type::kScalar_Kind) {
236 for (int i = b.fLeft->fType.columns(); i > 1; --i) {
237 this->write(ByteCodeInstruction::kDup);
238 }
239 }
240 int count = slot_count(b.fType);
241 if (count > 1) {
242 this->write(ByteCodeInstruction::kVector);
243 this->write8(count);
244 }
245 switch (op) {
246 case Token::Kind::EQEQ:
247 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareIEQ,
248 ByteCodeInstruction::kCompareIEQ,
249 ByteCodeInstruction::kCompareFEQ);
250 break;
251 case Token::Kind::GT:
252 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGT,
253 ByteCodeInstruction::kCompareUGT,
254 ByteCodeInstruction::kCompareFGT);
255 break;
256 case Token::Kind::GTEQ:
257 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGTEQ,
258 ByteCodeInstruction::kCompareUGTEQ,
259 ByteCodeInstruction::kCompareFGTEQ);
260 break;
261 case Token::Kind::LT:
262 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLT,
263 ByteCodeInstruction::kCompareULT,
264 ByteCodeInstruction::kCompareFLT);
265 break;
266 case Token::Kind::LTEQ:
267 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLTEQ,
268 ByteCodeInstruction::kCompareULTEQ,
269 ByteCodeInstruction::kCompareFLTEQ);
270 break;
271 case Token::Kind::MINUS:
272 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kSubtractI,
273 ByteCodeInstruction::kSubtractI,
274 ByteCodeInstruction::kSubtractF);
275 break;
276 case Token::Kind::NEQ:
277 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareINEQ,
278 ByteCodeInstruction::kCompareINEQ,
279 ByteCodeInstruction::kCompareFNEQ);
280 break;
281 case Token::Kind::PERCENT:
282 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kRemainderS,
283 ByteCodeInstruction::kRemainderU,
Brian Osman3b41baf2019-05-08 09:24:46 -0400284 ByteCodeInstruction::kRemainderF);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400285 break;
286 case Token::Kind::PLUS:
287 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kAddI,
288 ByteCodeInstruction::kAddI,
289 ByteCodeInstruction::kAddF);
290 break;
291 case Token::Kind::SLASH:
292 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kDivideS,
293 ByteCodeInstruction::kDivideU,
294 ByteCodeInstruction::kDivideF);
295 break;
296 case Token::Kind::STAR:
Ethan Nicholas91164d12019-05-15 15:29:54 -0400297 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kMultiplyI,
298 ByteCodeInstruction::kMultiplyI,
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400299 ByteCodeInstruction::kMultiplyF);
300 break;
301 default:
302 SkASSERT(false);
303 }
304 if (lvalue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400305 lvalue->store();
306 }
307}
308
309void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400310 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400311 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osman44d44762019-05-13 14:19:12 -0400312 this->write32(b.fValue ? 1 : 0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400313}
314
315void ByteCodeGenerator::writeConstructor(const Constructor& c) {
316 if (c.fArguments.size() == 1 &&
317 type_category(c.fType) == type_category(c.fArguments[0]->fType)) {
318 // cast from float to half or similar no-op
319 this->writeExpression(*c.fArguments[0]);
320 return;
321 }
322 for (const auto& arg : c.fArguments) {
323 this->writeExpression(*arg);
324 }
325 if (c.fArguments.size() == 1) {
326 TypeCategory inCategory = type_category(c.fArguments[0]->fType);
327 TypeCategory outCategory = type_category(c.fType);
328 if (inCategory != outCategory) {
329 int count = c.fType.columns();
330 if (count > 1) {
331 this->write(ByteCodeInstruction::kVector);
332 this->write8(count);
333 }
334 if (inCategory == TypeCategory::kFloat) {
335 SkASSERT(outCategory == TypeCategory::kSigned ||
336 outCategory == TypeCategory::kUnsigned);
337 this->write(ByteCodeInstruction::kFloatToInt);
338 } else if (outCategory == TypeCategory::kFloat) {
339 if (inCategory == TypeCategory::kSigned) {
340 this->write(ByteCodeInstruction::kSignedToFloat);
341 } else {
342 SkASSERT(inCategory == TypeCategory::kUnsigned);
343 this->write(ByteCodeInstruction::kUnsignedToFloat);
344 }
345 } else {
346 SkASSERT(false);
347 }
348 }
349 }
350}
351
Ethan Nicholas91164d12019-05-15 15:29:54 -0400352void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
353 int count = slot_count(e.fValue->type());
354 if (count > 1) {
355 this->write(ByteCodeInstruction::kVector);
356 this->write8(count);
357 }
358 this->write(ByteCodeInstruction::kReadExternal);
359 int index = fOutput->fExternalValues.size();
360 fOutput->fExternalValues.push_back(e.fValue);
361 SkASSERT(index <= 255);
362 this->write8(index);
363}
364
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400365void ByteCodeGenerator::writeFieldAccess(const FieldAccess& f) {
366 // not yet implemented
367 abort();
368}
369
370void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400371 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400372 this->write(ByteCodeInstruction::kPushImmediate);
373 union { float f; uint32_t u; } pun = { (float) f.fValue };
374 this->write32(pun.u);
375}
376
377void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Brian Osman226668a2019-05-14 16:47:30 -0400378 for (const auto& arg : f.fArguments) {
379 this->writeExpression(*arg);
380 }
381 this->write(ByteCodeInstruction::kCall);
382 fCallTargets.emplace_back(this, f.fFunction);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400383}
384
385void ByteCodeGenerator::writeIndexExpression(const IndexExpression& i) {
386 // not yet implemented
387 abort();
388}
389
390void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400391 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400392 this->write(ByteCodeInstruction::kPushImmediate);
393 this->write32(i.fValue);
394}
395
396void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
397 // not yet implemented
398 abort();
399}
400
401void ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p) {
402 switch (p.fOperator) {
403 case Token::Kind::PLUSPLUS: // fall through
404 case Token::Kind::MINUSMINUS: {
405 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
406 lvalue->load();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400407 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400408 this->write(ByteCodeInstruction::kPushImmediate);
409 this->write32(1);
410 if (p.fOperator == Token::Kind::PLUSPLUS) {
411 this->writeTypedInstruction(p.fType,
412 ByteCodeInstruction::kAddI,
413 ByteCodeInstruction::kAddI,
414 ByteCodeInstruction::kAddF);
415 } else {
416 this->writeTypedInstruction(p.fType,
417 ByteCodeInstruction::kSubtractI,
418 ByteCodeInstruction::kSubtractI,
419 ByteCodeInstruction::kSubtractF);
420 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400421 lvalue->store();
422 break;
423 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400424 case Token::Kind::MINUS: {
425 this->writeExpression(*p.fOperand);
426 int count = slot_count(p.fOperand->fType);
427 if (count > 1) {
428 this->write(ByteCodeInstruction::kVector);
429 this->write8(count);
430 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400431 this->writeTypedInstruction(p.fType,
432 ByteCodeInstruction::kNegateS,
433 ByteCodeInstruction::kInvalid,
434 ByteCodeInstruction::kNegateF);
435 break;
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400436 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400437 default:
438 SkASSERT(false);
439 }
440}
441
442void ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p) {
443 // not yet implemented
444 abort();
445}
446
447void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
448 switch (s.fBase->fKind) {
449 case Expression::kVariableReference_Kind: {
450 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
Brian Osmanb7451292019-05-15 13:02:13 -0400451 if (var.fStorage == Variable::kGlobal_Storage) {
452 this->write(ByteCodeInstruction::kLoadSwizzleGlobal);
453 this->write8(this->getLocation(var));
454 } else {
455 this->align(4, 3);
456 this->write(ByteCodeInstruction::kPushImmediate);
457 this->write32(this->getLocation(var));
458 this->write(ByteCodeInstruction::kLoadSwizzle);
459 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400460 this->write8(s.fComponents.size());
461 for (int c : s.fComponents) {
462 this->write8(c);
463 }
464 break;
465 }
466 default:
467 this->writeExpression(*s.fBase);
468 this->write(ByteCodeInstruction::kSwizzle);
469 this->write8(s.fBase->fType.columns());
470 this->write8(s.fComponents.size());
471 for (int c : s.fComponents) {
472 this->write8(c);
473 }
474 }
475}
476
477void ByteCodeGenerator::writeVariableReference(const VariableReference& v) {
478 if (v.fVariable.fStorage == Variable::kGlobal_Storage) {
Brian Osmanb7451292019-05-15 13:02:13 -0400479 int count = slot_count(v.fType);
480 if (count > 1) {
481 this->write(ByteCodeInstruction::kVector);
482 this->write8(count);
483 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400484 this->write(ByteCodeInstruction::kLoadGlobal);
Brian Osmanb7451292019-05-15 13:02:13 -0400485 this->write8(this->getLocation(v.fVariable));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400486 } else {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400487 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400488 this->write(ByteCodeInstruction::kPushImmediate);
489 this->write32(this->getLocation(v.fVariable));
490 int count = slot_count(v.fType);
491 if (count > 1) {
492 this->write(ByteCodeInstruction::kVector);
493 this->write8(count);
494 }
495 this->write(ByteCodeInstruction::kLoad);
496 }
497}
498
499void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
500 // not yet implemented
501 abort();
502}
503
504void ByteCodeGenerator::writeExpression(const Expression& e) {
505 switch (e.fKind) {
506 case Expression::kBinary_Kind:
507 this->writeBinaryExpression((BinaryExpression&) e);
508 break;
509 case Expression::kBoolLiteral_Kind:
510 this->writeBoolLiteral((BoolLiteral&) e);
511 break;
512 case Expression::kConstructor_Kind:
513 this->writeConstructor((Constructor&) e);
514 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400515 case Expression::kExternalValue_Kind:
516 this->writeExternalValue((ExternalValueReference&) e);
517 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400518 case Expression::kFieldAccess_Kind:
519 this->writeFieldAccess((FieldAccess&) e);
520 break;
521 case Expression::kFloatLiteral_Kind:
522 this->writeFloatLiteral((FloatLiteral&) e);
523 break;
524 case Expression::kFunctionCall_Kind:
525 this->writeFunctionCall((FunctionCall&) e);
526 break;
527 case Expression::kIndex_Kind:
528 this->writeIndexExpression((IndexExpression&) e);
529 break;
530 case Expression::kIntLiteral_Kind:
531 this->writeIntLiteral((IntLiteral&) e);
532 break;
533 case Expression::kNullLiteral_Kind:
534 this->writeNullLiteral((NullLiteral&) e);
535 break;
536 case Expression::kPrefix_Kind:
537 this->writePrefixExpression((PrefixExpression&) e);
538 break;
539 case Expression::kPostfix_Kind:
540 this->writePostfixExpression((PostfixExpression&) e);
541 break;
542 case Expression::kSwizzle_Kind:
543 this->writeSwizzle((Swizzle&) e);
544 break;
545 case Expression::kVariableReference_Kind:
546 this->writeVariableReference((VariableReference&) e);
547 break;
548 case Expression::kTernary_Kind:
549 this->writeTernaryExpression((TernaryExpression&) e);
550 break;
551 default:
552 printf("unsupported expression %s\n", e.description().c_str());
553 SkASSERT(false);
554 }
555}
556
557void ByteCodeGenerator::writeTarget(const Expression& e) {
558 switch (e.fKind) {
559 case Expression::kVariableReference_Kind:
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400560 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400561 this->write(ByteCodeInstruction::kPushImmediate);
562 this->write32(this->getLocation(((VariableReference&) e).fVariable));
563 break;
564 case Expression::kIndex_Kind:
565 case Expression::kTernary_Kind:
566 default:
567 printf("unsupported target %s\n", e.description().c_str());
568 SkASSERT(false);
569 }
570}
571
Ethan Nicholas91164d12019-05-15 15:29:54 -0400572class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
573public:
574 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
575 : INHERITED(*generator)
576 , fCount(slot_count(value.type()))
577 , fIndex(index) {}
578
579 void load() override {
580 if (fCount > 1) {
581 fGenerator.write(ByteCodeInstruction::kVector);
582 fGenerator.write8(fCount);
583 }
584 fGenerator.write(ByteCodeInstruction::kReadExternal);
585 fGenerator.write8(fIndex);
586 }
587
588 void store() override {
589 if (fCount > 1) {
590 fGenerator.write(ByteCodeInstruction::kVector);
591 fGenerator.write8(fCount);
592 }
593 fGenerator.write(ByteCodeInstruction::kDup);
594 if (fCount > 1) {
595 fGenerator.write(ByteCodeInstruction::kVector);
596 fGenerator.write8(fCount);
597 }
598 fGenerator.write(ByteCodeInstruction::kWriteExternal);
599 fGenerator.write8(fIndex);
600 }
601
602private:
603 typedef LValue INHERITED;
604
605 int fCount;
606
607 int fIndex;
608};
609
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400610class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
611public:
612 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
613 : INHERITED(*generator)
614 , fSwizzle(swizzle) {
615 fGenerator.writeTarget(*swizzle.fBase);
616 }
617
618 void load() override {
619 fGenerator.write(ByteCodeInstruction::kDup);
620 fGenerator.write(ByteCodeInstruction::kLoadSwizzle);
621 fGenerator.write8(fSwizzle.fComponents.size());
622 for (int c : fSwizzle.fComponents) {
623 fGenerator.write8(c);
624 }
625 }
626
627 void store() override {
Ethan Nicholas91164d12019-05-15 15:29:54 -0400628 size_t count = fSwizzle.fComponents.size();
629 fGenerator.write(ByteCodeInstruction::kDupDown);
630 fGenerator.write8(count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400631 fGenerator.write(ByteCodeInstruction::kStoreSwizzle);
Ethan Nicholas91164d12019-05-15 15:29:54 -0400632 fGenerator.write8(count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400633 for (int c : fSwizzle.fComponents) {
634 fGenerator.write8(c);
635 }
636 }
637
638private:
639 const Swizzle& fSwizzle;
640
641 typedef LValue INHERITED;
642};
643
644class ByteCodeVariableLValue : public ByteCodeGenerator::LValue {
645public:
646 ByteCodeVariableLValue(ByteCodeGenerator* generator, const Variable& var)
647 : INHERITED(*generator)
648 , fCount(slot_count(var.fType))
649 , fIsGlobal(var.fStorage == Variable::kGlobal_Storage) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400650 fGenerator.align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400651 fGenerator.write(ByteCodeInstruction::kPushImmediate);
652 fGenerator.write32(generator->getLocation(var));
653 }
654
655 void load() override {
656 fGenerator.write(ByteCodeInstruction::kDup);
657 if (fCount > 1) {
658 fGenerator.write(ByteCodeInstruction::kVector);
659 fGenerator.write8(fCount);
660 }
661 fGenerator.write(fIsGlobal ? ByteCodeInstruction::kLoadGlobal : ByteCodeInstruction::kLoad);
662 }
663
664 void store() override {
Ethan Nicholas91164d12019-05-15 15:29:54 -0400665 fGenerator.write(ByteCodeInstruction::kDupDown);
666 fGenerator.write8(fCount);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400667 if (fCount > 1) {
668 fGenerator.write(ByteCodeInstruction::kVector);
669 fGenerator.write8(fCount);
670 }
671 fGenerator.write(fIsGlobal ? ByteCodeInstruction::kStoreGlobal
672 : ByteCodeInstruction::kStore);
673 }
674
675private:
676 typedef LValue INHERITED;
677
678 int fCount;
679
680 bool fIsGlobal;
681};
682
683std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
684 switch (e.fKind) {
Ethan Nicholas91164d12019-05-15 15:29:54 -0400685 case Expression::kExternalValue_Kind: {
686 ExternalValue* value = ((ExternalValueReference&) e).fValue;
687 int index = fOutput->fExternalValues.size();
688 fOutput->fExternalValues.push_back(value);
689 SkASSERT(index <= 255);
690 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
691 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400692 case Expression::kIndex_Kind:
693 // not yet implemented
694 abort();
695 case Expression::kVariableReference_Kind:
696 return std::unique_ptr<LValue>(new ByteCodeVariableLValue(this,
697 ((VariableReference&) e).fVariable));
698 case Expression::kSwizzle_Kind:
699 return std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, (Swizzle&) e));
700 case Expression::kTernary_Kind:
701 default:
702 printf("unsupported lvalue %s\n", e.description().c_str());
703 return nullptr;
704 }
705}
706
707void ByteCodeGenerator::writeBlock(const Block& b) {
708 for (const auto& s : b.fStatements) {
709 this->writeStatement(*s);
710 }
711}
712
713void ByteCodeGenerator::setBreakTargets() {
714 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
715 for (DeferredLocation& b : breaks) {
716 b.set();
717 }
718 fBreakTargets.pop();
719}
720
721void ByteCodeGenerator::setContinueTargets() {
722 std::vector<DeferredLocation>& continues = fContinueTargets.top();
723 for (DeferredLocation& c : continues) {
724 c.set();
725 }
726 fContinueTargets.pop();
727}
728
729void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400730 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400731 this->write(ByteCodeInstruction::kBranch);
732 fBreakTargets.top().emplace_back(this);
733}
734
735void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400736 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400737 this->write(ByteCodeInstruction::kBranch);
738 fContinueTargets.top().emplace_back(this);
739}
740
741void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
742 fContinueTargets.emplace();
743 fBreakTargets.emplace();
744 size_t start = fCode->size();
745 this->writeStatement(*d.fStatement);
746 this->setContinueTargets();
747 this->writeExpression(*d.fTest);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400748 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400749 this->write(ByteCodeInstruction::kConditionalBranch);
750 this->write16(start);
751 this->setBreakTargets();
752}
753
754void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
755 fContinueTargets.emplace();
756 fBreakTargets.emplace();
757 if (f.fInitializer) {
758 this->writeStatement(*f.fInitializer);
759 }
760 size_t start = fCode->size();
761 if (f.fTest) {
762 this->writeExpression(*f.fTest);
763 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400764 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400765 this->write(ByteCodeInstruction::kConditionalBranch);
766 DeferredLocation endLocation(this);
767 this->writeStatement(*f.fStatement);
768 this->setContinueTargets();
769 if (f.fNext) {
770 this->writeExpression(*f.fNext);
771 this->write(ByteCodeInstruction::kPop);
772 this->write8(slot_count(f.fNext->fType));
773 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400774 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400775 this->write(ByteCodeInstruction::kBranch);
776 this->write16(start);
777 endLocation.set();
778 } else {
779 this->writeStatement(*f.fStatement);
780 this->setContinueTargets();
781 if (f.fNext) {
782 this->writeExpression(*f.fNext);
783 this->write(ByteCodeInstruction::kPop);
784 this->write8(slot_count(f.fNext->fType));
785 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400786 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400787 this->write(ByteCodeInstruction::kBranch);
788 this->write16(start);
789 }
790 this->setBreakTargets();
791}
792
793void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
794 this->writeExpression(*i.fTest);
795 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400796 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400797 this->write(ByteCodeInstruction::kConditionalBranch);
798 DeferredLocation elseLocation(this);
799 this->writeStatement(*i.fIfTrue);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400800 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400801 this->write(ByteCodeInstruction::kBranch);
802 DeferredLocation endLocation(this);
803 elseLocation.set();
804 if (i.fIfFalse) {
805 this->writeStatement(*i.fIfFalse);
806 }
807 endLocation.set();
808}
809
810void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -0400811 this->writeExpression(*r.fExpression);
812 this->write(ByteCodeInstruction::kReturn);
813 this->write8(r.fExpression->fType.columns() * r.fExpression->fType.rows());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400814}
815
816void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
817 // not yet implemented
818 abort();
819}
820
821void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
822 for (const auto& declStatement : v.fVars) {
823 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
824 // we need to grab the location even if we don't use it, to ensure it
825 // has been allocated
826 int location = getLocation(*decl.fVar);
827 if (decl.fValue) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400828 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400829 this->write(ByteCodeInstruction::kPushImmediate);
830 this->write32(location);
831 this->writeExpression(*decl.fValue);
832 int count = slot_count(decl.fValue->fType);
833 if (count > 1) {
834 this->write(ByteCodeInstruction::kVector);
835 this->write8(count);
836 }
837 this->write(ByteCodeInstruction::kStore);
838 }
839 }
840}
841
842void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
843 fContinueTargets.emplace();
844 fBreakTargets.emplace();
845 size_t start = fCode->size();
846 this->writeExpression(*w.fTest);
847 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400848 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400849 this->write(ByteCodeInstruction::kConditionalBranch);
850 DeferredLocation endLocation(this);
851 this->writeStatement(*w.fStatement);
852 this->setContinueTargets();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400853 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400854 this->write(ByteCodeInstruction::kBranch);
855 this->write16(start);
856 endLocation.set();
857 this->setBreakTargets();
858}
859
860void ByteCodeGenerator::writeStatement(const Statement& s) {
861 switch (s.fKind) {
862 case Statement::kBlock_Kind:
863 this->writeBlock((Block&) s);
864 break;
865 case Statement::kBreak_Kind:
866 this->writeBreakStatement((BreakStatement&) s);
867 break;
868 case Statement::kContinue_Kind:
869 this->writeContinueStatement((ContinueStatement&) s);
870 break;
871 case Statement::kDiscard_Kind:
872 // not yet implemented
873 abort();
874 case Statement::kDo_Kind:
875 this->writeDoStatement((DoStatement&) s);
876 break;
877 case Statement::kExpression_Kind: {
878 const Expression& expr = *((ExpressionStatement&) s).fExpression;
879 this->writeExpression(expr);
880 this->write(ByteCodeInstruction::kPop);
881 this->write8(slot_count(expr.fType));
882 break;
883 }
884 case Statement::kFor_Kind:
885 this->writeForStatement((ForStatement&) s);
886 break;
887 case Statement::kIf_Kind:
888 this->writeIfStatement((IfStatement&) s);
889 break;
890 case Statement::kNop_Kind:
891 break;
892 case Statement::kReturn_Kind:
893 this->writeReturnStatement((ReturnStatement&) s);
894 break;
895 case Statement::kSwitch_Kind:
896 this->writeSwitchStatement((SwitchStatement&) s);
897 break;
898 case Statement::kVarDeclarations_Kind:
899 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
900 break;
901 case Statement::kWhile_Kind:
902 this->writeWhileStatement((WhileStatement&) s);
903 break;
904 default:
905 SkASSERT(false);
906 }
907}
908
909}