blob: 74464c2adad96ecf04288dc5990f956e119bc134 [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) {
Brian Osman1091f022019-05-16 09:42:16 -0400112 SkASSERT(fParameterCount + i <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400113 return fParameterCount + i;
114 }
115 }
116 int result = fParameterCount + fLocals.size();
117 fLocals.push_back(&var);
118 for (int i = 0; i < slot_count(var.fType) - 1; ++i) {
119 fLocals.push_back(nullptr);
120 }
Brian Osman1091f022019-05-16 09:42:16 -0400121 SkASSERT(result <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400122 return result;
123 }
124 case Variable::kParameter_Storage: {
125 int offset = 0;
126 for (const auto& p : fFunction->fDeclaration.fParameters) {
127 if (p == &var) {
Brian Osman1091f022019-05-16 09:42:16 -0400128 SkASSERT(offset <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400129 return offset;
130 }
131 offset += slot_count(p->fType);
132 }
133 SkASSERT(false);
Brian Osman1091f022019-05-16 09:42:16 -0400134 return 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400135 }
136 case Variable::kGlobal_Storage: {
137 int offset = 0;
138 for (const auto& e : fProgram) {
139 if (e.fKind == ProgramElement::kVar_Kind) {
140 VarDeclarations& decl = (VarDeclarations&) e;
141 for (const auto& v : decl.fVars) {
142 const Variable* declVar = ((VarDeclaration&) *v).fVar;
143 if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
144 continue;
145 }
146 if (declVar == &var) {
Brian Osmanb7451292019-05-15 13:02:13 -0400147 SkASSERT(offset <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400148 return offset;
149 }
150 offset += slot_count(declVar->fType);
151 }
152 }
153 }
154 SkASSERT(false);
Brian Osman1091f022019-05-16 09:42:16 -0400155 return 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400156 }
157 default:
158 SkASSERT(false);
159 return 0;
160 }
161}
162
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400163void ByteCodeGenerator::align(int divisor, int remainder) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400164 switch (remainder - (int) fCode->size() % divisor) {
165 case 0: return;
166 case 3: this->write(ByteCodeInstruction::kNop3); // fall through
167 case 2: this->write(ByteCodeInstruction::kNop2); // fall through
168 case 1: this->write(ByteCodeInstruction::kNop1);
169 break;
170 default: SkASSERT(false);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400171 }
172}
173
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400174void ByteCodeGenerator::write8(uint8_t b) {
175 fCode->push_back(b);
176}
177
178void ByteCodeGenerator::write16(uint16_t i) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400179 SkASSERT(fCode->size() % 2 == 0);
180 this->write8(i >> 0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400181 this->write8(i >> 8);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400182}
183
184void ByteCodeGenerator::write32(uint32_t i) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400185 SkASSERT(fCode->size() % 4 == 0);
Brian Osmane1e988d2019-03-21 14:06:24 -0400186 this->write8((i >> 0) & 0xFF);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400187 this->write8((i >> 8) & 0xFF);
188 this->write8((i >> 16) & 0xFF);
189 this->write8((i >> 24) & 0xFF);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400190}
191
192void ByteCodeGenerator::write(ByteCodeInstruction i) {
193 this->write8((uint8_t) i);
194}
195
196void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
197 ByteCodeInstruction u, ByteCodeInstruction f) {
198 switch (type_category(type)) {
199 case TypeCategory::kSigned:
200 this->write(s);
201 break;
202 case TypeCategory::kUnsigned:
203 this->write(u);
204 break;
205 case TypeCategory::kFloat:
206 this->write(f);
207 break;
208 default:
209 SkASSERT(false);
210 }
211}
212
213void ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b) {
214 if (b.fOperator == Token::Kind::EQ) {
215 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
216 this->writeExpression(*b.fRight);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400217 lvalue->store();
218 return;
219 }
220 Token::Kind op;
221 std::unique_ptr<LValue> lvalue;
222 if (is_assignment(b.fOperator)) {
223 lvalue = this->getLValue(*b.fLeft);
224 lvalue->load();
225 op = remove_assignment(b.fOperator);
226 } else {
227 this->writeExpression(*b.fLeft);
228 op = b.fOperator;
229 if (b.fLeft->fType.kind() == Type::kScalar_Kind &&
230 b.fRight->fType.kind() == Type::kVector_Kind) {
231 for (int i = b.fRight->fType.columns(); i > 1; --i) {
232 this->write(ByteCodeInstruction::kDup);
233 }
234 }
235 }
236 this->writeExpression(*b.fRight);
237 if (b.fLeft->fType.kind() == Type::kVector_Kind &&
238 b.fRight->fType.kind() == Type::kScalar_Kind) {
239 for (int i = b.fLeft->fType.columns(); i > 1; --i) {
240 this->write(ByteCodeInstruction::kDup);
241 }
242 }
243 int count = slot_count(b.fType);
244 if (count > 1) {
245 this->write(ByteCodeInstruction::kVector);
246 this->write8(count);
247 }
248 switch (op) {
249 case Token::Kind::EQEQ:
250 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareIEQ,
251 ByteCodeInstruction::kCompareIEQ,
252 ByteCodeInstruction::kCompareFEQ);
253 break;
254 case Token::Kind::GT:
255 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGT,
256 ByteCodeInstruction::kCompareUGT,
257 ByteCodeInstruction::kCompareFGT);
258 break;
259 case Token::Kind::GTEQ:
260 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGTEQ,
261 ByteCodeInstruction::kCompareUGTEQ,
262 ByteCodeInstruction::kCompareFGTEQ);
263 break;
264 case Token::Kind::LT:
265 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLT,
266 ByteCodeInstruction::kCompareULT,
267 ByteCodeInstruction::kCompareFLT);
268 break;
269 case Token::Kind::LTEQ:
270 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLTEQ,
271 ByteCodeInstruction::kCompareULTEQ,
272 ByteCodeInstruction::kCompareFLTEQ);
273 break;
274 case Token::Kind::MINUS:
275 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kSubtractI,
276 ByteCodeInstruction::kSubtractI,
277 ByteCodeInstruction::kSubtractF);
278 break;
279 case Token::Kind::NEQ:
280 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareINEQ,
281 ByteCodeInstruction::kCompareINEQ,
282 ByteCodeInstruction::kCompareFNEQ);
283 break;
284 case Token::Kind::PERCENT:
285 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kRemainderS,
286 ByteCodeInstruction::kRemainderU,
Brian Osman3b41baf2019-05-08 09:24:46 -0400287 ByteCodeInstruction::kRemainderF);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400288 break;
289 case Token::Kind::PLUS:
290 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kAddI,
291 ByteCodeInstruction::kAddI,
292 ByteCodeInstruction::kAddF);
293 break;
294 case Token::Kind::SLASH:
295 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kDivideS,
296 ByteCodeInstruction::kDivideU,
297 ByteCodeInstruction::kDivideF);
298 break;
299 case Token::Kind::STAR:
Ethan Nicholas91164d12019-05-15 15:29:54 -0400300 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kMultiplyI,
301 ByteCodeInstruction::kMultiplyI,
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400302 ByteCodeInstruction::kMultiplyF);
303 break;
304 default:
305 SkASSERT(false);
306 }
307 if (lvalue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400308 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
Ethan Nicholas91164d12019-05-15 15:29:54 -0400355void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
356 int count = slot_count(e.fValue->type());
357 if (count > 1) {
358 this->write(ByteCodeInstruction::kVector);
359 this->write8(count);
360 }
361 this->write(ByteCodeInstruction::kReadExternal);
362 int index = fOutput->fExternalValues.size();
363 fOutput->fExternalValues.push_back(e.fValue);
364 SkASSERT(index <= 255);
365 this->write8(index);
366}
367
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400368void ByteCodeGenerator::writeFieldAccess(const FieldAccess& f) {
369 // not yet implemented
370 abort();
371}
372
373void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400374 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400375 this->write(ByteCodeInstruction::kPushImmediate);
376 union { float f; uint32_t u; } pun = { (float) f.fValue };
377 this->write32(pun.u);
378}
379
380void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Brian Osman226668a2019-05-14 16:47:30 -0400381 for (const auto& arg : f.fArguments) {
382 this->writeExpression(*arg);
383 }
384 this->write(ByteCodeInstruction::kCall);
385 fCallTargets.emplace_back(this, f.fFunction);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400386}
387
388void ByteCodeGenerator::writeIndexExpression(const IndexExpression& i) {
389 // not yet implemented
390 abort();
391}
392
393void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400394 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400395 this->write(ByteCodeInstruction::kPushImmediate);
396 this->write32(i.fValue);
397}
398
399void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
400 // not yet implemented
401 abort();
402}
403
404void ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p) {
405 switch (p.fOperator) {
406 case Token::Kind::PLUSPLUS: // fall through
407 case Token::Kind::MINUSMINUS: {
408 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
409 lvalue->load();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400410 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400411 this->write(ByteCodeInstruction::kPushImmediate);
412 this->write32(1);
413 if (p.fOperator == Token::Kind::PLUSPLUS) {
414 this->writeTypedInstruction(p.fType,
415 ByteCodeInstruction::kAddI,
416 ByteCodeInstruction::kAddI,
417 ByteCodeInstruction::kAddF);
418 } else {
419 this->writeTypedInstruction(p.fType,
420 ByteCodeInstruction::kSubtractI,
421 ByteCodeInstruction::kSubtractI,
422 ByteCodeInstruction::kSubtractF);
423 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400424 lvalue->store();
425 break;
426 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400427 case Token::Kind::MINUS: {
428 this->writeExpression(*p.fOperand);
429 int count = slot_count(p.fOperand->fType);
430 if (count > 1) {
431 this->write(ByteCodeInstruction::kVector);
432 this->write8(count);
433 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400434 this->writeTypedInstruction(p.fType,
435 ByteCodeInstruction::kNegateS,
436 ByteCodeInstruction::kInvalid,
437 ByteCodeInstruction::kNegateF);
438 break;
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400439 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400440 default:
441 SkASSERT(false);
442 }
443}
444
445void ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p) {
446 // not yet implemented
447 abort();
448}
449
450void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
451 switch (s.fBase->fKind) {
452 case Expression::kVariableReference_Kind: {
453 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
Brian Osman1091f022019-05-16 09:42:16 -0400454 this->write(var.fStorage == Variable::kGlobal_Storage
455 ? ByteCodeInstruction::kLoadSwizzleGlobal
456 : ByteCodeInstruction::kLoadSwizzle);
457 this->write8(this->getLocation(var));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400458 this->write8(s.fComponents.size());
459 for (int c : s.fComponents) {
460 this->write8(c);
461 }
462 break;
463 }
464 default:
465 this->writeExpression(*s.fBase);
466 this->write(ByteCodeInstruction::kSwizzle);
467 this->write8(s.fBase->fType.columns());
468 this->write8(s.fComponents.size());
469 for (int c : s.fComponents) {
470 this->write8(c);
471 }
472 }
473}
474
475void ByteCodeGenerator::writeVariableReference(const VariableReference& v) {
Brian Osman1091f022019-05-16 09:42:16 -0400476 int count = slot_count(v.fType);
477 if (count > 1) {
478 this->write(ByteCodeInstruction::kVector);
479 this->write8(count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400480 }
Brian Osman1091f022019-05-16 09:42:16 -0400481 this->write(v.fVariable.fStorage == Variable::kGlobal_Storage
482 ? ByteCodeInstruction::kLoadGlobal
483 : ByteCodeInstruction::kLoad);
484 this->write8(this->getLocation(v.fVariable));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400485}
486
487void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
488 // not yet implemented
489 abort();
490}
491
492void ByteCodeGenerator::writeExpression(const Expression& e) {
493 switch (e.fKind) {
494 case Expression::kBinary_Kind:
495 this->writeBinaryExpression((BinaryExpression&) e);
496 break;
497 case Expression::kBoolLiteral_Kind:
498 this->writeBoolLiteral((BoolLiteral&) e);
499 break;
500 case Expression::kConstructor_Kind:
501 this->writeConstructor((Constructor&) e);
502 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400503 case Expression::kExternalValue_Kind:
504 this->writeExternalValue((ExternalValueReference&) e);
505 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400506 case Expression::kFieldAccess_Kind:
507 this->writeFieldAccess((FieldAccess&) e);
508 break;
509 case Expression::kFloatLiteral_Kind:
510 this->writeFloatLiteral((FloatLiteral&) e);
511 break;
512 case Expression::kFunctionCall_Kind:
513 this->writeFunctionCall((FunctionCall&) e);
514 break;
515 case Expression::kIndex_Kind:
516 this->writeIndexExpression((IndexExpression&) e);
517 break;
518 case Expression::kIntLiteral_Kind:
519 this->writeIntLiteral((IntLiteral&) e);
520 break;
521 case Expression::kNullLiteral_Kind:
522 this->writeNullLiteral((NullLiteral&) e);
523 break;
524 case Expression::kPrefix_Kind:
525 this->writePrefixExpression((PrefixExpression&) e);
526 break;
527 case Expression::kPostfix_Kind:
528 this->writePostfixExpression((PostfixExpression&) e);
529 break;
530 case Expression::kSwizzle_Kind:
531 this->writeSwizzle((Swizzle&) e);
532 break;
533 case Expression::kVariableReference_Kind:
534 this->writeVariableReference((VariableReference&) e);
535 break;
536 case Expression::kTernary_Kind:
537 this->writeTernaryExpression((TernaryExpression&) e);
538 break;
539 default:
540 printf("unsupported expression %s\n", e.description().c_str());
541 SkASSERT(false);
542 }
543}
544
Ethan Nicholas91164d12019-05-15 15:29:54 -0400545class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
546public:
547 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
548 : INHERITED(*generator)
549 , fCount(slot_count(value.type()))
550 , fIndex(index) {}
551
552 void load() override {
553 if (fCount > 1) {
554 fGenerator.write(ByteCodeInstruction::kVector);
555 fGenerator.write8(fCount);
556 }
557 fGenerator.write(ByteCodeInstruction::kReadExternal);
558 fGenerator.write8(fIndex);
559 }
560
561 void store() override {
562 if (fCount > 1) {
563 fGenerator.write(ByteCodeInstruction::kVector);
564 fGenerator.write8(fCount);
565 }
566 fGenerator.write(ByteCodeInstruction::kDup);
567 if (fCount > 1) {
568 fGenerator.write(ByteCodeInstruction::kVector);
569 fGenerator.write8(fCount);
570 }
571 fGenerator.write(ByteCodeInstruction::kWriteExternal);
572 fGenerator.write8(fIndex);
573 }
574
575private:
576 typedef LValue INHERITED;
577
578 int fCount;
579
580 int fIndex;
581};
582
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400583class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
584public:
585 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
586 : INHERITED(*generator)
587 , fSwizzle(swizzle) {
Brian Osman1091f022019-05-16 09:42:16 -0400588 SkASSERT(fSwizzle.fBase->fKind == Expression::kVariableReference_Kind);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400589 }
590
591 void load() override {
Brian Osman1091f022019-05-16 09:42:16 -0400592 fGenerator.writeSwizzle(fSwizzle);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400593 }
594
595 void store() override {
Brian Osman1091f022019-05-16 09:42:16 -0400596 const Variable& var = ((VariableReference&)*fSwizzle.fBase).fVariable;
597 if (fSwizzle.fComponents.size() > 1) {
598 fGenerator.write(ByteCodeInstruction::kVector);
599 fGenerator.write8(fSwizzle.fComponents.size());
600 }
601 fGenerator.write(ByteCodeInstruction::kDup);
602 fGenerator.write(var.fStorage == Variable::kGlobal_Storage
603 ? ByteCodeInstruction::kStoreSwizzleGlobal
604 : ByteCodeInstruction::kStoreSwizzle);
605 fGenerator.write8(fGenerator.getLocation(var));
606 fGenerator.write8(fSwizzle.fComponents.size());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400607 for (int c : fSwizzle.fComponents) {
608 fGenerator.write8(c);
609 }
610 }
611
612private:
613 const Swizzle& fSwizzle;
614
615 typedef LValue INHERITED;
616};
617
618class ByteCodeVariableLValue : public ByteCodeGenerator::LValue {
619public:
620 ByteCodeVariableLValue(ByteCodeGenerator* generator, const Variable& var)
621 : INHERITED(*generator)
622 , fCount(slot_count(var.fType))
Brian Osman1091f022019-05-16 09:42:16 -0400623 , fLocation(generator->getLocation(var))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400624 , fIsGlobal(var.fStorage == Variable::kGlobal_Storage) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400625 }
626
627 void load() override {
Brian Osman1091f022019-05-16 09:42:16 -0400628 if (fCount > 1) {
629 fGenerator.write(ByteCodeInstruction::kVector);
630 fGenerator.write8(fCount);
631 }
632 fGenerator.write(fIsGlobal ? ByteCodeInstruction::kLoadGlobal
633 : ByteCodeInstruction::kLoad);
634 fGenerator.write8(fLocation);
635 }
636
637 void store() override {
638 if (fCount > 1) {
639 fGenerator.write(ByteCodeInstruction::kVector);
640 fGenerator.write8(fCount);
641 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400642 fGenerator.write(ByteCodeInstruction::kDup);
643 if (fCount > 1) {
644 fGenerator.write(ByteCodeInstruction::kVector);
645 fGenerator.write8(fCount);
646 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400647 fGenerator.write(fIsGlobal ? ByteCodeInstruction::kStoreGlobal
Brian Osman1091f022019-05-16 09:42:16 -0400648 : ByteCodeInstruction::kStore);
649 fGenerator.write8(fLocation);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400650 }
651
652private:
653 typedef LValue INHERITED;
654
655 int fCount;
Brian Osman1091f022019-05-16 09:42:16 -0400656 int fLocation;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400657 bool fIsGlobal;
658};
659
660std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
661 switch (e.fKind) {
Ethan Nicholas91164d12019-05-15 15:29:54 -0400662 case Expression::kExternalValue_Kind: {
663 ExternalValue* value = ((ExternalValueReference&) e).fValue;
664 int index = fOutput->fExternalValues.size();
665 fOutput->fExternalValues.push_back(value);
666 SkASSERT(index <= 255);
667 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
668 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400669 case Expression::kIndex_Kind:
670 // not yet implemented
671 abort();
672 case Expression::kVariableReference_Kind:
673 return std::unique_ptr<LValue>(new ByteCodeVariableLValue(this,
674 ((VariableReference&) e).fVariable));
675 case Expression::kSwizzle_Kind:
676 return std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, (Swizzle&) e));
677 case Expression::kTernary_Kind:
678 default:
679 printf("unsupported lvalue %s\n", e.description().c_str());
680 return nullptr;
681 }
682}
683
684void ByteCodeGenerator::writeBlock(const Block& b) {
685 for (const auto& s : b.fStatements) {
686 this->writeStatement(*s);
687 }
688}
689
690void ByteCodeGenerator::setBreakTargets() {
691 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
692 for (DeferredLocation& b : breaks) {
693 b.set();
694 }
695 fBreakTargets.pop();
696}
697
698void ByteCodeGenerator::setContinueTargets() {
699 std::vector<DeferredLocation>& continues = fContinueTargets.top();
700 for (DeferredLocation& c : continues) {
701 c.set();
702 }
703 fContinueTargets.pop();
704}
705
706void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400707 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400708 this->write(ByteCodeInstruction::kBranch);
709 fBreakTargets.top().emplace_back(this);
710}
711
712void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400713 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400714 this->write(ByteCodeInstruction::kBranch);
715 fContinueTargets.top().emplace_back(this);
716}
717
718void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
719 fContinueTargets.emplace();
720 fBreakTargets.emplace();
721 size_t start = fCode->size();
722 this->writeStatement(*d.fStatement);
723 this->setContinueTargets();
724 this->writeExpression(*d.fTest);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400725 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400726 this->write(ByteCodeInstruction::kConditionalBranch);
727 this->write16(start);
728 this->setBreakTargets();
729}
730
731void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
732 fContinueTargets.emplace();
733 fBreakTargets.emplace();
734 if (f.fInitializer) {
735 this->writeStatement(*f.fInitializer);
736 }
737 size_t start = fCode->size();
738 if (f.fTest) {
739 this->writeExpression(*f.fTest);
740 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400741 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400742 this->write(ByteCodeInstruction::kConditionalBranch);
743 DeferredLocation endLocation(this);
744 this->writeStatement(*f.fStatement);
745 this->setContinueTargets();
746 if (f.fNext) {
747 this->writeExpression(*f.fNext);
748 this->write(ByteCodeInstruction::kPop);
749 this->write8(slot_count(f.fNext->fType));
750 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400751 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400752 this->write(ByteCodeInstruction::kBranch);
753 this->write16(start);
754 endLocation.set();
755 } else {
756 this->writeStatement(*f.fStatement);
757 this->setContinueTargets();
758 if (f.fNext) {
759 this->writeExpression(*f.fNext);
760 this->write(ByteCodeInstruction::kPop);
761 this->write8(slot_count(f.fNext->fType));
762 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400763 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400764 this->write(ByteCodeInstruction::kBranch);
765 this->write16(start);
766 }
767 this->setBreakTargets();
768}
769
770void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
771 this->writeExpression(*i.fTest);
772 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400773 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400774 this->write(ByteCodeInstruction::kConditionalBranch);
775 DeferredLocation elseLocation(this);
776 this->writeStatement(*i.fIfTrue);
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 DeferredLocation endLocation(this);
780 elseLocation.set();
781 if (i.fIfFalse) {
782 this->writeStatement(*i.fIfFalse);
783 }
784 endLocation.set();
785}
786
787void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -0400788 this->writeExpression(*r.fExpression);
789 this->write(ByteCodeInstruction::kReturn);
790 this->write8(r.fExpression->fType.columns() * r.fExpression->fType.rows());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400791}
792
793void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
794 // not yet implemented
795 abort();
796}
797
798void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
799 for (const auto& declStatement : v.fVars) {
800 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
801 // we need to grab the location even if we don't use it, to ensure it
802 // has been allocated
803 int location = getLocation(*decl.fVar);
804 if (decl.fValue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400805 this->writeExpression(*decl.fValue);
806 int count = slot_count(decl.fValue->fType);
807 if (count > 1) {
808 this->write(ByteCodeInstruction::kVector);
809 this->write8(count);
810 }
811 this->write(ByteCodeInstruction::kStore);
Brian Osman1091f022019-05-16 09:42:16 -0400812 this->write8(location);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400813 }
814 }
815}
816
817void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
818 fContinueTargets.emplace();
819 fBreakTargets.emplace();
820 size_t start = fCode->size();
821 this->writeExpression(*w.fTest);
822 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400823 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400824 this->write(ByteCodeInstruction::kConditionalBranch);
825 DeferredLocation endLocation(this);
826 this->writeStatement(*w.fStatement);
827 this->setContinueTargets();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400828 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400829 this->write(ByteCodeInstruction::kBranch);
830 this->write16(start);
831 endLocation.set();
832 this->setBreakTargets();
833}
834
835void ByteCodeGenerator::writeStatement(const Statement& s) {
836 switch (s.fKind) {
837 case Statement::kBlock_Kind:
838 this->writeBlock((Block&) s);
839 break;
840 case Statement::kBreak_Kind:
841 this->writeBreakStatement((BreakStatement&) s);
842 break;
843 case Statement::kContinue_Kind:
844 this->writeContinueStatement((ContinueStatement&) s);
845 break;
846 case Statement::kDiscard_Kind:
847 // not yet implemented
848 abort();
849 case Statement::kDo_Kind:
850 this->writeDoStatement((DoStatement&) s);
851 break;
852 case Statement::kExpression_Kind: {
853 const Expression& expr = *((ExpressionStatement&) s).fExpression;
854 this->writeExpression(expr);
855 this->write(ByteCodeInstruction::kPop);
856 this->write8(slot_count(expr.fType));
857 break;
858 }
859 case Statement::kFor_Kind:
860 this->writeForStatement((ForStatement&) s);
861 break;
862 case Statement::kIf_Kind:
863 this->writeIfStatement((IfStatement&) s);
864 break;
865 case Statement::kNop_Kind:
866 break;
867 case Statement::kReturn_Kind:
868 this->writeReturnStatement((ReturnStatement&) s);
869 break;
870 case Statement::kSwitch_Kind:
871 this->writeSwitchStatement((SwitchStatement&) s);
872 break;
873 case Statement::kVarDeclarations_Kind:
874 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
875 break;
876 case Statement::kWhile_Kind:
877 this->writeWhileStatement((WhileStatement&) s);
878 break;
879 default:
880 SkASSERT(false);
881 }
882}
883
884}