blob: 1aee081faf730db134fbce7cca635038fd1e19c7 [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"
Brian Osmanf3fa6002019-05-17 14:26:53 -04009#include "src/sksl/SkSLInterpreter.h"
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040010
Brian Osman95253bd2019-06-05 10:28:45 -040011#include <algorithm>
12
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040013namespace SkSL {
14
Ethan Nicholas82162ee2019-05-21 16:05:08 -040015ByteCodeGenerator::ByteCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
16 ByteCode* output)
17 : INHERITED(program, errors, nullptr)
18 , fContext(*context)
Ethan Nicholasae9633b2019-05-24 12:46:34 -040019 , fOutput(output)
20 , fIntrinsics {
21 { "cos", ByteCodeInstruction::kCos },
22 { "cross", ByteCodeInstruction::kCross },
23 { "dot", SpecialIntrinsic::kDot },
24 { "sin", ByteCodeInstruction::kSin },
25 { "sqrt", ByteCodeInstruction::kSqrt },
26 { "tan", ByteCodeInstruction::kTan },
27 { "mix", ByteCodeInstruction::kMix },
28 } {}
29
Ethan Nicholas82162ee2019-05-21 16:05:08 -040030
Brian Osman07c117b2019-05-23 12:51:06 -070031int ByteCodeGenerator::SlotCount(const Type& type) {
32 if (type.kind() == Type::kStruct_Kind) {
33 int slots = 0;
34 for (const auto& f : type.fields()) {
35 slots += SlotCount(*f.fType);
36 }
37 SkASSERT(slots <= 255);
38 return slots;
39 } else if (type.kind() == Type::kArray_Kind) {
40 int columns = type.columns();
41 SkASSERT(columns >= 0);
42 int slots = columns * SlotCount(type.componentType());
43 SkASSERT(slots <= 255);
44 return slots;
45 } else {
46 return type.columns() * type.rows();
47 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040048}
49
50bool ByteCodeGenerator::generateCode() {
51 for (const auto& e : fProgram) {
52 switch (e.fKind) {
53 case ProgramElement::kFunction_Kind: {
54 std::unique_ptr<ByteCodeFunction> f = this->writeFunction((FunctionDefinition&) e);
55 if (!f) {
56 return false;
57 }
58 fOutput->fFunctions.push_back(std::move(f));
59 break;
60 }
61 case ProgramElement::kVar_Kind: {
62 VarDeclarations& decl = (VarDeclarations&) e;
63 for (const auto& v : decl.fVars) {
64 const Variable* declVar = ((VarDeclaration&) *v).fVar;
65 if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
66 continue;
67 }
68 if (declVar->fModifiers.fFlags & Modifiers::kIn_Flag) {
Brian Osman07c117b2019-05-23 12:51:06 -070069 for (int i = SlotCount(declVar->fType); i > 0; --i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040070 fOutput->fInputSlots.push_back(fOutput->fGlobalCount++);
71 }
72 } else {
Brian Osman07c117b2019-05-23 12:51:06 -070073 fOutput->fGlobalCount += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040074 }
75 }
76 break;
77 }
78 default:
79 ; // ignore
80 }
81 }
Brian Osman226668a2019-05-14 16:47:30 -040082 for (auto& call : fCallTargets) {
83 if (!call.set()) {
84 return false;
85 }
86 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040087 return true;
88}
89
90std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
91 fFunction = &f;
Brian Osman226668a2019-05-14 16:47:30 -040092 std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040093 fParameterCount = 0;
94 for (const auto& p : f.fDeclaration.fParameters) {
Brian Osman07c117b2019-05-23 12:51:06 -070095 fParameterCount += SlotCount(p->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040096 }
97 fCode = &result->fCode;
98 this->writeStatement(*f.fBody);
Ethan Nicholas7e603db2019-05-03 12:57:47 -040099 this->write(ByteCodeInstruction::kReturn);
100 this->write8(0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400101 result->fParameterCount = fParameterCount;
102 result->fLocalCount = fLocals.size();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400103 const Type& returnType = f.fDeclaration.fReturnType;
104 if (returnType != *fContext.fVoid_Type) {
Brian Osman07c117b2019-05-23 12:51:06 -0700105 result->fReturnCount = SlotCount(returnType);
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400106 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400107 fLocals.clear();
108 fFunction = nullptr;
109 return result;
110}
111
112enum class TypeCategory {
113 kBool,
114 kSigned,
115 kUnsigned,
116 kFloat,
117};
118
119static TypeCategory type_category(const Type& type) {
120 switch (type.kind()) {
121 case Type::Kind::kVector_Kind:
122 case Type::Kind::kMatrix_Kind:
123 return type_category(type.componentType());
124 default:
125 if (type.fName == "bool") {
126 return TypeCategory::kBool;
127 } else if (type.fName == "int" || type.fName == "short") {
128 return TypeCategory::kSigned;
129 } else if (type.fName == "uint" || type.fName == "ushort") {
130 return TypeCategory::kUnsigned;
131 } else {
132 SkASSERT(type.fName == "float" || type.fName == "half");
133 return TypeCategory::kFloat;
134 }
135 ABORT("unsupported type: %s\n", type.description().c_str());
136 }
137}
138
Brian Osman0785db02019-05-24 14:19:11 -0400139// A "simple" Swizzle is based on a variable (or a compound variable like a struct or array), and
140// that references consecutive values, such that it can be implemented using normal load/store ops
141// with an offset. Note that all single-component swizzles (of suitable base types) are simple.
142static bool swizzle_is_simple(const Swizzle& s) {
143 switch (s.fBase->fKind) {
144 case Expression::kFieldAccess_Kind:
145 case Expression::kIndex_Kind:
146 case Expression::kVariableReference_Kind:
147 break;
148 default:
149 return false;
150 }
151
152 for (size_t i = 1; i < s.fComponents.size(); ++i) {
153 if (s.fComponents[i] != s.fComponents[i - 1] + 1) {
154 return false;
155 }
156 }
157 return true;
158}
159
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400160int ByteCodeGenerator::getLocation(const Variable& var) {
161 // given that we seldom have more than a couple of variables, linear search is probably the most
162 // efficient way to handle lookups
163 switch (var.fStorage) {
164 case Variable::kLocal_Storage: {
165 for (int i = fLocals.size() - 1; i >= 0; --i) {
166 if (fLocals[i] == &var) {
Brian Osman1091f022019-05-16 09:42:16 -0400167 SkASSERT(fParameterCount + i <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400168 return fParameterCount + i;
169 }
170 }
171 int result = fParameterCount + fLocals.size();
172 fLocals.push_back(&var);
Brian Osman07c117b2019-05-23 12:51:06 -0700173 for (int i = 0; i < SlotCount(var.fType) - 1; ++i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400174 fLocals.push_back(nullptr);
175 }
Brian Osman1091f022019-05-16 09:42:16 -0400176 SkASSERT(result <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400177 return result;
178 }
179 case Variable::kParameter_Storage: {
180 int offset = 0;
181 for (const auto& p : fFunction->fDeclaration.fParameters) {
182 if (p == &var) {
Brian Osman1091f022019-05-16 09:42:16 -0400183 SkASSERT(offset <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400184 return offset;
185 }
Brian Osman07c117b2019-05-23 12:51:06 -0700186 offset += SlotCount(p->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400187 }
188 SkASSERT(false);
Brian Osman1091f022019-05-16 09:42:16 -0400189 return 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400190 }
191 case Variable::kGlobal_Storage: {
192 int offset = 0;
193 for (const auto& e : fProgram) {
194 if (e.fKind == ProgramElement::kVar_Kind) {
195 VarDeclarations& decl = (VarDeclarations&) e;
196 for (const auto& v : decl.fVars) {
197 const Variable* declVar = ((VarDeclaration&) *v).fVar;
198 if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
199 continue;
200 }
201 if (declVar == &var) {
Brian Osmanb7451292019-05-15 13:02:13 -0400202 SkASSERT(offset <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400203 return offset;
204 }
Brian Osman07c117b2019-05-23 12:51:06 -0700205 offset += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400206 }
207 }
208 }
209 SkASSERT(false);
Brian Osman1091f022019-05-16 09:42:16 -0400210 return 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400211 }
212 default:
213 SkASSERT(false);
214 return 0;
215 }
216}
217
Brian Osman0785db02019-05-24 14:19:11 -0400218// TODO: Elide Add 0 and Mul 1 sequences
Brian Osman07c117b2019-05-23 12:51:06 -0700219int ByteCodeGenerator::getLocation(const Expression& expr, Variable::Storage* storage) {
220 switch (expr.fKind) {
221 case Expression::kFieldAccess_Kind: {
222 const FieldAccess& f = (const FieldAccess&)expr;
223 int baseAddr = this->getLocation(*f.fBase, storage);
224 int offset = 0;
225 for (int i = 0; i < f.fFieldIndex; ++i) {
226 offset += SlotCount(*f.fBase->fType.fields()[i].fType);
227 }
228 if (baseAddr < 0) {
229 this->write(ByteCodeInstruction::kPushImmediate);
230 this->write32(offset);
231 this->write(ByteCodeInstruction::kAddI);
232 return -1;
233 } else {
234 return baseAddr + offset;
235 }
236 }
237 case Expression::kIndex_Kind: {
238 const IndexExpression& i = (const IndexExpression&)expr;
239 int stride = SlotCount(i.fType);
240 int offset = -1;
241 if (i.fIndex->isConstant()) {
242 offset = i.fIndex->getConstantInt() * stride;
243 } else {
244 this->writeExpression(*i.fIndex);
245 this->write(ByteCodeInstruction::kPushImmediate);
246 this->write32(stride);
247 this->write(ByteCodeInstruction::kMultiplyI);
248 }
249 int baseAddr = this->getLocation(*i.fBase, storage);
250 if (baseAddr >= 0 && offset >= 0) {
251 return baseAddr + offset;
252 }
253 if (baseAddr >= 0) {
254 this->write(ByteCodeInstruction::kPushImmediate);
255 this->write32(baseAddr);
256 }
257 if (offset >= 0) {
258 this->write(ByteCodeInstruction::kPushImmediate);
259 this->write32(offset);
260 }
261 this->write(ByteCodeInstruction::kAddI);
262 return -1;
263 }
Brian Osman0785db02019-05-24 14:19:11 -0400264 case Expression::kSwizzle_Kind: {
265 const Swizzle& s = (const Swizzle&)expr;
266 SkASSERT(swizzle_is_simple(s));
267 int baseAddr = this->getLocation(*s.fBase, storage);
268 int offset = s.fComponents[0];
269 if (baseAddr < 0) {
270 this->write(ByteCodeInstruction::kPushImmediate);
271 this->write32(offset);
272 this->write(ByteCodeInstruction::kAddI);
273 return -1;
274 } else {
275 return baseAddr + offset;
276 }
277 }
Brian Osman07c117b2019-05-23 12:51:06 -0700278 case Expression::kVariableReference_Kind: {
279 const Variable& var = ((const VariableReference&)expr).fVariable;
280 *storage = var.fStorage;
281 return this->getLocation(var);
282 }
283 default:
284 SkASSERT(false);
285 return 0;
286 }
287}
288
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400289void ByteCodeGenerator::write8(uint8_t b) {
290 fCode->push_back(b);
291}
292
293void ByteCodeGenerator::write16(uint16_t i) {
Mike Klein76346ac2019-05-17 11:57:10 -0500294 size_t n = fCode->size();
295 fCode->resize(n+2);
296 memcpy(fCode->data() + n, &i, 2);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400297}
298
299void ByteCodeGenerator::write32(uint32_t i) {
Mike Klein76346ac2019-05-17 11:57:10 -0500300 size_t n = fCode->size();
301 fCode->resize(n+4);
302 memcpy(fCode->data() + n, &i, 4);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400303}
304
305void ByteCodeGenerator::write(ByteCodeInstruction i) {
Mike Klein108e9352019-05-21 11:05:17 -0500306 this->write16((uint16_t)i);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400307}
308
Mike Klein76346ac2019-05-17 11:57:10 -0500309static ByteCodeInstruction vector_instruction(ByteCodeInstruction base, int count) {
Brian Osman07c117b2019-05-23 12:51:06 -0700310 SkASSERT(count >= 1 && count <= 4);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400311 return ((ByteCodeInstruction) ((int) base + count - 1));
312}
313
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400314void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400315 ByteCodeInstruction u, ByteCodeInstruction f,
316 int count) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400317 switch (type_category(type)) {
318 case TypeCategory::kSigned:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400319 this->write(vector_instruction(s, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400320 break;
321 case TypeCategory::kUnsigned:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400322 this->write(vector_instruction(u, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400323 break;
Brian Osman1e855b22019-05-29 15:21:52 -0400324 case TypeCategory::kFloat: {
325 if (count > 4) {
326 this->write((ByteCodeInstruction)((int)f + 4));
327 this->write8(count);
328 } else {
329 this->write(vector_instruction(f, count));
330 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400331 break;
Brian Osman1e855b22019-05-29 15:21:52 -0400332 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400333 default:
334 SkASSERT(false);
335 }
336}
337
Brian Osman3e29f1d2019-05-28 09:35:05 -0400338bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool discard) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400339 if (b.fOperator == Token::Kind::EQ) {
340 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
341 this->writeExpression(*b.fRight);
Brian Osman3e29f1d2019-05-28 09:35:05 -0400342 lvalue->store(discard);
343 discard = false;
344 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400345 }
Brian Osman16e6fd52019-05-29 11:19:00 -0400346 const Type& lType = b.fLeft->fType;
347 const Type& rType = b.fRight->fType;
Brian Osman909231c2019-05-29 15:34:36 -0400348 bool lVecOrMtx = (lType.kind() == Type::kVector_Kind || lType.kind() == Type::kMatrix_Kind);
349 bool rVecOrMtx = (rType.kind() == Type::kVector_Kind || rType.kind() == Type::kMatrix_Kind);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400350 Token::Kind op;
351 std::unique_ptr<LValue> lvalue;
352 if (is_assignment(b.fOperator)) {
353 lvalue = this->getLValue(*b.fLeft);
354 lvalue->load();
355 op = remove_assignment(b.fOperator);
356 } else {
357 this->writeExpression(*b.fLeft);
358 op = b.fOperator;
Brian Osman909231c2019-05-29 15:34:36 -0400359 if (!lVecOrMtx && rVecOrMtx) {
Brian Osman16e6fd52019-05-29 11:19:00 -0400360 for (int i = SlotCount(rType); i > 1; --i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400361 this->write(ByteCodeInstruction::kDup);
362 }
363 }
364 }
365 this->writeExpression(*b.fRight);
Brian Osman909231c2019-05-29 15:34:36 -0400366 if (lVecOrMtx && !rVecOrMtx) {
Brian Osman16e6fd52019-05-29 11:19:00 -0400367 for (int i = SlotCount(lType); i > 1; --i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400368 this->write(ByteCodeInstruction::kDup);
369 }
370 }
Brian Osman909231c2019-05-29 15:34:36 -0400371 // Special case for M*V, V*M, M*M (but not V*V!)
372 if (op == Token::Kind::STAR && lVecOrMtx && rVecOrMtx &&
373 !(lType.kind() == Type::kVector_Kind && rType.kind() == Type::kVector_Kind)) {
374 this->write(ByteCodeInstruction::kMatrixMultiply);
375 int rCols = rType.columns(),
376 rRows = rType.rows(),
377 lCols = lType.columns(),
378 lRows = lType.rows();
379 // M*V treats the vector as a column
380 if (rType.kind() == Type::kVector_Kind) {
381 std::swap(rCols, rRows);
382 }
383 SkASSERT(lCols == rRows);
384 SkASSERT(SlotCount(b.fType) == lRows * rCols);
385 this->write8(lCols);
386 this->write8(lRows);
387 this->write8(rCols);
388 } else {
389 int count = std::max(SlotCount(lType), SlotCount(rType));
390 switch (op) {
391 case Token::Kind::EQEQ:
392 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareIEQ,
393 ByteCodeInstruction::kCompareIEQ,
394 ByteCodeInstruction::kCompareFEQ,
395 count);
396 // Collapse to a single bool
397 for (int i = count; i > 1; --i) {
398 this->write(ByteCodeInstruction::kAndB);
399 }
400 break;
401 case Token::Kind::GT:
402 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGT,
403 ByteCodeInstruction::kCompareUGT,
404 ByteCodeInstruction::kCompareFGT,
405 count);
406 break;
407 case Token::Kind::GTEQ:
408 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGTEQ,
409 ByteCodeInstruction::kCompareUGTEQ,
410 ByteCodeInstruction::kCompareFGTEQ,
411 count);
412 break;
413 case Token::Kind::LT:
414 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLT,
415 ByteCodeInstruction::kCompareULT,
416 ByteCodeInstruction::kCompareFLT,
417 count);
418 break;
419 case Token::Kind::LTEQ:
420 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLTEQ,
421 ByteCodeInstruction::kCompareULTEQ,
422 ByteCodeInstruction::kCompareFLTEQ,
423 count);
424 break;
425 case Token::Kind::MINUS:
426 this->writeTypedInstruction(lType, ByteCodeInstruction::kSubtractI,
427 ByteCodeInstruction::kSubtractI,
428 ByteCodeInstruction::kSubtractF,
429 count);
430 break;
431 case Token::Kind::NEQ:
432 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareINEQ,
433 ByteCodeInstruction::kCompareINEQ,
434 ByteCodeInstruction::kCompareFNEQ,
435 count);
436 // Collapse to a single bool
437 for (int i = count; i > 1; --i) {
438 this->write(ByteCodeInstruction::kOrB);
439 }
440 break;
441 case Token::Kind::PERCENT:
442 this->writeTypedInstruction(lType, ByteCodeInstruction::kRemainderS,
443 ByteCodeInstruction::kRemainderU,
444 ByteCodeInstruction::kRemainderF,
445 count);
446 break;
447 case Token::Kind::PLUS:
448 this->writeTypedInstruction(lType, ByteCodeInstruction::kAddI,
449 ByteCodeInstruction::kAddI,
450 ByteCodeInstruction::kAddF,
451 count);
452 break;
453 case Token::Kind::SLASH:
454 this->writeTypedInstruction(lType, ByteCodeInstruction::kDivideS,
455 ByteCodeInstruction::kDivideU,
456 ByteCodeInstruction::kDivideF,
457 count);
458 break;
459 case Token::Kind::STAR:
460 this->writeTypedInstruction(lType, ByteCodeInstruction::kMultiplyI,
461 ByteCodeInstruction::kMultiplyI,
462 ByteCodeInstruction::kMultiplyF,
463 count);
464 break;
465 default:
466 SkASSERT(false);
467 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400468 }
469 if (lvalue) {
Brian Osman3e29f1d2019-05-28 09:35:05 -0400470 lvalue->store(discard);
471 discard = false;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400472 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400473 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400474}
475
476void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
477 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osman44d44762019-05-13 14:19:12 -0400478 this->write32(b.fValue ? 1 : 0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400479}
480
481void ByteCodeGenerator::writeConstructor(const Constructor& c) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400482 for (const auto& arg : c.fArguments) {
483 this->writeExpression(*arg);
484 }
485 if (c.fArguments.size() == 1) {
Brian Osman29e013d2019-05-28 17:16:03 -0400486 const Type& inType = c.fArguments[0]->fType;
487 const Type& outType = c.fType;
488 TypeCategory inCategory = type_category(inType);
489 TypeCategory outCategory = type_category(outType);
490 int inCount = SlotCount(inType);
491 int outCount = SlotCount(outType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400492 if (inCategory != outCategory) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700493 SkASSERT(inCount == outCount);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400494 if (inCategory == TypeCategory::kFloat) {
495 SkASSERT(outCategory == TypeCategory::kSigned ||
496 outCategory == TypeCategory::kUnsigned);
Brian Osmanc51d7912019-05-22 15:16:16 -0700497 this->write(vector_instruction(ByteCodeInstruction::kConvertFtoI, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400498 } else if (outCategory == TypeCategory::kFloat) {
499 if (inCategory == TypeCategory::kSigned) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700500 this->write(vector_instruction(ByteCodeInstruction::kConvertStoF, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400501 } else {
502 SkASSERT(inCategory == TypeCategory::kUnsigned);
Brian Osmanc51d7912019-05-22 15:16:16 -0700503 this->write(vector_instruction(ByteCodeInstruction::kConvertUtoF, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400504 }
505 } else {
506 SkASSERT(false);
507 }
508 }
Brian Osman29e013d2019-05-28 17:16:03 -0400509 if (inType.kind() == Type::kMatrix_Kind && outType.kind() == Type::kMatrix_Kind) {
510 this->write(ByteCodeInstruction::kMatrixToMatrix);
511 this->write8(inType.columns());
512 this->write8(inType.rows());
513 this->write8(outType.columns());
514 this->write8(outType.rows());
515 } else if (inCount != outCount) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700516 SkASSERT(inCount == 1);
Brian Osman29e013d2019-05-28 17:16:03 -0400517 if (outType.kind() == Type::kMatrix_Kind) {
518 this->write(ByteCodeInstruction::kScalarToMatrix);
519 this->write8(outType.columns());
520 this->write8(outType.rows());
521 } else {
522 SkASSERT(outType.kind() == Type::kVector_Kind);
523 for (; inCount != outCount; ++inCount) {
524 this->write(ByteCodeInstruction::kDup);
525 }
Brian Osmanc51d7912019-05-22 15:16:16 -0700526 }
527 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400528 }
529}
530
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400531void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f) {
532 int argumentCount = 0;
533 for (const auto& arg : f.fArguments) {
534 this->writeExpression(*arg);
Brian Osman07c117b2019-05-23 12:51:06 -0700535 argumentCount += SlotCount(arg->fType);
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400536 }
537 this->write(ByteCodeInstruction::kCallExternal);
538 SkASSERT(argumentCount <= 255);
539 this->write8(argumentCount);
Brian Osman07c117b2019-05-23 12:51:06 -0700540 this->write8(SlotCount(f.fType));
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400541 int index = fOutput->fExternalValues.size();
542 fOutput->fExternalValues.push_back(f.fFunction);
543 SkASSERT(index <= 255);
544 this->write8(index);
545}
546
Ethan Nicholas91164d12019-05-15 15:29:54 -0400547void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400548 this->write(vector_instruction(ByteCodeInstruction::kReadExternal,
Brian Osman07c117b2019-05-23 12:51:06 -0700549 SlotCount(e.fValue->type())));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400550 int index = fOutput->fExternalValues.size();
551 fOutput->fExternalValues.push_back(e.fValue);
552 SkASSERT(index <= 255);
553 this->write8(index);
554}
555
Brian Osman07c117b2019-05-23 12:51:06 -0700556void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
557 Variable::Storage storage;
558 int location = this->getLocation(expr, &storage);
559 bool isGlobal = storage == Variable::kGlobal_Storage;
560 int count = SlotCount(expr.fType);
561 if (location < 0 || count > 4) {
562 if (location >= 0) {
563 this->write(ByteCodeInstruction::kPushImmediate);
564 this->write32(location);
565 }
566 this->write(isGlobal ? ByteCodeInstruction::kLoadExtendedGlobal
567 : ByteCodeInstruction::kLoadExtended);
568 this->write8(count);
569 } else {
570 this->write(vector_instruction(isGlobal ? ByteCodeInstruction::kLoadGlobal
571 : ByteCodeInstruction::kLoad,
572 count));
573 this->write8(location);
574 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400575}
576
577void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
578 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400579 this->write32(Interpreter::Value((float) f.fValue).fUnsigned);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400580}
581
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400582void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
583 auto found = fIntrinsics.find(c.fFunction.fName);
584 if (found == fIntrinsics.end()) {
585 fErrors.error(c.fOffset, "unsupported intrinsic function");
586 return;
587 }
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400588 if (found->second.fIsSpecial) {
589 SkASSERT(found->second.fValue.fSpecial == SpecialIntrinsic::kDot);
590 SkASSERT(c.fArguments.size() == 2);
591 SkASSERT(SlotCount(c.fArguments[0]->fType) == SlotCount(c.fArguments[1]->fType));
592 this->write((ByteCodeInstruction) ((int) ByteCodeInstruction::kMultiplyF +
593 SlotCount(c.fArguments[0]->fType) - 1));
594 for (int i = SlotCount(c.fArguments[0]->fType); i > 1; --i) {
595 this->write(ByteCodeInstruction::kAddF);
596 }
597 } else {
598 switch (found->second.fValue.fInstruction) {
599 case ByteCodeInstruction::kCos:
600 case ByteCodeInstruction::kMix:
601 case ByteCodeInstruction::kSin:
602 case ByteCodeInstruction::kSqrt:
603 case ByteCodeInstruction::kTan:
604 SkASSERT(c.fArguments.size() > 0);
605 this->write((ByteCodeInstruction) ((int) found->second.fValue.fInstruction +
606 SlotCount(c.fArguments[0]->fType) - 1));
607 break;
608 case ByteCodeInstruction::kCross:
609 this->write(found->second.fValue.fInstruction);
610 break;
611 default:
612 SkASSERT(false);
613 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400614 }
615}
616
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400617void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400618 for (const auto& arg : f.fArguments) {
619 this->writeExpression(*arg);
620 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400621 if (f.fFunction.fBuiltin) {
622 this->writeIntrinsicCall(f);
623 return;
624 }
Brian Osman226668a2019-05-14 16:47:30 -0400625 this->write(ByteCodeInstruction::kCall);
626 fCallTargets.emplace_back(this, f.fFunction);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400627}
628
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400629void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
630 this->write(ByteCodeInstruction::kPushImmediate);
631 this->write32(i.fValue);
632}
633
634void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
635 // not yet implemented
636 abort();
637}
638
Brian Osman3e29f1d2019-05-28 09:35:05 -0400639bool ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p, bool discard) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400640 switch (p.fOperator) {
641 case Token::Kind::PLUSPLUS: // fall through
642 case Token::Kind::MINUSMINUS: {
Brian Osman07c117b2019-05-23 12:51:06 -0700643 SkASSERT(SlotCount(p.fOperand->fType) == 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400644 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
645 lvalue->load();
646 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400647 this->write32(type_category(p.fType) == TypeCategory::kFloat
648 ? Interpreter::Value(1.0f).fUnsigned : 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400649 if (p.fOperator == Token::Kind::PLUSPLUS) {
650 this->writeTypedInstruction(p.fType,
651 ByteCodeInstruction::kAddI,
652 ByteCodeInstruction::kAddI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400653 ByteCodeInstruction::kAddF,
654 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400655 } else {
656 this->writeTypedInstruction(p.fType,
657 ByteCodeInstruction::kSubtractI,
658 ByteCodeInstruction::kSubtractI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400659 ByteCodeInstruction::kSubtractF,
660 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400661 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400662 lvalue->store(discard);
663 discard = false;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400664 break;
665 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400666 case Token::Kind::MINUS: {
667 this->writeExpression(*p.fOperand);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400668 this->writeTypedInstruction(p.fType,
Mike Klein12710912019-05-21 11:04:59 -0500669 ByteCodeInstruction::kNegateI,
670 ByteCodeInstruction::kNegateI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400671 ByteCodeInstruction::kNegateF,
Brian Osman07c117b2019-05-23 12:51:06 -0700672 SlotCount(p.fOperand->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400673 break;
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400674 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400675 default:
676 SkASSERT(false);
677 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400678 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400679}
680
Brian Osman3e29f1d2019-05-28 09:35:05 -0400681bool ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p, bool discard) {
Brian Osmanf3fa6002019-05-17 14:26:53 -0400682 switch (p.fOperator) {
683 case Token::Kind::PLUSPLUS: // fall through
684 case Token::Kind::MINUSMINUS: {
Brian Osman07c117b2019-05-23 12:51:06 -0700685 SkASSERT(SlotCount(p.fOperand->fType) == 1);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400686 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
687 lvalue->load();
Brian Osman3e29f1d2019-05-28 09:35:05 -0400688 if (!discard) {
689 this->write(ByteCodeInstruction::kDup);
690 }
Brian Osmanf3fa6002019-05-17 14:26:53 -0400691 this->write(ByteCodeInstruction::kPushImmediate);
692 this->write32(type_category(p.fType) == TypeCategory::kFloat
693 ? Interpreter::Value(1.0f).fUnsigned : 1);
694 if (p.fOperator == Token::Kind::PLUSPLUS) {
695 this->writeTypedInstruction(p.fType,
696 ByteCodeInstruction::kAddI,
697 ByteCodeInstruction::kAddI,
698 ByteCodeInstruction::kAddF,
699 1);
700 } else {
701 this->writeTypedInstruction(p.fType,
702 ByteCodeInstruction::kSubtractI,
703 ByteCodeInstruction::kSubtractI,
704 ByteCodeInstruction::kSubtractF,
705 1);
706 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400707 lvalue->store(discard);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400708 this->write(ByteCodeInstruction::kPop);
Brian Osman3e29f1d2019-05-28 09:35:05 -0400709 discard = false;
Brian Osmanf3fa6002019-05-17 14:26:53 -0400710 break;
711 }
712 default:
713 SkASSERT(false);
714 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400715 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400716}
717
718void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
Brian Osman0785db02019-05-24 14:19:11 -0400719 if (swizzle_is_simple(s)) {
720 this->writeVariableExpression(s);
721 return;
722 }
723
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400724 switch (s.fBase->fKind) {
725 case Expression::kVariableReference_Kind: {
726 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
Brian Osman1091f022019-05-16 09:42:16 -0400727 this->write(var.fStorage == Variable::kGlobal_Storage
728 ? ByteCodeInstruction::kLoadSwizzleGlobal
729 : ByteCodeInstruction::kLoadSwizzle);
730 this->write8(this->getLocation(var));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400731 this->write8(s.fComponents.size());
732 for (int c : s.fComponents) {
733 this->write8(c);
734 }
735 break;
736 }
737 default:
738 this->writeExpression(*s.fBase);
739 this->write(ByteCodeInstruction::kSwizzle);
740 this->write8(s.fBase->fType.columns());
741 this->write8(s.fComponents.size());
742 for (int c : s.fComponents) {
743 this->write8(c);
744 }
745 }
746}
747
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400748void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Brian Osman4e93feb2019-05-16 15:38:00 -0400749 this->writeExpression(*t.fTest);
Brian Osman4e93feb2019-05-16 15:38:00 -0400750 this->write(ByteCodeInstruction::kConditionalBranch);
751 DeferredLocation trueLocation(this);
752 this->writeExpression(*t.fIfFalse);
Brian Osman4e93feb2019-05-16 15:38:00 -0400753 this->write(ByteCodeInstruction::kBranch);
754 DeferredLocation endLocation(this);
755 trueLocation.set();
756 this->writeExpression(*t.fIfTrue);
757 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400758}
759
Brian Osman3e29f1d2019-05-28 09:35:05 -0400760void ByteCodeGenerator::writeExpression(const Expression& e, bool discard) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400761 switch (e.fKind) {
762 case Expression::kBinary_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400763 discard = this->writeBinaryExpression((BinaryExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400764 break;
765 case Expression::kBoolLiteral_Kind:
766 this->writeBoolLiteral((BoolLiteral&) e);
767 break;
768 case Expression::kConstructor_Kind:
769 this->writeConstructor((Constructor&) e);
770 break;
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400771 case Expression::kExternalFunctionCall_Kind:
772 this->writeExternalFunctionCall((ExternalFunctionCall&) e);
773 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400774 case Expression::kExternalValue_Kind:
775 this->writeExternalValue((ExternalValueReference&) e);
776 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400777 case Expression::kFieldAccess_Kind:
Brian Osman07c117b2019-05-23 12:51:06 -0700778 case Expression::kIndex_Kind:
779 case Expression::kVariableReference_Kind:
780 this->writeVariableExpression(e);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400781 break;
782 case Expression::kFloatLiteral_Kind:
783 this->writeFloatLiteral((FloatLiteral&) e);
784 break;
785 case Expression::kFunctionCall_Kind:
786 this->writeFunctionCall((FunctionCall&) e);
787 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400788 case Expression::kIntLiteral_Kind:
789 this->writeIntLiteral((IntLiteral&) e);
790 break;
791 case Expression::kNullLiteral_Kind:
792 this->writeNullLiteral((NullLiteral&) e);
793 break;
794 case Expression::kPrefix_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400795 discard = this->writePrefixExpression((PrefixExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400796 break;
797 case Expression::kPostfix_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400798 discard = this->writePostfixExpression((PostfixExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400799 break;
800 case Expression::kSwizzle_Kind:
801 this->writeSwizzle((Swizzle&) e);
802 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400803 case Expression::kTernary_Kind:
804 this->writeTernaryExpression((TernaryExpression&) e);
805 break;
806 default:
807 printf("unsupported expression %s\n", e.description().c_str());
808 SkASSERT(false);
809 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400810 if (discard) {
811 int count = SlotCount(e.fType);
812 if (count > 4) {
813 this->write(ByteCodeInstruction::kPopN);
814 this->write8(count);
815 } else {
816 this->write(vector_instruction(ByteCodeInstruction::kPop, count));
817 }
818 discard = false;
819 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400820}
821
Ethan Nicholas91164d12019-05-15 15:29:54 -0400822class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
823public:
824 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
825 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700826 , fCount(ByteCodeGenerator::SlotCount(value.type()))
Ethan Nicholas91164d12019-05-15 15:29:54 -0400827 , fIndex(index) {}
828
829 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400830 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400831 fGenerator.write8(fIndex);
832 }
833
Brian Osman3e29f1d2019-05-28 09:35:05 -0400834 void store(bool discard) override {
835 if (!discard) {
836 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
837 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400838 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400839 fGenerator.write8(fIndex);
840 }
841
842private:
843 typedef LValue INHERITED;
844
845 int fCount;
846
847 int fIndex;
848};
849
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400850class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
851public:
852 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
853 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700854 , fSwizzle(swizzle) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400855
856 void load() override {
Brian Osman1091f022019-05-16 09:42:16 -0400857 fGenerator.writeSwizzle(fSwizzle);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400858 }
859
Brian Osman3e29f1d2019-05-28 09:35:05 -0400860 void store(bool discard) override {
861 if (!discard) {
862 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup,
863 fSwizzle.fComponents.size()));
864 }
Brian Osman07c117b2019-05-23 12:51:06 -0700865 Variable::Storage storage;
866 int location = fGenerator.getLocation(*fSwizzle.fBase, &storage);
867 bool isGlobal = storage == Variable::kGlobal_Storage;
868 if (location < 0) {
869 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleIndirectGlobal
870 : ByteCodeInstruction::kStoreSwizzleIndirect);
871 } else {
872 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleGlobal
873 : ByteCodeInstruction::kStoreSwizzle);
874 fGenerator.write8(location);
875 }
Brian Osman1091f022019-05-16 09:42:16 -0400876 fGenerator.write8(fSwizzle.fComponents.size());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400877 for (int c : fSwizzle.fComponents) {
878 fGenerator.write8(c);
879 }
880 }
881
882private:
883 const Swizzle& fSwizzle;
884
885 typedef LValue INHERITED;
886};
887
Brian Osman07c117b2019-05-23 12:51:06 -0700888class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400889public:
Brian Osman07c117b2019-05-23 12:51:06 -0700890 ByteCodeExpressionLValue(ByteCodeGenerator* generator, const Expression& expr)
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400891 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700892 , fExpression(expr) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400893
894 void load() override {
Brian Osman07c117b2019-05-23 12:51:06 -0700895 fGenerator.writeVariableExpression(fExpression);
Brian Osman1091f022019-05-16 09:42:16 -0400896 }
897
Brian Osman3e29f1d2019-05-28 09:35:05 -0400898 void store(bool discard) override {
Brian Osman07c117b2019-05-23 12:51:06 -0700899 int count = ByteCodeGenerator::SlotCount(fExpression.fType);
Brian Osman3e29f1d2019-05-28 09:35:05 -0400900 if (!discard) {
901 if (count > 4) {
902 fGenerator.write(ByteCodeInstruction::kDupN);
903 fGenerator.write8(count);
904 } else {
905 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
906 }
Brian Osman07c117b2019-05-23 12:51:06 -0700907 }
908 Variable::Storage storage;
909 int location = fGenerator.getLocation(fExpression, &storage);
910 bool isGlobal = storage == Variable::kGlobal_Storage;
911 if (location < 0 || count > 4) {
912 if (location >= 0) {
913 fGenerator.write(ByteCodeInstruction::kPushImmediate);
914 fGenerator.write32(location);
915 }
916 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreExtendedGlobal
917 : ByteCodeInstruction::kStoreExtended);
918 fGenerator.write8(count);
919 } else {
920 fGenerator.write(vector_instruction(isGlobal ? ByteCodeInstruction::kStoreGlobal
921 : ByteCodeInstruction::kStore,
922 count));
923 fGenerator.write8(location);
924 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400925 }
926
927private:
928 typedef LValue INHERITED;
929
Brian Osman07c117b2019-05-23 12:51:06 -0700930 const Expression& fExpression;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400931};
932
933std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
934 switch (e.fKind) {
Ethan Nicholas91164d12019-05-15 15:29:54 -0400935 case Expression::kExternalValue_Kind: {
936 ExternalValue* value = ((ExternalValueReference&) e).fValue;
937 int index = fOutput->fExternalValues.size();
938 fOutput->fExternalValues.push_back(value);
939 SkASSERT(index <= 255);
940 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
941 }
Brian Osman07c117b2019-05-23 12:51:06 -0700942 case Expression::kFieldAccess_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400943 case Expression::kIndex_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400944 case Expression::kVariableReference_Kind:
Brian Osman07c117b2019-05-23 12:51:06 -0700945 return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
Brian Osman0785db02019-05-24 14:19:11 -0400946 case Expression::kSwizzle_Kind: {
947 const Swizzle& s = (const Swizzle&) e;
948 return swizzle_is_simple(s)
949 ? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e))
950 : std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s));
951 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400952 case Expression::kTernary_Kind:
953 default:
954 printf("unsupported lvalue %s\n", e.description().c_str());
955 return nullptr;
956 }
957}
958
959void ByteCodeGenerator::writeBlock(const Block& b) {
960 for (const auto& s : b.fStatements) {
961 this->writeStatement(*s);
962 }
963}
964
965void ByteCodeGenerator::setBreakTargets() {
966 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
967 for (DeferredLocation& b : breaks) {
968 b.set();
969 }
970 fBreakTargets.pop();
971}
972
973void ByteCodeGenerator::setContinueTargets() {
974 std::vector<DeferredLocation>& continues = fContinueTargets.top();
975 for (DeferredLocation& c : continues) {
976 c.set();
977 }
978 fContinueTargets.pop();
979}
980
981void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
982 this->write(ByteCodeInstruction::kBranch);
983 fBreakTargets.top().emplace_back(this);
984}
985
986void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
987 this->write(ByteCodeInstruction::kBranch);
988 fContinueTargets.top().emplace_back(this);
989}
990
991void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
992 fContinueTargets.emplace();
993 fBreakTargets.emplace();
994 size_t start = fCode->size();
995 this->writeStatement(*d.fStatement);
996 this->setContinueTargets();
997 this->writeExpression(*d.fTest);
998 this->write(ByteCodeInstruction::kConditionalBranch);
999 this->write16(start);
1000 this->setBreakTargets();
1001}
1002
1003void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
1004 fContinueTargets.emplace();
1005 fBreakTargets.emplace();
1006 if (f.fInitializer) {
1007 this->writeStatement(*f.fInitializer);
1008 }
1009 size_t start = fCode->size();
1010 if (f.fTest) {
1011 this->writeExpression(*f.fTest);
1012 this->write(ByteCodeInstruction::kNot);
1013 this->write(ByteCodeInstruction::kConditionalBranch);
1014 DeferredLocation endLocation(this);
1015 this->writeStatement(*f.fStatement);
1016 this->setContinueTargets();
1017 if (f.fNext) {
Brian Osman3e29f1d2019-05-28 09:35:05 -04001018 this->writeExpression(*f.fNext, true);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001019 }
1020 this->write(ByteCodeInstruction::kBranch);
1021 this->write16(start);
1022 endLocation.set();
1023 } else {
1024 this->writeStatement(*f.fStatement);
1025 this->setContinueTargets();
1026 if (f.fNext) {
Brian Osman3e29f1d2019-05-28 09:35:05 -04001027 this->writeExpression(*f.fNext, true);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001028 }
1029 this->write(ByteCodeInstruction::kBranch);
1030 this->write16(start);
1031 }
1032 this->setBreakTargets();
1033}
1034
1035void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001036 if (i.fIfFalse) {
Mike Kleinb45ee832019-05-17 11:11:11 -05001037 // if (test) { ..ifTrue.. } else { .. ifFalse .. }
1038 this->writeExpression(*i.fTest);
Mike Kleinb45ee832019-05-17 11:11:11 -05001039 this->write(ByteCodeInstruction::kConditionalBranch);
1040 DeferredLocation trueLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001041 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -05001042 this->write(ByteCodeInstruction::kBranch);
1043 DeferredLocation endLocation(this);
1044 trueLocation.set();
1045 this->writeStatement(*i.fIfTrue);
1046 endLocation.set();
1047 } else {
1048 // if (test) { ..ifTrue.. }
1049 this->writeExpression(*i.fTest);
1050 this->write(ByteCodeInstruction::kNot);
Mike Kleinb45ee832019-05-17 11:11:11 -05001051 this->write(ByteCodeInstruction::kConditionalBranch);
1052 DeferredLocation endLocation(this);
1053 this->writeStatement(*i.fIfTrue);
1054 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001055 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001056}
1057
1058void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -04001059 this->writeExpression(*r.fExpression);
1060 this->write(ByteCodeInstruction::kReturn);
Brian Osman07c117b2019-05-23 12:51:06 -07001061 this->write8(SlotCount(r.fExpression->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001062}
1063
1064void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
1065 // not yet implemented
1066 abort();
1067}
1068
1069void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1070 for (const auto& declStatement : v.fVars) {
1071 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
1072 // we need to grab the location even if we don't use it, to ensure it
1073 // has been allocated
1074 int location = getLocation(*decl.fVar);
1075 if (decl.fValue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001076 this->writeExpression(*decl.fValue);
Brian Osman07c117b2019-05-23 12:51:06 -07001077 int count = SlotCount(decl.fValue->fType);
1078 if (count > 4) {
1079 this->write(ByteCodeInstruction::kPushImmediate);
1080 this->write32(location);
1081 this->write(ByteCodeInstruction::kStoreExtended);
1082 this->write8(count);
1083 } else {
1084 this->write(vector_instruction(ByteCodeInstruction::kStore, count));
1085 this->write8(location);
1086 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001087 }
1088 }
1089}
1090
1091void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
1092 fContinueTargets.emplace();
1093 fBreakTargets.emplace();
1094 size_t start = fCode->size();
1095 this->writeExpression(*w.fTest);
1096 this->write(ByteCodeInstruction::kNot);
1097 this->write(ByteCodeInstruction::kConditionalBranch);
1098 DeferredLocation endLocation(this);
1099 this->writeStatement(*w.fStatement);
1100 this->setContinueTargets();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001101 this->write(ByteCodeInstruction::kBranch);
1102 this->write16(start);
1103 endLocation.set();
1104 this->setBreakTargets();
1105}
1106
1107void ByteCodeGenerator::writeStatement(const Statement& s) {
1108 switch (s.fKind) {
1109 case Statement::kBlock_Kind:
1110 this->writeBlock((Block&) s);
1111 break;
1112 case Statement::kBreak_Kind:
1113 this->writeBreakStatement((BreakStatement&) s);
1114 break;
1115 case Statement::kContinue_Kind:
1116 this->writeContinueStatement((ContinueStatement&) s);
1117 break;
1118 case Statement::kDiscard_Kind:
1119 // not yet implemented
1120 abort();
1121 case Statement::kDo_Kind:
1122 this->writeDoStatement((DoStatement&) s);
1123 break;
Brian Osman3e29f1d2019-05-28 09:35:05 -04001124 case Statement::kExpression_Kind:
1125 this->writeExpression(*((ExpressionStatement&) s).fExpression, true);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001126 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001127 case Statement::kFor_Kind:
1128 this->writeForStatement((ForStatement&) s);
1129 break;
1130 case Statement::kIf_Kind:
1131 this->writeIfStatement((IfStatement&) s);
1132 break;
1133 case Statement::kNop_Kind:
1134 break;
1135 case Statement::kReturn_Kind:
1136 this->writeReturnStatement((ReturnStatement&) s);
1137 break;
1138 case Statement::kSwitch_Kind:
1139 this->writeSwitchStatement((SwitchStatement&) s);
1140 break;
1141 case Statement::kVarDeclarations_Kind:
1142 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1143 break;
1144 case Statement::kWhile_Kind:
1145 this->writeWhileStatement((WhileStatement&) s);
1146 break;
1147 default:
1148 SkASSERT(false);
1149 }
1150}
1151
1152}