blob: c2e9a14e202a3d67a72cf28f2ec3a70a3f771253 [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 Osman226668a2019-05-14 16:47:30 -040084 for (auto& call : fCallTargets) {
85 if (!call.set()) {
86 return false;
87 }
88 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040089 return true;
90}
91
92std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
93 fFunction = &f;
Brian Osman226668a2019-05-14 16:47:30 -040094 std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
Brian Osman80164412019-06-07 13:00:23 -040095 fParameterCount = result->fParameterCount;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040096 fCode = &result->fCode;
97 this->writeStatement(*f.fBody);
Ethan Nicholas7e603db2019-05-03 12:57:47 -040098 this->write(ByteCodeInstruction::kReturn);
99 this->write8(0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400100 result->fLocalCount = fLocals.size();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400101 const Type& returnType = f.fDeclaration.fReturnType;
102 if (returnType != *fContext.fVoid_Type) {
Brian Osman07c117b2019-05-23 12:51:06 -0700103 result->fReturnCount = SlotCount(returnType);
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400104 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400105 fLocals.clear();
106 fFunction = nullptr;
107 return result;
108}
109
110enum class TypeCategory {
111 kBool,
112 kSigned,
113 kUnsigned,
114 kFloat,
115};
116
117static TypeCategory type_category(const Type& type) {
118 switch (type.kind()) {
119 case Type::Kind::kVector_Kind:
120 case Type::Kind::kMatrix_Kind:
121 return type_category(type.componentType());
122 default:
123 if (type.fName == "bool") {
124 return TypeCategory::kBool;
125 } else if (type.fName == "int" || type.fName == "short") {
126 return TypeCategory::kSigned;
127 } else if (type.fName == "uint" || type.fName == "ushort") {
128 return TypeCategory::kUnsigned;
129 } else {
130 SkASSERT(type.fName == "float" || type.fName == "half");
131 return TypeCategory::kFloat;
132 }
133 ABORT("unsupported type: %s\n", type.description().c_str());
134 }
135}
136
Brian Osman0785db02019-05-24 14:19:11 -0400137// A "simple" Swizzle is based on a variable (or a compound variable like a struct or array), and
138// that references consecutive values, such that it can be implemented using normal load/store ops
139// with an offset. Note that all single-component swizzles (of suitable base types) are simple.
140static bool swizzle_is_simple(const Swizzle& s) {
141 switch (s.fBase->fKind) {
142 case Expression::kFieldAccess_Kind:
143 case Expression::kIndex_Kind:
144 case Expression::kVariableReference_Kind:
145 break;
146 default:
147 return false;
148 }
149
150 for (size_t i = 1; i < s.fComponents.size(); ++i) {
151 if (s.fComponents[i] != s.fComponents[i - 1] + 1) {
152 return false;
153 }
154 }
155 return true;
156}
157
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400158int ByteCodeGenerator::getLocation(const Variable& var) {
159 // given that we seldom have more than a couple of variables, linear search is probably the most
160 // efficient way to handle lookups
161 switch (var.fStorage) {
162 case Variable::kLocal_Storage: {
163 for (int i = fLocals.size() - 1; i >= 0; --i) {
164 if (fLocals[i] == &var) {
Brian Osman1091f022019-05-16 09:42:16 -0400165 SkASSERT(fParameterCount + i <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400166 return fParameterCount + i;
167 }
168 }
169 int result = fParameterCount + fLocals.size();
170 fLocals.push_back(&var);
Brian Osman07c117b2019-05-23 12:51:06 -0700171 for (int i = 0; i < SlotCount(var.fType) - 1; ++i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400172 fLocals.push_back(nullptr);
173 }
Brian Osman1091f022019-05-16 09:42:16 -0400174 SkASSERT(result <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400175 return result;
176 }
177 case Variable::kParameter_Storage: {
178 int offset = 0;
179 for (const auto& p : fFunction->fDeclaration.fParameters) {
180 if (p == &var) {
Brian Osman1091f022019-05-16 09:42:16 -0400181 SkASSERT(offset <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400182 return offset;
183 }
Brian Osman07c117b2019-05-23 12:51:06 -0700184 offset += SlotCount(p->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400185 }
186 SkASSERT(false);
Brian Osman1091f022019-05-16 09:42:16 -0400187 return 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400188 }
189 case Variable::kGlobal_Storage: {
190 int offset = 0;
191 for (const auto& e : fProgram) {
192 if (e.fKind == ProgramElement::kVar_Kind) {
193 VarDeclarations& decl = (VarDeclarations&) e;
194 for (const auto& v : decl.fVars) {
195 const Variable* declVar = ((VarDeclaration&) *v).fVar;
196 if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
197 continue;
198 }
199 if (declVar == &var) {
Brian Osmanb7451292019-05-15 13:02:13 -0400200 SkASSERT(offset <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400201 return offset;
202 }
Brian Osman07c117b2019-05-23 12:51:06 -0700203 offset += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400204 }
205 }
206 }
207 SkASSERT(false);
Brian Osman1091f022019-05-16 09:42:16 -0400208 return 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400209 }
210 default:
211 SkASSERT(false);
212 return 0;
213 }
214}
215
Brian Osman0785db02019-05-24 14:19:11 -0400216// TODO: Elide Add 0 and Mul 1 sequences
Brian Osman07c117b2019-05-23 12:51:06 -0700217int ByteCodeGenerator::getLocation(const Expression& expr, Variable::Storage* storage) {
218 switch (expr.fKind) {
219 case Expression::kFieldAccess_Kind: {
220 const FieldAccess& f = (const FieldAccess&)expr;
221 int baseAddr = this->getLocation(*f.fBase, storage);
222 int offset = 0;
223 for (int i = 0; i < f.fFieldIndex; ++i) {
224 offset += SlotCount(*f.fBase->fType.fields()[i].fType);
225 }
226 if (baseAddr < 0) {
227 this->write(ByteCodeInstruction::kPushImmediate);
228 this->write32(offset);
229 this->write(ByteCodeInstruction::kAddI);
230 return -1;
231 } else {
232 return baseAddr + offset;
233 }
234 }
235 case Expression::kIndex_Kind: {
236 const IndexExpression& i = (const IndexExpression&)expr;
237 int stride = SlotCount(i.fType);
238 int offset = -1;
239 if (i.fIndex->isConstant()) {
240 offset = i.fIndex->getConstantInt() * stride;
241 } else {
242 this->writeExpression(*i.fIndex);
243 this->write(ByteCodeInstruction::kPushImmediate);
244 this->write32(stride);
245 this->write(ByteCodeInstruction::kMultiplyI);
246 }
247 int baseAddr = this->getLocation(*i.fBase, storage);
248 if (baseAddr >= 0 && offset >= 0) {
249 return baseAddr + offset;
250 }
251 if (baseAddr >= 0) {
252 this->write(ByteCodeInstruction::kPushImmediate);
253 this->write32(baseAddr);
254 }
255 if (offset >= 0) {
256 this->write(ByteCodeInstruction::kPushImmediate);
257 this->write32(offset);
258 }
259 this->write(ByteCodeInstruction::kAddI);
260 return -1;
261 }
Brian Osman0785db02019-05-24 14:19:11 -0400262 case Expression::kSwizzle_Kind: {
263 const Swizzle& s = (const Swizzle&)expr;
264 SkASSERT(swizzle_is_simple(s));
265 int baseAddr = this->getLocation(*s.fBase, storage);
266 int offset = s.fComponents[0];
267 if (baseAddr < 0) {
268 this->write(ByteCodeInstruction::kPushImmediate);
269 this->write32(offset);
270 this->write(ByteCodeInstruction::kAddI);
271 return -1;
272 } else {
273 return baseAddr + offset;
274 }
275 }
Brian Osman07c117b2019-05-23 12:51:06 -0700276 case Expression::kVariableReference_Kind: {
277 const Variable& var = ((const VariableReference&)expr).fVariable;
278 *storage = var.fStorage;
279 return this->getLocation(var);
280 }
281 default:
282 SkASSERT(false);
283 return 0;
284 }
285}
286
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400287void ByteCodeGenerator::write8(uint8_t b) {
288 fCode->push_back(b);
289}
290
291void ByteCodeGenerator::write16(uint16_t i) {
Mike Klein76346ac2019-05-17 11:57:10 -0500292 size_t n = fCode->size();
293 fCode->resize(n+2);
294 memcpy(fCode->data() + n, &i, 2);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400295}
296
297void ByteCodeGenerator::write32(uint32_t i) {
Mike Klein76346ac2019-05-17 11:57:10 -0500298 size_t n = fCode->size();
299 fCode->resize(n+4);
300 memcpy(fCode->data() + n, &i, 4);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400301}
302
303void ByteCodeGenerator::write(ByteCodeInstruction i) {
Mike Klein108e9352019-05-21 11:05:17 -0500304 this->write16((uint16_t)i);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400305}
306
Mike Klein76346ac2019-05-17 11:57:10 -0500307static ByteCodeInstruction vector_instruction(ByteCodeInstruction base, int count) {
Brian Osman07c117b2019-05-23 12:51:06 -0700308 SkASSERT(count >= 1 && count <= 4);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400309 return ((ByteCodeInstruction) ((int) base + count - 1));
310}
311
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400312void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400313 ByteCodeInstruction u, ByteCodeInstruction f,
314 int count) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400315 switch (type_category(type)) {
316 case TypeCategory::kSigned:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400317 this->write(vector_instruction(s, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400318 break;
319 case TypeCategory::kUnsigned:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400320 this->write(vector_instruction(u, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400321 break;
Brian Osman1e855b22019-05-29 15:21:52 -0400322 case TypeCategory::kFloat: {
323 if (count > 4) {
324 this->write((ByteCodeInstruction)((int)f + 4));
325 this->write8(count);
326 } else {
327 this->write(vector_instruction(f, count));
328 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400329 break;
Brian Osman1e855b22019-05-29 15:21:52 -0400330 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400331 default:
332 SkASSERT(false);
333 }
334}
335
Brian Osman3e29f1d2019-05-28 09:35:05 -0400336bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool discard) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400337 if (b.fOperator == Token::Kind::EQ) {
338 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
339 this->writeExpression(*b.fRight);
Brian Osman3e29f1d2019-05-28 09:35:05 -0400340 lvalue->store(discard);
341 discard = false;
342 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400343 }
Brian Osman16e6fd52019-05-29 11:19:00 -0400344 const Type& lType = b.fLeft->fType;
345 const Type& rType = b.fRight->fType;
Brian Osman909231c2019-05-29 15:34:36 -0400346 bool lVecOrMtx = (lType.kind() == Type::kVector_Kind || lType.kind() == Type::kMatrix_Kind);
347 bool rVecOrMtx = (rType.kind() == Type::kVector_Kind || rType.kind() == Type::kMatrix_Kind);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400348 Token::Kind op;
349 std::unique_ptr<LValue> lvalue;
350 if (is_assignment(b.fOperator)) {
351 lvalue = this->getLValue(*b.fLeft);
352 lvalue->load();
353 op = remove_assignment(b.fOperator);
354 } else {
355 this->writeExpression(*b.fLeft);
356 op = b.fOperator;
Brian Osman909231c2019-05-29 15:34:36 -0400357 if (!lVecOrMtx && rVecOrMtx) {
Brian Osman16e6fd52019-05-29 11:19:00 -0400358 for (int i = SlotCount(rType); i > 1; --i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400359 this->write(ByteCodeInstruction::kDup);
360 }
361 }
362 }
363 this->writeExpression(*b.fRight);
Brian Osman909231c2019-05-29 15:34:36 -0400364 if (lVecOrMtx && !rVecOrMtx) {
Brian Osman16e6fd52019-05-29 11:19:00 -0400365 for (int i = SlotCount(lType); i > 1; --i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400366 this->write(ByteCodeInstruction::kDup);
367 }
368 }
Brian Osman909231c2019-05-29 15:34:36 -0400369 // Special case for M*V, V*M, M*M (but not V*V!)
370 if (op == Token::Kind::STAR && lVecOrMtx && rVecOrMtx &&
371 !(lType.kind() == Type::kVector_Kind && rType.kind() == Type::kVector_Kind)) {
372 this->write(ByteCodeInstruction::kMatrixMultiply);
373 int rCols = rType.columns(),
374 rRows = rType.rows(),
375 lCols = lType.columns(),
376 lRows = lType.rows();
377 // M*V treats the vector as a column
378 if (rType.kind() == Type::kVector_Kind) {
379 std::swap(rCols, rRows);
380 }
381 SkASSERT(lCols == rRows);
382 SkASSERT(SlotCount(b.fType) == lRows * rCols);
383 this->write8(lCols);
384 this->write8(lRows);
385 this->write8(rCols);
386 } else {
387 int count = std::max(SlotCount(lType), SlotCount(rType));
388 switch (op) {
389 case Token::Kind::EQEQ:
390 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareIEQ,
391 ByteCodeInstruction::kCompareIEQ,
392 ByteCodeInstruction::kCompareFEQ,
393 count);
394 // Collapse to a single bool
395 for (int i = count; i > 1; --i) {
396 this->write(ByteCodeInstruction::kAndB);
397 }
398 break;
399 case Token::Kind::GT:
400 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGT,
401 ByteCodeInstruction::kCompareUGT,
402 ByteCodeInstruction::kCompareFGT,
403 count);
404 break;
405 case Token::Kind::GTEQ:
406 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGTEQ,
407 ByteCodeInstruction::kCompareUGTEQ,
408 ByteCodeInstruction::kCompareFGTEQ,
409 count);
410 break;
411 case Token::Kind::LT:
412 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLT,
413 ByteCodeInstruction::kCompareULT,
414 ByteCodeInstruction::kCompareFLT,
415 count);
416 break;
417 case Token::Kind::LTEQ:
418 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLTEQ,
419 ByteCodeInstruction::kCompareULTEQ,
420 ByteCodeInstruction::kCompareFLTEQ,
421 count);
422 break;
423 case Token::Kind::MINUS:
424 this->writeTypedInstruction(lType, ByteCodeInstruction::kSubtractI,
425 ByteCodeInstruction::kSubtractI,
426 ByteCodeInstruction::kSubtractF,
427 count);
428 break;
429 case Token::Kind::NEQ:
430 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareINEQ,
431 ByteCodeInstruction::kCompareINEQ,
432 ByteCodeInstruction::kCompareFNEQ,
433 count);
434 // Collapse to a single bool
435 for (int i = count; i > 1; --i) {
436 this->write(ByteCodeInstruction::kOrB);
437 }
438 break;
439 case Token::Kind::PERCENT:
440 this->writeTypedInstruction(lType, ByteCodeInstruction::kRemainderS,
441 ByteCodeInstruction::kRemainderU,
442 ByteCodeInstruction::kRemainderF,
443 count);
444 break;
445 case Token::Kind::PLUS:
446 this->writeTypedInstruction(lType, ByteCodeInstruction::kAddI,
447 ByteCodeInstruction::kAddI,
448 ByteCodeInstruction::kAddF,
449 count);
450 break;
451 case Token::Kind::SLASH:
452 this->writeTypedInstruction(lType, ByteCodeInstruction::kDivideS,
453 ByteCodeInstruction::kDivideU,
454 ByteCodeInstruction::kDivideF,
455 count);
456 break;
457 case Token::Kind::STAR:
458 this->writeTypedInstruction(lType, ByteCodeInstruction::kMultiplyI,
459 ByteCodeInstruction::kMultiplyI,
460 ByteCodeInstruction::kMultiplyF,
461 count);
462 break;
Brian Osman569f12f2019-06-13 11:23:57 -0400463
464 case Token::Kind::LOGICALAND:
465 SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
466 this->write(ByteCodeInstruction::kAndB);
467 break;
468 case Token::Kind::LOGICALNOT:
469 SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
470 this->write(ByteCodeInstruction::kNotB);
471 break;
472 case Token::Kind::LOGICALOR:
473 SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
474 this->write(ByteCodeInstruction::kOrB);
475 break;
476 case Token::Kind::LOGICALXOR:
477 SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
478 this->write(ByteCodeInstruction::kXorB);
479 break;
480
Brian Osman909231c2019-05-29 15:34:36 -0400481 default:
482 SkASSERT(false);
483 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400484 }
485 if (lvalue) {
Brian Osman3e29f1d2019-05-28 09:35:05 -0400486 lvalue->store(discard);
487 discard = false;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400488 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400489 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400490}
491
492void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
493 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osman569f12f2019-06-13 11:23:57 -0400494 this->write32(b.fValue ? ~0 : 0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400495}
496
497void ByteCodeGenerator::writeConstructor(const Constructor& c) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400498 for (const auto& arg : c.fArguments) {
499 this->writeExpression(*arg);
500 }
501 if (c.fArguments.size() == 1) {
Brian Osman29e013d2019-05-28 17:16:03 -0400502 const Type& inType = c.fArguments[0]->fType;
503 const Type& outType = c.fType;
504 TypeCategory inCategory = type_category(inType);
505 TypeCategory outCategory = type_category(outType);
506 int inCount = SlotCount(inType);
507 int outCount = SlotCount(outType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400508 if (inCategory != outCategory) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700509 SkASSERT(inCount == outCount);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400510 if (inCategory == TypeCategory::kFloat) {
511 SkASSERT(outCategory == TypeCategory::kSigned ||
512 outCategory == TypeCategory::kUnsigned);
Brian Osmanc51d7912019-05-22 15:16:16 -0700513 this->write(vector_instruction(ByteCodeInstruction::kConvertFtoI, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400514 } else if (outCategory == TypeCategory::kFloat) {
515 if (inCategory == TypeCategory::kSigned) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700516 this->write(vector_instruction(ByteCodeInstruction::kConvertStoF, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400517 } else {
518 SkASSERT(inCategory == TypeCategory::kUnsigned);
Brian Osmanc51d7912019-05-22 15:16:16 -0700519 this->write(vector_instruction(ByteCodeInstruction::kConvertUtoF, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400520 }
521 } else {
522 SkASSERT(false);
523 }
524 }
Brian Osman29e013d2019-05-28 17:16:03 -0400525 if (inType.kind() == Type::kMatrix_Kind && outType.kind() == Type::kMatrix_Kind) {
526 this->write(ByteCodeInstruction::kMatrixToMatrix);
527 this->write8(inType.columns());
528 this->write8(inType.rows());
529 this->write8(outType.columns());
530 this->write8(outType.rows());
531 } else if (inCount != outCount) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700532 SkASSERT(inCount == 1);
Brian Osman29e013d2019-05-28 17:16:03 -0400533 if (outType.kind() == Type::kMatrix_Kind) {
534 this->write(ByteCodeInstruction::kScalarToMatrix);
535 this->write8(outType.columns());
536 this->write8(outType.rows());
537 } else {
538 SkASSERT(outType.kind() == Type::kVector_Kind);
539 for (; inCount != outCount; ++inCount) {
540 this->write(ByteCodeInstruction::kDup);
541 }
Brian Osmanc51d7912019-05-22 15:16:16 -0700542 }
543 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400544 }
545}
546
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400547void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f) {
548 int argumentCount = 0;
549 for (const auto& arg : f.fArguments) {
550 this->writeExpression(*arg);
Brian Osman07c117b2019-05-23 12:51:06 -0700551 argumentCount += SlotCount(arg->fType);
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400552 }
553 this->write(ByteCodeInstruction::kCallExternal);
554 SkASSERT(argumentCount <= 255);
555 this->write8(argumentCount);
Brian Osman07c117b2019-05-23 12:51:06 -0700556 this->write8(SlotCount(f.fType));
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400557 int index = fOutput->fExternalValues.size();
558 fOutput->fExternalValues.push_back(f.fFunction);
559 SkASSERT(index <= 255);
560 this->write8(index);
561}
562
Ethan Nicholas91164d12019-05-15 15:29:54 -0400563void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400564 this->write(vector_instruction(ByteCodeInstruction::kReadExternal,
Brian Osman07c117b2019-05-23 12:51:06 -0700565 SlotCount(e.fValue->type())));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400566 int index = fOutput->fExternalValues.size();
567 fOutput->fExternalValues.push_back(e.fValue);
568 SkASSERT(index <= 255);
569 this->write8(index);
570}
571
Brian Osman07c117b2019-05-23 12:51:06 -0700572void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
573 Variable::Storage storage;
574 int location = this->getLocation(expr, &storage);
575 bool isGlobal = storage == Variable::kGlobal_Storage;
576 int count = SlotCount(expr.fType);
577 if (location < 0 || count > 4) {
578 if (location >= 0) {
579 this->write(ByteCodeInstruction::kPushImmediate);
580 this->write32(location);
581 }
582 this->write(isGlobal ? ByteCodeInstruction::kLoadExtendedGlobal
583 : ByteCodeInstruction::kLoadExtended);
584 this->write8(count);
585 } else {
586 this->write(vector_instruction(isGlobal ? ByteCodeInstruction::kLoadGlobal
587 : ByteCodeInstruction::kLoad,
588 count));
589 this->write8(location);
590 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400591}
592
Brian Osmand30e0392019-06-14 14:05:14 -0400593static inline uint32_t float_to_bits(float x) {
594 uint32_t u;
595 memcpy(&u, &x, sizeof(uint32_t));
596 return u;
597}
598
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400599void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
600 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmand30e0392019-06-14 14:05:14 -0400601 this->write32(float_to_bits(f.fValue));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400602}
603
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400604void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
605 auto found = fIntrinsics.find(c.fFunction.fName);
606 if (found == fIntrinsics.end()) {
607 fErrors.error(c.fOffset, "unsupported intrinsic function");
608 return;
609 }
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400610 if (found->second.fIsSpecial) {
611 SkASSERT(found->second.fValue.fSpecial == SpecialIntrinsic::kDot);
612 SkASSERT(c.fArguments.size() == 2);
613 SkASSERT(SlotCount(c.fArguments[0]->fType) == SlotCount(c.fArguments[1]->fType));
614 this->write((ByteCodeInstruction) ((int) ByteCodeInstruction::kMultiplyF +
615 SlotCount(c.fArguments[0]->fType) - 1));
616 for (int i = SlotCount(c.fArguments[0]->fType); i > 1; --i) {
617 this->write(ByteCodeInstruction::kAddF);
618 }
619 } else {
620 switch (found->second.fValue.fInstruction) {
621 case ByteCodeInstruction::kCos:
622 case ByteCodeInstruction::kMix:
623 case ByteCodeInstruction::kSin:
624 case ByteCodeInstruction::kSqrt:
625 case ByteCodeInstruction::kTan:
626 SkASSERT(c.fArguments.size() > 0);
627 this->write((ByteCodeInstruction) ((int) found->second.fValue.fInstruction +
628 SlotCount(c.fArguments[0]->fType) - 1));
629 break;
630 case ByteCodeInstruction::kCross:
631 this->write(found->second.fValue.fInstruction);
632 break;
633 default:
634 SkASSERT(false);
635 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400636 }
637}
638
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400639void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Brian Osmand3494ed2019-06-20 15:41:34 -0400640 // Builtins have simple signatures...
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400641 if (f.fFunction.fBuiltin) {
Brian Osmand3494ed2019-06-20 15:41:34 -0400642 for (const auto& arg : f.fArguments) {
643 this->writeExpression(*arg);
644 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400645 this->writeIntrinsicCall(f);
646 return;
647 }
Brian Osmand3494ed2019-06-20 15:41:34 -0400648
649 // Otherwise, we may need to deal with out parameters, so the sequence is trickier...
650 if (int returnCount = SlotCount(f.fType)) {
651 this->write(ByteCodeInstruction::kReserve);
652 this->write8(returnCount);
653 }
654
655 int argCount = f.fArguments.size();
656 std::vector<std::unique_ptr<LValue>> lvalues;
657 for (int i = 0; i < argCount; ++i) {
658 const auto& param = f.fFunction.fParameters[i];
659 const auto& arg = f.fArguments[i];
660 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
661 lvalues.emplace_back(this->getLValue(*arg));
662 lvalues.back()->load();
663 } else {
664 this->writeExpression(*arg);
665 }
666 }
667
Brian Osman226668a2019-05-14 16:47:30 -0400668 this->write(ByteCodeInstruction::kCall);
669 fCallTargets.emplace_back(this, f.fFunction);
Brian Osmand3494ed2019-06-20 15:41:34 -0400670
671 // After the called function returns, the stack will still contain our arguments. We have to
672 // pop them (storing any out parameters back to their lvalues as we go). We glob together slot
673 // counts for all parameters that aren't out-params, so we can pop them in one big chunk.
674 int popCount = 0;
675 auto pop = [&]() {
676 if (popCount > 4) {
677 this->write(ByteCodeInstruction::kPopN);
678 this->write8(popCount);
679 } else if (popCount > 0) {
680 this->write(vector_instruction(ByteCodeInstruction::kPop, popCount));
681 }
682 popCount = 0;
683 };
684
685 for (int i = argCount - 1; i >= 0; --i) {
686 const auto& param = f.fFunction.fParameters[i];
687 const auto& arg = f.fArguments[i];
688 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
689 pop();
690 lvalues.back()->store(true);
691 lvalues.pop_back();
692 } else {
693 popCount += SlotCount(arg->fType);
694 }
695 }
696 pop();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400697}
698
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400699void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
700 this->write(ByteCodeInstruction::kPushImmediate);
701 this->write32(i.fValue);
702}
703
704void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
705 // not yet implemented
706 abort();
707}
708
Brian Osman3e29f1d2019-05-28 09:35:05 -0400709bool ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p, bool discard) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400710 switch (p.fOperator) {
711 case Token::Kind::PLUSPLUS: // fall through
712 case Token::Kind::MINUSMINUS: {
Brian Osman07c117b2019-05-23 12:51:06 -0700713 SkASSERT(SlotCount(p.fOperand->fType) == 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400714 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
715 lvalue->load();
716 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmand30e0392019-06-14 14:05:14 -0400717 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400718 if (p.fOperator == Token::Kind::PLUSPLUS) {
719 this->writeTypedInstruction(p.fType,
720 ByteCodeInstruction::kAddI,
721 ByteCodeInstruction::kAddI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400722 ByteCodeInstruction::kAddF,
723 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400724 } else {
725 this->writeTypedInstruction(p.fType,
726 ByteCodeInstruction::kSubtractI,
727 ByteCodeInstruction::kSubtractI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400728 ByteCodeInstruction::kSubtractF,
729 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400730 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400731 lvalue->store(discard);
732 discard = false;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400733 break;
734 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400735 case Token::Kind::MINUS: {
736 this->writeExpression(*p.fOperand);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400737 this->writeTypedInstruction(p.fType,
Mike Klein12710912019-05-21 11:04:59 -0500738 ByteCodeInstruction::kNegateI,
739 ByteCodeInstruction::kNegateI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400740 ByteCodeInstruction::kNegateF,
Brian Osman07c117b2019-05-23 12:51:06 -0700741 SlotCount(p.fOperand->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400742 break;
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400743 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400744 default:
745 SkASSERT(false);
746 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400747 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400748}
749
Brian Osman3e29f1d2019-05-28 09:35:05 -0400750bool ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p, bool discard) {
Brian Osmanf3fa6002019-05-17 14:26:53 -0400751 switch (p.fOperator) {
752 case Token::Kind::PLUSPLUS: // fall through
753 case Token::Kind::MINUSMINUS: {
Brian Osman07c117b2019-05-23 12:51:06 -0700754 SkASSERT(SlotCount(p.fOperand->fType) == 1);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400755 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
756 lvalue->load();
Brian Osman3e29f1d2019-05-28 09:35:05 -0400757 if (!discard) {
758 this->write(ByteCodeInstruction::kDup);
759 }
Brian Osmanf3fa6002019-05-17 14:26:53 -0400760 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmand30e0392019-06-14 14:05:14 -0400761 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400762 if (p.fOperator == Token::Kind::PLUSPLUS) {
763 this->writeTypedInstruction(p.fType,
764 ByteCodeInstruction::kAddI,
765 ByteCodeInstruction::kAddI,
766 ByteCodeInstruction::kAddF,
767 1);
768 } else {
769 this->writeTypedInstruction(p.fType,
770 ByteCodeInstruction::kSubtractI,
771 ByteCodeInstruction::kSubtractI,
772 ByteCodeInstruction::kSubtractF,
773 1);
774 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400775 lvalue->store(discard);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400776 this->write(ByteCodeInstruction::kPop);
Brian Osman3e29f1d2019-05-28 09:35:05 -0400777 discard = false;
Brian Osmanf3fa6002019-05-17 14:26:53 -0400778 break;
779 }
780 default:
781 SkASSERT(false);
782 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400783 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400784}
785
786void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
Brian Osman0785db02019-05-24 14:19:11 -0400787 if (swizzle_is_simple(s)) {
788 this->writeVariableExpression(s);
789 return;
790 }
791
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400792 switch (s.fBase->fKind) {
793 case Expression::kVariableReference_Kind: {
794 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
Brian Osman1091f022019-05-16 09:42:16 -0400795 this->write(var.fStorage == Variable::kGlobal_Storage
796 ? ByteCodeInstruction::kLoadSwizzleGlobal
797 : ByteCodeInstruction::kLoadSwizzle);
798 this->write8(this->getLocation(var));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400799 this->write8(s.fComponents.size());
800 for (int c : s.fComponents) {
801 this->write8(c);
802 }
803 break;
804 }
805 default:
806 this->writeExpression(*s.fBase);
807 this->write(ByteCodeInstruction::kSwizzle);
808 this->write8(s.fBase->fType.columns());
809 this->write8(s.fComponents.size());
810 for (int c : s.fComponents) {
811 this->write8(c);
812 }
813 }
814}
815
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400816void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Brian Osman4e93feb2019-05-16 15:38:00 -0400817 this->writeExpression(*t.fTest);
Brian Osman569f12f2019-06-13 11:23:57 -0400818 this->write(ByteCodeInstruction::kMaskPush);
Brian Osman4e93feb2019-05-16 15:38:00 -0400819 this->writeExpression(*t.fIfTrue);
Brian Osman569f12f2019-06-13 11:23:57 -0400820 this->write(ByteCodeInstruction::kMaskNegate);
821 this->writeExpression(*t.fIfFalse);
822 this->write(ByteCodeInstruction::kMaskBlend);
823 this->write8(SlotCount(t.fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400824}
825
Brian Osman3e29f1d2019-05-28 09:35:05 -0400826void ByteCodeGenerator::writeExpression(const Expression& e, bool discard) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400827 switch (e.fKind) {
828 case Expression::kBinary_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400829 discard = this->writeBinaryExpression((BinaryExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400830 break;
831 case Expression::kBoolLiteral_Kind:
832 this->writeBoolLiteral((BoolLiteral&) e);
833 break;
834 case Expression::kConstructor_Kind:
835 this->writeConstructor((Constructor&) e);
836 break;
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400837 case Expression::kExternalFunctionCall_Kind:
838 this->writeExternalFunctionCall((ExternalFunctionCall&) e);
839 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400840 case Expression::kExternalValue_Kind:
841 this->writeExternalValue((ExternalValueReference&) e);
842 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400843 case Expression::kFieldAccess_Kind:
Brian Osman07c117b2019-05-23 12:51:06 -0700844 case Expression::kIndex_Kind:
845 case Expression::kVariableReference_Kind:
846 this->writeVariableExpression(e);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400847 break;
848 case Expression::kFloatLiteral_Kind:
849 this->writeFloatLiteral((FloatLiteral&) e);
850 break;
851 case Expression::kFunctionCall_Kind:
852 this->writeFunctionCall((FunctionCall&) e);
853 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400854 case Expression::kIntLiteral_Kind:
855 this->writeIntLiteral((IntLiteral&) e);
856 break;
857 case Expression::kNullLiteral_Kind:
858 this->writeNullLiteral((NullLiteral&) e);
859 break;
860 case Expression::kPrefix_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400861 discard = this->writePrefixExpression((PrefixExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400862 break;
863 case Expression::kPostfix_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400864 discard = this->writePostfixExpression((PostfixExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400865 break;
866 case Expression::kSwizzle_Kind:
867 this->writeSwizzle((Swizzle&) e);
868 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400869 case Expression::kTernary_Kind:
870 this->writeTernaryExpression((TernaryExpression&) e);
871 break;
872 default:
873 printf("unsupported expression %s\n", e.description().c_str());
874 SkASSERT(false);
875 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400876 if (discard) {
877 int count = SlotCount(e.fType);
878 if (count > 4) {
879 this->write(ByteCodeInstruction::kPopN);
880 this->write8(count);
Brian Osmanfba386b2019-06-20 14:54:15 -0400881 } else if (count != 0) {
Brian Osman3e29f1d2019-05-28 09:35:05 -0400882 this->write(vector_instruction(ByteCodeInstruction::kPop, count));
883 }
884 discard = false;
885 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400886}
887
Ethan Nicholas91164d12019-05-15 15:29:54 -0400888class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
889public:
890 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
891 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700892 , fCount(ByteCodeGenerator::SlotCount(value.type()))
Ethan Nicholas91164d12019-05-15 15:29:54 -0400893 , fIndex(index) {}
894
895 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400896 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400897 fGenerator.write8(fIndex);
898 }
899
Brian Osman3e29f1d2019-05-28 09:35:05 -0400900 void store(bool discard) override {
901 if (!discard) {
902 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
903 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400904 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400905 fGenerator.write8(fIndex);
906 }
907
908private:
909 typedef LValue INHERITED;
910
911 int fCount;
912
913 int fIndex;
914};
915
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400916class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
917public:
918 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
919 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700920 , fSwizzle(swizzle) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400921
922 void load() override {
Brian Osman1091f022019-05-16 09:42:16 -0400923 fGenerator.writeSwizzle(fSwizzle);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400924 }
925
Brian Osman3e29f1d2019-05-28 09:35:05 -0400926 void store(bool discard) override {
927 if (!discard) {
928 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup,
929 fSwizzle.fComponents.size()));
930 }
Brian Osman07c117b2019-05-23 12:51:06 -0700931 Variable::Storage storage;
932 int location = fGenerator.getLocation(*fSwizzle.fBase, &storage);
933 bool isGlobal = storage == Variable::kGlobal_Storage;
934 if (location < 0) {
935 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleIndirectGlobal
936 : ByteCodeInstruction::kStoreSwizzleIndirect);
937 } else {
938 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleGlobal
939 : ByteCodeInstruction::kStoreSwizzle);
940 fGenerator.write8(location);
941 }
Brian Osman1091f022019-05-16 09:42:16 -0400942 fGenerator.write8(fSwizzle.fComponents.size());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400943 for (int c : fSwizzle.fComponents) {
944 fGenerator.write8(c);
945 }
946 }
947
948private:
949 const Swizzle& fSwizzle;
950
951 typedef LValue INHERITED;
952};
953
Brian Osman07c117b2019-05-23 12:51:06 -0700954class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400955public:
Brian Osman07c117b2019-05-23 12:51:06 -0700956 ByteCodeExpressionLValue(ByteCodeGenerator* generator, const Expression& expr)
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400957 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700958 , fExpression(expr) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400959
960 void load() override {
Brian Osman07c117b2019-05-23 12:51:06 -0700961 fGenerator.writeVariableExpression(fExpression);
Brian Osman1091f022019-05-16 09:42:16 -0400962 }
963
Brian Osman3e29f1d2019-05-28 09:35:05 -0400964 void store(bool discard) override {
Brian Osman07c117b2019-05-23 12:51:06 -0700965 int count = ByteCodeGenerator::SlotCount(fExpression.fType);
Brian Osman3e29f1d2019-05-28 09:35:05 -0400966 if (!discard) {
967 if (count > 4) {
968 fGenerator.write(ByteCodeInstruction::kDupN);
969 fGenerator.write8(count);
970 } else {
971 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
972 }
Brian Osman07c117b2019-05-23 12:51:06 -0700973 }
974 Variable::Storage storage;
975 int location = fGenerator.getLocation(fExpression, &storage);
976 bool isGlobal = storage == Variable::kGlobal_Storage;
977 if (location < 0 || count > 4) {
978 if (location >= 0) {
979 fGenerator.write(ByteCodeInstruction::kPushImmediate);
980 fGenerator.write32(location);
981 }
982 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreExtendedGlobal
983 : ByteCodeInstruction::kStoreExtended);
984 fGenerator.write8(count);
985 } else {
986 fGenerator.write(vector_instruction(isGlobal ? ByteCodeInstruction::kStoreGlobal
987 : ByteCodeInstruction::kStore,
988 count));
989 fGenerator.write8(location);
990 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400991 }
992
993private:
994 typedef LValue INHERITED;
995
Brian Osman07c117b2019-05-23 12:51:06 -0700996 const Expression& fExpression;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400997};
998
999std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
1000 switch (e.fKind) {
Ethan Nicholas91164d12019-05-15 15:29:54 -04001001 case Expression::kExternalValue_Kind: {
1002 ExternalValue* value = ((ExternalValueReference&) e).fValue;
1003 int index = fOutput->fExternalValues.size();
1004 fOutput->fExternalValues.push_back(value);
1005 SkASSERT(index <= 255);
1006 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
1007 }
Brian Osman07c117b2019-05-23 12:51:06 -07001008 case Expression::kFieldAccess_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001009 case Expression::kIndex_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001010 case Expression::kVariableReference_Kind:
Brian Osman07c117b2019-05-23 12:51:06 -07001011 return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
Brian Osman0785db02019-05-24 14:19:11 -04001012 case Expression::kSwizzle_Kind: {
1013 const Swizzle& s = (const Swizzle&) e;
1014 return swizzle_is_simple(s)
1015 ? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e))
1016 : std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s));
1017 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001018 case Expression::kTernary_Kind:
1019 default:
1020 printf("unsupported lvalue %s\n", e.description().c_str());
1021 return nullptr;
1022 }
1023}
1024
1025void ByteCodeGenerator::writeBlock(const Block& b) {
1026 for (const auto& s : b.fStatements) {
1027 this->writeStatement(*s);
1028 }
1029}
1030
1031void ByteCodeGenerator::setBreakTargets() {
1032 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
1033 for (DeferredLocation& b : breaks) {
1034 b.set();
1035 }
1036 fBreakTargets.pop();
1037}
1038
1039void ByteCodeGenerator::setContinueTargets() {
1040 std::vector<DeferredLocation>& continues = fContinueTargets.top();
1041 for (DeferredLocation& c : continues) {
1042 c.set();
1043 }
1044 fContinueTargets.pop();
1045}
1046
1047void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
Brian Osman569f12f2019-06-13 11:23:57 -04001048 // TODO: Include BranchIfAllFalse to top-most LoopNext
1049 this->write(ByteCodeInstruction::kLoopBreak);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001050}
1051
1052void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
Brian Osman569f12f2019-06-13 11:23:57 -04001053 // TODO: Include BranchIfAllFalse to top-most LoopNext
1054 this->write(ByteCodeInstruction::kLoopContinue);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001055}
1056
1057void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
Brian Osman569f12f2019-06-13 11:23:57 -04001058 this->write(ByteCodeInstruction::kLoopBegin);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001059 size_t start = fCode->size();
1060 this->writeStatement(*d.fStatement);
Brian Osman569f12f2019-06-13 11:23:57 -04001061 this->write(ByteCodeInstruction::kLoopNext);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001062 this->writeExpression(*d.fTest);
Brian Osman569f12f2019-06-13 11:23:57 -04001063 this->write(ByteCodeInstruction::kLoopMask);
1064 // TODO: Could shorten this with kBranchIfAnyTrue
1065 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1066 DeferredLocation endLocation(this);
1067 this->write(ByteCodeInstruction::kBranch);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001068 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001069 endLocation.set();
1070 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001071}
1072
1073void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
1074 fContinueTargets.emplace();
1075 fBreakTargets.emplace();
1076 if (f.fInitializer) {
1077 this->writeStatement(*f.fInitializer);
1078 }
Brian Osman569f12f2019-06-13 11:23:57 -04001079 this->write(ByteCodeInstruction::kLoopBegin);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001080 size_t start = fCode->size();
1081 if (f.fTest) {
1082 this->writeExpression(*f.fTest);
Brian Osman569f12f2019-06-13 11:23:57 -04001083 this->write(ByteCodeInstruction::kLoopMask);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001084 }
Brian Osman569f12f2019-06-13 11:23:57 -04001085 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1086 DeferredLocation endLocation(this);
1087 this->writeStatement(*f.fStatement);
1088 this->write(ByteCodeInstruction::kLoopNext);
1089 if (f.fNext) {
1090 this->writeExpression(*f.fNext, true);
1091 }
1092 this->write(ByteCodeInstruction::kBranch);
1093 this->write16(start);
1094 endLocation.set();
1095 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001096}
1097
1098void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Brian Osman569f12f2019-06-13 11:23:57 -04001099 this->writeExpression(*i.fTest);
1100 this->write(ByteCodeInstruction::kMaskPush);
1101 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1102 DeferredLocation falseLocation(this);
1103 this->writeStatement(*i.fIfTrue);
1104 falseLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001105 if (i.fIfFalse) {
Brian Osman569f12f2019-06-13 11:23:57 -04001106 this->write(ByteCodeInstruction::kMaskNegate);
1107 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1108 DeferredLocation endLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001109 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -05001110 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001111 }
Brian Osman569f12f2019-06-13 11:23:57 -04001112 this->write(ByteCodeInstruction::kMaskPop);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001113}
1114
1115void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -04001116 this->writeExpression(*r.fExpression);
1117 this->write(ByteCodeInstruction::kReturn);
Brian Osman07c117b2019-05-23 12:51:06 -07001118 this->write8(SlotCount(r.fExpression->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001119}
1120
1121void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
1122 // not yet implemented
1123 abort();
1124}
1125
1126void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1127 for (const auto& declStatement : v.fVars) {
1128 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
1129 // we need to grab the location even if we don't use it, to ensure it
1130 // has been allocated
1131 int location = getLocation(*decl.fVar);
1132 if (decl.fValue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001133 this->writeExpression(*decl.fValue);
Brian Osman07c117b2019-05-23 12:51:06 -07001134 int count = SlotCount(decl.fValue->fType);
1135 if (count > 4) {
1136 this->write(ByteCodeInstruction::kPushImmediate);
1137 this->write32(location);
1138 this->write(ByteCodeInstruction::kStoreExtended);
1139 this->write8(count);
1140 } else {
1141 this->write(vector_instruction(ByteCodeInstruction::kStore, count));
1142 this->write8(location);
1143 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001144 }
1145 }
1146}
1147
1148void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
Brian Osman569f12f2019-06-13 11:23:57 -04001149 this->write(ByteCodeInstruction::kLoopBegin);
1150 size_t cond = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001151 this->writeExpression(*w.fTest);
Brian Osman569f12f2019-06-13 11:23:57 -04001152 this->write(ByteCodeInstruction::kLoopMask);
1153 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001154 DeferredLocation endLocation(this);
1155 this->writeStatement(*w.fStatement);
Brian Osman569f12f2019-06-13 11:23:57 -04001156 this->write(ByteCodeInstruction::kLoopNext);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001157 this->write(ByteCodeInstruction::kBranch);
Brian Osman569f12f2019-06-13 11:23:57 -04001158 this->write16(cond);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001159 endLocation.set();
Brian Osman569f12f2019-06-13 11:23:57 -04001160 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001161}
1162
1163void ByteCodeGenerator::writeStatement(const Statement& s) {
1164 switch (s.fKind) {
1165 case Statement::kBlock_Kind:
1166 this->writeBlock((Block&) s);
1167 break;
1168 case Statement::kBreak_Kind:
1169 this->writeBreakStatement((BreakStatement&) s);
1170 break;
1171 case Statement::kContinue_Kind:
1172 this->writeContinueStatement((ContinueStatement&) s);
1173 break;
1174 case Statement::kDiscard_Kind:
1175 // not yet implemented
1176 abort();
1177 case Statement::kDo_Kind:
1178 this->writeDoStatement((DoStatement&) s);
1179 break;
Brian Osman3e29f1d2019-05-28 09:35:05 -04001180 case Statement::kExpression_Kind:
1181 this->writeExpression(*((ExpressionStatement&) s).fExpression, true);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001182 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001183 case Statement::kFor_Kind:
1184 this->writeForStatement((ForStatement&) s);
1185 break;
1186 case Statement::kIf_Kind:
1187 this->writeIfStatement((IfStatement&) s);
1188 break;
1189 case Statement::kNop_Kind:
1190 break;
1191 case Statement::kReturn_Kind:
1192 this->writeReturnStatement((ReturnStatement&) s);
1193 break;
1194 case Statement::kSwitch_Kind:
1195 this->writeSwitchStatement((SwitchStatement&) s);
1196 break;
1197 case Statement::kVarDeclarations_Kind:
1198 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1199 break;
1200 case Statement::kWhile_Kind:
1201 this->writeWhileStatement((WhileStatement&) s);
1202 break;
1203 default:
1204 SkASSERT(false);
1205 }
1206}
1207
Brian Osman80164412019-06-07 13:00:23 -04001208ByteCodeFunction::ByteCodeFunction(const FunctionDeclaration* declaration)
1209 : fName(declaration->fName) {
1210 fParameterCount = 0;
1211 for (const auto& p : declaration->fParameters) {
1212 int slots = ByteCodeGenerator::SlotCount(p->fType);
1213 fParameters.push_back({ slots, (bool)(p->fModifiers.fFlags & Modifiers::kOut_Flag) });
1214 fParameterCount += slots;
1215 }
1216}
1217
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001218}