blob: 4a71b0daec68df7e98134e099d0903ddd9a9dcf3 [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) {
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400640 for (const auto& arg : f.fArguments) {
641 this->writeExpression(*arg);
642 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400643 if (f.fFunction.fBuiltin) {
644 this->writeIntrinsicCall(f);
645 return;
646 }
Brian Osman226668a2019-05-14 16:47:30 -0400647 this->write(ByteCodeInstruction::kCall);
648 fCallTargets.emplace_back(this, f.fFunction);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400649}
650
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400651void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
652 this->write(ByteCodeInstruction::kPushImmediate);
653 this->write32(i.fValue);
654}
655
656void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
657 // not yet implemented
658 abort();
659}
660
Brian Osman3e29f1d2019-05-28 09:35:05 -0400661bool ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p, bool discard) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400662 switch (p.fOperator) {
663 case Token::Kind::PLUSPLUS: // fall through
664 case Token::Kind::MINUSMINUS: {
Brian Osman07c117b2019-05-23 12:51:06 -0700665 SkASSERT(SlotCount(p.fOperand->fType) == 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400666 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
667 lvalue->load();
668 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmand30e0392019-06-14 14:05:14 -0400669 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400670 if (p.fOperator == Token::Kind::PLUSPLUS) {
671 this->writeTypedInstruction(p.fType,
672 ByteCodeInstruction::kAddI,
673 ByteCodeInstruction::kAddI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400674 ByteCodeInstruction::kAddF,
675 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400676 } else {
677 this->writeTypedInstruction(p.fType,
678 ByteCodeInstruction::kSubtractI,
679 ByteCodeInstruction::kSubtractI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400680 ByteCodeInstruction::kSubtractF,
681 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400682 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400683 lvalue->store(discard);
684 discard = false;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400685 break;
686 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400687 case Token::Kind::MINUS: {
688 this->writeExpression(*p.fOperand);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400689 this->writeTypedInstruction(p.fType,
Mike Klein12710912019-05-21 11:04:59 -0500690 ByteCodeInstruction::kNegateI,
691 ByteCodeInstruction::kNegateI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400692 ByteCodeInstruction::kNegateF,
Brian Osman07c117b2019-05-23 12:51:06 -0700693 SlotCount(p.fOperand->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400694 break;
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400695 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400696 default:
697 SkASSERT(false);
698 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400699 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400700}
701
Brian Osman3e29f1d2019-05-28 09:35:05 -0400702bool ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p, bool discard) {
Brian Osmanf3fa6002019-05-17 14:26:53 -0400703 switch (p.fOperator) {
704 case Token::Kind::PLUSPLUS: // fall through
705 case Token::Kind::MINUSMINUS: {
Brian Osman07c117b2019-05-23 12:51:06 -0700706 SkASSERT(SlotCount(p.fOperand->fType) == 1);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400707 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
708 lvalue->load();
Brian Osman3e29f1d2019-05-28 09:35:05 -0400709 if (!discard) {
710 this->write(ByteCodeInstruction::kDup);
711 }
Brian Osmanf3fa6002019-05-17 14:26:53 -0400712 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmand30e0392019-06-14 14:05:14 -0400713 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400714 if (p.fOperator == Token::Kind::PLUSPLUS) {
715 this->writeTypedInstruction(p.fType,
716 ByteCodeInstruction::kAddI,
717 ByteCodeInstruction::kAddI,
718 ByteCodeInstruction::kAddF,
719 1);
720 } else {
721 this->writeTypedInstruction(p.fType,
722 ByteCodeInstruction::kSubtractI,
723 ByteCodeInstruction::kSubtractI,
724 ByteCodeInstruction::kSubtractF,
725 1);
726 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400727 lvalue->store(discard);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400728 this->write(ByteCodeInstruction::kPop);
Brian Osman3e29f1d2019-05-28 09:35:05 -0400729 discard = false;
Brian Osmanf3fa6002019-05-17 14:26:53 -0400730 break;
731 }
732 default:
733 SkASSERT(false);
734 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400735 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400736}
737
738void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
Brian Osman0785db02019-05-24 14:19:11 -0400739 if (swizzle_is_simple(s)) {
740 this->writeVariableExpression(s);
741 return;
742 }
743
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400744 switch (s.fBase->fKind) {
745 case Expression::kVariableReference_Kind: {
746 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
Brian Osman1091f022019-05-16 09:42:16 -0400747 this->write(var.fStorage == Variable::kGlobal_Storage
748 ? ByteCodeInstruction::kLoadSwizzleGlobal
749 : ByteCodeInstruction::kLoadSwizzle);
750 this->write8(this->getLocation(var));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400751 this->write8(s.fComponents.size());
752 for (int c : s.fComponents) {
753 this->write8(c);
754 }
755 break;
756 }
757 default:
758 this->writeExpression(*s.fBase);
759 this->write(ByteCodeInstruction::kSwizzle);
760 this->write8(s.fBase->fType.columns());
761 this->write8(s.fComponents.size());
762 for (int c : s.fComponents) {
763 this->write8(c);
764 }
765 }
766}
767
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400768void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Brian Osman4e93feb2019-05-16 15:38:00 -0400769 this->writeExpression(*t.fTest);
Brian Osman569f12f2019-06-13 11:23:57 -0400770 this->write(ByteCodeInstruction::kMaskPush);
Brian Osman4e93feb2019-05-16 15:38:00 -0400771 this->writeExpression(*t.fIfTrue);
Brian Osman569f12f2019-06-13 11:23:57 -0400772 this->write(ByteCodeInstruction::kMaskNegate);
773 this->writeExpression(*t.fIfFalse);
774 this->write(ByteCodeInstruction::kMaskBlend);
775 this->write8(SlotCount(t.fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400776}
777
Brian Osman3e29f1d2019-05-28 09:35:05 -0400778void ByteCodeGenerator::writeExpression(const Expression& e, bool discard) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400779 switch (e.fKind) {
780 case Expression::kBinary_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400781 discard = this->writeBinaryExpression((BinaryExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400782 break;
783 case Expression::kBoolLiteral_Kind:
784 this->writeBoolLiteral((BoolLiteral&) e);
785 break;
786 case Expression::kConstructor_Kind:
787 this->writeConstructor((Constructor&) e);
788 break;
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400789 case Expression::kExternalFunctionCall_Kind:
790 this->writeExternalFunctionCall((ExternalFunctionCall&) e);
791 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400792 case Expression::kExternalValue_Kind:
793 this->writeExternalValue((ExternalValueReference&) e);
794 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400795 case Expression::kFieldAccess_Kind:
Brian Osman07c117b2019-05-23 12:51:06 -0700796 case Expression::kIndex_Kind:
797 case Expression::kVariableReference_Kind:
798 this->writeVariableExpression(e);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400799 break;
800 case Expression::kFloatLiteral_Kind:
801 this->writeFloatLiteral((FloatLiteral&) e);
802 break;
803 case Expression::kFunctionCall_Kind:
804 this->writeFunctionCall((FunctionCall&) e);
805 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400806 case Expression::kIntLiteral_Kind:
807 this->writeIntLiteral((IntLiteral&) e);
808 break;
809 case Expression::kNullLiteral_Kind:
810 this->writeNullLiteral((NullLiteral&) e);
811 break;
812 case Expression::kPrefix_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400813 discard = this->writePrefixExpression((PrefixExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400814 break;
815 case Expression::kPostfix_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400816 discard = this->writePostfixExpression((PostfixExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400817 break;
818 case Expression::kSwizzle_Kind:
819 this->writeSwizzle((Swizzle&) e);
820 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400821 case Expression::kTernary_Kind:
822 this->writeTernaryExpression((TernaryExpression&) e);
823 break;
824 default:
825 printf("unsupported expression %s\n", e.description().c_str());
826 SkASSERT(false);
827 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400828 if (discard) {
829 int count = SlotCount(e.fType);
830 if (count > 4) {
831 this->write(ByteCodeInstruction::kPopN);
832 this->write8(count);
Brian Osmanfba386b2019-06-20 14:54:15 -0400833 } else if (count != 0) {
Brian Osman3e29f1d2019-05-28 09:35:05 -0400834 this->write(vector_instruction(ByteCodeInstruction::kPop, count));
835 }
836 discard = false;
837 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400838}
839
Ethan Nicholas91164d12019-05-15 15:29:54 -0400840class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
841public:
842 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
843 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700844 , fCount(ByteCodeGenerator::SlotCount(value.type()))
Ethan Nicholas91164d12019-05-15 15:29:54 -0400845 , fIndex(index) {}
846
847 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400848 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400849 fGenerator.write8(fIndex);
850 }
851
Brian Osman3e29f1d2019-05-28 09:35:05 -0400852 void store(bool discard) override {
853 if (!discard) {
854 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
855 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400856 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400857 fGenerator.write8(fIndex);
858 }
859
860private:
861 typedef LValue INHERITED;
862
863 int fCount;
864
865 int fIndex;
866};
867
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400868class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
869public:
870 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
871 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700872 , fSwizzle(swizzle) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400873
874 void load() override {
Brian Osman1091f022019-05-16 09:42:16 -0400875 fGenerator.writeSwizzle(fSwizzle);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400876 }
877
Brian Osman3e29f1d2019-05-28 09:35:05 -0400878 void store(bool discard) override {
879 if (!discard) {
880 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup,
881 fSwizzle.fComponents.size()));
882 }
Brian Osman07c117b2019-05-23 12:51:06 -0700883 Variable::Storage storage;
884 int location = fGenerator.getLocation(*fSwizzle.fBase, &storage);
885 bool isGlobal = storage == Variable::kGlobal_Storage;
886 if (location < 0) {
887 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleIndirectGlobal
888 : ByteCodeInstruction::kStoreSwizzleIndirect);
889 } else {
890 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleGlobal
891 : ByteCodeInstruction::kStoreSwizzle);
892 fGenerator.write8(location);
893 }
Brian Osman1091f022019-05-16 09:42:16 -0400894 fGenerator.write8(fSwizzle.fComponents.size());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400895 for (int c : fSwizzle.fComponents) {
896 fGenerator.write8(c);
897 }
898 }
899
900private:
901 const Swizzle& fSwizzle;
902
903 typedef LValue INHERITED;
904};
905
Brian Osman07c117b2019-05-23 12:51:06 -0700906class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400907public:
Brian Osman07c117b2019-05-23 12:51:06 -0700908 ByteCodeExpressionLValue(ByteCodeGenerator* generator, const Expression& expr)
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400909 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700910 , fExpression(expr) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400911
912 void load() override {
Brian Osman07c117b2019-05-23 12:51:06 -0700913 fGenerator.writeVariableExpression(fExpression);
Brian Osman1091f022019-05-16 09:42:16 -0400914 }
915
Brian Osman3e29f1d2019-05-28 09:35:05 -0400916 void store(bool discard) override {
Brian Osman07c117b2019-05-23 12:51:06 -0700917 int count = ByteCodeGenerator::SlotCount(fExpression.fType);
Brian Osman3e29f1d2019-05-28 09:35:05 -0400918 if (!discard) {
919 if (count > 4) {
920 fGenerator.write(ByteCodeInstruction::kDupN);
921 fGenerator.write8(count);
922 } else {
923 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
924 }
Brian Osman07c117b2019-05-23 12:51:06 -0700925 }
926 Variable::Storage storage;
927 int location = fGenerator.getLocation(fExpression, &storage);
928 bool isGlobal = storage == Variable::kGlobal_Storage;
929 if (location < 0 || count > 4) {
930 if (location >= 0) {
931 fGenerator.write(ByteCodeInstruction::kPushImmediate);
932 fGenerator.write32(location);
933 }
934 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreExtendedGlobal
935 : ByteCodeInstruction::kStoreExtended);
936 fGenerator.write8(count);
937 } else {
938 fGenerator.write(vector_instruction(isGlobal ? ByteCodeInstruction::kStoreGlobal
939 : ByteCodeInstruction::kStore,
940 count));
941 fGenerator.write8(location);
942 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400943 }
944
945private:
946 typedef LValue INHERITED;
947
Brian Osman07c117b2019-05-23 12:51:06 -0700948 const Expression& fExpression;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400949};
950
951std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
952 switch (e.fKind) {
Ethan Nicholas91164d12019-05-15 15:29:54 -0400953 case Expression::kExternalValue_Kind: {
954 ExternalValue* value = ((ExternalValueReference&) e).fValue;
955 int index = fOutput->fExternalValues.size();
956 fOutput->fExternalValues.push_back(value);
957 SkASSERT(index <= 255);
958 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
959 }
Brian Osman07c117b2019-05-23 12:51:06 -0700960 case Expression::kFieldAccess_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400961 case Expression::kIndex_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400962 case Expression::kVariableReference_Kind:
Brian Osman07c117b2019-05-23 12:51:06 -0700963 return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
Brian Osman0785db02019-05-24 14:19:11 -0400964 case Expression::kSwizzle_Kind: {
965 const Swizzle& s = (const Swizzle&) e;
966 return swizzle_is_simple(s)
967 ? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e))
968 : std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s));
969 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400970 case Expression::kTernary_Kind:
971 default:
972 printf("unsupported lvalue %s\n", e.description().c_str());
973 return nullptr;
974 }
975}
976
977void ByteCodeGenerator::writeBlock(const Block& b) {
978 for (const auto& s : b.fStatements) {
979 this->writeStatement(*s);
980 }
981}
982
983void ByteCodeGenerator::setBreakTargets() {
984 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
985 for (DeferredLocation& b : breaks) {
986 b.set();
987 }
988 fBreakTargets.pop();
989}
990
991void ByteCodeGenerator::setContinueTargets() {
992 std::vector<DeferredLocation>& continues = fContinueTargets.top();
993 for (DeferredLocation& c : continues) {
994 c.set();
995 }
996 fContinueTargets.pop();
997}
998
999void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
Brian Osman569f12f2019-06-13 11:23:57 -04001000 // TODO: Include BranchIfAllFalse to top-most LoopNext
1001 this->write(ByteCodeInstruction::kLoopBreak);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001002}
1003
1004void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
Brian Osman569f12f2019-06-13 11:23:57 -04001005 // TODO: Include BranchIfAllFalse to top-most LoopNext
1006 this->write(ByteCodeInstruction::kLoopContinue);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001007}
1008
1009void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
Brian Osman569f12f2019-06-13 11:23:57 -04001010 this->write(ByteCodeInstruction::kLoopBegin);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001011 size_t start = fCode->size();
1012 this->writeStatement(*d.fStatement);
Brian Osman569f12f2019-06-13 11:23:57 -04001013 this->write(ByteCodeInstruction::kLoopNext);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001014 this->writeExpression(*d.fTest);
Brian Osman569f12f2019-06-13 11:23:57 -04001015 this->write(ByteCodeInstruction::kLoopMask);
1016 // TODO: Could shorten this with kBranchIfAnyTrue
1017 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1018 DeferredLocation endLocation(this);
1019 this->write(ByteCodeInstruction::kBranch);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001020 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001021 endLocation.set();
1022 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001023}
1024
1025void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
1026 fContinueTargets.emplace();
1027 fBreakTargets.emplace();
1028 if (f.fInitializer) {
1029 this->writeStatement(*f.fInitializer);
1030 }
Brian Osman569f12f2019-06-13 11:23:57 -04001031 this->write(ByteCodeInstruction::kLoopBegin);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001032 size_t start = fCode->size();
1033 if (f.fTest) {
1034 this->writeExpression(*f.fTest);
Brian Osman569f12f2019-06-13 11:23:57 -04001035 this->write(ByteCodeInstruction::kLoopMask);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001036 }
Brian Osman569f12f2019-06-13 11:23:57 -04001037 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1038 DeferredLocation endLocation(this);
1039 this->writeStatement(*f.fStatement);
1040 this->write(ByteCodeInstruction::kLoopNext);
1041 if (f.fNext) {
1042 this->writeExpression(*f.fNext, true);
1043 }
1044 this->write(ByteCodeInstruction::kBranch);
1045 this->write16(start);
1046 endLocation.set();
1047 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001048}
1049
1050void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Brian Osman569f12f2019-06-13 11:23:57 -04001051 this->writeExpression(*i.fTest);
1052 this->write(ByteCodeInstruction::kMaskPush);
1053 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1054 DeferredLocation falseLocation(this);
1055 this->writeStatement(*i.fIfTrue);
1056 falseLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001057 if (i.fIfFalse) {
Brian Osman569f12f2019-06-13 11:23:57 -04001058 this->write(ByteCodeInstruction::kMaskNegate);
1059 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1060 DeferredLocation endLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001061 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -05001062 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001063 }
Brian Osman569f12f2019-06-13 11:23:57 -04001064 this->write(ByteCodeInstruction::kMaskPop);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001065}
1066
1067void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -04001068 this->writeExpression(*r.fExpression);
1069 this->write(ByteCodeInstruction::kReturn);
Brian Osman07c117b2019-05-23 12:51:06 -07001070 this->write8(SlotCount(r.fExpression->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001071}
1072
1073void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
1074 // not yet implemented
1075 abort();
1076}
1077
1078void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1079 for (const auto& declStatement : v.fVars) {
1080 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
1081 // we need to grab the location even if we don't use it, to ensure it
1082 // has been allocated
1083 int location = getLocation(*decl.fVar);
1084 if (decl.fValue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001085 this->writeExpression(*decl.fValue);
Brian Osman07c117b2019-05-23 12:51:06 -07001086 int count = SlotCount(decl.fValue->fType);
1087 if (count > 4) {
1088 this->write(ByteCodeInstruction::kPushImmediate);
1089 this->write32(location);
1090 this->write(ByteCodeInstruction::kStoreExtended);
1091 this->write8(count);
1092 } else {
1093 this->write(vector_instruction(ByteCodeInstruction::kStore, count));
1094 this->write8(location);
1095 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001096 }
1097 }
1098}
1099
1100void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
Brian Osman569f12f2019-06-13 11:23:57 -04001101 this->write(ByteCodeInstruction::kLoopBegin);
1102 size_t cond = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001103 this->writeExpression(*w.fTest);
Brian Osman569f12f2019-06-13 11:23:57 -04001104 this->write(ByteCodeInstruction::kLoopMask);
1105 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001106 DeferredLocation endLocation(this);
1107 this->writeStatement(*w.fStatement);
Brian Osman569f12f2019-06-13 11:23:57 -04001108 this->write(ByteCodeInstruction::kLoopNext);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001109 this->write(ByteCodeInstruction::kBranch);
Brian Osman569f12f2019-06-13 11:23:57 -04001110 this->write16(cond);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001111 endLocation.set();
Brian Osman569f12f2019-06-13 11:23:57 -04001112 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001113}
1114
1115void ByteCodeGenerator::writeStatement(const Statement& s) {
1116 switch (s.fKind) {
1117 case Statement::kBlock_Kind:
1118 this->writeBlock((Block&) s);
1119 break;
1120 case Statement::kBreak_Kind:
1121 this->writeBreakStatement((BreakStatement&) s);
1122 break;
1123 case Statement::kContinue_Kind:
1124 this->writeContinueStatement((ContinueStatement&) s);
1125 break;
1126 case Statement::kDiscard_Kind:
1127 // not yet implemented
1128 abort();
1129 case Statement::kDo_Kind:
1130 this->writeDoStatement((DoStatement&) s);
1131 break;
Brian Osman3e29f1d2019-05-28 09:35:05 -04001132 case Statement::kExpression_Kind:
1133 this->writeExpression(*((ExpressionStatement&) s).fExpression, true);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001134 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001135 case Statement::kFor_Kind:
1136 this->writeForStatement((ForStatement&) s);
1137 break;
1138 case Statement::kIf_Kind:
1139 this->writeIfStatement((IfStatement&) s);
1140 break;
1141 case Statement::kNop_Kind:
1142 break;
1143 case Statement::kReturn_Kind:
1144 this->writeReturnStatement((ReturnStatement&) s);
1145 break;
1146 case Statement::kSwitch_Kind:
1147 this->writeSwitchStatement((SwitchStatement&) s);
1148 break;
1149 case Statement::kVarDeclarations_Kind:
1150 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1151 break;
1152 case Statement::kWhile_Kind:
1153 this->writeWhileStatement((WhileStatement&) s);
1154 break;
1155 default:
1156 SkASSERT(false);
1157 }
1158}
1159
Brian Osman80164412019-06-07 13:00:23 -04001160ByteCodeFunction::ByteCodeFunction(const FunctionDeclaration* declaration)
1161 : fName(declaration->fName) {
1162 fParameterCount = 0;
1163 for (const auto& p : declaration->fParameters) {
1164 int slots = ByteCodeGenerator::SlotCount(p->fType);
1165 fParameters.push_back({ slots, (bool)(p->fModifiers.fFlags & Modifiers::kOut_Flag) });
1166 fParameterCount += slots;
1167 }
1168}
1169
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001170}