blob: d8dcb256a9ef16f24d9f32f8a6c69a68f654b807 [file] [log] [blame]
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001/*
2 * Copyright 2019 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/sksl/SkSLByteCodeGenerator.h"
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04009
Brian Osman95253bd2019-06-05 10:28:45 -040010#include <algorithm>
11
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040012namespace SkSL {
13
Ethan Nicholas82162ee2019-05-21 16:05:08 -040014ByteCodeGenerator::ByteCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
15 ByteCode* output)
16 : INHERITED(program, errors, nullptr)
17 , fContext(*context)
Ethan Nicholasae9633b2019-05-24 12:46:34 -040018 , fOutput(output)
19 , fIntrinsics {
20 { "cos", ByteCodeInstruction::kCos },
21 { "cross", ByteCodeInstruction::kCross },
22 { "dot", SpecialIntrinsic::kDot },
23 { "sin", ByteCodeInstruction::kSin },
24 { "sqrt", ByteCodeInstruction::kSqrt },
25 { "tan", ByteCodeInstruction::kTan },
26 { "mix", ByteCodeInstruction::kMix },
27 } {}
28
Ethan Nicholas82162ee2019-05-21 16:05:08 -040029
Brian Osman07c117b2019-05-23 12:51:06 -070030int ByteCodeGenerator::SlotCount(const Type& type) {
31 if (type.kind() == Type::kStruct_Kind) {
32 int slots = 0;
33 for (const auto& f : type.fields()) {
34 slots += SlotCount(*f.fType);
35 }
36 SkASSERT(slots <= 255);
37 return slots;
38 } else if (type.kind() == Type::kArray_Kind) {
39 int columns = type.columns();
40 SkASSERT(columns >= 0);
41 int slots = columns * SlotCount(type.componentType());
42 SkASSERT(slots <= 255);
43 return slots;
44 } else {
45 return type.columns() * type.rows();
46 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040047}
48
49bool ByteCodeGenerator::generateCode() {
50 for (const auto& e : fProgram) {
51 switch (e.fKind) {
52 case ProgramElement::kFunction_Kind: {
53 std::unique_ptr<ByteCodeFunction> f = this->writeFunction((FunctionDefinition&) e);
54 if (!f) {
55 return false;
56 }
57 fOutput->fFunctions.push_back(std::move(f));
Brian Osman80164412019-06-07 13:00:23 -040058 fFunctions.push_back(&(FunctionDefinition&)e);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040059 break;
60 }
61 case ProgramElement::kVar_Kind: {
62 VarDeclarations& decl = (VarDeclarations&) e;
63 for (const auto& v : decl.fVars) {
64 const Variable* declVar = ((VarDeclaration&) *v).fVar;
65 if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
66 continue;
67 }
68 if (declVar->fModifiers.fFlags & Modifiers::kIn_Flag) {
Brian Osman07c117b2019-05-23 12:51:06 -070069 for (int i = SlotCount(declVar->fType); i > 0; --i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040070 fOutput->fInputSlots.push_back(fOutput->fGlobalCount++);
71 }
72 } else {
Brian Osman07c117b2019-05-23 12:51:06 -070073 fOutput->fGlobalCount += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040074 }
75 }
76 break;
77 }
78 default:
79 ; // ignore
80 }
81 }
Brian Osman226668a2019-05-14 16:47:30 -040082 for (auto& call : fCallTargets) {
83 if (!call.set()) {
84 return false;
85 }
86 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040087 return true;
88}
89
90std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
91 fFunction = &f;
Brian Osman226668a2019-05-14 16:47:30 -040092 std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
Brian Osman80164412019-06-07 13:00:23 -040093 fParameterCount = result->fParameterCount;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040094 fCode = &result->fCode;
95 this->writeStatement(*f.fBody);
Ethan Nicholas7e603db2019-05-03 12:57:47 -040096 this->write(ByteCodeInstruction::kReturn);
97 this->write8(0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040098 result->fLocalCount = fLocals.size();
Ethan Nicholasdfcad062019-05-07 12:53:34 -040099 const Type& returnType = f.fDeclaration.fReturnType;
100 if (returnType != *fContext.fVoid_Type) {
Brian Osman07c117b2019-05-23 12:51:06 -0700101 result->fReturnCount = SlotCount(returnType);
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400102 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400103 fLocals.clear();
104 fFunction = nullptr;
105 return result;
106}
107
108enum class TypeCategory {
109 kBool,
110 kSigned,
111 kUnsigned,
112 kFloat,
113};
114
115static TypeCategory type_category(const Type& type) {
116 switch (type.kind()) {
117 case Type::Kind::kVector_Kind:
118 case Type::Kind::kMatrix_Kind:
119 return type_category(type.componentType());
120 default:
121 if (type.fName == "bool") {
122 return TypeCategory::kBool;
123 } else if (type.fName == "int" || type.fName == "short") {
124 return TypeCategory::kSigned;
125 } else if (type.fName == "uint" || type.fName == "ushort") {
126 return TypeCategory::kUnsigned;
127 } else {
128 SkASSERT(type.fName == "float" || type.fName == "half");
129 return TypeCategory::kFloat;
130 }
131 ABORT("unsupported type: %s\n", type.description().c_str());
132 }
133}
134
Brian Osman0785db02019-05-24 14:19:11 -0400135// A "simple" Swizzle is based on a variable (or a compound variable like a struct or array), and
136// that references consecutive values, such that it can be implemented using normal load/store ops
137// with an offset. Note that all single-component swizzles (of suitable base types) are simple.
138static bool swizzle_is_simple(const Swizzle& s) {
139 switch (s.fBase->fKind) {
140 case Expression::kFieldAccess_Kind:
141 case Expression::kIndex_Kind:
142 case Expression::kVariableReference_Kind:
143 break;
144 default:
145 return false;
146 }
147
148 for (size_t i = 1; i < s.fComponents.size(); ++i) {
149 if (s.fComponents[i] != s.fComponents[i - 1] + 1) {
150 return false;
151 }
152 }
153 return true;
154}
155
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400156int ByteCodeGenerator::getLocation(const Variable& var) {
157 // given that we seldom have more than a couple of variables, linear search is probably the most
158 // efficient way to handle lookups
159 switch (var.fStorage) {
160 case Variable::kLocal_Storage: {
161 for (int i = fLocals.size() - 1; i >= 0; --i) {
162 if (fLocals[i] == &var) {
Brian Osman1091f022019-05-16 09:42:16 -0400163 SkASSERT(fParameterCount + i <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400164 return fParameterCount + i;
165 }
166 }
167 int result = fParameterCount + fLocals.size();
168 fLocals.push_back(&var);
Brian Osman07c117b2019-05-23 12:51:06 -0700169 for (int i = 0; i < SlotCount(var.fType) - 1; ++i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400170 fLocals.push_back(nullptr);
171 }
Brian Osman1091f022019-05-16 09:42:16 -0400172 SkASSERT(result <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400173 return result;
174 }
175 case Variable::kParameter_Storage: {
176 int offset = 0;
177 for (const auto& p : fFunction->fDeclaration.fParameters) {
178 if (p == &var) {
Brian Osman1091f022019-05-16 09:42:16 -0400179 SkASSERT(offset <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400180 return offset;
181 }
Brian Osman07c117b2019-05-23 12:51:06 -0700182 offset += SlotCount(p->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400183 }
184 SkASSERT(false);
Brian Osman1091f022019-05-16 09:42:16 -0400185 return 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400186 }
187 case Variable::kGlobal_Storage: {
188 int offset = 0;
189 for (const auto& e : fProgram) {
190 if (e.fKind == ProgramElement::kVar_Kind) {
191 VarDeclarations& decl = (VarDeclarations&) e;
192 for (const auto& v : decl.fVars) {
193 const Variable* declVar = ((VarDeclaration&) *v).fVar;
194 if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
195 continue;
196 }
197 if (declVar == &var) {
Brian Osmanb7451292019-05-15 13:02:13 -0400198 SkASSERT(offset <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400199 return offset;
200 }
Brian Osman07c117b2019-05-23 12:51:06 -0700201 offset += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400202 }
203 }
204 }
205 SkASSERT(false);
Brian Osman1091f022019-05-16 09:42:16 -0400206 return 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400207 }
208 default:
209 SkASSERT(false);
210 return 0;
211 }
212}
213
Brian Osman0785db02019-05-24 14:19:11 -0400214// TODO: Elide Add 0 and Mul 1 sequences
Brian Osman07c117b2019-05-23 12:51:06 -0700215int ByteCodeGenerator::getLocation(const Expression& expr, Variable::Storage* storage) {
216 switch (expr.fKind) {
217 case Expression::kFieldAccess_Kind: {
218 const FieldAccess& f = (const FieldAccess&)expr;
219 int baseAddr = this->getLocation(*f.fBase, storage);
220 int offset = 0;
221 for (int i = 0; i < f.fFieldIndex; ++i) {
222 offset += SlotCount(*f.fBase->fType.fields()[i].fType);
223 }
224 if (baseAddr < 0) {
225 this->write(ByteCodeInstruction::kPushImmediate);
226 this->write32(offset);
227 this->write(ByteCodeInstruction::kAddI);
228 return -1;
229 } else {
230 return baseAddr + offset;
231 }
232 }
233 case Expression::kIndex_Kind: {
234 const IndexExpression& i = (const IndexExpression&)expr;
235 int stride = SlotCount(i.fType);
236 int offset = -1;
237 if (i.fIndex->isConstant()) {
238 offset = i.fIndex->getConstantInt() * stride;
239 } else {
240 this->writeExpression(*i.fIndex);
241 this->write(ByteCodeInstruction::kPushImmediate);
242 this->write32(stride);
243 this->write(ByteCodeInstruction::kMultiplyI);
244 }
245 int baseAddr = this->getLocation(*i.fBase, storage);
246 if (baseAddr >= 0 && offset >= 0) {
247 return baseAddr + offset;
248 }
249 if (baseAddr >= 0) {
250 this->write(ByteCodeInstruction::kPushImmediate);
251 this->write32(baseAddr);
252 }
253 if (offset >= 0) {
254 this->write(ByteCodeInstruction::kPushImmediate);
255 this->write32(offset);
256 }
257 this->write(ByteCodeInstruction::kAddI);
258 return -1;
259 }
Brian Osman0785db02019-05-24 14:19:11 -0400260 case Expression::kSwizzle_Kind: {
261 const Swizzle& s = (const Swizzle&)expr;
262 SkASSERT(swizzle_is_simple(s));
263 int baseAddr = this->getLocation(*s.fBase, storage);
264 int offset = s.fComponents[0];
265 if (baseAddr < 0) {
266 this->write(ByteCodeInstruction::kPushImmediate);
267 this->write32(offset);
268 this->write(ByteCodeInstruction::kAddI);
269 return -1;
270 } else {
271 return baseAddr + offset;
272 }
273 }
Brian Osman07c117b2019-05-23 12:51:06 -0700274 case Expression::kVariableReference_Kind: {
275 const Variable& var = ((const VariableReference&)expr).fVariable;
276 *storage = var.fStorage;
277 return this->getLocation(var);
278 }
279 default:
280 SkASSERT(false);
281 return 0;
282 }
283}
284
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400285void ByteCodeGenerator::write8(uint8_t b) {
286 fCode->push_back(b);
287}
288
289void ByteCodeGenerator::write16(uint16_t i) {
Mike Klein76346ac2019-05-17 11:57:10 -0500290 size_t n = fCode->size();
291 fCode->resize(n+2);
292 memcpy(fCode->data() + n, &i, 2);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400293}
294
295void ByteCodeGenerator::write32(uint32_t i) {
Mike Klein76346ac2019-05-17 11:57:10 -0500296 size_t n = fCode->size();
297 fCode->resize(n+4);
298 memcpy(fCode->data() + n, &i, 4);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400299}
300
301void ByteCodeGenerator::write(ByteCodeInstruction i) {
Mike Klein108e9352019-05-21 11:05:17 -0500302 this->write16((uint16_t)i);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400303}
304
Mike Klein76346ac2019-05-17 11:57:10 -0500305static ByteCodeInstruction vector_instruction(ByteCodeInstruction base, int count) {
Brian Osman07c117b2019-05-23 12:51:06 -0700306 SkASSERT(count >= 1 && count <= 4);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400307 return ((ByteCodeInstruction) ((int) base + count - 1));
308}
309
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400310void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400311 ByteCodeInstruction u, ByteCodeInstruction f,
312 int count) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400313 switch (type_category(type)) {
314 case TypeCategory::kSigned:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400315 this->write(vector_instruction(s, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400316 break;
317 case TypeCategory::kUnsigned:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400318 this->write(vector_instruction(u, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400319 break;
Brian Osman1e855b22019-05-29 15:21:52 -0400320 case TypeCategory::kFloat: {
321 if (count > 4) {
322 this->write((ByteCodeInstruction)((int)f + 4));
323 this->write8(count);
324 } else {
325 this->write(vector_instruction(f, count));
326 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400327 break;
Brian Osman1e855b22019-05-29 15:21:52 -0400328 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400329 default:
330 SkASSERT(false);
331 }
332}
333
Brian Osman3e29f1d2019-05-28 09:35:05 -0400334bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool discard) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400335 if (b.fOperator == Token::Kind::EQ) {
336 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
337 this->writeExpression(*b.fRight);
Brian Osman3e29f1d2019-05-28 09:35:05 -0400338 lvalue->store(discard);
339 discard = false;
340 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400341 }
Brian Osman16e6fd52019-05-29 11:19:00 -0400342 const Type& lType = b.fLeft->fType;
343 const Type& rType = b.fRight->fType;
Brian Osman909231c2019-05-29 15:34:36 -0400344 bool lVecOrMtx = (lType.kind() == Type::kVector_Kind || lType.kind() == Type::kMatrix_Kind);
345 bool rVecOrMtx = (rType.kind() == Type::kVector_Kind || rType.kind() == Type::kMatrix_Kind);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400346 Token::Kind op;
347 std::unique_ptr<LValue> lvalue;
348 if (is_assignment(b.fOperator)) {
349 lvalue = this->getLValue(*b.fLeft);
350 lvalue->load();
351 op = remove_assignment(b.fOperator);
352 } else {
353 this->writeExpression(*b.fLeft);
354 op = b.fOperator;
Brian Osman909231c2019-05-29 15:34:36 -0400355 if (!lVecOrMtx && rVecOrMtx) {
Brian Osman16e6fd52019-05-29 11:19:00 -0400356 for (int i = SlotCount(rType); i > 1; --i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400357 this->write(ByteCodeInstruction::kDup);
358 }
359 }
360 }
361 this->writeExpression(*b.fRight);
Brian Osman909231c2019-05-29 15:34:36 -0400362 if (lVecOrMtx && !rVecOrMtx) {
Brian Osman16e6fd52019-05-29 11:19:00 -0400363 for (int i = SlotCount(lType); i > 1; --i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400364 this->write(ByteCodeInstruction::kDup);
365 }
366 }
Brian Osman909231c2019-05-29 15:34:36 -0400367 // Special case for M*V, V*M, M*M (but not V*V!)
368 if (op == Token::Kind::STAR && lVecOrMtx && rVecOrMtx &&
369 !(lType.kind() == Type::kVector_Kind && rType.kind() == Type::kVector_Kind)) {
370 this->write(ByteCodeInstruction::kMatrixMultiply);
371 int rCols = rType.columns(),
372 rRows = rType.rows(),
373 lCols = lType.columns(),
374 lRows = lType.rows();
375 // M*V treats the vector as a column
376 if (rType.kind() == Type::kVector_Kind) {
377 std::swap(rCols, rRows);
378 }
379 SkASSERT(lCols == rRows);
380 SkASSERT(SlotCount(b.fType) == lRows * rCols);
381 this->write8(lCols);
382 this->write8(lRows);
383 this->write8(rCols);
384 } else {
385 int count = std::max(SlotCount(lType), SlotCount(rType));
386 switch (op) {
387 case Token::Kind::EQEQ:
388 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareIEQ,
389 ByteCodeInstruction::kCompareIEQ,
390 ByteCodeInstruction::kCompareFEQ,
391 count);
392 // Collapse to a single bool
393 for (int i = count; i > 1; --i) {
394 this->write(ByteCodeInstruction::kAndB);
395 }
396 break;
397 case Token::Kind::GT:
398 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGT,
399 ByteCodeInstruction::kCompareUGT,
400 ByteCodeInstruction::kCompareFGT,
401 count);
402 break;
403 case Token::Kind::GTEQ:
404 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGTEQ,
405 ByteCodeInstruction::kCompareUGTEQ,
406 ByteCodeInstruction::kCompareFGTEQ,
407 count);
408 break;
409 case Token::Kind::LT:
410 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLT,
411 ByteCodeInstruction::kCompareULT,
412 ByteCodeInstruction::kCompareFLT,
413 count);
414 break;
415 case Token::Kind::LTEQ:
416 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLTEQ,
417 ByteCodeInstruction::kCompareULTEQ,
418 ByteCodeInstruction::kCompareFLTEQ,
419 count);
420 break;
421 case Token::Kind::MINUS:
422 this->writeTypedInstruction(lType, ByteCodeInstruction::kSubtractI,
423 ByteCodeInstruction::kSubtractI,
424 ByteCodeInstruction::kSubtractF,
425 count);
426 break;
427 case Token::Kind::NEQ:
428 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareINEQ,
429 ByteCodeInstruction::kCompareINEQ,
430 ByteCodeInstruction::kCompareFNEQ,
431 count);
432 // Collapse to a single bool
433 for (int i = count; i > 1; --i) {
434 this->write(ByteCodeInstruction::kOrB);
435 }
436 break;
437 case Token::Kind::PERCENT:
438 this->writeTypedInstruction(lType, ByteCodeInstruction::kRemainderS,
439 ByteCodeInstruction::kRemainderU,
440 ByteCodeInstruction::kRemainderF,
441 count);
442 break;
443 case Token::Kind::PLUS:
444 this->writeTypedInstruction(lType, ByteCodeInstruction::kAddI,
445 ByteCodeInstruction::kAddI,
446 ByteCodeInstruction::kAddF,
447 count);
448 break;
449 case Token::Kind::SLASH:
450 this->writeTypedInstruction(lType, ByteCodeInstruction::kDivideS,
451 ByteCodeInstruction::kDivideU,
452 ByteCodeInstruction::kDivideF,
453 count);
454 break;
455 case Token::Kind::STAR:
456 this->writeTypedInstruction(lType, ByteCodeInstruction::kMultiplyI,
457 ByteCodeInstruction::kMultiplyI,
458 ByteCodeInstruction::kMultiplyF,
459 count);
460 break;
Brian Osman569f12f2019-06-13 11:23:57 -0400461
462 case Token::Kind::LOGICALAND:
463 SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
464 this->write(ByteCodeInstruction::kAndB);
465 break;
466 case Token::Kind::LOGICALNOT:
467 SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
468 this->write(ByteCodeInstruction::kNotB);
469 break;
470 case Token::Kind::LOGICALOR:
471 SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
472 this->write(ByteCodeInstruction::kOrB);
473 break;
474 case Token::Kind::LOGICALXOR:
475 SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
476 this->write(ByteCodeInstruction::kXorB);
477 break;
478
Brian Osman909231c2019-05-29 15:34:36 -0400479 default:
480 SkASSERT(false);
481 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400482 }
483 if (lvalue) {
Brian Osman3e29f1d2019-05-28 09:35:05 -0400484 lvalue->store(discard);
485 discard = false;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400486 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400487 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400488}
489
490void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
491 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osman569f12f2019-06-13 11:23:57 -0400492 this->write32(b.fValue ? ~0 : 0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400493}
494
495void ByteCodeGenerator::writeConstructor(const Constructor& c) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400496 for (const auto& arg : c.fArguments) {
497 this->writeExpression(*arg);
498 }
499 if (c.fArguments.size() == 1) {
Brian Osman29e013d2019-05-28 17:16:03 -0400500 const Type& inType = c.fArguments[0]->fType;
501 const Type& outType = c.fType;
502 TypeCategory inCategory = type_category(inType);
503 TypeCategory outCategory = type_category(outType);
504 int inCount = SlotCount(inType);
505 int outCount = SlotCount(outType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400506 if (inCategory != outCategory) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700507 SkASSERT(inCount == outCount);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400508 if (inCategory == TypeCategory::kFloat) {
509 SkASSERT(outCategory == TypeCategory::kSigned ||
510 outCategory == TypeCategory::kUnsigned);
Brian Osmanc51d7912019-05-22 15:16:16 -0700511 this->write(vector_instruction(ByteCodeInstruction::kConvertFtoI, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400512 } else if (outCategory == TypeCategory::kFloat) {
513 if (inCategory == TypeCategory::kSigned) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700514 this->write(vector_instruction(ByteCodeInstruction::kConvertStoF, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400515 } else {
516 SkASSERT(inCategory == TypeCategory::kUnsigned);
Brian Osmanc51d7912019-05-22 15:16:16 -0700517 this->write(vector_instruction(ByteCodeInstruction::kConvertUtoF, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400518 }
519 } else {
520 SkASSERT(false);
521 }
522 }
Brian Osman29e013d2019-05-28 17:16:03 -0400523 if (inType.kind() == Type::kMatrix_Kind && outType.kind() == Type::kMatrix_Kind) {
524 this->write(ByteCodeInstruction::kMatrixToMatrix);
525 this->write8(inType.columns());
526 this->write8(inType.rows());
527 this->write8(outType.columns());
528 this->write8(outType.rows());
529 } else if (inCount != outCount) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700530 SkASSERT(inCount == 1);
Brian Osman29e013d2019-05-28 17:16:03 -0400531 if (outType.kind() == Type::kMatrix_Kind) {
532 this->write(ByteCodeInstruction::kScalarToMatrix);
533 this->write8(outType.columns());
534 this->write8(outType.rows());
535 } else {
536 SkASSERT(outType.kind() == Type::kVector_Kind);
537 for (; inCount != outCount; ++inCount) {
538 this->write(ByteCodeInstruction::kDup);
539 }
Brian Osmanc51d7912019-05-22 15:16:16 -0700540 }
541 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400542 }
543}
544
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400545void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f) {
546 int argumentCount = 0;
547 for (const auto& arg : f.fArguments) {
548 this->writeExpression(*arg);
Brian Osman07c117b2019-05-23 12:51:06 -0700549 argumentCount += SlotCount(arg->fType);
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400550 }
551 this->write(ByteCodeInstruction::kCallExternal);
552 SkASSERT(argumentCount <= 255);
553 this->write8(argumentCount);
Brian Osman07c117b2019-05-23 12:51:06 -0700554 this->write8(SlotCount(f.fType));
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400555 int index = fOutput->fExternalValues.size();
556 fOutput->fExternalValues.push_back(f.fFunction);
557 SkASSERT(index <= 255);
558 this->write8(index);
559}
560
Ethan Nicholas91164d12019-05-15 15:29:54 -0400561void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400562 this->write(vector_instruction(ByteCodeInstruction::kReadExternal,
Brian Osman07c117b2019-05-23 12:51:06 -0700563 SlotCount(e.fValue->type())));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400564 int index = fOutput->fExternalValues.size();
565 fOutput->fExternalValues.push_back(e.fValue);
566 SkASSERT(index <= 255);
567 this->write8(index);
568}
569
Brian Osman07c117b2019-05-23 12:51:06 -0700570void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
571 Variable::Storage storage;
572 int location = this->getLocation(expr, &storage);
573 bool isGlobal = storage == Variable::kGlobal_Storage;
574 int count = SlotCount(expr.fType);
575 if (location < 0 || count > 4) {
576 if (location >= 0) {
577 this->write(ByteCodeInstruction::kPushImmediate);
578 this->write32(location);
579 }
580 this->write(isGlobal ? ByteCodeInstruction::kLoadExtendedGlobal
581 : ByteCodeInstruction::kLoadExtended);
582 this->write8(count);
583 } else {
584 this->write(vector_instruction(isGlobal ? ByteCodeInstruction::kLoadGlobal
585 : ByteCodeInstruction::kLoad,
586 count));
587 this->write8(location);
588 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400589}
590
Brian Osmand30e0392019-06-14 14:05:14 -0400591static inline uint32_t float_to_bits(float x) {
592 uint32_t u;
593 memcpy(&u, &x, sizeof(uint32_t));
594 return u;
595}
596
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400597void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
598 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmand30e0392019-06-14 14:05:14 -0400599 this->write32(float_to_bits(f.fValue));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400600}
601
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400602void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
603 auto found = fIntrinsics.find(c.fFunction.fName);
604 if (found == fIntrinsics.end()) {
605 fErrors.error(c.fOffset, "unsupported intrinsic function");
606 return;
607 }
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400608 if (found->second.fIsSpecial) {
609 SkASSERT(found->second.fValue.fSpecial == SpecialIntrinsic::kDot);
610 SkASSERT(c.fArguments.size() == 2);
611 SkASSERT(SlotCount(c.fArguments[0]->fType) == SlotCount(c.fArguments[1]->fType));
612 this->write((ByteCodeInstruction) ((int) ByteCodeInstruction::kMultiplyF +
613 SlotCount(c.fArguments[0]->fType) - 1));
614 for (int i = SlotCount(c.fArguments[0]->fType); i > 1; --i) {
615 this->write(ByteCodeInstruction::kAddF);
616 }
617 } else {
618 switch (found->second.fValue.fInstruction) {
619 case ByteCodeInstruction::kCos:
620 case ByteCodeInstruction::kMix:
621 case ByteCodeInstruction::kSin:
622 case ByteCodeInstruction::kSqrt:
623 case ByteCodeInstruction::kTan:
624 SkASSERT(c.fArguments.size() > 0);
625 this->write((ByteCodeInstruction) ((int) found->second.fValue.fInstruction +
626 SlotCount(c.fArguments[0]->fType) - 1));
627 break;
628 case ByteCodeInstruction::kCross:
629 this->write(found->second.fValue.fInstruction);
630 break;
631 default:
632 SkASSERT(false);
633 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400634 }
635}
636
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400637void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400638 for (const auto& arg : f.fArguments) {
639 this->writeExpression(*arg);
640 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400641 if (f.fFunction.fBuiltin) {
642 this->writeIntrinsicCall(f);
643 return;
644 }
Brian Osman226668a2019-05-14 16:47:30 -0400645 this->write(ByteCodeInstruction::kCall);
646 fCallTargets.emplace_back(this, f.fFunction);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400647}
648
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400649void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
650 this->write(ByteCodeInstruction::kPushImmediate);
651 this->write32(i.fValue);
652}
653
654void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
655 // not yet implemented
656 abort();
657}
658
Brian Osman3e29f1d2019-05-28 09:35:05 -0400659bool ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p, bool discard) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400660 switch (p.fOperator) {
661 case Token::Kind::PLUSPLUS: // fall through
662 case Token::Kind::MINUSMINUS: {
Brian Osman07c117b2019-05-23 12:51:06 -0700663 SkASSERT(SlotCount(p.fOperand->fType) == 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400664 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
665 lvalue->load();
666 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmand30e0392019-06-14 14:05:14 -0400667 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400668 if (p.fOperator == Token::Kind::PLUSPLUS) {
669 this->writeTypedInstruction(p.fType,
670 ByteCodeInstruction::kAddI,
671 ByteCodeInstruction::kAddI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400672 ByteCodeInstruction::kAddF,
673 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400674 } else {
675 this->writeTypedInstruction(p.fType,
676 ByteCodeInstruction::kSubtractI,
677 ByteCodeInstruction::kSubtractI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400678 ByteCodeInstruction::kSubtractF,
679 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400680 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400681 lvalue->store(discard);
682 discard = false;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400683 break;
684 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400685 case Token::Kind::MINUS: {
686 this->writeExpression(*p.fOperand);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400687 this->writeTypedInstruction(p.fType,
Mike Klein12710912019-05-21 11:04:59 -0500688 ByteCodeInstruction::kNegateI,
689 ByteCodeInstruction::kNegateI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400690 ByteCodeInstruction::kNegateF,
Brian Osman07c117b2019-05-23 12:51:06 -0700691 SlotCount(p.fOperand->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400692 break;
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400693 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400694 default:
695 SkASSERT(false);
696 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400697 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400698}
699
Brian Osman3e29f1d2019-05-28 09:35:05 -0400700bool ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p, bool discard) {
Brian Osmanf3fa6002019-05-17 14:26:53 -0400701 switch (p.fOperator) {
702 case Token::Kind::PLUSPLUS: // fall through
703 case Token::Kind::MINUSMINUS: {
Brian Osman07c117b2019-05-23 12:51:06 -0700704 SkASSERT(SlotCount(p.fOperand->fType) == 1);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400705 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
706 lvalue->load();
Brian Osman3e29f1d2019-05-28 09:35:05 -0400707 if (!discard) {
708 this->write(ByteCodeInstruction::kDup);
709 }
Brian Osmanf3fa6002019-05-17 14:26:53 -0400710 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmand30e0392019-06-14 14:05:14 -0400711 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400712 if (p.fOperator == Token::Kind::PLUSPLUS) {
713 this->writeTypedInstruction(p.fType,
714 ByteCodeInstruction::kAddI,
715 ByteCodeInstruction::kAddI,
716 ByteCodeInstruction::kAddF,
717 1);
718 } else {
719 this->writeTypedInstruction(p.fType,
720 ByteCodeInstruction::kSubtractI,
721 ByteCodeInstruction::kSubtractI,
722 ByteCodeInstruction::kSubtractF,
723 1);
724 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400725 lvalue->store(discard);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400726 this->write(ByteCodeInstruction::kPop);
Brian Osman3e29f1d2019-05-28 09:35:05 -0400727 discard = false;
Brian Osmanf3fa6002019-05-17 14:26:53 -0400728 break;
729 }
730 default:
731 SkASSERT(false);
732 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400733 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400734}
735
736void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
Brian Osman0785db02019-05-24 14:19:11 -0400737 if (swizzle_is_simple(s)) {
738 this->writeVariableExpression(s);
739 return;
740 }
741
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400742 switch (s.fBase->fKind) {
743 case Expression::kVariableReference_Kind: {
744 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
Brian Osman1091f022019-05-16 09:42:16 -0400745 this->write(var.fStorage == Variable::kGlobal_Storage
746 ? ByteCodeInstruction::kLoadSwizzleGlobal
747 : ByteCodeInstruction::kLoadSwizzle);
748 this->write8(this->getLocation(var));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400749 this->write8(s.fComponents.size());
750 for (int c : s.fComponents) {
751 this->write8(c);
752 }
753 break;
754 }
755 default:
756 this->writeExpression(*s.fBase);
757 this->write(ByteCodeInstruction::kSwizzle);
758 this->write8(s.fBase->fType.columns());
759 this->write8(s.fComponents.size());
760 for (int c : s.fComponents) {
761 this->write8(c);
762 }
763 }
764}
765
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400766void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Brian Osman4e93feb2019-05-16 15:38:00 -0400767 this->writeExpression(*t.fTest);
Brian Osman569f12f2019-06-13 11:23:57 -0400768 this->write(ByteCodeInstruction::kMaskPush);
Brian Osman4e93feb2019-05-16 15:38:00 -0400769 this->writeExpression(*t.fIfTrue);
Brian Osman569f12f2019-06-13 11:23:57 -0400770 this->write(ByteCodeInstruction::kMaskNegate);
771 this->writeExpression(*t.fIfFalse);
772 this->write(ByteCodeInstruction::kMaskBlend);
773 this->write8(SlotCount(t.fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400774}
775
Brian Osman3e29f1d2019-05-28 09:35:05 -0400776void ByteCodeGenerator::writeExpression(const Expression& e, bool discard) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400777 switch (e.fKind) {
778 case Expression::kBinary_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400779 discard = this->writeBinaryExpression((BinaryExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400780 break;
781 case Expression::kBoolLiteral_Kind:
782 this->writeBoolLiteral((BoolLiteral&) e);
783 break;
784 case Expression::kConstructor_Kind:
785 this->writeConstructor((Constructor&) e);
786 break;
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400787 case Expression::kExternalFunctionCall_Kind:
788 this->writeExternalFunctionCall((ExternalFunctionCall&) e);
789 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400790 case Expression::kExternalValue_Kind:
791 this->writeExternalValue((ExternalValueReference&) e);
792 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400793 case Expression::kFieldAccess_Kind:
Brian Osman07c117b2019-05-23 12:51:06 -0700794 case Expression::kIndex_Kind:
795 case Expression::kVariableReference_Kind:
796 this->writeVariableExpression(e);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400797 break;
798 case Expression::kFloatLiteral_Kind:
799 this->writeFloatLiteral((FloatLiteral&) e);
800 break;
801 case Expression::kFunctionCall_Kind:
802 this->writeFunctionCall((FunctionCall&) e);
803 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400804 case Expression::kIntLiteral_Kind:
805 this->writeIntLiteral((IntLiteral&) e);
806 break;
807 case Expression::kNullLiteral_Kind:
808 this->writeNullLiteral((NullLiteral&) e);
809 break;
810 case Expression::kPrefix_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400811 discard = this->writePrefixExpression((PrefixExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400812 break;
813 case Expression::kPostfix_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400814 discard = this->writePostfixExpression((PostfixExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400815 break;
816 case Expression::kSwizzle_Kind:
817 this->writeSwizzle((Swizzle&) e);
818 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400819 case Expression::kTernary_Kind:
820 this->writeTernaryExpression((TernaryExpression&) e);
821 break;
822 default:
823 printf("unsupported expression %s\n", e.description().c_str());
824 SkASSERT(false);
825 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400826 if (discard) {
827 int count = SlotCount(e.fType);
828 if (count > 4) {
829 this->write(ByteCodeInstruction::kPopN);
830 this->write8(count);
831 } else {
832 this->write(vector_instruction(ByteCodeInstruction::kPop, count));
833 }
834 discard = false;
835 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400836}
837
Ethan Nicholas91164d12019-05-15 15:29:54 -0400838class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
839public:
840 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
841 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700842 , fCount(ByteCodeGenerator::SlotCount(value.type()))
Ethan Nicholas91164d12019-05-15 15:29:54 -0400843 , fIndex(index) {}
844
845 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400846 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400847 fGenerator.write8(fIndex);
848 }
849
Brian Osman3e29f1d2019-05-28 09:35:05 -0400850 void store(bool discard) override {
851 if (!discard) {
852 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
853 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400854 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400855 fGenerator.write8(fIndex);
856 }
857
858private:
859 typedef LValue INHERITED;
860
861 int fCount;
862
863 int fIndex;
864};
865
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400866class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
867public:
868 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
869 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700870 , fSwizzle(swizzle) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400871
872 void load() override {
Brian Osman1091f022019-05-16 09:42:16 -0400873 fGenerator.writeSwizzle(fSwizzle);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400874 }
875
Brian Osman3e29f1d2019-05-28 09:35:05 -0400876 void store(bool discard) override {
877 if (!discard) {
878 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup,
879 fSwizzle.fComponents.size()));
880 }
Brian Osman07c117b2019-05-23 12:51:06 -0700881 Variable::Storage storage;
882 int location = fGenerator.getLocation(*fSwizzle.fBase, &storage);
883 bool isGlobal = storage == Variable::kGlobal_Storage;
884 if (location < 0) {
885 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleIndirectGlobal
886 : ByteCodeInstruction::kStoreSwizzleIndirect);
887 } else {
888 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleGlobal
889 : ByteCodeInstruction::kStoreSwizzle);
890 fGenerator.write8(location);
891 }
Brian Osman1091f022019-05-16 09:42:16 -0400892 fGenerator.write8(fSwizzle.fComponents.size());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400893 for (int c : fSwizzle.fComponents) {
894 fGenerator.write8(c);
895 }
896 }
897
898private:
899 const Swizzle& fSwizzle;
900
901 typedef LValue INHERITED;
902};
903
Brian Osman07c117b2019-05-23 12:51:06 -0700904class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400905public:
Brian Osman07c117b2019-05-23 12:51:06 -0700906 ByteCodeExpressionLValue(ByteCodeGenerator* generator, const Expression& expr)
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400907 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700908 , fExpression(expr) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400909
910 void load() override {
Brian Osman07c117b2019-05-23 12:51:06 -0700911 fGenerator.writeVariableExpression(fExpression);
Brian Osman1091f022019-05-16 09:42:16 -0400912 }
913
Brian Osman3e29f1d2019-05-28 09:35:05 -0400914 void store(bool discard) override {
Brian Osman07c117b2019-05-23 12:51:06 -0700915 int count = ByteCodeGenerator::SlotCount(fExpression.fType);
Brian Osman3e29f1d2019-05-28 09:35:05 -0400916 if (!discard) {
917 if (count > 4) {
918 fGenerator.write(ByteCodeInstruction::kDupN);
919 fGenerator.write8(count);
920 } else {
921 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
922 }
Brian Osman07c117b2019-05-23 12:51:06 -0700923 }
924 Variable::Storage storage;
925 int location = fGenerator.getLocation(fExpression, &storage);
926 bool isGlobal = storage == Variable::kGlobal_Storage;
927 if (location < 0 || count > 4) {
928 if (location >= 0) {
929 fGenerator.write(ByteCodeInstruction::kPushImmediate);
930 fGenerator.write32(location);
931 }
932 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreExtendedGlobal
933 : ByteCodeInstruction::kStoreExtended);
934 fGenerator.write8(count);
935 } else {
936 fGenerator.write(vector_instruction(isGlobal ? ByteCodeInstruction::kStoreGlobal
937 : ByteCodeInstruction::kStore,
938 count));
939 fGenerator.write8(location);
940 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400941 }
942
943private:
944 typedef LValue INHERITED;
945
Brian Osman07c117b2019-05-23 12:51:06 -0700946 const Expression& fExpression;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400947};
948
949std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
950 switch (e.fKind) {
Ethan Nicholas91164d12019-05-15 15:29:54 -0400951 case Expression::kExternalValue_Kind: {
952 ExternalValue* value = ((ExternalValueReference&) e).fValue;
953 int index = fOutput->fExternalValues.size();
954 fOutput->fExternalValues.push_back(value);
955 SkASSERT(index <= 255);
956 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
957 }
Brian Osman07c117b2019-05-23 12:51:06 -0700958 case Expression::kFieldAccess_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400959 case Expression::kIndex_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400960 case Expression::kVariableReference_Kind:
Brian Osman07c117b2019-05-23 12:51:06 -0700961 return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
Brian Osman0785db02019-05-24 14:19:11 -0400962 case Expression::kSwizzle_Kind: {
963 const Swizzle& s = (const Swizzle&) e;
964 return swizzle_is_simple(s)
965 ? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e))
966 : std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s));
967 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400968 case Expression::kTernary_Kind:
969 default:
970 printf("unsupported lvalue %s\n", e.description().c_str());
971 return nullptr;
972 }
973}
974
975void ByteCodeGenerator::writeBlock(const Block& b) {
976 for (const auto& s : b.fStatements) {
977 this->writeStatement(*s);
978 }
979}
980
981void ByteCodeGenerator::setBreakTargets() {
982 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
983 for (DeferredLocation& b : breaks) {
984 b.set();
985 }
986 fBreakTargets.pop();
987}
988
989void ByteCodeGenerator::setContinueTargets() {
990 std::vector<DeferredLocation>& continues = fContinueTargets.top();
991 for (DeferredLocation& c : continues) {
992 c.set();
993 }
994 fContinueTargets.pop();
995}
996
997void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
Brian Osman569f12f2019-06-13 11:23:57 -0400998 // TODO: Include BranchIfAllFalse to top-most LoopNext
999 this->write(ByteCodeInstruction::kLoopBreak);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001000}
1001
1002void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
Brian Osman569f12f2019-06-13 11:23:57 -04001003 // TODO: Include BranchIfAllFalse to top-most LoopNext
1004 this->write(ByteCodeInstruction::kLoopContinue);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001005}
1006
1007void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
Brian Osman569f12f2019-06-13 11:23:57 -04001008 this->write(ByteCodeInstruction::kLoopBegin);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001009 size_t start = fCode->size();
1010 this->writeStatement(*d.fStatement);
Brian Osman569f12f2019-06-13 11:23:57 -04001011 this->write(ByteCodeInstruction::kLoopNext);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001012 this->writeExpression(*d.fTest);
Brian Osman569f12f2019-06-13 11:23:57 -04001013 this->write(ByteCodeInstruction::kLoopMask);
1014 // TODO: Could shorten this with kBranchIfAnyTrue
1015 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1016 DeferredLocation endLocation(this);
1017 this->write(ByteCodeInstruction::kBranch);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001018 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001019 endLocation.set();
1020 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001021}
1022
1023void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
1024 fContinueTargets.emplace();
1025 fBreakTargets.emplace();
1026 if (f.fInitializer) {
1027 this->writeStatement(*f.fInitializer);
1028 }
Brian Osman569f12f2019-06-13 11:23:57 -04001029 this->write(ByteCodeInstruction::kLoopBegin);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001030 size_t start = fCode->size();
1031 if (f.fTest) {
1032 this->writeExpression(*f.fTest);
Brian Osman569f12f2019-06-13 11:23:57 -04001033 this->write(ByteCodeInstruction::kLoopMask);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001034 }
Brian Osman569f12f2019-06-13 11:23:57 -04001035 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1036 DeferredLocation endLocation(this);
1037 this->writeStatement(*f.fStatement);
1038 this->write(ByteCodeInstruction::kLoopNext);
1039 if (f.fNext) {
1040 this->writeExpression(*f.fNext, true);
1041 }
1042 this->write(ByteCodeInstruction::kBranch);
1043 this->write16(start);
1044 endLocation.set();
1045 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001046}
1047
1048void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Brian Osman569f12f2019-06-13 11:23:57 -04001049 this->writeExpression(*i.fTest);
1050 this->write(ByteCodeInstruction::kMaskPush);
1051 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1052 DeferredLocation falseLocation(this);
1053 this->writeStatement(*i.fIfTrue);
1054 falseLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001055 if (i.fIfFalse) {
Brian Osman569f12f2019-06-13 11:23:57 -04001056 this->write(ByteCodeInstruction::kMaskNegate);
1057 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1058 DeferredLocation endLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001059 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -05001060 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001061 }
Brian Osman569f12f2019-06-13 11:23:57 -04001062 this->write(ByteCodeInstruction::kMaskPop);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001063}
1064
1065void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -04001066 this->writeExpression(*r.fExpression);
1067 this->write(ByteCodeInstruction::kReturn);
Brian Osman07c117b2019-05-23 12:51:06 -07001068 this->write8(SlotCount(r.fExpression->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001069}
1070
1071void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
1072 // not yet implemented
1073 abort();
1074}
1075
1076void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1077 for (const auto& declStatement : v.fVars) {
1078 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
1079 // we need to grab the location even if we don't use it, to ensure it
1080 // has been allocated
1081 int location = getLocation(*decl.fVar);
1082 if (decl.fValue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001083 this->writeExpression(*decl.fValue);
Brian Osman07c117b2019-05-23 12:51:06 -07001084 int count = SlotCount(decl.fValue->fType);
1085 if (count > 4) {
1086 this->write(ByteCodeInstruction::kPushImmediate);
1087 this->write32(location);
1088 this->write(ByteCodeInstruction::kStoreExtended);
1089 this->write8(count);
1090 } else {
1091 this->write(vector_instruction(ByteCodeInstruction::kStore, count));
1092 this->write8(location);
1093 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001094 }
1095 }
1096}
1097
1098void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
Brian Osman569f12f2019-06-13 11:23:57 -04001099 this->write(ByteCodeInstruction::kLoopBegin);
1100 size_t cond = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001101 this->writeExpression(*w.fTest);
Brian Osman569f12f2019-06-13 11:23:57 -04001102 this->write(ByteCodeInstruction::kLoopMask);
1103 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001104 DeferredLocation endLocation(this);
1105 this->writeStatement(*w.fStatement);
Brian Osman569f12f2019-06-13 11:23:57 -04001106 this->write(ByteCodeInstruction::kLoopNext);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001107 this->write(ByteCodeInstruction::kBranch);
Brian Osman569f12f2019-06-13 11:23:57 -04001108 this->write16(cond);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001109 endLocation.set();
Brian Osman569f12f2019-06-13 11:23:57 -04001110 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001111}
1112
1113void ByteCodeGenerator::writeStatement(const Statement& s) {
1114 switch (s.fKind) {
1115 case Statement::kBlock_Kind:
1116 this->writeBlock((Block&) s);
1117 break;
1118 case Statement::kBreak_Kind:
1119 this->writeBreakStatement((BreakStatement&) s);
1120 break;
1121 case Statement::kContinue_Kind:
1122 this->writeContinueStatement((ContinueStatement&) s);
1123 break;
1124 case Statement::kDiscard_Kind:
1125 // not yet implemented
1126 abort();
1127 case Statement::kDo_Kind:
1128 this->writeDoStatement((DoStatement&) s);
1129 break;
Brian Osman3e29f1d2019-05-28 09:35:05 -04001130 case Statement::kExpression_Kind:
1131 this->writeExpression(*((ExpressionStatement&) s).fExpression, true);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001132 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001133 case Statement::kFor_Kind:
1134 this->writeForStatement((ForStatement&) s);
1135 break;
1136 case Statement::kIf_Kind:
1137 this->writeIfStatement((IfStatement&) s);
1138 break;
1139 case Statement::kNop_Kind:
1140 break;
1141 case Statement::kReturn_Kind:
1142 this->writeReturnStatement((ReturnStatement&) s);
1143 break;
1144 case Statement::kSwitch_Kind:
1145 this->writeSwitchStatement((SwitchStatement&) s);
1146 break;
1147 case Statement::kVarDeclarations_Kind:
1148 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1149 break;
1150 case Statement::kWhile_Kind:
1151 this->writeWhileStatement((WhileStatement&) s);
1152 break;
1153 default:
1154 SkASSERT(false);
1155 }
1156}
1157
Brian Osman80164412019-06-07 13:00:23 -04001158ByteCodeFunction::ByteCodeFunction(const FunctionDeclaration* declaration)
1159 : fName(declaration->fName) {
1160 fParameterCount = 0;
1161 for (const auto& p : declaration->fParameters) {
1162 int slots = ByteCodeGenerator::SlotCount(p->fType);
1163 fParameters.push_back({ slots, (bool)(p->fModifiers.fFlags & Modifiers::kOut_Flag) });
1164 fParameterCount += slots;
1165 }
1166}
1167
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001168}