blob: 9d779f2dd7fdbf77df0fd17ca4f2478220ce696a [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
Brian Osman08a84962019-06-14 10:17:16 -04008#include "include/private/SkFloatBits.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -05009#include "src/sksl/SkSLByteCodeGenerator.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 Osman08a84962019-06-14 10:17:16 -0400594 this->write32(SkFloat2Bits(f.fValue));
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 Osman08a84962019-06-14 10:17:16 -0400662 this->write32(type_category(p.fType) == TypeCategory::kFloat ? SkFloat2Bits(1.0f) : 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400663 if (p.fOperator == Token::Kind::PLUSPLUS) {
664 this->writeTypedInstruction(p.fType,
665 ByteCodeInstruction::kAddI,
666 ByteCodeInstruction::kAddI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400667 ByteCodeInstruction::kAddF,
668 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400669 } else {
670 this->writeTypedInstruction(p.fType,
671 ByteCodeInstruction::kSubtractI,
672 ByteCodeInstruction::kSubtractI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400673 ByteCodeInstruction::kSubtractF,
674 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400675 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400676 lvalue->store(discard);
677 discard = false;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400678 break;
679 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400680 case Token::Kind::MINUS: {
681 this->writeExpression(*p.fOperand);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400682 this->writeTypedInstruction(p.fType,
Mike Klein12710912019-05-21 11:04:59 -0500683 ByteCodeInstruction::kNegateI,
684 ByteCodeInstruction::kNegateI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400685 ByteCodeInstruction::kNegateF,
Brian Osman07c117b2019-05-23 12:51:06 -0700686 SlotCount(p.fOperand->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400687 break;
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400688 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400689 default:
690 SkASSERT(false);
691 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400692 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400693}
694
Brian Osman3e29f1d2019-05-28 09:35:05 -0400695bool ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p, bool discard) {
Brian Osmanf3fa6002019-05-17 14:26:53 -0400696 switch (p.fOperator) {
697 case Token::Kind::PLUSPLUS: // fall through
698 case Token::Kind::MINUSMINUS: {
Brian Osman07c117b2019-05-23 12:51:06 -0700699 SkASSERT(SlotCount(p.fOperand->fType) == 1);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400700 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
701 lvalue->load();
Brian Osman3e29f1d2019-05-28 09:35:05 -0400702 if (!discard) {
703 this->write(ByteCodeInstruction::kDup);
704 }
Brian Osmanf3fa6002019-05-17 14:26:53 -0400705 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osman08a84962019-06-14 10:17:16 -0400706 this->write32(type_category(p.fType) == TypeCategory::kFloat ? SkFloat2Bits(1.0f) : 1);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400707 if (p.fOperator == Token::Kind::PLUSPLUS) {
708 this->writeTypedInstruction(p.fType,
709 ByteCodeInstruction::kAddI,
710 ByteCodeInstruction::kAddI,
711 ByteCodeInstruction::kAddF,
712 1);
713 } else {
714 this->writeTypedInstruction(p.fType,
715 ByteCodeInstruction::kSubtractI,
716 ByteCodeInstruction::kSubtractI,
717 ByteCodeInstruction::kSubtractF,
718 1);
719 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400720 lvalue->store(discard);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400721 this->write(ByteCodeInstruction::kPop);
Brian Osman3e29f1d2019-05-28 09:35:05 -0400722 discard = false;
Brian Osmanf3fa6002019-05-17 14:26:53 -0400723 break;
724 }
725 default:
726 SkASSERT(false);
727 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400728 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400729}
730
731void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
Brian Osman0785db02019-05-24 14:19:11 -0400732 if (swizzle_is_simple(s)) {
733 this->writeVariableExpression(s);
734 return;
735 }
736
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400737 switch (s.fBase->fKind) {
738 case Expression::kVariableReference_Kind: {
739 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
Brian Osman1091f022019-05-16 09:42:16 -0400740 this->write(var.fStorage == Variable::kGlobal_Storage
741 ? ByteCodeInstruction::kLoadSwizzleGlobal
742 : ByteCodeInstruction::kLoadSwizzle);
743 this->write8(this->getLocation(var));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400744 this->write8(s.fComponents.size());
745 for (int c : s.fComponents) {
746 this->write8(c);
747 }
748 break;
749 }
750 default:
751 this->writeExpression(*s.fBase);
752 this->write(ByteCodeInstruction::kSwizzle);
753 this->write8(s.fBase->fType.columns());
754 this->write8(s.fComponents.size());
755 for (int c : s.fComponents) {
756 this->write8(c);
757 }
758 }
759}
760
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400761void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Brian Osman4e93feb2019-05-16 15:38:00 -0400762 this->writeExpression(*t.fTest);
Brian Osman569f12f2019-06-13 11:23:57 -0400763 this->write(ByteCodeInstruction::kMaskPush);
Brian Osman4e93feb2019-05-16 15:38:00 -0400764 this->writeExpression(*t.fIfTrue);
Brian Osman569f12f2019-06-13 11:23:57 -0400765 this->write(ByteCodeInstruction::kMaskNegate);
766 this->writeExpression(*t.fIfFalse);
767 this->write(ByteCodeInstruction::kMaskBlend);
768 this->write8(SlotCount(t.fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400769}
770
Brian Osman3e29f1d2019-05-28 09:35:05 -0400771void ByteCodeGenerator::writeExpression(const Expression& e, bool discard) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400772 switch (e.fKind) {
773 case Expression::kBinary_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400774 discard = this->writeBinaryExpression((BinaryExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400775 break;
776 case Expression::kBoolLiteral_Kind:
777 this->writeBoolLiteral((BoolLiteral&) e);
778 break;
779 case Expression::kConstructor_Kind:
780 this->writeConstructor((Constructor&) e);
781 break;
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400782 case Expression::kExternalFunctionCall_Kind:
783 this->writeExternalFunctionCall((ExternalFunctionCall&) e);
784 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400785 case Expression::kExternalValue_Kind:
786 this->writeExternalValue((ExternalValueReference&) e);
787 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400788 case Expression::kFieldAccess_Kind:
Brian Osman07c117b2019-05-23 12:51:06 -0700789 case Expression::kIndex_Kind:
790 case Expression::kVariableReference_Kind:
791 this->writeVariableExpression(e);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400792 break;
793 case Expression::kFloatLiteral_Kind:
794 this->writeFloatLiteral((FloatLiteral&) e);
795 break;
796 case Expression::kFunctionCall_Kind:
797 this->writeFunctionCall((FunctionCall&) e);
798 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400799 case Expression::kIntLiteral_Kind:
800 this->writeIntLiteral((IntLiteral&) e);
801 break;
802 case Expression::kNullLiteral_Kind:
803 this->writeNullLiteral((NullLiteral&) e);
804 break;
805 case Expression::kPrefix_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400806 discard = this->writePrefixExpression((PrefixExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400807 break;
808 case Expression::kPostfix_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400809 discard = this->writePostfixExpression((PostfixExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400810 break;
811 case Expression::kSwizzle_Kind:
812 this->writeSwizzle((Swizzle&) e);
813 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400814 case Expression::kTernary_Kind:
815 this->writeTernaryExpression((TernaryExpression&) e);
816 break;
817 default:
818 printf("unsupported expression %s\n", e.description().c_str());
819 SkASSERT(false);
820 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400821 if (discard) {
822 int count = SlotCount(e.fType);
823 if (count > 4) {
824 this->write(ByteCodeInstruction::kPopN);
825 this->write8(count);
826 } else {
827 this->write(vector_instruction(ByteCodeInstruction::kPop, count));
828 }
829 discard = false;
830 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400831}
832
Ethan Nicholas91164d12019-05-15 15:29:54 -0400833class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
834public:
835 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
836 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700837 , fCount(ByteCodeGenerator::SlotCount(value.type()))
Ethan Nicholas91164d12019-05-15 15:29:54 -0400838 , fIndex(index) {}
839
840 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400841 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400842 fGenerator.write8(fIndex);
843 }
844
Brian Osman3e29f1d2019-05-28 09:35:05 -0400845 void store(bool discard) override {
846 if (!discard) {
847 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
848 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400849 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400850 fGenerator.write8(fIndex);
851 }
852
853private:
854 typedef LValue INHERITED;
855
856 int fCount;
857
858 int fIndex;
859};
860
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400861class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
862public:
863 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
864 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700865 , fSwizzle(swizzle) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400866
867 void load() override {
Brian Osman1091f022019-05-16 09:42:16 -0400868 fGenerator.writeSwizzle(fSwizzle);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400869 }
870
Brian Osman3e29f1d2019-05-28 09:35:05 -0400871 void store(bool discard) override {
872 if (!discard) {
873 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup,
874 fSwizzle.fComponents.size()));
875 }
Brian Osman07c117b2019-05-23 12:51:06 -0700876 Variable::Storage storage;
877 int location = fGenerator.getLocation(*fSwizzle.fBase, &storage);
878 bool isGlobal = storage == Variable::kGlobal_Storage;
879 if (location < 0) {
880 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleIndirectGlobal
881 : ByteCodeInstruction::kStoreSwizzleIndirect);
882 } else {
883 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleGlobal
884 : ByteCodeInstruction::kStoreSwizzle);
885 fGenerator.write8(location);
886 }
Brian Osman1091f022019-05-16 09:42:16 -0400887 fGenerator.write8(fSwizzle.fComponents.size());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400888 for (int c : fSwizzle.fComponents) {
889 fGenerator.write8(c);
890 }
891 }
892
893private:
894 const Swizzle& fSwizzle;
895
896 typedef LValue INHERITED;
897};
898
Brian Osman07c117b2019-05-23 12:51:06 -0700899class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400900public:
Brian Osman07c117b2019-05-23 12:51:06 -0700901 ByteCodeExpressionLValue(ByteCodeGenerator* generator, const Expression& expr)
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400902 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700903 , fExpression(expr) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400904
905 void load() override {
Brian Osman07c117b2019-05-23 12:51:06 -0700906 fGenerator.writeVariableExpression(fExpression);
Brian Osman1091f022019-05-16 09:42:16 -0400907 }
908
Brian Osman3e29f1d2019-05-28 09:35:05 -0400909 void store(bool discard) override {
Brian Osman07c117b2019-05-23 12:51:06 -0700910 int count = ByteCodeGenerator::SlotCount(fExpression.fType);
Brian Osman3e29f1d2019-05-28 09:35:05 -0400911 if (!discard) {
912 if (count > 4) {
913 fGenerator.write(ByteCodeInstruction::kDupN);
914 fGenerator.write8(count);
915 } else {
916 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
917 }
Brian Osman07c117b2019-05-23 12:51:06 -0700918 }
919 Variable::Storage storage;
920 int location = fGenerator.getLocation(fExpression, &storage);
921 bool isGlobal = storage == Variable::kGlobal_Storage;
922 if (location < 0 || count > 4) {
923 if (location >= 0) {
924 fGenerator.write(ByteCodeInstruction::kPushImmediate);
925 fGenerator.write32(location);
926 }
927 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreExtendedGlobal
928 : ByteCodeInstruction::kStoreExtended);
929 fGenerator.write8(count);
930 } else {
931 fGenerator.write(vector_instruction(isGlobal ? ByteCodeInstruction::kStoreGlobal
932 : ByteCodeInstruction::kStore,
933 count));
934 fGenerator.write8(location);
935 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400936 }
937
938private:
939 typedef LValue INHERITED;
940
Brian Osman07c117b2019-05-23 12:51:06 -0700941 const Expression& fExpression;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400942};
943
944std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
945 switch (e.fKind) {
Ethan Nicholas91164d12019-05-15 15:29:54 -0400946 case Expression::kExternalValue_Kind: {
947 ExternalValue* value = ((ExternalValueReference&) e).fValue;
948 int index = fOutput->fExternalValues.size();
949 fOutput->fExternalValues.push_back(value);
950 SkASSERT(index <= 255);
951 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
952 }
Brian Osman07c117b2019-05-23 12:51:06 -0700953 case Expression::kFieldAccess_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400954 case Expression::kIndex_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400955 case Expression::kVariableReference_Kind:
Brian Osman07c117b2019-05-23 12:51:06 -0700956 return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
Brian Osman0785db02019-05-24 14:19:11 -0400957 case Expression::kSwizzle_Kind: {
958 const Swizzle& s = (const Swizzle&) e;
959 return swizzle_is_simple(s)
960 ? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e))
961 : std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s));
962 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400963 case Expression::kTernary_Kind:
964 default:
965 printf("unsupported lvalue %s\n", e.description().c_str());
966 return nullptr;
967 }
968}
969
970void ByteCodeGenerator::writeBlock(const Block& b) {
971 for (const auto& s : b.fStatements) {
972 this->writeStatement(*s);
973 }
974}
975
976void ByteCodeGenerator::setBreakTargets() {
977 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
978 for (DeferredLocation& b : breaks) {
979 b.set();
980 }
981 fBreakTargets.pop();
982}
983
984void ByteCodeGenerator::setContinueTargets() {
985 std::vector<DeferredLocation>& continues = fContinueTargets.top();
986 for (DeferredLocation& c : continues) {
987 c.set();
988 }
989 fContinueTargets.pop();
990}
991
992void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
Brian Osman569f12f2019-06-13 11:23:57 -0400993 // TODO: Include BranchIfAllFalse to top-most LoopNext
994 this->write(ByteCodeInstruction::kLoopBreak);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400995}
996
997void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
Brian Osman569f12f2019-06-13 11:23:57 -0400998 // TODO: Include BranchIfAllFalse to top-most LoopNext
999 this->write(ByteCodeInstruction::kLoopContinue);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001000}
1001
1002void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
Brian Osman569f12f2019-06-13 11:23:57 -04001003 this->write(ByteCodeInstruction::kLoopBegin);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001004 size_t start = fCode->size();
1005 this->writeStatement(*d.fStatement);
Brian Osman569f12f2019-06-13 11:23:57 -04001006 this->write(ByteCodeInstruction::kLoopNext);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001007 this->writeExpression(*d.fTest);
Brian Osman569f12f2019-06-13 11:23:57 -04001008 this->write(ByteCodeInstruction::kLoopMask);
1009 // TODO: Could shorten this with kBranchIfAnyTrue
1010 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1011 DeferredLocation endLocation(this);
1012 this->write(ByteCodeInstruction::kBranch);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001013 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001014 endLocation.set();
1015 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001016}
1017
1018void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
1019 fContinueTargets.emplace();
1020 fBreakTargets.emplace();
1021 if (f.fInitializer) {
1022 this->writeStatement(*f.fInitializer);
1023 }
Brian Osman569f12f2019-06-13 11:23:57 -04001024 this->write(ByteCodeInstruction::kLoopBegin);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001025 size_t start = fCode->size();
1026 if (f.fTest) {
1027 this->writeExpression(*f.fTest);
Brian Osman569f12f2019-06-13 11:23:57 -04001028 this->write(ByteCodeInstruction::kLoopMask);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001029 }
Brian Osman569f12f2019-06-13 11:23:57 -04001030 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1031 DeferredLocation endLocation(this);
1032 this->writeStatement(*f.fStatement);
1033 this->write(ByteCodeInstruction::kLoopNext);
1034 if (f.fNext) {
1035 this->writeExpression(*f.fNext, true);
1036 }
1037 this->write(ByteCodeInstruction::kBranch);
1038 this->write16(start);
1039 endLocation.set();
1040 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001041}
1042
1043void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Brian Osman569f12f2019-06-13 11:23:57 -04001044 this->writeExpression(*i.fTest);
1045 this->write(ByteCodeInstruction::kMaskPush);
1046 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1047 DeferredLocation falseLocation(this);
1048 this->writeStatement(*i.fIfTrue);
1049 falseLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001050 if (i.fIfFalse) {
Brian Osman569f12f2019-06-13 11:23:57 -04001051 this->write(ByteCodeInstruction::kMaskNegate);
1052 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1053 DeferredLocation endLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001054 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -05001055 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001056 }
Brian Osman569f12f2019-06-13 11:23:57 -04001057 this->write(ByteCodeInstruction::kMaskPop);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001058}
1059
1060void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -04001061 this->writeExpression(*r.fExpression);
1062 this->write(ByteCodeInstruction::kReturn);
Brian Osman07c117b2019-05-23 12:51:06 -07001063 this->write8(SlotCount(r.fExpression->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001064}
1065
1066void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
1067 // not yet implemented
1068 abort();
1069}
1070
1071void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1072 for (const auto& declStatement : v.fVars) {
1073 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
1074 // we need to grab the location even if we don't use it, to ensure it
1075 // has been allocated
1076 int location = getLocation(*decl.fVar);
1077 if (decl.fValue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001078 this->writeExpression(*decl.fValue);
Brian Osman07c117b2019-05-23 12:51:06 -07001079 int count = SlotCount(decl.fValue->fType);
1080 if (count > 4) {
1081 this->write(ByteCodeInstruction::kPushImmediate);
1082 this->write32(location);
1083 this->write(ByteCodeInstruction::kStoreExtended);
1084 this->write8(count);
1085 } else {
1086 this->write(vector_instruction(ByteCodeInstruction::kStore, count));
1087 this->write8(location);
1088 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001089 }
1090 }
1091}
1092
1093void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
Brian Osman569f12f2019-06-13 11:23:57 -04001094 this->write(ByteCodeInstruction::kLoopBegin);
1095 size_t cond = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001096 this->writeExpression(*w.fTest);
Brian Osman569f12f2019-06-13 11:23:57 -04001097 this->write(ByteCodeInstruction::kLoopMask);
1098 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001099 DeferredLocation endLocation(this);
1100 this->writeStatement(*w.fStatement);
Brian Osman569f12f2019-06-13 11:23:57 -04001101 this->write(ByteCodeInstruction::kLoopNext);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001102 this->write(ByteCodeInstruction::kBranch);
Brian Osman569f12f2019-06-13 11:23:57 -04001103 this->write16(cond);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001104 endLocation.set();
Brian Osman569f12f2019-06-13 11:23:57 -04001105 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001106}
1107
1108void ByteCodeGenerator::writeStatement(const Statement& s) {
1109 switch (s.fKind) {
1110 case Statement::kBlock_Kind:
1111 this->writeBlock((Block&) s);
1112 break;
1113 case Statement::kBreak_Kind:
1114 this->writeBreakStatement((BreakStatement&) s);
1115 break;
1116 case Statement::kContinue_Kind:
1117 this->writeContinueStatement((ContinueStatement&) s);
1118 break;
1119 case Statement::kDiscard_Kind:
1120 // not yet implemented
1121 abort();
1122 case Statement::kDo_Kind:
1123 this->writeDoStatement((DoStatement&) s);
1124 break;
Brian Osman3e29f1d2019-05-28 09:35:05 -04001125 case Statement::kExpression_Kind:
1126 this->writeExpression(*((ExpressionStatement&) s).fExpression, true);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001127 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001128 case Statement::kFor_Kind:
1129 this->writeForStatement((ForStatement&) s);
1130 break;
1131 case Statement::kIf_Kind:
1132 this->writeIfStatement((IfStatement&) s);
1133 break;
1134 case Statement::kNop_Kind:
1135 break;
1136 case Statement::kReturn_Kind:
1137 this->writeReturnStatement((ReturnStatement&) s);
1138 break;
1139 case Statement::kSwitch_Kind:
1140 this->writeSwitchStatement((SwitchStatement&) s);
1141 break;
1142 case Statement::kVarDeclarations_Kind:
1143 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1144 break;
1145 case Statement::kWhile_Kind:
1146 this->writeWhileStatement((WhileStatement&) s);
1147 break;
1148 default:
1149 SkASSERT(false);
1150 }
1151}
1152
Brian Osman80164412019-06-07 13:00:23 -04001153ByteCodeFunction::ByteCodeFunction(const FunctionDeclaration* declaration)
1154 : fName(declaration->fName) {
1155 fParameterCount = 0;
1156 for (const auto& p : declaration->fParameters) {
1157 int slots = ByteCodeGenerator::SlotCount(p->fType);
1158 fParameters.push_back({ slots, (bool)(p->fModifiers.fFlags & Modifiers::kOut_Flag) });
1159 fParameterCount += slots;
1160 }
1161}
1162
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001163}