blob: 13ffc9e3b6a2176dde3444a42205cf7475009e97 [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));
Brian Osman80164412019-06-07 13:00:23 -040059 fFunctions.push_back(&(FunctionDefinition&)e);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040060 break;
61 }
62 case ProgramElement::kVar_Kind: {
63 VarDeclarations& decl = (VarDeclarations&) e;
64 for (const auto& v : decl.fVars) {
65 const Variable* declVar = ((VarDeclaration&) *v).fVar;
66 if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
67 continue;
68 }
69 if (declVar->fModifiers.fFlags & Modifiers::kIn_Flag) {
Brian Osman07c117b2019-05-23 12:51:06 -070070 for (int i = SlotCount(declVar->fType); i > 0; --i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040071 fOutput->fInputSlots.push_back(fOutput->fGlobalCount++);
72 }
73 } else {
Brian Osman07c117b2019-05-23 12:51:06 -070074 fOutput->fGlobalCount += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040075 }
76 }
77 break;
78 }
79 default:
80 ; // ignore
81 }
82 }
Brian Osman226668a2019-05-14 16:47:30 -040083 for (auto& call : fCallTargets) {
84 if (!call.set()) {
85 return false;
86 }
87 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040088 return true;
89}
90
91std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
92 fFunction = &f;
Brian Osman226668a2019-05-14 16:47:30 -040093 std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
Brian Osman80164412019-06-07 13:00:23 -040094 fParameterCount = result->fParameterCount;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040095 fCode = &result->fCode;
96 this->writeStatement(*f.fBody);
Ethan Nicholas7e603db2019-05-03 12:57:47 -040097 this->write(ByteCodeInstruction::kReturn);
98 this->write8(0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040099 result->fLocalCount = fLocals.size();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400100 const Type& returnType = f.fDeclaration.fReturnType;
101 if (returnType != *fContext.fVoid_Type) {
Brian Osman07c117b2019-05-23 12:51:06 -0700102 result->fReturnCount = SlotCount(returnType);
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400103 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400104 fLocals.clear();
105 fFunction = nullptr;
106 return result;
107}
108
109enum class TypeCategory {
110 kBool,
111 kSigned,
112 kUnsigned,
113 kFloat,
114};
115
116static TypeCategory type_category(const Type& type) {
117 switch (type.kind()) {
118 case Type::Kind::kVector_Kind:
119 case Type::Kind::kMatrix_Kind:
120 return type_category(type.componentType());
121 default:
122 if (type.fName == "bool") {
123 return TypeCategory::kBool;
124 } else if (type.fName == "int" || type.fName == "short") {
125 return TypeCategory::kSigned;
126 } else if (type.fName == "uint" || type.fName == "ushort") {
127 return TypeCategory::kUnsigned;
128 } else {
129 SkASSERT(type.fName == "float" || type.fName == "half");
130 return TypeCategory::kFloat;
131 }
132 ABORT("unsupported type: %s\n", type.description().c_str());
133 }
134}
135
Brian Osman0785db02019-05-24 14:19:11 -0400136// A "simple" Swizzle is based on a variable (or a compound variable like a struct or array), and
137// that references consecutive values, such that it can be implemented using normal load/store ops
138// with an offset. Note that all single-component swizzles (of suitable base types) are simple.
139static bool swizzle_is_simple(const Swizzle& s) {
140 switch (s.fBase->fKind) {
141 case Expression::kFieldAccess_Kind:
142 case Expression::kIndex_Kind:
143 case Expression::kVariableReference_Kind:
144 break;
145 default:
146 return false;
147 }
148
149 for (size_t i = 1; i < s.fComponents.size(); ++i) {
150 if (s.fComponents[i] != s.fComponents[i - 1] + 1) {
151 return false;
152 }
153 }
154 return true;
155}
156
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400157int ByteCodeGenerator::getLocation(const Variable& var) {
158 // given that we seldom have more than a couple of variables, linear search is probably the most
159 // efficient way to handle lookups
160 switch (var.fStorage) {
161 case Variable::kLocal_Storage: {
162 for (int i = fLocals.size() - 1; i >= 0; --i) {
163 if (fLocals[i] == &var) {
Brian Osman1091f022019-05-16 09:42:16 -0400164 SkASSERT(fParameterCount + i <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400165 return fParameterCount + i;
166 }
167 }
168 int result = fParameterCount + fLocals.size();
169 fLocals.push_back(&var);
Brian Osman07c117b2019-05-23 12:51:06 -0700170 for (int i = 0; i < SlotCount(var.fType) - 1; ++i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400171 fLocals.push_back(nullptr);
172 }
Brian Osman1091f022019-05-16 09:42:16 -0400173 SkASSERT(result <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400174 return result;
175 }
176 case Variable::kParameter_Storage: {
177 int offset = 0;
178 for (const auto& p : fFunction->fDeclaration.fParameters) {
179 if (p == &var) {
Brian Osman1091f022019-05-16 09:42:16 -0400180 SkASSERT(offset <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400181 return offset;
182 }
Brian Osman07c117b2019-05-23 12:51:06 -0700183 offset += SlotCount(p->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400184 }
185 SkASSERT(false);
Brian Osman1091f022019-05-16 09:42:16 -0400186 return 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400187 }
188 case Variable::kGlobal_Storage: {
189 int offset = 0;
190 for (const auto& e : fProgram) {
191 if (e.fKind == ProgramElement::kVar_Kind) {
192 VarDeclarations& decl = (VarDeclarations&) e;
193 for (const auto& v : decl.fVars) {
194 const Variable* declVar = ((VarDeclaration&) *v).fVar;
195 if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
196 continue;
197 }
198 if (declVar == &var) {
Brian Osmanb7451292019-05-15 13:02:13 -0400199 SkASSERT(offset <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400200 return offset;
201 }
Brian Osman07c117b2019-05-23 12:51:06 -0700202 offset += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400203 }
204 }
205 }
206 SkASSERT(false);
Brian Osman1091f022019-05-16 09:42:16 -0400207 return 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400208 }
209 default:
210 SkASSERT(false);
211 return 0;
212 }
213}
214
Brian Osman0785db02019-05-24 14:19:11 -0400215// TODO: Elide Add 0 and Mul 1 sequences
Brian Osman07c117b2019-05-23 12:51:06 -0700216int ByteCodeGenerator::getLocation(const Expression& expr, Variable::Storage* storage) {
217 switch (expr.fKind) {
218 case Expression::kFieldAccess_Kind: {
219 const FieldAccess& f = (const FieldAccess&)expr;
220 int baseAddr = this->getLocation(*f.fBase, storage);
221 int offset = 0;
222 for (int i = 0; i < f.fFieldIndex; ++i) {
223 offset += SlotCount(*f.fBase->fType.fields()[i].fType);
224 }
225 if (baseAddr < 0) {
226 this->write(ByteCodeInstruction::kPushImmediate);
227 this->write32(offset);
228 this->write(ByteCodeInstruction::kAddI);
229 return -1;
230 } else {
231 return baseAddr + offset;
232 }
233 }
234 case Expression::kIndex_Kind: {
235 const IndexExpression& i = (const IndexExpression&)expr;
236 int stride = SlotCount(i.fType);
237 int offset = -1;
238 if (i.fIndex->isConstant()) {
239 offset = i.fIndex->getConstantInt() * stride;
240 } else {
241 this->writeExpression(*i.fIndex);
242 this->write(ByteCodeInstruction::kPushImmediate);
243 this->write32(stride);
244 this->write(ByteCodeInstruction::kMultiplyI);
245 }
246 int baseAddr = this->getLocation(*i.fBase, storage);
247 if (baseAddr >= 0 && offset >= 0) {
248 return baseAddr + offset;
249 }
250 if (baseAddr >= 0) {
251 this->write(ByteCodeInstruction::kPushImmediate);
252 this->write32(baseAddr);
253 }
254 if (offset >= 0) {
255 this->write(ByteCodeInstruction::kPushImmediate);
256 this->write32(offset);
257 }
258 this->write(ByteCodeInstruction::kAddI);
259 return -1;
260 }
Brian Osman0785db02019-05-24 14:19:11 -0400261 case Expression::kSwizzle_Kind: {
262 const Swizzle& s = (const Swizzle&)expr;
263 SkASSERT(swizzle_is_simple(s));
264 int baseAddr = this->getLocation(*s.fBase, storage);
265 int offset = s.fComponents[0];
266 if (baseAddr < 0) {
267 this->write(ByteCodeInstruction::kPushImmediate);
268 this->write32(offset);
269 this->write(ByteCodeInstruction::kAddI);
270 return -1;
271 } else {
272 return baseAddr + offset;
273 }
274 }
Brian Osman07c117b2019-05-23 12:51:06 -0700275 case Expression::kVariableReference_Kind: {
276 const Variable& var = ((const VariableReference&)expr).fVariable;
277 *storage = var.fStorage;
278 return this->getLocation(var);
279 }
280 default:
281 SkASSERT(false);
282 return 0;
283 }
284}
285
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400286void ByteCodeGenerator::write8(uint8_t b) {
287 fCode->push_back(b);
288}
289
290void ByteCodeGenerator::write16(uint16_t i) {
Mike Klein76346ac2019-05-17 11:57:10 -0500291 size_t n = fCode->size();
292 fCode->resize(n+2);
293 memcpy(fCode->data() + n, &i, 2);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400294}
295
296void ByteCodeGenerator::write32(uint32_t i) {
Mike Klein76346ac2019-05-17 11:57:10 -0500297 size_t n = fCode->size();
298 fCode->resize(n+4);
299 memcpy(fCode->data() + n, &i, 4);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400300}
301
302void ByteCodeGenerator::write(ByteCodeInstruction i) {
Mike Klein108e9352019-05-21 11:05:17 -0500303 this->write16((uint16_t)i);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400304}
305
Mike Klein76346ac2019-05-17 11:57:10 -0500306static ByteCodeInstruction vector_instruction(ByteCodeInstruction base, int count) {
Brian Osman07c117b2019-05-23 12:51:06 -0700307 SkASSERT(count >= 1 && count <= 4);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400308 return ((ByteCodeInstruction) ((int) base + count - 1));
309}
310
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400311void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400312 ByteCodeInstruction u, ByteCodeInstruction f,
313 int count) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400314 switch (type_category(type)) {
315 case TypeCategory::kSigned:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400316 this->write(vector_instruction(s, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400317 break;
318 case TypeCategory::kUnsigned:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400319 this->write(vector_instruction(u, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400320 break;
Brian Osman1e855b22019-05-29 15:21:52 -0400321 case TypeCategory::kFloat: {
322 if (count > 4) {
323 this->write((ByteCodeInstruction)((int)f + 4));
324 this->write8(count);
325 } else {
326 this->write(vector_instruction(f, count));
327 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400328 break;
Brian Osman1e855b22019-05-29 15:21:52 -0400329 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400330 default:
331 SkASSERT(false);
332 }
333}
334
Brian Osman3e29f1d2019-05-28 09:35:05 -0400335bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool discard) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400336 if (b.fOperator == Token::Kind::EQ) {
337 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
338 this->writeExpression(*b.fRight);
Brian Osman3e29f1d2019-05-28 09:35:05 -0400339 lvalue->store(discard);
340 discard = false;
341 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400342 }
Brian Osman16e6fd52019-05-29 11:19:00 -0400343 const Type& lType = b.fLeft->fType;
344 const Type& rType = b.fRight->fType;
Brian Osman909231c2019-05-29 15:34:36 -0400345 bool lVecOrMtx = (lType.kind() == Type::kVector_Kind || lType.kind() == Type::kMatrix_Kind);
346 bool rVecOrMtx = (rType.kind() == Type::kVector_Kind || rType.kind() == Type::kMatrix_Kind);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400347 Token::Kind op;
348 std::unique_ptr<LValue> lvalue;
349 if (is_assignment(b.fOperator)) {
350 lvalue = this->getLValue(*b.fLeft);
351 lvalue->load();
352 op = remove_assignment(b.fOperator);
353 } else {
354 this->writeExpression(*b.fLeft);
355 op = b.fOperator;
Brian Osman909231c2019-05-29 15:34:36 -0400356 if (!lVecOrMtx && rVecOrMtx) {
Brian Osman16e6fd52019-05-29 11:19:00 -0400357 for (int i = SlotCount(rType); i > 1; --i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400358 this->write(ByteCodeInstruction::kDup);
359 }
360 }
361 }
362 this->writeExpression(*b.fRight);
Brian Osman909231c2019-05-29 15:34:36 -0400363 if (lVecOrMtx && !rVecOrMtx) {
Brian Osman16e6fd52019-05-29 11:19:00 -0400364 for (int i = SlotCount(lType); i > 1; --i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400365 this->write(ByteCodeInstruction::kDup);
366 }
367 }
Brian Osman909231c2019-05-29 15:34:36 -0400368 // Special case for M*V, V*M, M*M (but not V*V!)
369 if (op == Token::Kind::STAR && lVecOrMtx && rVecOrMtx &&
370 !(lType.kind() == Type::kVector_Kind && rType.kind() == Type::kVector_Kind)) {
371 this->write(ByteCodeInstruction::kMatrixMultiply);
372 int rCols = rType.columns(),
373 rRows = rType.rows(),
374 lCols = lType.columns(),
375 lRows = lType.rows();
376 // M*V treats the vector as a column
377 if (rType.kind() == Type::kVector_Kind) {
378 std::swap(rCols, rRows);
379 }
380 SkASSERT(lCols == rRows);
381 SkASSERT(SlotCount(b.fType) == lRows * rCols);
382 this->write8(lCols);
383 this->write8(lRows);
384 this->write8(rCols);
385 } else {
386 int count = std::max(SlotCount(lType), SlotCount(rType));
387 switch (op) {
388 case Token::Kind::EQEQ:
389 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareIEQ,
390 ByteCodeInstruction::kCompareIEQ,
391 ByteCodeInstruction::kCompareFEQ,
392 count);
393 // Collapse to a single bool
394 for (int i = count; i > 1; --i) {
395 this->write(ByteCodeInstruction::kAndB);
396 }
397 break;
398 case Token::Kind::GT:
399 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGT,
400 ByteCodeInstruction::kCompareUGT,
401 ByteCodeInstruction::kCompareFGT,
402 count);
403 break;
404 case Token::Kind::GTEQ:
405 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGTEQ,
406 ByteCodeInstruction::kCompareUGTEQ,
407 ByteCodeInstruction::kCompareFGTEQ,
408 count);
409 break;
410 case Token::Kind::LT:
411 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLT,
412 ByteCodeInstruction::kCompareULT,
413 ByteCodeInstruction::kCompareFLT,
414 count);
415 break;
416 case Token::Kind::LTEQ:
417 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLTEQ,
418 ByteCodeInstruction::kCompareULTEQ,
419 ByteCodeInstruction::kCompareFLTEQ,
420 count);
421 break;
422 case Token::Kind::MINUS:
423 this->writeTypedInstruction(lType, ByteCodeInstruction::kSubtractI,
424 ByteCodeInstruction::kSubtractI,
425 ByteCodeInstruction::kSubtractF,
426 count);
427 break;
428 case Token::Kind::NEQ:
429 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareINEQ,
430 ByteCodeInstruction::kCompareINEQ,
431 ByteCodeInstruction::kCompareFNEQ,
432 count);
433 // Collapse to a single bool
434 for (int i = count; i > 1; --i) {
435 this->write(ByteCodeInstruction::kOrB);
436 }
437 break;
438 case Token::Kind::PERCENT:
439 this->writeTypedInstruction(lType, ByteCodeInstruction::kRemainderS,
440 ByteCodeInstruction::kRemainderU,
441 ByteCodeInstruction::kRemainderF,
442 count);
443 break;
444 case Token::Kind::PLUS:
445 this->writeTypedInstruction(lType, ByteCodeInstruction::kAddI,
446 ByteCodeInstruction::kAddI,
447 ByteCodeInstruction::kAddF,
448 count);
449 break;
450 case Token::Kind::SLASH:
451 this->writeTypedInstruction(lType, ByteCodeInstruction::kDivideS,
452 ByteCodeInstruction::kDivideU,
453 ByteCodeInstruction::kDivideF,
454 count);
455 break;
456 case Token::Kind::STAR:
457 this->writeTypedInstruction(lType, ByteCodeInstruction::kMultiplyI,
458 ByteCodeInstruction::kMultiplyI,
459 ByteCodeInstruction::kMultiplyF,
460 count);
461 break;
Brian Osman569f12f2019-06-13 11:23:57 -0400462
463 case Token::Kind::LOGICALAND:
464 SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
465 this->write(ByteCodeInstruction::kAndB);
466 break;
467 case Token::Kind::LOGICALNOT:
468 SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
469 this->write(ByteCodeInstruction::kNotB);
470 break;
471 case Token::Kind::LOGICALOR:
472 SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
473 this->write(ByteCodeInstruction::kOrB);
474 break;
475 case Token::Kind::LOGICALXOR:
476 SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
477 this->write(ByteCodeInstruction::kXorB);
478 break;
479
Brian Osman909231c2019-05-29 15:34:36 -0400480 default:
481 SkASSERT(false);
482 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400483 }
484 if (lvalue) {
Brian Osman3e29f1d2019-05-28 09:35:05 -0400485 lvalue->store(discard);
486 discard = false;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400487 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400488 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400489}
490
491void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
492 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osman569f12f2019-06-13 11:23:57 -0400493 this->write32(b.fValue ? ~0 : 0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400494}
495
496void ByteCodeGenerator::writeConstructor(const Constructor& c) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400497 for (const auto& arg : c.fArguments) {
498 this->writeExpression(*arg);
499 }
500 if (c.fArguments.size() == 1) {
Brian Osman29e013d2019-05-28 17:16:03 -0400501 const Type& inType = c.fArguments[0]->fType;
502 const Type& outType = c.fType;
503 TypeCategory inCategory = type_category(inType);
504 TypeCategory outCategory = type_category(outType);
505 int inCount = SlotCount(inType);
506 int outCount = SlotCount(outType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400507 if (inCategory != outCategory) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700508 SkASSERT(inCount == outCount);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400509 if (inCategory == TypeCategory::kFloat) {
510 SkASSERT(outCategory == TypeCategory::kSigned ||
511 outCategory == TypeCategory::kUnsigned);
Brian Osmanc51d7912019-05-22 15:16:16 -0700512 this->write(vector_instruction(ByteCodeInstruction::kConvertFtoI, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400513 } else if (outCategory == TypeCategory::kFloat) {
514 if (inCategory == TypeCategory::kSigned) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700515 this->write(vector_instruction(ByteCodeInstruction::kConvertStoF, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400516 } else {
517 SkASSERT(inCategory == TypeCategory::kUnsigned);
Brian Osmanc51d7912019-05-22 15:16:16 -0700518 this->write(vector_instruction(ByteCodeInstruction::kConvertUtoF, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400519 }
520 } else {
521 SkASSERT(false);
522 }
523 }
Brian Osman29e013d2019-05-28 17:16:03 -0400524 if (inType.kind() == Type::kMatrix_Kind && outType.kind() == Type::kMatrix_Kind) {
525 this->write(ByteCodeInstruction::kMatrixToMatrix);
526 this->write8(inType.columns());
527 this->write8(inType.rows());
528 this->write8(outType.columns());
529 this->write8(outType.rows());
530 } else if (inCount != outCount) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700531 SkASSERT(inCount == 1);
Brian Osman29e013d2019-05-28 17:16:03 -0400532 if (outType.kind() == Type::kMatrix_Kind) {
533 this->write(ByteCodeInstruction::kScalarToMatrix);
534 this->write8(outType.columns());
535 this->write8(outType.rows());
536 } else {
537 SkASSERT(outType.kind() == Type::kVector_Kind);
538 for (; inCount != outCount; ++inCount) {
539 this->write(ByteCodeInstruction::kDup);
540 }
Brian Osmanc51d7912019-05-22 15:16:16 -0700541 }
542 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400543 }
544}
545
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400546void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f) {
547 int argumentCount = 0;
548 for (const auto& arg : f.fArguments) {
549 this->writeExpression(*arg);
Brian Osman07c117b2019-05-23 12:51:06 -0700550 argumentCount += SlotCount(arg->fType);
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400551 }
552 this->write(ByteCodeInstruction::kCallExternal);
553 SkASSERT(argumentCount <= 255);
554 this->write8(argumentCount);
Brian Osman07c117b2019-05-23 12:51:06 -0700555 this->write8(SlotCount(f.fType));
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400556 int index = fOutput->fExternalValues.size();
557 fOutput->fExternalValues.push_back(f.fFunction);
558 SkASSERT(index <= 255);
559 this->write8(index);
560}
561
Ethan Nicholas91164d12019-05-15 15:29:54 -0400562void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400563 this->write(vector_instruction(ByteCodeInstruction::kReadExternal,
Brian Osman07c117b2019-05-23 12:51:06 -0700564 SlotCount(e.fValue->type())));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400565 int index = fOutput->fExternalValues.size();
566 fOutput->fExternalValues.push_back(e.fValue);
567 SkASSERT(index <= 255);
568 this->write8(index);
569}
570
Brian Osman07c117b2019-05-23 12:51:06 -0700571void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
572 Variable::Storage storage;
573 int location = this->getLocation(expr, &storage);
574 bool isGlobal = storage == Variable::kGlobal_Storage;
575 int count = SlotCount(expr.fType);
576 if (location < 0 || count > 4) {
577 if (location >= 0) {
578 this->write(ByteCodeInstruction::kPushImmediate);
579 this->write32(location);
580 }
581 this->write(isGlobal ? ByteCodeInstruction::kLoadExtendedGlobal
582 : ByteCodeInstruction::kLoadExtended);
583 this->write8(count);
584 } else {
585 this->write(vector_instruction(isGlobal ? ByteCodeInstruction::kLoadGlobal
586 : ByteCodeInstruction::kLoad,
587 count));
588 this->write8(location);
589 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400590}
591
592void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
593 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400594 this->write32(Interpreter::Value((float) f.fValue).fUnsigned);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400595}
596
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400597void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
598 auto found = fIntrinsics.find(c.fFunction.fName);
599 if (found == fIntrinsics.end()) {
600 fErrors.error(c.fOffset, "unsupported intrinsic function");
601 return;
602 }
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400603 if (found->second.fIsSpecial) {
604 SkASSERT(found->second.fValue.fSpecial == SpecialIntrinsic::kDot);
605 SkASSERT(c.fArguments.size() == 2);
606 SkASSERT(SlotCount(c.fArguments[0]->fType) == SlotCount(c.fArguments[1]->fType));
607 this->write((ByteCodeInstruction) ((int) ByteCodeInstruction::kMultiplyF +
608 SlotCount(c.fArguments[0]->fType) - 1));
609 for (int i = SlotCount(c.fArguments[0]->fType); i > 1; --i) {
610 this->write(ByteCodeInstruction::kAddF);
611 }
612 } else {
613 switch (found->second.fValue.fInstruction) {
614 case ByteCodeInstruction::kCos:
615 case ByteCodeInstruction::kMix:
616 case ByteCodeInstruction::kSin:
617 case ByteCodeInstruction::kSqrt:
618 case ByteCodeInstruction::kTan:
619 SkASSERT(c.fArguments.size() > 0);
620 this->write((ByteCodeInstruction) ((int) found->second.fValue.fInstruction +
621 SlotCount(c.fArguments[0]->fType) - 1));
622 break;
623 case ByteCodeInstruction::kCross:
624 this->write(found->second.fValue.fInstruction);
625 break;
626 default:
627 SkASSERT(false);
628 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400629 }
630}
631
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400632void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400633 for (const auto& arg : f.fArguments) {
634 this->writeExpression(*arg);
635 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400636 if (f.fFunction.fBuiltin) {
637 this->writeIntrinsicCall(f);
638 return;
639 }
Brian Osman226668a2019-05-14 16:47:30 -0400640 this->write(ByteCodeInstruction::kCall);
641 fCallTargets.emplace_back(this, f.fFunction);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400642}
643
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400644void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
645 this->write(ByteCodeInstruction::kPushImmediate);
646 this->write32(i.fValue);
647}
648
649void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
650 // not yet implemented
651 abort();
652}
653
Brian Osman3e29f1d2019-05-28 09:35:05 -0400654bool ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p, bool discard) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400655 switch (p.fOperator) {
656 case Token::Kind::PLUSPLUS: // fall through
657 case Token::Kind::MINUSMINUS: {
Brian Osman07c117b2019-05-23 12:51:06 -0700658 SkASSERT(SlotCount(p.fOperand->fType) == 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400659 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
660 lvalue->load();
661 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400662 this->write32(type_category(p.fType) == TypeCategory::kFloat
663 ? Interpreter::Value(1.0f).fUnsigned : 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400664 if (p.fOperator == Token::Kind::PLUSPLUS) {
665 this->writeTypedInstruction(p.fType,
666 ByteCodeInstruction::kAddI,
667 ByteCodeInstruction::kAddI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400668 ByteCodeInstruction::kAddF,
669 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400670 } else {
671 this->writeTypedInstruction(p.fType,
672 ByteCodeInstruction::kSubtractI,
673 ByteCodeInstruction::kSubtractI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400674 ByteCodeInstruction::kSubtractF,
675 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400676 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400677 lvalue->store(discard);
678 discard = false;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400679 break;
680 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400681 case Token::Kind::MINUS: {
682 this->writeExpression(*p.fOperand);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400683 this->writeTypedInstruction(p.fType,
Mike Klein12710912019-05-21 11:04:59 -0500684 ByteCodeInstruction::kNegateI,
685 ByteCodeInstruction::kNegateI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400686 ByteCodeInstruction::kNegateF,
Brian Osman07c117b2019-05-23 12:51:06 -0700687 SlotCount(p.fOperand->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400688 break;
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400689 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400690 default:
691 SkASSERT(false);
692 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400693 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400694}
695
Brian Osman3e29f1d2019-05-28 09:35:05 -0400696bool ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p, bool discard) {
Brian Osmanf3fa6002019-05-17 14:26:53 -0400697 switch (p.fOperator) {
698 case Token::Kind::PLUSPLUS: // fall through
699 case Token::Kind::MINUSMINUS: {
Brian Osman07c117b2019-05-23 12:51:06 -0700700 SkASSERT(SlotCount(p.fOperand->fType) == 1);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400701 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
702 lvalue->load();
Brian Osman3e29f1d2019-05-28 09:35:05 -0400703 if (!discard) {
704 this->write(ByteCodeInstruction::kDup);
705 }
Brian Osmanf3fa6002019-05-17 14:26:53 -0400706 this->write(ByteCodeInstruction::kPushImmediate);
707 this->write32(type_category(p.fType) == TypeCategory::kFloat
708 ? Interpreter::Value(1.0f).fUnsigned : 1);
709 if (p.fOperator == Token::Kind::PLUSPLUS) {
710 this->writeTypedInstruction(p.fType,
711 ByteCodeInstruction::kAddI,
712 ByteCodeInstruction::kAddI,
713 ByteCodeInstruction::kAddF,
714 1);
715 } else {
716 this->writeTypedInstruction(p.fType,
717 ByteCodeInstruction::kSubtractI,
718 ByteCodeInstruction::kSubtractI,
719 ByteCodeInstruction::kSubtractF,
720 1);
721 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400722 lvalue->store(discard);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400723 this->write(ByteCodeInstruction::kPop);
Brian Osman3e29f1d2019-05-28 09:35:05 -0400724 discard = false;
Brian Osmanf3fa6002019-05-17 14:26:53 -0400725 break;
726 }
727 default:
728 SkASSERT(false);
729 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400730 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400731}
732
733void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
Brian Osman0785db02019-05-24 14:19:11 -0400734 if (swizzle_is_simple(s)) {
735 this->writeVariableExpression(s);
736 return;
737 }
738
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400739 switch (s.fBase->fKind) {
740 case Expression::kVariableReference_Kind: {
741 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
Brian Osman1091f022019-05-16 09:42:16 -0400742 this->write(var.fStorage == Variable::kGlobal_Storage
743 ? ByteCodeInstruction::kLoadSwizzleGlobal
744 : ByteCodeInstruction::kLoadSwizzle);
745 this->write8(this->getLocation(var));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400746 this->write8(s.fComponents.size());
747 for (int c : s.fComponents) {
748 this->write8(c);
749 }
750 break;
751 }
752 default:
753 this->writeExpression(*s.fBase);
754 this->write(ByteCodeInstruction::kSwizzle);
755 this->write8(s.fBase->fType.columns());
756 this->write8(s.fComponents.size());
757 for (int c : s.fComponents) {
758 this->write8(c);
759 }
760 }
761}
762
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400763void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Brian Osman4e93feb2019-05-16 15:38:00 -0400764 this->writeExpression(*t.fTest);
Brian Osman569f12f2019-06-13 11:23:57 -0400765 this->write(ByteCodeInstruction::kMaskPush);
Brian Osman4e93feb2019-05-16 15:38:00 -0400766 this->writeExpression(*t.fIfTrue);
Brian Osman569f12f2019-06-13 11:23:57 -0400767 this->write(ByteCodeInstruction::kMaskNegate);
768 this->writeExpression(*t.fIfFalse);
769 this->write(ByteCodeInstruction::kMaskBlend);
770 this->write8(SlotCount(t.fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400771}
772
Brian Osman3e29f1d2019-05-28 09:35:05 -0400773void ByteCodeGenerator::writeExpression(const Expression& e, bool discard) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400774 switch (e.fKind) {
775 case Expression::kBinary_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400776 discard = this->writeBinaryExpression((BinaryExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400777 break;
778 case Expression::kBoolLiteral_Kind:
779 this->writeBoolLiteral((BoolLiteral&) e);
780 break;
781 case Expression::kConstructor_Kind:
782 this->writeConstructor((Constructor&) e);
783 break;
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400784 case Expression::kExternalFunctionCall_Kind:
785 this->writeExternalFunctionCall((ExternalFunctionCall&) e);
786 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400787 case Expression::kExternalValue_Kind:
788 this->writeExternalValue((ExternalValueReference&) e);
789 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400790 case Expression::kFieldAccess_Kind:
Brian Osman07c117b2019-05-23 12:51:06 -0700791 case Expression::kIndex_Kind:
792 case Expression::kVariableReference_Kind:
793 this->writeVariableExpression(e);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400794 break;
795 case Expression::kFloatLiteral_Kind:
796 this->writeFloatLiteral((FloatLiteral&) e);
797 break;
798 case Expression::kFunctionCall_Kind:
799 this->writeFunctionCall((FunctionCall&) e);
800 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400801 case Expression::kIntLiteral_Kind:
802 this->writeIntLiteral((IntLiteral&) e);
803 break;
804 case Expression::kNullLiteral_Kind:
805 this->writeNullLiteral((NullLiteral&) e);
806 break;
807 case Expression::kPrefix_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400808 discard = this->writePrefixExpression((PrefixExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400809 break;
810 case Expression::kPostfix_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400811 discard = this->writePostfixExpression((PostfixExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400812 break;
813 case Expression::kSwizzle_Kind:
814 this->writeSwizzle((Swizzle&) e);
815 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400816 case Expression::kTernary_Kind:
817 this->writeTernaryExpression((TernaryExpression&) e);
818 break;
819 default:
820 printf("unsupported expression %s\n", e.description().c_str());
821 SkASSERT(false);
822 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400823 if (discard) {
824 int count = SlotCount(e.fType);
825 if (count > 4) {
826 this->write(ByteCodeInstruction::kPopN);
827 this->write8(count);
828 } else {
829 this->write(vector_instruction(ByteCodeInstruction::kPop, count));
830 }
831 discard = false;
832 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400833}
834
Ethan Nicholas91164d12019-05-15 15:29:54 -0400835class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
836public:
837 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
838 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700839 , fCount(ByteCodeGenerator::SlotCount(value.type()))
Ethan Nicholas91164d12019-05-15 15:29:54 -0400840 , fIndex(index) {}
841
842 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400843 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400844 fGenerator.write8(fIndex);
845 }
846
Brian Osman3e29f1d2019-05-28 09:35:05 -0400847 void store(bool discard) override {
848 if (!discard) {
849 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
850 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400851 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400852 fGenerator.write8(fIndex);
853 }
854
855private:
856 typedef LValue INHERITED;
857
858 int fCount;
859
860 int fIndex;
861};
862
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400863class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
864public:
865 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
866 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700867 , fSwizzle(swizzle) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400868
869 void load() override {
Brian Osman1091f022019-05-16 09:42:16 -0400870 fGenerator.writeSwizzle(fSwizzle);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400871 }
872
Brian Osman3e29f1d2019-05-28 09:35:05 -0400873 void store(bool discard) override {
874 if (!discard) {
875 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup,
876 fSwizzle.fComponents.size()));
877 }
Brian Osman07c117b2019-05-23 12:51:06 -0700878 Variable::Storage storage;
879 int location = fGenerator.getLocation(*fSwizzle.fBase, &storage);
880 bool isGlobal = storage == Variable::kGlobal_Storage;
881 if (location < 0) {
882 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleIndirectGlobal
883 : ByteCodeInstruction::kStoreSwizzleIndirect);
884 } else {
885 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleGlobal
886 : ByteCodeInstruction::kStoreSwizzle);
887 fGenerator.write8(location);
888 }
Brian Osman1091f022019-05-16 09:42:16 -0400889 fGenerator.write8(fSwizzle.fComponents.size());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400890 for (int c : fSwizzle.fComponents) {
891 fGenerator.write8(c);
892 }
893 }
894
895private:
896 const Swizzle& fSwizzle;
897
898 typedef LValue INHERITED;
899};
900
Brian Osman07c117b2019-05-23 12:51:06 -0700901class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400902public:
Brian Osman07c117b2019-05-23 12:51:06 -0700903 ByteCodeExpressionLValue(ByteCodeGenerator* generator, const Expression& expr)
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400904 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700905 , fExpression(expr) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400906
907 void load() override {
Brian Osman07c117b2019-05-23 12:51:06 -0700908 fGenerator.writeVariableExpression(fExpression);
Brian Osman1091f022019-05-16 09:42:16 -0400909 }
910
Brian Osman3e29f1d2019-05-28 09:35:05 -0400911 void store(bool discard) override {
Brian Osman07c117b2019-05-23 12:51:06 -0700912 int count = ByteCodeGenerator::SlotCount(fExpression.fType);
Brian Osman3e29f1d2019-05-28 09:35:05 -0400913 if (!discard) {
914 if (count > 4) {
915 fGenerator.write(ByteCodeInstruction::kDupN);
916 fGenerator.write8(count);
917 } else {
918 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
919 }
Brian Osman07c117b2019-05-23 12:51:06 -0700920 }
921 Variable::Storage storage;
922 int location = fGenerator.getLocation(fExpression, &storage);
923 bool isGlobal = storage == Variable::kGlobal_Storage;
924 if (location < 0 || count > 4) {
925 if (location >= 0) {
926 fGenerator.write(ByteCodeInstruction::kPushImmediate);
927 fGenerator.write32(location);
928 }
929 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreExtendedGlobal
930 : ByteCodeInstruction::kStoreExtended);
931 fGenerator.write8(count);
932 } else {
933 fGenerator.write(vector_instruction(isGlobal ? ByteCodeInstruction::kStoreGlobal
934 : ByteCodeInstruction::kStore,
935 count));
936 fGenerator.write8(location);
937 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400938 }
939
940private:
941 typedef LValue INHERITED;
942
Brian Osman07c117b2019-05-23 12:51:06 -0700943 const Expression& fExpression;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400944};
945
946std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
947 switch (e.fKind) {
Ethan Nicholas91164d12019-05-15 15:29:54 -0400948 case Expression::kExternalValue_Kind: {
949 ExternalValue* value = ((ExternalValueReference&) e).fValue;
950 int index = fOutput->fExternalValues.size();
951 fOutput->fExternalValues.push_back(value);
952 SkASSERT(index <= 255);
953 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
954 }
Brian Osman07c117b2019-05-23 12:51:06 -0700955 case Expression::kFieldAccess_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400956 case Expression::kIndex_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400957 case Expression::kVariableReference_Kind:
Brian Osman07c117b2019-05-23 12:51:06 -0700958 return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
Brian Osman0785db02019-05-24 14:19:11 -0400959 case Expression::kSwizzle_Kind: {
960 const Swizzle& s = (const Swizzle&) e;
961 return swizzle_is_simple(s)
962 ? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e))
963 : std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s));
964 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400965 case Expression::kTernary_Kind:
966 default:
967 printf("unsupported lvalue %s\n", e.description().c_str());
968 return nullptr;
969 }
970}
971
972void ByteCodeGenerator::writeBlock(const Block& b) {
973 for (const auto& s : b.fStatements) {
974 this->writeStatement(*s);
975 }
976}
977
978void ByteCodeGenerator::setBreakTargets() {
979 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
980 for (DeferredLocation& b : breaks) {
981 b.set();
982 }
983 fBreakTargets.pop();
984}
985
986void ByteCodeGenerator::setContinueTargets() {
987 std::vector<DeferredLocation>& continues = fContinueTargets.top();
988 for (DeferredLocation& c : continues) {
989 c.set();
990 }
991 fContinueTargets.pop();
992}
993
994void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
Brian Osman569f12f2019-06-13 11:23:57 -0400995 // TODO: Include BranchIfAllFalse to top-most LoopNext
996 this->write(ByteCodeInstruction::kLoopBreak);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400997}
998
999void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
Brian Osman569f12f2019-06-13 11:23:57 -04001000 // TODO: Include BranchIfAllFalse to top-most LoopNext
1001 this->write(ByteCodeInstruction::kLoopContinue);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001002}
1003
1004void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
Brian Osman569f12f2019-06-13 11:23:57 -04001005 this->write(ByteCodeInstruction::kLoopBegin);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001006 size_t start = fCode->size();
1007 this->writeStatement(*d.fStatement);
Brian Osman569f12f2019-06-13 11:23:57 -04001008 this->write(ByteCodeInstruction::kLoopNext);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001009 this->writeExpression(*d.fTest);
Brian Osman569f12f2019-06-13 11:23:57 -04001010 this->write(ByteCodeInstruction::kLoopMask);
1011 // TODO: Could shorten this with kBranchIfAnyTrue
1012 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1013 DeferredLocation endLocation(this);
1014 this->write(ByteCodeInstruction::kBranch);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001015 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001016 endLocation.set();
1017 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001018}
1019
1020void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
1021 fContinueTargets.emplace();
1022 fBreakTargets.emplace();
1023 if (f.fInitializer) {
1024 this->writeStatement(*f.fInitializer);
1025 }
Brian Osman569f12f2019-06-13 11:23:57 -04001026 this->write(ByteCodeInstruction::kLoopBegin);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001027 size_t start = fCode->size();
1028 if (f.fTest) {
1029 this->writeExpression(*f.fTest);
Brian Osman569f12f2019-06-13 11:23:57 -04001030 this->write(ByteCodeInstruction::kLoopMask);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001031 }
Brian Osman569f12f2019-06-13 11:23:57 -04001032 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1033 DeferredLocation endLocation(this);
1034 this->writeStatement(*f.fStatement);
1035 this->write(ByteCodeInstruction::kLoopNext);
1036 if (f.fNext) {
1037 this->writeExpression(*f.fNext, true);
1038 }
1039 this->write(ByteCodeInstruction::kBranch);
1040 this->write16(start);
1041 endLocation.set();
1042 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001043}
1044
1045void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Brian Osman569f12f2019-06-13 11:23:57 -04001046 this->writeExpression(*i.fTest);
1047 this->write(ByteCodeInstruction::kMaskPush);
1048 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1049 DeferredLocation falseLocation(this);
1050 this->writeStatement(*i.fIfTrue);
1051 falseLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001052 if (i.fIfFalse) {
Brian Osman569f12f2019-06-13 11:23:57 -04001053 this->write(ByteCodeInstruction::kMaskNegate);
1054 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1055 DeferredLocation endLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001056 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -05001057 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001058 }
Brian Osman569f12f2019-06-13 11:23:57 -04001059 this->write(ByteCodeInstruction::kMaskPop);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001060}
1061
1062void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -04001063 this->writeExpression(*r.fExpression);
1064 this->write(ByteCodeInstruction::kReturn);
Brian Osman07c117b2019-05-23 12:51:06 -07001065 this->write8(SlotCount(r.fExpression->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001066}
1067
1068void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
1069 // not yet implemented
1070 abort();
1071}
1072
1073void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1074 for (const auto& declStatement : v.fVars) {
1075 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
1076 // we need to grab the location even if we don't use it, to ensure it
1077 // has been allocated
1078 int location = getLocation(*decl.fVar);
1079 if (decl.fValue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001080 this->writeExpression(*decl.fValue);
Brian Osman07c117b2019-05-23 12:51:06 -07001081 int count = SlotCount(decl.fValue->fType);
1082 if (count > 4) {
1083 this->write(ByteCodeInstruction::kPushImmediate);
1084 this->write32(location);
1085 this->write(ByteCodeInstruction::kStoreExtended);
1086 this->write8(count);
1087 } else {
1088 this->write(vector_instruction(ByteCodeInstruction::kStore, count));
1089 this->write8(location);
1090 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001091 }
1092 }
1093}
1094
1095void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
Brian Osman569f12f2019-06-13 11:23:57 -04001096 this->write(ByteCodeInstruction::kLoopBegin);
1097 size_t cond = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001098 this->writeExpression(*w.fTest);
Brian Osman569f12f2019-06-13 11:23:57 -04001099 this->write(ByteCodeInstruction::kLoopMask);
1100 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001101 DeferredLocation endLocation(this);
1102 this->writeStatement(*w.fStatement);
Brian Osman569f12f2019-06-13 11:23:57 -04001103 this->write(ByteCodeInstruction::kLoopNext);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001104 this->write(ByteCodeInstruction::kBranch);
Brian Osman569f12f2019-06-13 11:23:57 -04001105 this->write16(cond);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001106 endLocation.set();
Brian Osman569f12f2019-06-13 11:23:57 -04001107 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001108}
1109
1110void ByteCodeGenerator::writeStatement(const Statement& s) {
1111 switch (s.fKind) {
1112 case Statement::kBlock_Kind:
1113 this->writeBlock((Block&) s);
1114 break;
1115 case Statement::kBreak_Kind:
1116 this->writeBreakStatement((BreakStatement&) s);
1117 break;
1118 case Statement::kContinue_Kind:
1119 this->writeContinueStatement((ContinueStatement&) s);
1120 break;
1121 case Statement::kDiscard_Kind:
1122 // not yet implemented
1123 abort();
1124 case Statement::kDo_Kind:
1125 this->writeDoStatement((DoStatement&) s);
1126 break;
Brian Osman3e29f1d2019-05-28 09:35:05 -04001127 case Statement::kExpression_Kind:
1128 this->writeExpression(*((ExpressionStatement&) s).fExpression, true);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001129 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001130 case Statement::kFor_Kind:
1131 this->writeForStatement((ForStatement&) s);
1132 break;
1133 case Statement::kIf_Kind:
1134 this->writeIfStatement((IfStatement&) s);
1135 break;
1136 case Statement::kNop_Kind:
1137 break;
1138 case Statement::kReturn_Kind:
1139 this->writeReturnStatement((ReturnStatement&) s);
1140 break;
1141 case Statement::kSwitch_Kind:
1142 this->writeSwitchStatement((SwitchStatement&) s);
1143 break;
1144 case Statement::kVarDeclarations_Kind:
1145 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1146 break;
1147 case Statement::kWhile_Kind:
1148 this->writeWhileStatement((WhileStatement&) s);
1149 break;
1150 default:
1151 SkASSERT(false);
1152 }
1153}
1154
Brian Osman80164412019-06-07 13:00:23 -04001155ByteCodeFunction::ByteCodeFunction(const FunctionDeclaration* declaration)
1156 : fName(declaration->fName) {
1157 fParameterCount = 0;
1158 for (const auto& p : declaration->fParameters) {
1159 int slots = ByteCodeGenerator::SlotCount(p->fType);
1160 fParameters.push_back({ slots, (bool)(p->fModifiers.fFlags & Modifiers::kOut_Flag) });
1161 fParameterCount += slots;
1162 }
1163}
1164
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001165}