blob: 5a8030abfcccc9ac88cc48cf60cc171a90ee6cc2 [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) {
Brian Osmanfba386b2019-06-20 14:54:15 -040031 if (type.kind() == Type::kOther_Kind) {
32 return 0;
33 } else if (type.kind() == Type::kStruct_Kind) {
Brian Osman07c117b2019-05-23 12:51:06 -070034 int slots = 0;
35 for (const auto& f : type.fields()) {
36 slots += SlotCount(*f.fType);
37 }
38 SkASSERT(slots <= 255);
39 return slots;
40 } else if (type.kind() == Type::kArray_Kind) {
41 int columns = type.columns();
42 SkASSERT(columns >= 0);
43 int slots = columns * SlotCount(type.componentType());
44 SkASSERT(slots <= 255);
45 return slots;
46 } else {
47 return type.columns() * type.rows();
48 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040049}
50
51bool ByteCodeGenerator::generateCode() {
52 for (const auto& e : fProgram) {
53 switch (e.fKind) {
54 case ProgramElement::kFunction_Kind: {
55 std::unique_ptr<ByteCodeFunction> f = this->writeFunction((FunctionDefinition&) e);
56 if (!f) {
57 return false;
58 }
59 fOutput->fFunctions.push_back(std::move(f));
Brian Osman80164412019-06-07 13:00:23 -040060 fFunctions.push_back(&(FunctionDefinition&)e);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040061 break;
62 }
63 case ProgramElement::kVar_Kind: {
64 VarDeclarations& decl = (VarDeclarations&) e;
65 for (const auto& v : decl.fVars) {
66 const Variable* declVar = ((VarDeclaration&) *v).fVar;
67 if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
68 continue;
69 }
70 if (declVar->fModifiers.fFlags & Modifiers::kIn_Flag) {
Brian Osman07c117b2019-05-23 12:51:06 -070071 for (int i = SlotCount(declVar->fType); i > 0; --i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040072 fOutput->fInputSlots.push_back(fOutput->fGlobalCount++);
73 }
74 } else {
Brian Osman07c117b2019-05-23 12:51:06 -070075 fOutput->fGlobalCount += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040076 }
77 }
78 break;
79 }
80 default:
81 ; // ignore
82 }
83 }
Brian Osman6f5358f2019-07-09 14:17:23 -040084 return 0 == fErrors.errorCount();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040085}
86
87std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
88 fFunction = &f;
Brian Osman226668a2019-05-14 16:47:30 -040089 std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
Brian Osman80164412019-06-07 13:00:23 -040090 fParameterCount = result->fParameterCount;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040091 fCode = &result->fCode;
92 this->writeStatement(*f.fBody);
Ethan Nicholas7e603db2019-05-03 12:57:47 -040093 this->write(ByteCodeInstruction::kReturn);
94 this->write8(0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040095 result->fLocalCount = fLocals.size();
Ethan Nicholasdfcad062019-05-07 12:53:34 -040096 const Type& returnType = f.fDeclaration.fReturnType;
97 if (returnType != *fContext.fVoid_Type) {
Brian Osman07c117b2019-05-23 12:51:06 -070098 result->fReturnCount = SlotCount(returnType);
Ethan Nicholasdfcad062019-05-07 12:53:34 -040099 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400100 fLocals.clear();
101 fFunction = nullptr;
102 return result;
103}
104
105enum class TypeCategory {
106 kBool,
107 kSigned,
108 kUnsigned,
109 kFloat,
110};
111
112static TypeCategory type_category(const Type& type) {
113 switch (type.kind()) {
114 case Type::Kind::kVector_Kind:
115 case Type::Kind::kMatrix_Kind:
116 return type_category(type.componentType());
117 default:
118 if (type.fName == "bool") {
119 return TypeCategory::kBool;
120 } else if (type.fName == "int" || type.fName == "short") {
121 return TypeCategory::kSigned;
122 } else if (type.fName == "uint" || type.fName == "ushort") {
123 return TypeCategory::kUnsigned;
124 } else {
125 SkASSERT(type.fName == "float" || type.fName == "half");
126 return TypeCategory::kFloat;
127 }
128 ABORT("unsupported type: %s\n", type.description().c_str());
129 }
130}
131
Brian Osman0785db02019-05-24 14:19:11 -0400132// A "simple" Swizzle is based on a variable (or a compound variable like a struct or array), and
133// that references consecutive values, such that it can be implemented using normal load/store ops
134// with an offset. Note that all single-component swizzles (of suitable base types) are simple.
135static bool swizzle_is_simple(const Swizzle& s) {
136 switch (s.fBase->fKind) {
137 case Expression::kFieldAccess_Kind:
138 case Expression::kIndex_Kind:
139 case Expression::kVariableReference_Kind:
140 break;
141 default:
142 return false;
143 }
144
145 for (size_t i = 1; i < s.fComponents.size(); ++i) {
146 if (s.fComponents[i] != s.fComponents[i - 1] + 1) {
147 return false;
148 }
149 }
150 return true;
151}
152
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400153int ByteCodeGenerator::getLocation(const Variable& var) {
154 // given that we seldom have more than a couple of variables, linear search is probably the most
155 // efficient way to handle lookups
156 switch (var.fStorage) {
157 case Variable::kLocal_Storage: {
158 for (int i = fLocals.size() - 1; i >= 0; --i) {
159 if (fLocals[i] == &var) {
Brian Osman1091f022019-05-16 09:42:16 -0400160 SkASSERT(fParameterCount + i <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400161 return fParameterCount + i;
162 }
163 }
164 int result = fParameterCount + fLocals.size();
165 fLocals.push_back(&var);
Brian Osman07c117b2019-05-23 12:51:06 -0700166 for (int i = 0; i < SlotCount(var.fType) - 1; ++i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400167 fLocals.push_back(nullptr);
168 }
Brian Osman1091f022019-05-16 09:42:16 -0400169 SkASSERT(result <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400170 return result;
171 }
172 case Variable::kParameter_Storage: {
173 int offset = 0;
174 for (const auto& p : fFunction->fDeclaration.fParameters) {
175 if (p == &var) {
Brian Osman1091f022019-05-16 09:42:16 -0400176 SkASSERT(offset <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400177 return offset;
178 }
Brian Osman07c117b2019-05-23 12:51:06 -0700179 offset += SlotCount(p->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400180 }
181 SkASSERT(false);
Brian Osman1091f022019-05-16 09:42:16 -0400182 return 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400183 }
184 case Variable::kGlobal_Storage: {
185 int offset = 0;
186 for (const auto& e : fProgram) {
187 if (e.fKind == ProgramElement::kVar_Kind) {
188 VarDeclarations& decl = (VarDeclarations&) e;
189 for (const auto& v : decl.fVars) {
190 const Variable* declVar = ((VarDeclaration&) *v).fVar;
191 if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
192 continue;
193 }
194 if (declVar == &var) {
Brian Osmanb7451292019-05-15 13:02:13 -0400195 SkASSERT(offset <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400196 return offset;
197 }
Brian Osman07c117b2019-05-23 12:51:06 -0700198 offset += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400199 }
200 }
201 }
202 SkASSERT(false);
Brian Osman1091f022019-05-16 09:42:16 -0400203 return 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400204 }
205 default:
206 SkASSERT(false);
207 return 0;
208 }
209}
210
Brian Osman07c117b2019-05-23 12:51:06 -0700211int ByteCodeGenerator::getLocation(const Expression& expr, Variable::Storage* storage) {
212 switch (expr.fKind) {
213 case Expression::kFieldAccess_Kind: {
214 const FieldAccess& f = (const FieldAccess&)expr;
215 int baseAddr = this->getLocation(*f.fBase, storage);
216 int offset = 0;
217 for (int i = 0; i < f.fFieldIndex; ++i) {
218 offset += SlotCount(*f.fBase->fType.fields()[i].fType);
219 }
220 if (baseAddr < 0) {
Brian Osman86769292019-06-21 11:05:47 -0400221 if (offset != 0) {
222 this->write(ByteCodeInstruction::kPushImmediate);
223 this->write32(offset);
224 this->write(ByteCodeInstruction::kAddI);
225 }
Brian Osman07c117b2019-05-23 12:51:06 -0700226 return -1;
227 } else {
228 return baseAddr + offset;
229 }
230 }
231 case Expression::kIndex_Kind: {
232 const IndexExpression& i = (const IndexExpression&)expr;
233 int stride = SlotCount(i.fType);
234 int offset = -1;
235 if (i.fIndex->isConstant()) {
236 offset = i.fIndex->getConstantInt() * stride;
237 } else {
Brian Osman86769292019-06-21 11:05:47 -0400238 if (i.fIndex->hasSideEffects()) {
239 // Having a side-effect in an indexer is technically safe for an rvalue,
240 // but with lvalues we have to evaluate the indexer twice, so make it an error.
241 fErrors.error(i.fIndex->fOffset,
242 "Index expressions with side-effects not supported in byte code.");
243 return 0;
244 }
Brian Osman07c117b2019-05-23 12:51:06 -0700245 this->writeExpression(*i.fIndex);
Brian Osman86769292019-06-21 11:05:47 -0400246 if (stride != 1) {
247 this->write(ByteCodeInstruction::kPushImmediate);
248 this->write32(stride);
249 this->write(ByteCodeInstruction::kMultiplyI);
250 }
Brian Osman07c117b2019-05-23 12:51:06 -0700251 }
252 int baseAddr = this->getLocation(*i.fBase, storage);
Brian Osman86769292019-06-21 11:05:47 -0400253
254 // Are both components known statically?
Brian Osman07c117b2019-05-23 12:51:06 -0700255 if (baseAddr >= 0 && offset >= 0) {
256 return baseAddr + offset;
257 }
Brian Osman86769292019-06-21 11:05:47 -0400258
259 // At least one component is dynamic (and on the stack).
260
261 // If the other component is zero, we're done
262 if (baseAddr == 0 || offset == 0) {
263 return -1;
264 }
265
266 // Push the non-dynamic component (if any) to the stack, then add the two
Brian Osman07c117b2019-05-23 12:51:06 -0700267 if (baseAddr >= 0) {
268 this->write(ByteCodeInstruction::kPushImmediate);
269 this->write32(baseAddr);
270 }
271 if (offset >= 0) {
272 this->write(ByteCodeInstruction::kPushImmediate);
273 this->write32(offset);
274 }
275 this->write(ByteCodeInstruction::kAddI);
276 return -1;
277 }
Brian Osman0785db02019-05-24 14:19:11 -0400278 case Expression::kSwizzle_Kind: {
279 const Swizzle& s = (const Swizzle&)expr;
280 SkASSERT(swizzle_is_simple(s));
281 int baseAddr = this->getLocation(*s.fBase, storage);
282 int offset = s.fComponents[0];
283 if (baseAddr < 0) {
Brian Osman86769292019-06-21 11:05:47 -0400284 if (offset != 0) {
285 this->write(ByteCodeInstruction::kPushImmediate);
286 this->write32(offset);
287 this->write(ByteCodeInstruction::kAddI);
288 }
Brian Osman0785db02019-05-24 14:19:11 -0400289 return -1;
290 } else {
291 return baseAddr + offset;
292 }
293 }
Brian Osman07c117b2019-05-23 12:51:06 -0700294 case Expression::kVariableReference_Kind: {
295 const Variable& var = ((const VariableReference&)expr).fVariable;
296 *storage = var.fStorage;
297 return this->getLocation(var);
298 }
299 default:
300 SkASSERT(false);
301 return 0;
302 }
303}
304
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400305void ByteCodeGenerator::write8(uint8_t b) {
306 fCode->push_back(b);
307}
308
309void ByteCodeGenerator::write16(uint16_t i) {
Mike Klein76346ac2019-05-17 11:57:10 -0500310 size_t n = fCode->size();
311 fCode->resize(n+2);
312 memcpy(fCode->data() + n, &i, 2);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400313}
314
315void ByteCodeGenerator::write32(uint32_t i) {
Mike Klein76346ac2019-05-17 11:57:10 -0500316 size_t n = fCode->size();
317 fCode->resize(n+4);
318 memcpy(fCode->data() + n, &i, 4);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400319}
320
321void ByteCodeGenerator::write(ByteCodeInstruction i) {
Mike Klein108e9352019-05-21 11:05:17 -0500322 this->write16((uint16_t)i);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400323}
324
Mike Klein76346ac2019-05-17 11:57:10 -0500325static ByteCodeInstruction vector_instruction(ByteCodeInstruction base, int count) {
Brian Osman07c117b2019-05-23 12:51:06 -0700326 SkASSERT(count >= 1 && count <= 4);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400327 return ((ByteCodeInstruction) ((int) base + count - 1));
328}
329
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400330void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400331 ByteCodeInstruction u, ByteCodeInstruction f,
332 int count) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400333 switch (type_category(type)) {
334 case TypeCategory::kSigned:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400335 this->write(vector_instruction(s, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400336 break;
337 case TypeCategory::kUnsigned:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400338 this->write(vector_instruction(u, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400339 break;
Brian Osman1e855b22019-05-29 15:21:52 -0400340 case TypeCategory::kFloat: {
341 if (count > 4) {
342 this->write((ByteCodeInstruction)((int)f + 4));
343 this->write8(count);
344 } else {
345 this->write(vector_instruction(f, count));
346 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400347 break;
Brian Osman1e855b22019-05-29 15:21:52 -0400348 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400349 default:
350 SkASSERT(false);
351 }
352}
353
Brian Osman3e29f1d2019-05-28 09:35:05 -0400354bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool discard) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400355 if (b.fOperator == Token::Kind::EQ) {
356 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
357 this->writeExpression(*b.fRight);
Brian Osman3e29f1d2019-05-28 09:35:05 -0400358 lvalue->store(discard);
359 discard = false;
360 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400361 }
Brian Osman16e6fd52019-05-29 11:19:00 -0400362 const Type& lType = b.fLeft->fType;
363 const Type& rType = b.fRight->fType;
Brian Osman909231c2019-05-29 15:34:36 -0400364 bool lVecOrMtx = (lType.kind() == Type::kVector_Kind || lType.kind() == Type::kMatrix_Kind);
365 bool rVecOrMtx = (rType.kind() == Type::kVector_Kind || rType.kind() == Type::kMatrix_Kind);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400366 Token::Kind op;
367 std::unique_ptr<LValue> lvalue;
368 if (is_assignment(b.fOperator)) {
369 lvalue = this->getLValue(*b.fLeft);
370 lvalue->load();
371 op = remove_assignment(b.fOperator);
372 } else {
373 this->writeExpression(*b.fLeft);
374 op = b.fOperator;
Brian Osman909231c2019-05-29 15:34:36 -0400375 if (!lVecOrMtx && rVecOrMtx) {
Brian Osman16e6fd52019-05-29 11:19:00 -0400376 for (int i = SlotCount(rType); i > 1; --i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400377 this->write(ByteCodeInstruction::kDup);
378 }
379 }
380 }
381 this->writeExpression(*b.fRight);
Brian Osman909231c2019-05-29 15:34:36 -0400382 if (lVecOrMtx && !rVecOrMtx) {
Brian Osman16e6fd52019-05-29 11:19:00 -0400383 for (int i = SlotCount(lType); i > 1; --i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400384 this->write(ByteCodeInstruction::kDup);
385 }
386 }
Brian Osman909231c2019-05-29 15:34:36 -0400387 // Special case for M*V, V*M, M*M (but not V*V!)
388 if (op == Token::Kind::STAR && lVecOrMtx && rVecOrMtx &&
389 !(lType.kind() == Type::kVector_Kind && rType.kind() == Type::kVector_Kind)) {
390 this->write(ByteCodeInstruction::kMatrixMultiply);
391 int rCols = rType.columns(),
392 rRows = rType.rows(),
393 lCols = lType.columns(),
394 lRows = lType.rows();
395 // M*V treats the vector as a column
396 if (rType.kind() == Type::kVector_Kind) {
397 std::swap(rCols, rRows);
398 }
399 SkASSERT(lCols == rRows);
400 SkASSERT(SlotCount(b.fType) == lRows * rCols);
401 this->write8(lCols);
402 this->write8(lRows);
403 this->write8(rCols);
404 } else {
405 int count = std::max(SlotCount(lType), SlotCount(rType));
406 switch (op) {
407 case Token::Kind::EQEQ:
408 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareIEQ,
409 ByteCodeInstruction::kCompareIEQ,
410 ByteCodeInstruction::kCompareFEQ,
411 count);
412 // Collapse to a single bool
413 for (int i = count; i > 1; --i) {
414 this->write(ByteCodeInstruction::kAndB);
415 }
416 break;
417 case Token::Kind::GT:
418 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGT,
419 ByteCodeInstruction::kCompareUGT,
420 ByteCodeInstruction::kCompareFGT,
421 count);
422 break;
423 case Token::Kind::GTEQ:
424 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGTEQ,
425 ByteCodeInstruction::kCompareUGTEQ,
426 ByteCodeInstruction::kCompareFGTEQ,
427 count);
428 break;
429 case Token::Kind::LT:
430 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLT,
431 ByteCodeInstruction::kCompareULT,
432 ByteCodeInstruction::kCompareFLT,
433 count);
434 break;
435 case Token::Kind::LTEQ:
436 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLTEQ,
437 ByteCodeInstruction::kCompareULTEQ,
438 ByteCodeInstruction::kCompareFLTEQ,
439 count);
440 break;
441 case Token::Kind::MINUS:
442 this->writeTypedInstruction(lType, ByteCodeInstruction::kSubtractI,
443 ByteCodeInstruction::kSubtractI,
444 ByteCodeInstruction::kSubtractF,
445 count);
446 break;
447 case Token::Kind::NEQ:
448 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareINEQ,
449 ByteCodeInstruction::kCompareINEQ,
450 ByteCodeInstruction::kCompareFNEQ,
451 count);
452 // Collapse to a single bool
453 for (int i = count; i > 1; --i) {
454 this->write(ByteCodeInstruction::kOrB);
455 }
456 break;
457 case Token::Kind::PERCENT:
458 this->writeTypedInstruction(lType, ByteCodeInstruction::kRemainderS,
459 ByteCodeInstruction::kRemainderU,
460 ByteCodeInstruction::kRemainderF,
461 count);
462 break;
463 case Token::Kind::PLUS:
464 this->writeTypedInstruction(lType, ByteCodeInstruction::kAddI,
465 ByteCodeInstruction::kAddI,
466 ByteCodeInstruction::kAddF,
467 count);
468 break;
469 case Token::Kind::SLASH:
470 this->writeTypedInstruction(lType, ByteCodeInstruction::kDivideS,
471 ByteCodeInstruction::kDivideU,
472 ByteCodeInstruction::kDivideF,
473 count);
474 break;
475 case Token::Kind::STAR:
476 this->writeTypedInstruction(lType, ByteCodeInstruction::kMultiplyI,
477 ByteCodeInstruction::kMultiplyI,
478 ByteCodeInstruction::kMultiplyF,
479 count);
480 break;
Brian Osman569f12f2019-06-13 11:23:57 -0400481
482 case Token::Kind::LOGICALAND:
483 SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
484 this->write(ByteCodeInstruction::kAndB);
485 break;
486 case Token::Kind::LOGICALNOT:
487 SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
488 this->write(ByteCodeInstruction::kNotB);
489 break;
490 case Token::Kind::LOGICALOR:
491 SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
492 this->write(ByteCodeInstruction::kOrB);
493 break;
494 case Token::Kind::LOGICALXOR:
495 SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
496 this->write(ByteCodeInstruction::kXorB);
497 break;
498
Brian Osman909231c2019-05-29 15:34:36 -0400499 default:
500 SkASSERT(false);
501 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400502 }
503 if (lvalue) {
Brian Osman3e29f1d2019-05-28 09:35:05 -0400504 lvalue->store(discard);
505 discard = false;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400506 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400507 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400508}
509
510void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
511 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osman569f12f2019-06-13 11:23:57 -0400512 this->write32(b.fValue ? ~0 : 0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400513}
514
515void ByteCodeGenerator::writeConstructor(const Constructor& c) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400516 for (const auto& arg : c.fArguments) {
517 this->writeExpression(*arg);
518 }
519 if (c.fArguments.size() == 1) {
Brian Osman29e013d2019-05-28 17:16:03 -0400520 const Type& inType = c.fArguments[0]->fType;
521 const Type& outType = c.fType;
522 TypeCategory inCategory = type_category(inType);
523 TypeCategory outCategory = type_category(outType);
524 int inCount = SlotCount(inType);
525 int outCount = SlotCount(outType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400526 if (inCategory != outCategory) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700527 SkASSERT(inCount == outCount);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400528 if (inCategory == TypeCategory::kFloat) {
529 SkASSERT(outCategory == TypeCategory::kSigned ||
530 outCategory == TypeCategory::kUnsigned);
Brian Osmanc51d7912019-05-22 15:16:16 -0700531 this->write(vector_instruction(ByteCodeInstruction::kConvertFtoI, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400532 } else if (outCategory == TypeCategory::kFloat) {
533 if (inCategory == TypeCategory::kSigned) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700534 this->write(vector_instruction(ByteCodeInstruction::kConvertStoF, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400535 } else {
536 SkASSERT(inCategory == TypeCategory::kUnsigned);
Brian Osmanc51d7912019-05-22 15:16:16 -0700537 this->write(vector_instruction(ByteCodeInstruction::kConvertUtoF, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400538 }
539 } else {
540 SkASSERT(false);
541 }
542 }
Brian Osman29e013d2019-05-28 17:16:03 -0400543 if (inType.kind() == Type::kMatrix_Kind && outType.kind() == Type::kMatrix_Kind) {
544 this->write(ByteCodeInstruction::kMatrixToMatrix);
545 this->write8(inType.columns());
546 this->write8(inType.rows());
547 this->write8(outType.columns());
548 this->write8(outType.rows());
549 } else if (inCount != outCount) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700550 SkASSERT(inCount == 1);
Brian Osman29e013d2019-05-28 17:16:03 -0400551 if (outType.kind() == Type::kMatrix_Kind) {
552 this->write(ByteCodeInstruction::kScalarToMatrix);
553 this->write8(outType.columns());
554 this->write8(outType.rows());
555 } else {
556 SkASSERT(outType.kind() == Type::kVector_Kind);
557 for (; inCount != outCount; ++inCount) {
558 this->write(ByteCodeInstruction::kDup);
559 }
Brian Osmanc51d7912019-05-22 15:16:16 -0700560 }
561 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400562 }
563}
564
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400565void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f) {
566 int argumentCount = 0;
567 for (const auto& arg : f.fArguments) {
568 this->writeExpression(*arg);
Brian Osman07c117b2019-05-23 12:51:06 -0700569 argumentCount += SlotCount(arg->fType);
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400570 }
571 this->write(ByteCodeInstruction::kCallExternal);
572 SkASSERT(argumentCount <= 255);
573 this->write8(argumentCount);
Brian Osman07c117b2019-05-23 12:51:06 -0700574 this->write8(SlotCount(f.fType));
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400575 int index = fOutput->fExternalValues.size();
576 fOutput->fExternalValues.push_back(f.fFunction);
577 SkASSERT(index <= 255);
578 this->write8(index);
579}
580
Ethan Nicholas91164d12019-05-15 15:29:54 -0400581void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400582 this->write(vector_instruction(ByteCodeInstruction::kReadExternal,
Brian Osman07c117b2019-05-23 12:51:06 -0700583 SlotCount(e.fValue->type())));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400584 int index = fOutput->fExternalValues.size();
585 fOutput->fExternalValues.push_back(e.fValue);
586 SkASSERT(index <= 255);
587 this->write8(index);
588}
589
Brian Osman07c117b2019-05-23 12:51:06 -0700590void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
591 Variable::Storage storage;
592 int location = this->getLocation(expr, &storage);
593 bool isGlobal = storage == Variable::kGlobal_Storage;
594 int count = SlotCount(expr.fType);
595 if (location < 0 || count > 4) {
596 if (location >= 0) {
597 this->write(ByteCodeInstruction::kPushImmediate);
598 this->write32(location);
599 }
600 this->write(isGlobal ? ByteCodeInstruction::kLoadExtendedGlobal
601 : ByteCodeInstruction::kLoadExtended);
602 this->write8(count);
603 } else {
604 this->write(vector_instruction(isGlobal ? ByteCodeInstruction::kLoadGlobal
605 : ByteCodeInstruction::kLoad,
606 count));
607 this->write8(location);
608 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400609}
610
Brian Osmand30e0392019-06-14 14:05:14 -0400611static inline uint32_t float_to_bits(float x) {
612 uint32_t u;
613 memcpy(&u, &x, sizeof(uint32_t));
614 return u;
615}
616
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400617void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
618 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmand30e0392019-06-14 14:05:14 -0400619 this->write32(float_to_bits(f.fValue));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400620}
621
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400622void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
623 auto found = fIntrinsics.find(c.fFunction.fName);
624 if (found == fIntrinsics.end()) {
625 fErrors.error(c.fOffset, "unsupported intrinsic function");
626 return;
627 }
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400628 if (found->second.fIsSpecial) {
629 SkASSERT(found->second.fValue.fSpecial == SpecialIntrinsic::kDot);
630 SkASSERT(c.fArguments.size() == 2);
631 SkASSERT(SlotCount(c.fArguments[0]->fType) == SlotCount(c.fArguments[1]->fType));
632 this->write((ByteCodeInstruction) ((int) ByteCodeInstruction::kMultiplyF +
633 SlotCount(c.fArguments[0]->fType) - 1));
634 for (int i = SlotCount(c.fArguments[0]->fType); i > 1; --i) {
635 this->write(ByteCodeInstruction::kAddF);
636 }
637 } else {
638 switch (found->second.fValue.fInstruction) {
639 case ByteCodeInstruction::kCos:
640 case ByteCodeInstruction::kMix:
641 case ByteCodeInstruction::kSin:
642 case ByteCodeInstruction::kSqrt:
643 case ByteCodeInstruction::kTan:
644 SkASSERT(c.fArguments.size() > 0);
645 this->write((ByteCodeInstruction) ((int) found->second.fValue.fInstruction +
646 SlotCount(c.fArguments[0]->fType) - 1));
647 break;
648 case ByteCodeInstruction::kCross:
649 this->write(found->second.fValue.fInstruction);
650 break;
651 default:
652 SkASSERT(false);
653 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400654 }
655}
656
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400657void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Brian Osmand3494ed2019-06-20 15:41:34 -0400658 // Builtins have simple signatures...
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400659 if (f.fFunction.fBuiltin) {
Brian Osmand3494ed2019-06-20 15:41:34 -0400660 for (const auto& arg : f.fArguments) {
661 this->writeExpression(*arg);
662 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400663 this->writeIntrinsicCall(f);
664 return;
665 }
Brian Osmand3494ed2019-06-20 15:41:34 -0400666
Brian Osman6f5358f2019-07-09 14:17:23 -0400667 // Find the index of the function we're calling. We explicitly do not allow calls to functions
668 // before they're defined. This is an easy-to-understand rule that prevents recursion.
669 size_t idx;
670 for (idx = 0; idx < fFunctions.size(); ++idx) {
671 if (f.fFunction.matches(fFunctions[idx]->fDeclaration)) {
672 break;
673 }
674 }
675 if (idx > 255) {
676 fErrors.error(f.fOffset, "Function count limit exceeded");
677 return;
678 } else if (idx >= fFunctions.size()) {
679 fErrors.error(f.fOffset, "Call to undefined function");
680 return;
681 }
682
683 // We may need to deal with out parameters, so the sequence is tricky
Brian Osmand3494ed2019-06-20 15:41:34 -0400684 if (int returnCount = SlotCount(f.fType)) {
685 this->write(ByteCodeInstruction::kReserve);
686 this->write8(returnCount);
687 }
688
689 int argCount = f.fArguments.size();
690 std::vector<std::unique_ptr<LValue>> lvalues;
691 for (int i = 0; i < argCount; ++i) {
692 const auto& param = f.fFunction.fParameters[i];
693 const auto& arg = f.fArguments[i];
694 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
695 lvalues.emplace_back(this->getLValue(*arg));
696 lvalues.back()->load();
697 } else {
698 this->writeExpression(*arg);
699 }
700 }
701
Brian Osman226668a2019-05-14 16:47:30 -0400702 this->write(ByteCodeInstruction::kCall);
Brian Osman6f5358f2019-07-09 14:17:23 -0400703 this->write8(idx);
Brian Osmand3494ed2019-06-20 15:41:34 -0400704
705 // After the called function returns, the stack will still contain our arguments. We have to
706 // pop them (storing any out parameters back to their lvalues as we go). We glob together slot
707 // counts for all parameters that aren't out-params, so we can pop them in one big chunk.
708 int popCount = 0;
709 auto pop = [&]() {
710 if (popCount > 4) {
711 this->write(ByteCodeInstruction::kPopN);
712 this->write8(popCount);
713 } else if (popCount > 0) {
714 this->write(vector_instruction(ByteCodeInstruction::kPop, popCount));
715 }
716 popCount = 0;
717 };
718
719 for (int i = argCount - 1; i >= 0; --i) {
720 const auto& param = f.fFunction.fParameters[i];
721 const auto& arg = f.fArguments[i];
722 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
723 pop();
724 lvalues.back()->store(true);
725 lvalues.pop_back();
726 } else {
727 popCount += SlotCount(arg->fType);
728 }
729 }
730 pop();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400731}
732
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400733void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
734 this->write(ByteCodeInstruction::kPushImmediate);
735 this->write32(i.fValue);
736}
737
738void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
739 // not yet implemented
740 abort();
741}
742
Brian Osman3e29f1d2019-05-28 09:35:05 -0400743bool ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p, bool discard) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400744 switch (p.fOperator) {
745 case Token::Kind::PLUSPLUS: // fall through
746 case Token::Kind::MINUSMINUS: {
Brian Osman07c117b2019-05-23 12:51:06 -0700747 SkASSERT(SlotCount(p.fOperand->fType) == 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400748 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
749 lvalue->load();
750 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmand30e0392019-06-14 14:05:14 -0400751 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400752 if (p.fOperator == Token::Kind::PLUSPLUS) {
753 this->writeTypedInstruction(p.fType,
754 ByteCodeInstruction::kAddI,
755 ByteCodeInstruction::kAddI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400756 ByteCodeInstruction::kAddF,
757 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400758 } else {
759 this->writeTypedInstruction(p.fType,
760 ByteCodeInstruction::kSubtractI,
761 ByteCodeInstruction::kSubtractI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400762 ByteCodeInstruction::kSubtractF,
763 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400764 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400765 lvalue->store(discard);
766 discard = false;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400767 break;
768 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400769 case Token::Kind::MINUS: {
770 this->writeExpression(*p.fOperand);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400771 this->writeTypedInstruction(p.fType,
Mike Klein12710912019-05-21 11:04:59 -0500772 ByteCodeInstruction::kNegateI,
773 ByteCodeInstruction::kNegateI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400774 ByteCodeInstruction::kNegateF,
Brian Osman07c117b2019-05-23 12:51:06 -0700775 SlotCount(p.fOperand->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400776 break;
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400777 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400778 default:
779 SkASSERT(false);
780 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400781 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400782}
783
Brian Osman3e29f1d2019-05-28 09:35:05 -0400784bool ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p, bool discard) {
Brian Osmanf3fa6002019-05-17 14:26:53 -0400785 switch (p.fOperator) {
786 case Token::Kind::PLUSPLUS: // fall through
787 case Token::Kind::MINUSMINUS: {
Brian Osman07c117b2019-05-23 12:51:06 -0700788 SkASSERT(SlotCount(p.fOperand->fType) == 1);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400789 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
790 lvalue->load();
Brian Osman3e29f1d2019-05-28 09:35:05 -0400791 if (!discard) {
792 this->write(ByteCodeInstruction::kDup);
793 }
Brian Osmanf3fa6002019-05-17 14:26:53 -0400794 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmand30e0392019-06-14 14:05:14 -0400795 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400796 if (p.fOperator == Token::Kind::PLUSPLUS) {
797 this->writeTypedInstruction(p.fType,
798 ByteCodeInstruction::kAddI,
799 ByteCodeInstruction::kAddI,
800 ByteCodeInstruction::kAddF,
801 1);
802 } else {
803 this->writeTypedInstruction(p.fType,
804 ByteCodeInstruction::kSubtractI,
805 ByteCodeInstruction::kSubtractI,
806 ByteCodeInstruction::kSubtractF,
807 1);
808 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400809 lvalue->store(discard);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400810 this->write(ByteCodeInstruction::kPop);
Brian Osman3e29f1d2019-05-28 09:35:05 -0400811 discard = false;
Brian Osmanf3fa6002019-05-17 14:26:53 -0400812 break;
813 }
814 default:
815 SkASSERT(false);
816 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400817 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400818}
819
820void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
Brian Osman0785db02019-05-24 14:19:11 -0400821 if (swizzle_is_simple(s)) {
822 this->writeVariableExpression(s);
823 return;
824 }
825
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400826 switch (s.fBase->fKind) {
827 case Expression::kVariableReference_Kind: {
828 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
Brian Osman1091f022019-05-16 09:42:16 -0400829 this->write(var.fStorage == Variable::kGlobal_Storage
830 ? ByteCodeInstruction::kLoadSwizzleGlobal
831 : ByteCodeInstruction::kLoadSwizzle);
832 this->write8(this->getLocation(var));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400833 this->write8(s.fComponents.size());
834 for (int c : s.fComponents) {
835 this->write8(c);
836 }
837 break;
838 }
839 default:
840 this->writeExpression(*s.fBase);
841 this->write(ByteCodeInstruction::kSwizzle);
842 this->write8(s.fBase->fType.columns());
843 this->write8(s.fComponents.size());
844 for (int c : s.fComponents) {
845 this->write8(c);
846 }
847 }
848}
849
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400850void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Brian Osman4e93feb2019-05-16 15:38:00 -0400851 this->writeExpression(*t.fTest);
Brian Osman569f12f2019-06-13 11:23:57 -0400852 this->write(ByteCodeInstruction::kMaskPush);
Brian Osman4e93feb2019-05-16 15:38:00 -0400853 this->writeExpression(*t.fIfTrue);
Brian Osman569f12f2019-06-13 11:23:57 -0400854 this->write(ByteCodeInstruction::kMaskNegate);
855 this->writeExpression(*t.fIfFalse);
856 this->write(ByteCodeInstruction::kMaskBlend);
857 this->write8(SlotCount(t.fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400858}
859
Brian Osman3e29f1d2019-05-28 09:35:05 -0400860void ByteCodeGenerator::writeExpression(const Expression& e, bool discard) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400861 switch (e.fKind) {
862 case Expression::kBinary_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400863 discard = this->writeBinaryExpression((BinaryExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400864 break;
865 case Expression::kBoolLiteral_Kind:
866 this->writeBoolLiteral((BoolLiteral&) e);
867 break;
868 case Expression::kConstructor_Kind:
869 this->writeConstructor((Constructor&) e);
870 break;
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400871 case Expression::kExternalFunctionCall_Kind:
872 this->writeExternalFunctionCall((ExternalFunctionCall&) e);
873 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400874 case Expression::kExternalValue_Kind:
875 this->writeExternalValue((ExternalValueReference&) e);
876 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400877 case Expression::kFieldAccess_Kind:
Brian Osman07c117b2019-05-23 12:51:06 -0700878 case Expression::kIndex_Kind:
879 case Expression::kVariableReference_Kind:
880 this->writeVariableExpression(e);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400881 break;
882 case Expression::kFloatLiteral_Kind:
883 this->writeFloatLiteral((FloatLiteral&) e);
884 break;
885 case Expression::kFunctionCall_Kind:
886 this->writeFunctionCall((FunctionCall&) e);
887 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400888 case Expression::kIntLiteral_Kind:
889 this->writeIntLiteral((IntLiteral&) e);
890 break;
891 case Expression::kNullLiteral_Kind:
892 this->writeNullLiteral((NullLiteral&) e);
893 break;
894 case Expression::kPrefix_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400895 discard = this->writePrefixExpression((PrefixExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400896 break;
897 case Expression::kPostfix_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400898 discard = this->writePostfixExpression((PostfixExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400899 break;
900 case Expression::kSwizzle_Kind:
901 this->writeSwizzle((Swizzle&) e);
902 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400903 case Expression::kTernary_Kind:
904 this->writeTernaryExpression((TernaryExpression&) e);
905 break;
906 default:
907 printf("unsupported expression %s\n", e.description().c_str());
908 SkASSERT(false);
909 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400910 if (discard) {
911 int count = SlotCount(e.fType);
912 if (count > 4) {
913 this->write(ByteCodeInstruction::kPopN);
914 this->write8(count);
Brian Osmanfba386b2019-06-20 14:54:15 -0400915 } else if (count != 0) {
Brian Osman3e29f1d2019-05-28 09:35:05 -0400916 this->write(vector_instruction(ByteCodeInstruction::kPop, count));
917 }
918 discard = false;
919 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400920}
921
Ethan Nicholas91164d12019-05-15 15:29:54 -0400922class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
923public:
924 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
925 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700926 , fCount(ByteCodeGenerator::SlotCount(value.type()))
Ethan Nicholas91164d12019-05-15 15:29:54 -0400927 , fIndex(index) {}
928
929 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400930 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400931 fGenerator.write8(fIndex);
932 }
933
Brian Osman3e29f1d2019-05-28 09:35:05 -0400934 void store(bool discard) override {
935 if (!discard) {
936 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
937 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400938 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400939 fGenerator.write8(fIndex);
940 }
941
942private:
943 typedef LValue INHERITED;
944
945 int fCount;
946
947 int fIndex;
948};
949
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400950class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
951public:
952 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
953 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700954 , fSwizzle(swizzle) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400955
956 void load() override {
Brian Osman1091f022019-05-16 09:42:16 -0400957 fGenerator.writeSwizzle(fSwizzle);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400958 }
959
Brian Osman3e29f1d2019-05-28 09:35:05 -0400960 void store(bool discard) override {
961 if (!discard) {
962 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup,
963 fSwizzle.fComponents.size()));
964 }
Brian Osman07c117b2019-05-23 12:51:06 -0700965 Variable::Storage storage;
966 int location = fGenerator.getLocation(*fSwizzle.fBase, &storage);
967 bool isGlobal = storage == Variable::kGlobal_Storage;
968 if (location < 0) {
969 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleIndirectGlobal
970 : ByteCodeInstruction::kStoreSwizzleIndirect);
971 } else {
972 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleGlobal
973 : ByteCodeInstruction::kStoreSwizzle);
974 fGenerator.write8(location);
975 }
Brian Osman1091f022019-05-16 09:42:16 -0400976 fGenerator.write8(fSwizzle.fComponents.size());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400977 for (int c : fSwizzle.fComponents) {
978 fGenerator.write8(c);
979 }
980 }
981
982private:
983 const Swizzle& fSwizzle;
984
985 typedef LValue INHERITED;
986};
987
Brian Osman07c117b2019-05-23 12:51:06 -0700988class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400989public:
Brian Osman07c117b2019-05-23 12:51:06 -0700990 ByteCodeExpressionLValue(ByteCodeGenerator* generator, const Expression& expr)
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400991 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700992 , fExpression(expr) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400993
994 void load() override {
Brian Osman07c117b2019-05-23 12:51:06 -0700995 fGenerator.writeVariableExpression(fExpression);
Brian Osman1091f022019-05-16 09:42:16 -0400996 }
997
Brian Osman3e29f1d2019-05-28 09:35:05 -0400998 void store(bool discard) override {
Brian Osman07c117b2019-05-23 12:51:06 -0700999 int count = ByteCodeGenerator::SlotCount(fExpression.fType);
Brian Osman3e29f1d2019-05-28 09:35:05 -04001000 if (!discard) {
1001 if (count > 4) {
1002 fGenerator.write(ByteCodeInstruction::kDupN);
1003 fGenerator.write8(count);
1004 } else {
1005 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
1006 }
Brian Osman07c117b2019-05-23 12:51:06 -07001007 }
1008 Variable::Storage storage;
1009 int location = fGenerator.getLocation(fExpression, &storage);
1010 bool isGlobal = storage == Variable::kGlobal_Storage;
1011 if (location < 0 || count > 4) {
1012 if (location >= 0) {
1013 fGenerator.write(ByteCodeInstruction::kPushImmediate);
1014 fGenerator.write32(location);
1015 }
1016 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreExtendedGlobal
1017 : ByteCodeInstruction::kStoreExtended);
1018 fGenerator.write8(count);
1019 } else {
1020 fGenerator.write(vector_instruction(isGlobal ? ByteCodeInstruction::kStoreGlobal
1021 : ByteCodeInstruction::kStore,
1022 count));
1023 fGenerator.write8(location);
1024 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001025 }
1026
1027private:
1028 typedef LValue INHERITED;
1029
Brian Osman07c117b2019-05-23 12:51:06 -07001030 const Expression& fExpression;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001031};
1032
1033std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
1034 switch (e.fKind) {
Ethan Nicholas91164d12019-05-15 15:29:54 -04001035 case Expression::kExternalValue_Kind: {
1036 ExternalValue* value = ((ExternalValueReference&) e).fValue;
1037 int index = fOutput->fExternalValues.size();
1038 fOutput->fExternalValues.push_back(value);
1039 SkASSERT(index <= 255);
1040 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
1041 }
Brian Osman07c117b2019-05-23 12:51:06 -07001042 case Expression::kFieldAccess_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001043 case Expression::kIndex_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001044 case Expression::kVariableReference_Kind:
Brian Osman07c117b2019-05-23 12:51:06 -07001045 return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
Brian Osman0785db02019-05-24 14:19:11 -04001046 case Expression::kSwizzle_Kind: {
1047 const Swizzle& s = (const Swizzle&) e;
1048 return swizzle_is_simple(s)
1049 ? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e))
1050 : std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s));
1051 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001052 case Expression::kTernary_Kind:
1053 default:
1054 printf("unsupported lvalue %s\n", e.description().c_str());
1055 return nullptr;
1056 }
1057}
1058
1059void ByteCodeGenerator::writeBlock(const Block& b) {
1060 for (const auto& s : b.fStatements) {
1061 this->writeStatement(*s);
1062 }
1063}
1064
1065void ByteCodeGenerator::setBreakTargets() {
1066 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
1067 for (DeferredLocation& b : breaks) {
1068 b.set();
1069 }
1070 fBreakTargets.pop();
1071}
1072
1073void ByteCodeGenerator::setContinueTargets() {
1074 std::vector<DeferredLocation>& continues = fContinueTargets.top();
1075 for (DeferredLocation& c : continues) {
1076 c.set();
1077 }
1078 fContinueTargets.pop();
1079}
1080
1081void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
Brian Osman569f12f2019-06-13 11:23:57 -04001082 // TODO: Include BranchIfAllFalse to top-most LoopNext
1083 this->write(ByteCodeInstruction::kLoopBreak);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001084}
1085
1086void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
Brian Osman569f12f2019-06-13 11:23:57 -04001087 // TODO: Include BranchIfAllFalse to top-most LoopNext
1088 this->write(ByteCodeInstruction::kLoopContinue);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001089}
1090
1091void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
Brian Osman569f12f2019-06-13 11:23:57 -04001092 this->write(ByteCodeInstruction::kLoopBegin);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001093 size_t start = fCode->size();
1094 this->writeStatement(*d.fStatement);
Brian Osman569f12f2019-06-13 11:23:57 -04001095 this->write(ByteCodeInstruction::kLoopNext);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001096 this->writeExpression(*d.fTest);
Brian Osman569f12f2019-06-13 11:23:57 -04001097 this->write(ByteCodeInstruction::kLoopMask);
1098 // TODO: Could shorten this with kBranchIfAnyTrue
1099 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1100 DeferredLocation endLocation(this);
1101 this->write(ByteCodeInstruction::kBranch);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001102 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001103 endLocation.set();
1104 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001105}
1106
1107void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
1108 fContinueTargets.emplace();
1109 fBreakTargets.emplace();
1110 if (f.fInitializer) {
1111 this->writeStatement(*f.fInitializer);
1112 }
Brian Osman569f12f2019-06-13 11:23:57 -04001113 this->write(ByteCodeInstruction::kLoopBegin);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001114 size_t start = fCode->size();
1115 if (f.fTest) {
1116 this->writeExpression(*f.fTest);
Brian Osman569f12f2019-06-13 11:23:57 -04001117 this->write(ByteCodeInstruction::kLoopMask);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001118 }
Brian Osman569f12f2019-06-13 11:23:57 -04001119 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1120 DeferredLocation endLocation(this);
1121 this->writeStatement(*f.fStatement);
1122 this->write(ByteCodeInstruction::kLoopNext);
1123 if (f.fNext) {
1124 this->writeExpression(*f.fNext, true);
1125 }
1126 this->write(ByteCodeInstruction::kBranch);
1127 this->write16(start);
1128 endLocation.set();
1129 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001130}
1131
1132void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Brian Osman569f12f2019-06-13 11:23:57 -04001133 this->writeExpression(*i.fTest);
1134 this->write(ByteCodeInstruction::kMaskPush);
1135 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1136 DeferredLocation falseLocation(this);
1137 this->writeStatement(*i.fIfTrue);
1138 falseLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001139 if (i.fIfFalse) {
Brian Osman569f12f2019-06-13 11:23:57 -04001140 this->write(ByteCodeInstruction::kMaskNegate);
1141 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1142 DeferredLocation endLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001143 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -05001144 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001145 }
Brian Osman569f12f2019-06-13 11:23:57 -04001146 this->write(ByteCodeInstruction::kMaskPop);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001147}
1148
1149void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -04001150 this->writeExpression(*r.fExpression);
1151 this->write(ByteCodeInstruction::kReturn);
Brian Osman07c117b2019-05-23 12:51:06 -07001152 this->write8(SlotCount(r.fExpression->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001153}
1154
1155void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
1156 // not yet implemented
1157 abort();
1158}
1159
1160void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1161 for (const auto& declStatement : v.fVars) {
1162 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
1163 // we need to grab the location even if we don't use it, to ensure it
1164 // has been allocated
1165 int location = getLocation(*decl.fVar);
1166 if (decl.fValue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001167 this->writeExpression(*decl.fValue);
Brian Osman07c117b2019-05-23 12:51:06 -07001168 int count = SlotCount(decl.fValue->fType);
1169 if (count > 4) {
1170 this->write(ByteCodeInstruction::kPushImmediate);
1171 this->write32(location);
1172 this->write(ByteCodeInstruction::kStoreExtended);
1173 this->write8(count);
1174 } else {
1175 this->write(vector_instruction(ByteCodeInstruction::kStore, count));
1176 this->write8(location);
1177 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001178 }
1179 }
1180}
1181
1182void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
Brian Osman569f12f2019-06-13 11:23:57 -04001183 this->write(ByteCodeInstruction::kLoopBegin);
1184 size_t cond = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001185 this->writeExpression(*w.fTest);
Brian Osman569f12f2019-06-13 11:23:57 -04001186 this->write(ByteCodeInstruction::kLoopMask);
1187 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001188 DeferredLocation endLocation(this);
1189 this->writeStatement(*w.fStatement);
Brian Osman569f12f2019-06-13 11:23:57 -04001190 this->write(ByteCodeInstruction::kLoopNext);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001191 this->write(ByteCodeInstruction::kBranch);
Brian Osman569f12f2019-06-13 11:23:57 -04001192 this->write16(cond);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001193 endLocation.set();
Brian Osman569f12f2019-06-13 11:23:57 -04001194 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001195}
1196
1197void ByteCodeGenerator::writeStatement(const Statement& s) {
1198 switch (s.fKind) {
1199 case Statement::kBlock_Kind:
1200 this->writeBlock((Block&) s);
1201 break;
1202 case Statement::kBreak_Kind:
1203 this->writeBreakStatement((BreakStatement&) s);
1204 break;
1205 case Statement::kContinue_Kind:
1206 this->writeContinueStatement((ContinueStatement&) s);
1207 break;
1208 case Statement::kDiscard_Kind:
1209 // not yet implemented
1210 abort();
1211 case Statement::kDo_Kind:
1212 this->writeDoStatement((DoStatement&) s);
1213 break;
Brian Osman3e29f1d2019-05-28 09:35:05 -04001214 case Statement::kExpression_Kind:
1215 this->writeExpression(*((ExpressionStatement&) s).fExpression, true);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001216 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001217 case Statement::kFor_Kind:
1218 this->writeForStatement((ForStatement&) s);
1219 break;
1220 case Statement::kIf_Kind:
1221 this->writeIfStatement((IfStatement&) s);
1222 break;
1223 case Statement::kNop_Kind:
1224 break;
1225 case Statement::kReturn_Kind:
1226 this->writeReturnStatement((ReturnStatement&) s);
1227 break;
1228 case Statement::kSwitch_Kind:
1229 this->writeSwitchStatement((SwitchStatement&) s);
1230 break;
1231 case Statement::kVarDeclarations_Kind:
1232 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1233 break;
1234 case Statement::kWhile_Kind:
1235 this->writeWhileStatement((WhileStatement&) s);
1236 break;
1237 default:
1238 SkASSERT(false);
1239 }
1240}
1241
Brian Osman80164412019-06-07 13:00:23 -04001242ByteCodeFunction::ByteCodeFunction(const FunctionDeclaration* declaration)
1243 : fName(declaration->fName) {
1244 fParameterCount = 0;
1245 for (const auto& p : declaration->fParameters) {
1246 int slots = ByteCodeGenerator::SlotCount(p->fType);
1247 fParameters.push_back({ slots, (bool)(p->fModifiers.fFlags & Modifiers::kOut_Flag) });
1248 fParameterCount += slots;
1249 }
1250}
1251
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001252}