blob: 56a3384e36fcf4959e890e13d3cd1b346dd564ea [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"
Brian Osmanf3fa6002019-05-17 14:26:53 -04009#include "src/sksl/SkSLInterpreter.h"
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040010
Brian Osman95253bd2019-06-05 10:28:45 -040011#include <algorithm>
12
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040013namespace SkSL {
14
Ethan Nicholas82162ee2019-05-21 16:05:08 -040015ByteCodeGenerator::ByteCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
16 ByteCode* output)
17 : INHERITED(program, errors, nullptr)
18 , fContext(*context)
Ethan Nicholasae9633b2019-05-24 12:46:34 -040019 , fOutput(output)
20 , fIntrinsics {
21 { "cos", ByteCodeInstruction::kCos },
22 { "cross", ByteCodeInstruction::kCross },
23 { "dot", SpecialIntrinsic::kDot },
24 { "sin", ByteCodeInstruction::kSin },
25 { "sqrt", ByteCodeInstruction::kSqrt },
26 { "tan", ByteCodeInstruction::kTan },
27 { "mix", ByteCodeInstruction::kMix },
28 } {}
29
Ethan Nicholas82162ee2019-05-21 16:05:08 -040030
Brian Osman07c117b2019-05-23 12:51:06 -070031int ByteCodeGenerator::SlotCount(const Type& type) {
32 if (type.kind() == Type::kStruct_Kind) {
33 int slots = 0;
34 for (const auto& f : type.fields()) {
35 slots += SlotCount(*f.fType);
36 }
37 SkASSERT(slots <= 255);
38 return slots;
39 } else if (type.kind() == Type::kArray_Kind) {
40 int columns = type.columns();
41 SkASSERT(columns >= 0);
42 int slots = columns * SlotCount(type.componentType());
43 SkASSERT(slots <= 255);
44 return slots;
45 } else {
46 return type.columns() * type.rows();
47 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040048}
49
50bool ByteCodeGenerator::generateCode() {
51 for (const auto& e : fProgram) {
52 switch (e.fKind) {
53 case ProgramElement::kFunction_Kind: {
54 std::unique_ptr<ByteCodeFunction> f = this->writeFunction((FunctionDefinition&) e);
55 if (!f) {
56 return false;
57 }
58 fOutput->fFunctions.push_back(std::move(f));
Brian Osman80164412019-06-07 13:00:23 -040059 fFunctions.push_back(&(FunctionDefinition&)e);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040060 break;
61 }
62 case ProgramElement::kVar_Kind: {
63 VarDeclarations& decl = (VarDeclarations&) e;
64 for (const auto& v : decl.fVars) {
65 const Variable* declVar = ((VarDeclaration&) *v).fVar;
66 if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
67 continue;
68 }
69 if (declVar->fModifiers.fFlags & Modifiers::kIn_Flag) {
Brian Osman07c117b2019-05-23 12:51:06 -070070 for (int i = SlotCount(declVar->fType); i > 0; --i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040071 fOutput->fInputSlots.push_back(fOutput->fGlobalCount++);
72 }
73 } else {
Brian Osman07c117b2019-05-23 12:51:06 -070074 fOutput->fGlobalCount += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040075 }
76 }
77 break;
78 }
79 default:
80 ; // ignore
81 }
82 }
Brian Osman226668a2019-05-14 16:47:30 -040083 for (auto& call : fCallTargets) {
84 if (!call.set()) {
85 return false;
86 }
87 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040088 return true;
89}
90
91std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
92 fFunction = &f;
Brian Osman226668a2019-05-14 16:47:30 -040093 std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
Brian Osman80164412019-06-07 13:00:23 -040094 fParameterCount = result->fParameterCount;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040095 fCode = &result->fCode;
96 this->writeStatement(*f.fBody);
Ethan Nicholas7e603db2019-05-03 12:57:47 -040097 this->write(ByteCodeInstruction::kReturn);
98 this->write8(0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040099 result->fLocalCount = fLocals.size();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400100 const Type& returnType = f.fDeclaration.fReturnType;
101 if (returnType != *fContext.fVoid_Type) {
Brian Osman07c117b2019-05-23 12:51:06 -0700102 result->fReturnCount = SlotCount(returnType);
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400103 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400104 fLocals.clear();
105 fFunction = nullptr;
106 return result;
107}
108
109enum class TypeCategory {
110 kBool,
111 kSigned,
112 kUnsigned,
113 kFloat,
114};
115
116static TypeCategory type_category(const Type& type) {
117 switch (type.kind()) {
118 case Type::Kind::kVector_Kind:
119 case Type::Kind::kMatrix_Kind:
120 return type_category(type.componentType());
121 default:
122 if (type.fName == "bool") {
123 return TypeCategory::kBool;
124 } else if (type.fName == "int" || type.fName == "short") {
125 return TypeCategory::kSigned;
126 } else if (type.fName == "uint" || type.fName == "ushort") {
127 return TypeCategory::kUnsigned;
128 } else {
129 SkASSERT(type.fName == "float" || type.fName == "half");
130 return TypeCategory::kFloat;
131 }
132 ABORT("unsupported type: %s\n", type.description().c_str());
133 }
134}
135
Brian Osman0785db02019-05-24 14:19:11 -0400136// A "simple" Swizzle is based on a variable (or a compound variable like a struct or array), and
137// that references consecutive values, such that it can be implemented using normal load/store ops
138// with an offset. Note that all single-component swizzles (of suitable base types) are simple.
139static bool swizzle_is_simple(const Swizzle& s) {
140 switch (s.fBase->fKind) {
141 case Expression::kFieldAccess_Kind:
142 case Expression::kIndex_Kind:
143 case Expression::kVariableReference_Kind:
144 break;
145 default:
146 return false;
147 }
148
149 for (size_t i = 1; i < s.fComponents.size(); ++i) {
150 if (s.fComponents[i] != s.fComponents[i - 1] + 1) {
151 return false;
152 }
153 }
154 return true;
155}
156
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400157int ByteCodeGenerator::getLocation(const Variable& var) {
158 // given that we seldom have more than a couple of variables, linear search is probably the most
159 // efficient way to handle lookups
160 switch (var.fStorage) {
161 case Variable::kLocal_Storage: {
162 for (int i = fLocals.size() - 1; i >= 0; --i) {
163 if (fLocals[i] == &var) {
Brian Osman1091f022019-05-16 09:42:16 -0400164 SkASSERT(fParameterCount + i <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400165 return fParameterCount + i;
166 }
167 }
168 int result = fParameterCount + fLocals.size();
169 fLocals.push_back(&var);
Brian Osman07c117b2019-05-23 12:51:06 -0700170 for (int i = 0; i < SlotCount(var.fType) - 1; ++i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400171 fLocals.push_back(nullptr);
172 }
Brian Osman1091f022019-05-16 09:42:16 -0400173 SkASSERT(result <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400174 return result;
175 }
176 case Variable::kParameter_Storage: {
177 int offset = 0;
178 for (const auto& p : fFunction->fDeclaration.fParameters) {
179 if (p == &var) {
Brian Osman1091f022019-05-16 09:42:16 -0400180 SkASSERT(offset <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400181 return offset;
182 }
Brian Osman07c117b2019-05-23 12:51:06 -0700183 offset += SlotCount(p->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400184 }
185 SkASSERT(false);
Brian Osman1091f022019-05-16 09:42:16 -0400186 return 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400187 }
188 case Variable::kGlobal_Storage: {
189 int offset = 0;
190 for (const auto& e : fProgram) {
191 if (e.fKind == ProgramElement::kVar_Kind) {
192 VarDeclarations& decl = (VarDeclarations&) e;
193 for (const auto& v : decl.fVars) {
194 const Variable* declVar = ((VarDeclaration&) *v).fVar;
195 if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
196 continue;
197 }
198 if (declVar == &var) {
Brian Osmanb7451292019-05-15 13:02:13 -0400199 SkASSERT(offset <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400200 return offset;
201 }
Brian Osman07c117b2019-05-23 12:51:06 -0700202 offset += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400203 }
204 }
205 }
206 SkASSERT(false);
Brian Osman1091f022019-05-16 09:42:16 -0400207 return 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400208 }
209 default:
210 SkASSERT(false);
211 return 0;
212 }
213}
214
Brian Osman0785db02019-05-24 14:19:11 -0400215// TODO: Elide Add 0 and Mul 1 sequences
Brian Osman07c117b2019-05-23 12:51:06 -0700216int ByteCodeGenerator::getLocation(const Expression& expr, Variable::Storage* storage) {
217 switch (expr.fKind) {
218 case Expression::kFieldAccess_Kind: {
219 const FieldAccess& f = (const FieldAccess&)expr;
220 int baseAddr = this->getLocation(*f.fBase, storage);
221 int offset = 0;
222 for (int i = 0; i < f.fFieldIndex; ++i) {
223 offset += SlotCount(*f.fBase->fType.fields()[i].fType);
224 }
225 if (baseAddr < 0) {
226 this->write(ByteCodeInstruction::kPushImmediate);
227 this->write32(offset);
228 this->write(ByteCodeInstruction::kAddI);
229 return -1;
230 } else {
231 return baseAddr + offset;
232 }
233 }
234 case Expression::kIndex_Kind: {
235 const IndexExpression& i = (const IndexExpression&)expr;
236 int stride = SlotCount(i.fType);
237 int offset = -1;
238 if (i.fIndex->isConstant()) {
239 offset = i.fIndex->getConstantInt() * stride;
240 } else {
241 this->writeExpression(*i.fIndex);
242 this->write(ByteCodeInstruction::kPushImmediate);
243 this->write32(stride);
244 this->write(ByteCodeInstruction::kMultiplyI);
245 }
246 int baseAddr = this->getLocation(*i.fBase, storage);
247 if (baseAddr >= 0 && offset >= 0) {
248 return baseAddr + offset;
249 }
250 if (baseAddr >= 0) {
251 this->write(ByteCodeInstruction::kPushImmediate);
252 this->write32(baseAddr);
253 }
254 if (offset >= 0) {
255 this->write(ByteCodeInstruction::kPushImmediate);
256 this->write32(offset);
257 }
258 this->write(ByteCodeInstruction::kAddI);
259 return -1;
260 }
Brian Osman0785db02019-05-24 14:19:11 -0400261 case Expression::kSwizzle_Kind: {
262 const Swizzle& s = (const Swizzle&)expr;
263 SkASSERT(swizzle_is_simple(s));
264 int baseAddr = this->getLocation(*s.fBase, storage);
265 int offset = s.fComponents[0];
266 if (baseAddr < 0) {
267 this->write(ByteCodeInstruction::kPushImmediate);
268 this->write32(offset);
269 this->write(ByteCodeInstruction::kAddI);
270 return -1;
271 } else {
272 return baseAddr + offset;
273 }
274 }
Brian Osman07c117b2019-05-23 12:51:06 -0700275 case Expression::kVariableReference_Kind: {
276 const Variable& var = ((const VariableReference&)expr).fVariable;
277 *storage = var.fStorage;
278 return this->getLocation(var);
279 }
280 default:
281 SkASSERT(false);
282 return 0;
283 }
284}
285
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400286void ByteCodeGenerator::write8(uint8_t b) {
287 fCode->push_back(b);
288}
289
290void ByteCodeGenerator::write16(uint16_t i) {
Mike Klein76346ac2019-05-17 11:57:10 -0500291 size_t n = fCode->size();
292 fCode->resize(n+2);
293 memcpy(fCode->data() + n, &i, 2);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400294}
295
296void ByteCodeGenerator::write32(uint32_t i) {
Mike Klein76346ac2019-05-17 11:57:10 -0500297 size_t n = fCode->size();
298 fCode->resize(n+4);
299 memcpy(fCode->data() + n, &i, 4);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400300}
301
302void ByteCodeGenerator::write(ByteCodeInstruction i) {
Mike Klein108e9352019-05-21 11:05:17 -0500303 this->write16((uint16_t)i);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400304}
305
Mike Klein76346ac2019-05-17 11:57:10 -0500306static ByteCodeInstruction vector_instruction(ByteCodeInstruction base, int count) {
Brian Osman07c117b2019-05-23 12:51:06 -0700307 SkASSERT(count >= 1 && count <= 4);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400308 return ((ByteCodeInstruction) ((int) base + count - 1));
309}
310
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400311void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400312 ByteCodeInstruction u, ByteCodeInstruction f,
313 int count) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400314 switch (type_category(type)) {
315 case TypeCategory::kSigned:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400316 this->write(vector_instruction(s, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400317 break;
318 case TypeCategory::kUnsigned:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400319 this->write(vector_instruction(u, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400320 break;
Brian Osman1e855b22019-05-29 15:21:52 -0400321 case TypeCategory::kFloat: {
322 if (count > 4) {
323 this->write((ByteCodeInstruction)((int)f + 4));
324 this->write8(count);
325 } else {
326 this->write(vector_instruction(f, count));
327 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400328 break;
Brian Osman1e855b22019-05-29 15:21:52 -0400329 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400330 default:
331 SkASSERT(false);
332 }
333}
334
Brian Osman3e29f1d2019-05-28 09:35:05 -0400335bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool discard) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400336 if (b.fOperator == Token::Kind::EQ) {
337 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
338 this->writeExpression(*b.fRight);
Brian Osman3e29f1d2019-05-28 09:35:05 -0400339 lvalue->store(discard);
340 discard = false;
341 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400342 }
Brian Osman16e6fd52019-05-29 11:19:00 -0400343 const Type& lType = b.fLeft->fType;
344 const Type& rType = b.fRight->fType;
Brian Osman909231c2019-05-29 15:34:36 -0400345 bool lVecOrMtx = (lType.kind() == Type::kVector_Kind || lType.kind() == Type::kMatrix_Kind);
346 bool rVecOrMtx = (rType.kind() == Type::kVector_Kind || rType.kind() == Type::kMatrix_Kind);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400347 Token::Kind op;
348 std::unique_ptr<LValue> lvalue;
349 if (is_assignment(b.fOperator)) {
350 lvalue = this->getLValue(*b.fLeft);
351 lvalue->load();
352 op = remove_assignment(b.fOperator);
353 } else {
354 this->writeExpression(*b.fLeft);
355 op = b.fOperator;
Brian Osman909231c2019-05-29 15:34:36 -0400356 if (!lVecOrMtx && rVecOrMtx) {
Brian Osman16e6fd52019-05-29 11:19:00 -0400357 for (int i = SlotCount(rType); i > 1; --i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400358 this->write(ByteCodeInstruction::kDup);
359 }
360 }
361 }
362 this->writeExpression(*b.fRight);
Brian Osman909231c2019-05-29 15:34:36 -0400363 if (lVecOrMtx && !rVecOrMtx) {
Brian Osman16e6fd52019-05-29 11:19:00 -0400364 for (int i = SlotCount(lType); i > 1; --i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400365 this->write(ByteCodeInstruction::kDup);
366 }
367 }
Brian Osman909231c2019-05-29 15:34:36 -0400368 // Special case for M*V, V*M, M*M (but not V*V!)
369 if (op == Token::Kind::STAR && lVecOrMtx && rVecOrMtx &&
370 !(lType.kind() == Type::kVector_Kind && rType.kind() == Type::kVector_Kind)) {
371 this->write(ByteCodeInstruction::kMatrixMultiply);
372 int rCols = rType.columns(),
373 rRows = rType.rows(),
374 lCols = lType.columns(),
375 lRows = lType.rows();
376 // M*V treats the vector as a column
377 if (rType.kind() == Type::kVector_Kind) {
378 std::swap(rCols, rRows);
379 }
380 SkASSERT(lCols == rRows);
381 SkASSERT(SlotCount(b.fType) == lRows * rCols);
382 this->write8(lCols);
383 this->write8(lRows);
384 this->write8(rCols);
385 } else {
386 int count = std::max(SlotCount(lType), SlotCount(rType));
387 switch (op) {
388 case Token::Kind::EQEQ:
389 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareIEQ,
390 ByteCodeInstruction::kCompareIEQ,
391 ByteCodeInstruction::kCompareFEQ,
392 count);
393 // Collapse to a single bool
394 for (int i = count; i > 1; --i) {
395 this->write(ByteCodeInstruction::kAndB);
396 }
397 break;
398 case Token::Kind::GT:
399 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGT,
400 ByteCodeInstruction::kCompareUGT,
401 ByteCodeInstruction::kCompareFGT,
402 count);
403 break;
404 case Token::Kind::GTEQ:
405 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGTEQ,
406 ByteCodeInstruction::kCompareUGTEQ,
407 ByteCodeInstruction::kCompareFGTEQ,
408 count);
409 break;
410 case Token::Kind::LT:
411 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLT,
412 ByteCodeInstruction::kCompareULT,
413 ByteCodeInstruction::kCompareFLT,
414 count);
415 break;
416 case Token::Kind::LTEQ:
417 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLTEQ,
418 ByteCodeInstruction::kCompareULTEQ,
419 ByteCodeInstruction::kCompareFLTEQ,
420 count);
421 break;
422 case Token::Kind::MINUS:
423 this->writeTypedInstruction(lType, ByteCodeInstruction::kSubtractI,
424 ByteCodeInstruction::kSubtractI,
425 ByteCodeInstruction::kSubtractF,
426 count);
427 break;
428 case Token::Kind::NEQ:
429 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareINEQ,
430 ByteCodeInstruction::kCompareINEQ,
431 ByteCodeInstruction::kCompareFNEQ,
432 count);
433 // Collapse to a single bool
434 for (int i = count; i > 1; --i) {
435 this->write(ByteCodeInstruction::kOrB);
436 }
437 break;
438 case Token::Kind::PERCENT:
439 this->writeTypedInstruction(lType, ByteCodeInstruction::kRemainderS,
440 ByteCodeInstruction::kRemainderU,
441 ByteCodeInstruction::kRemainderF,
442 count);
443 break;
444 case Token::Kind::PLUS:
445 this->writeTypedInstruction(lType, ByteCodeInstruction::kAddI,
446 ByteCodeInstruction::kAddI,
447 ByteCodeInstruction::kAddF,
448 count);
449 break;
450 case Token::Kind::SLASH:
451 this->writeTypedInstruction(lType, ByteCodeInstruction::kDivideS,
452 ByteCodeInstruction::kDivideU,
453 ByteCodeInstruction::kDivideF,
454 count);
455 break;
456 case Token::Kind::STAR:
457 this->writeTypedInstruction(lType, ByteCodeInstruction::kMultiplyI,
458 ByteCodeInstruction::kMultiplyI,
459 ByteCodeInstruction::kMultiplyF,
460 count);
461 break;
462 default:
463 SkASSERT(false);
464 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400465 }
466 if (lvalue) {
Brian Osman3e29f1d2019-05-28 09:35:05 -0400467 lvalue->store(discard);
468 discard = false;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400469 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400470 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400471}
472
473void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
474 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osman44d44762019-05-13 14:19:12 -0400475 this->write32(b.fValue ? 1 : 0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400476}
477
478void ByteCodeGenerator::writeConstructor(const Constructor& c) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400479 for (const auto& arg : c.fArguments) {
480 this->writeExpression(*arg);
481 }
482 if (c.fArguments.size() == 1) {
Brian Osman29e013d2019-05-28 17:16:03 -0400483 const Type& inType = c.fArguments[0]->fType;
484 const Type& outType = c.fType;
485 TypeCategory inCategory = type_category(inType);
486 TypeCategory outCategory = type_category(outType);
487 int inCount = SlotCount(inType);
488 int outCount = SlotCount(outType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400489 if (inCategory != outCategory) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700490 SkASSERT(inCount == outCount);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400491 if (inCategory == TypeCategory::kFloat) {
492 SkASSERT(outCategory == TypeCategory::kSigned ||
493 outCategory == TypeCategory::kUnsigned);
Brian Osmanc51d7912019-05-22 15:16:16 -0700494 this->write(vector_instruction(ByteCodeInstruction::kConvertFtoI, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400495 } else if (outCategory == TypeCategory::kFloat) {
496 if (inCategory == TypeCategory::kSigned) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700497 this->write(vector_instruction(ByteCodeInstruction::kConvertStoF, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400498 } else {
499 SkASSERT(inCategory == TypeCategory::kUnsigned);
Brian Osmanc51d7912019-05-22 15:16:16 -0700500 this->write(vector_instruction(ByteCodeInstruction::kConvertUtoF, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400501 }
502 } else {
503 SkASSERT(false);
504 }
505 }
Brian Osman29e013d2019-05-28 17:16:03 -0400506 if (inType.kind() == Type::kMatrix_Kind && outType.kind() == Type::kMatrix_Kind) {
507 this->write(ByteCodeInstruction::kMatrixToMatrix);
508 this->write8(inType.columns());
509 this->write8(inType.rows());
510 this->write8(outType.columns());
511 this->write8(outType.rows());
512 } else if (inCount != outCount) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700513 SkASSERT(inCount == 1);
Brian Osman29e013d2019-05-28 17:16:03 -0400514 if (outType.kind() == Type::kMatrix_Kind) {
515 this->write(ByteCodeInstruction::kScalarToMatrix);
516 this->write8(outType.columns());
517 this->write8(outType.rows());
518 } else {
519 SkASSERT(outType.kind() == Type::kVector_Kind);
520 for (; inCount != outCount; ++inCount) {
521 this->write(ByteCodeInstruction::kDup);
522 }
Brian Osmanc51d7912019-05-22 15:16:16 -0700523 }
524 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400525 }
526}
527
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400528void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f) {
529 int argumentCount = 0;
530 for (const auto& arg : f.fArguments) {
531 this->writeExpression(*arg);
Brian Osman07c117b2019-05-23 12:51:06 -0700532 argumentCount += SlotCount(arg->fType);
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400533 }
534 this->write(ByteCodeInstruction::kCallExternal);
535 SkASSERT(argumentCount <= 255);
536 this->write8(argumentCount);
Brian Osman07c117b2019-05-23 12:51:06 -0700537 this->write8(SlotCount(f.fType));
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400538 int index = fOutput->fExternalValues.size();
539 fOutput->fExternalValues.push_back(f.fFunction);
540 SkASSERT(index <= 255);
541 this->write8(index);
542}
543
Ethan Nicholas91164d12019-05-15 15:29:54 -0400544void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400545 this->write(vector_instruction(ByteCodeInstruction::kReadExternal,
Brian Osman07c117b2019-05-23 12:51:06 -0700546 SlotCount(e.fValue->type())));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400547 int index = fOutput->fExternalValues.size();
548 fOutput->fExternalValues.push_back(e.fValue);
549 SkASSERT(index <= 255);
550 this->write8(index);
551}
552
Brian Osman07c117b2019-05-23 12:51:06 -0700553void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
554 Variable::Storage storage;
555 int location = this->getLocation(expr, &storage);
556 bool isGlobal = storage == Variable::kGlobal_Storage;
557 int count = SlotCount(expr.fType);
558 if (location < 0 || count > 4) {
559 if (location >= 0) {
560 this->write(ByteCodeInstruction::kPushImmediate);
561 this->write32(location);
562 }
563 this->write(isGlobal ? ByteCodeInstruction::kLoadExtendedGlobal
564 : ByteCodeInstruction::kLoadExtended);
565 this->write8(count);
566 } else {
567 this->write(vector_instruction(isGlobal ? ByteCodeInstruction::kLoadGlobal
568 : ByteCodeInstruction::kLoad,
569 count));
570 this->write8(location);
571 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400572}
573
574void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
575 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400576 this->write32(Interpreter::Value((float) f.fValue).fUnsigned);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400577}
578
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400579void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
580 auto found = fIntrinsics.find(c.fFunction.fName);
581 if (found == fIntrinsics.end()) {
582 fErrors.error(c.fOffset, "unsupported intrinsic function");
583 return;
584 }
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400585 if (found->second.fIsSpecial) {
586 SkASSERT(found->second.fValue.fSpecial == SpecialIntrinsic::kDot);
587 SkASSERT(c.fArguments.size() == 2);
588 SkASSERT(SlotCount(c.fArguments[0]->fType) == SlotCount(c.fArguments[1]->fType));
589 this->write((ByteCodeInstruction) ((int) ByteCodeInstruction::kMultiplyF +
590 SlotCount(c.fArguments[0]->fType) - 1));
591 for (int i = SlotCount(c.fArguments[0]->fType); i > 1; --i) {
592 this->write(ByteCodeInstruction::kAddF);
593 }
594 } else {
595 switch (found->second.fValue.fInstruction) {
596 case ByteCodeInstruction::kCos:
597 case ByteCodeInstruction::kMix:
598 case ByteCodeInstruction::kSin:
599 case ByteCodeInstruction::kSqrt:
600 case ByteCodeInstruction::kTan:
601 SkASSERT(c.fArguments.size() > 0);
602 this->write((ByteCodeInstruction) ((int) found->second.fValue.fInstruction +
603 SlotCount(c.fArguments[0]->fType) - 1));
604 break;
605 case ByteCodeInstruction::kCross:
606 this->write(found->second.fValue.fInstruction);
607 break;
608 default:
609 SkASSERT(false);
610 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400611 }
612}
613
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400614void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400615 for (const auto& arg : f.fArguments) {
616 this->writeExpression(*arg);
617 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400618 if (f.fFunction.fBuiltin) {
619 this->writeIntrinsicCall(f);
620 return;
621 }
Brian Osman226668a2019-05-14 16:47:30 -0400622 this->write(ByteCodeInstruction::kCall);
623 fCallTargets.emplace_back(this, f.fFunction);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400624}
625
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400626void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
627 this->write(ByteCodeInstruction::kPushImmediate);
628 this->write32(i.fValue);
629}
630
631void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
632 // not yet implemented
633 abort();
634}
635
Brian Osman3e29f1d2019-05-28 09:35:05 -0400636bool ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p, bool discard) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400637 switch (p.fOperator) {
638 case Token::Kind::PLUSPLUS: // fall through
639 case Token::Kind::MINUSMINUS: {
Brian Osman07c117b2019-05-23 12:51:06 -0700640 SkASSERT(SlotCount(p.fOperand->fType) == 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400641 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
642 lvalue->load();
643 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400644 this->write32(type_category(p.fType) == TypeCategory::kFloat
645 ? Interpreter::Value(1.0f).fUnsigned : 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400646 if (p.fOperator == Token::Kind::PLUSPLUS) {
647 this->writeTypedInstruction(p.fType,
648 ByteCodeInstruction::kAddI,
649 ByteCodeInstruction::kAddI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400650 ByteCodeInstruction::kAddF,
651 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400652 } else {
653 this->writeTypedInstruction(p.fType,
654 ByteCodeInstruction::kSubtractI,
655 ByteCodeInstruction::kSubtractI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400656 ByteCodeInstruction::kSubtractF,
657 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400658 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400659 lvalue->store(discard);
660 discard = false;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400661 break;
662 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400663 case Token::Kind::MINUS: {
664 this->writeExpression(*p.fOperand);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400665 this->writeTypedInstruction(p.fType,
Mike Klein12710912019-05-21 11:04:59 -0500666 ByteCodeInstruction::kNegateI,
667 ByteCodeInstruction::kNegateI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400668 ByteCodeInstruction::kNegateF,
Brian Osman07c117b2019-05-23 12:51:06 -0700669 SlotCount(p.fOperand->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400670 break;
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400671 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400672 default:
673 SkASSERT(false);
674 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400675 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400676}
677
Brian Osman3e29f1d2019-05-28 09:35:05 -0400678bool ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p, bool discard) {
Brian Osmanf3fa6002019-05-17 14:26:53 -0400679 switch (p.fOperator) {
680 case Token::Kind::PLUSPLUS: // fall through
681 case Token::Kind::MINUSMINUS: {
Brian Osman07c117b2019-05-23 12:51:06 -0700682 SkASSERT(SlotCount(p.fOperand->fType) == 1);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400683 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
684 lvalue->load();
Brian Osman3e29f1d2019-05-28 09:35:05 -0400685 if (!discard) {
686 this->write(ByteCodeInstruction::kDup);
687 }
Brian Osmanf3fa6002019-05-17 14:26:53 -0400688 this->write(ByteCodeInstruction::kPushImmediate);
689 this->write32(type_category(p.fType) == TypeCategory::kFloat
690 ? Interpreter::Value(1.0f).fUnsigned : 1);
691 if (p.fOperator == Token::Kind::PLUSPLUS) {
692 this->writeTypedInstruction(p.fType,
693 ByteCodeInstruction::kAddI,
694 ByteCodeInstruction::kAddI,
695 ByteCodeInstruction::kAddF,
696 1);
697 } else {
698 this->writeTypedInstruction(p.fType,
699 ByteCodeInstruction::kSubtractI,
700 ByteCodeInstruction::kSubtractI,
701 ByteCodeInstruction::kSubtractF,
702 1);
703 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400704 lvalue->store(discard);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400705 this->write(ByteCodeInstruction::kPop);
Brian Osman3e29f1d2019-05-28 09:35:05 -0400706 discard = false;
Brian Osmanf3fa6002019-05-17 14:26:53 -0400707 break;
708 }
709 default:
710 SkASSERT(false);
711 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400712 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400713}
714
715void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
Brian Osman0785db02019-05-24 14:19:11 -0400716 if (swizzle_is_simple(s)) {
717 this->writeVariableExpression(s);
718 return;
719 }
720
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400721 switch (s.fBase->fKind) {
722 case Expression::kVariableReference_Kind: {
723 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
Brian Osman1091f022019-05-16 09:42:16 -0400724 this->write(var.fStorage == Variable::kGlobal_Storage
725 ? ByteCodeInstruction::kLoadSwizzleGlobal
726 : ByteCodeInstruction::kLoadSwizzle);
727 this->write8(this->getLocation(var));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400728 this->write8(s.fComponents.size());
729 for (int c : s.fComponents) {
730 this->write8(c);
731 }
732 break;
733 }
734 default:
735 this->writeExpression(*s.fBase);
736 this->write(ByteCodeInstruction::kSwizzle);
737 this->write8(s.fBase->fType.columns());
738 this->write8(s.fComponents.size());
739 for (int c : s.fComponents) {
740 this->write8(c);
741 }
742 }
743}
744
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400745void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Brian Osman4e93feb2019-05-16 15:38:00 -0400746 this->writeExpression(*t.fTest);
Brian Osman4e93feb2019-05-16 15:38:00 -0400747 this->write(ByteCodeInstruction::kConditionalBranch);
748 DeferredLocation trueLocation(this);
749 this->writeExpression(*t.fIfFalse);
Brian Osman4e93feb2019-05-16 15:38:00 -0400750 this->write(ByteCodeInstruction::kBranch);
751 DeferredLocation endLocation(this);
752 trueLocation.set();
753 this->writeExpression(*t.fIfTrue);
754 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400755}
756
Brian Osman3e29f1d2019-05-28 09:35:05 -0400757void ByteCodeGenerator::writeExpression(const Expression& e, bool discard) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400758 switch (e.fKind) {
759 case Expression::kBinary_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400760 discard = this->writeBinaryExpression((BinaryExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400761 break;
762 case Expression::kBoolLiteral_Kind:
763 this->writeBoolLiteral((BoolLiteral&) e);
764 break;
765 case Expression::kConstructor_Kind:
766 this->writeConstructor((Constructor&) e);
767 break;
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400768 case Expression::kExternalFunctionCall_Kind:
769 this->writeExternalFunctionCall((ExternalFunctionCall&) e);
770 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400771 case Expression::kExternalValue_Kind:
772 this->writeExternalValue((ExternalValueReference&) e);
773 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400774 case Expression::kFieldAccess_Kind:
Brian Osman07c117b2019-05-23 12:51:06 -0700775 case Expression::kIndex_Kind:
776 case Expression::kVariableReference_Kind:
777 this->writeVariableExpression(e);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400778 break;
779 case Expression::kFloatLiteral_Kind:
780 this->writeFloatLiteral((FloatLiteral&) e);
781 break;
782 case Expression::kFunctionCall_Kind:
783 this->writeFunctionCall((FunctionCall&) e);
784 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400785 case Expression::kIntLiteral_Kind:
786 this->writeIntLiteral((IntLiteral&) e);
787 break;
788 case Expression::kNullLiteral_Kind:
789 this->writeNullLiteral((NullLiteral&) e);
790 break;
791 case Expression::kPrefix_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400792 discard = this->writePrefixExpression((PrefixExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400793 break;
794 case Expression::kPostfix_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400795 discard = this->writePostfixExpression((PostfixExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400796 break;
797 case Expression::kSwizzle_Kind:
798 this->writeSwizzle((Swizzle&) e);
799 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400800 case Expression::kTernary_Kind:
801 this->writeTernaryExpression((TernaryExpression&) e);
802 break;
803 default:
804 printf("unsupported expression %s\n", e.description().c_str());
805 SkASSERT(false);
806 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400807 if (discard) {
808 int count = SlotCount(e.fType);
809 if (count > 4) {
810 this->write(ByteCodeInstruction::kPopN);
811 this->write8(count);
812 } else {
813 this->write(vector_instruction(ByteCodeInstruction::kPop, count));
814 }
815 discard = false;
816 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400817}
818
Ethan Nicholas91164d12019-05-15 15:29:54 -0400819class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
820public:
821 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
822 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700823 , fCount(ByteCodeGenerator::SlotCount(value.type()))
Ethan Nicholas91164d12019-05-15 15:29:54 -0400824 , fIndex(index) {}
825
826 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400827 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400828 fGenerator.write8(fIndex);
829 }
830
Brian Osman3e29f1d2019-05-28 09:35:05 -0400831 void store(bool discard) override {
832 if (!discard) {
833 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
834 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400835 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400836 fGenerator.write8(fIndex);
837 }
838
839private:
840 typedef LValue INHERITED;
841
842 int fCount;
843
844 int fIndex;
845};
846
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400847class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
848public:
849 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
850 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700851 , fSwizzle(swizzle) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400852
853 void load() override {
Brian Osman1091f022019-05-16 09:42:16 -0400854 fGenerator.writeSwizzle(fSwizzle);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400855 }
856
Brian Osman3e29f1d2019-05-28 09:35:05 -0400857 void store(bool discard) override {
858 if (!discard) {
859 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup,
860 fSwizzle.fComponents.size()));
861 }
Brian Osman07c117b2019-05-23 12:51:06 -0700862 Variable::Storage storage;
863 int location = fGenerator.getLocation(*fSwizzle.fBase, &storage);
864 bool isGlobal = storage == Variable::kGlobal_Storage;
865 if (location < 0) {
866 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleIndirectGlobal
867 : ByteCodeInstruction::kStoreSwizzleIndirect);
868 } else {
869 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleGlobal
870 : ByteCodeInstruction::kStoreSwizzle);
871 fGenerator.write8(location);
872 }
Brian Osman1091f022019-05-16 09:42:16 -0400873 fGenerator.write8(fSwizzle.fComponents.size());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400874 for (int c : fSwizzle.fComponents) {
875 fGenerator.write8(c);
876 }
877 }
878
879private:
880 const Swizzle& fSwizzle;
881
882 typedef LValue INHERITED;
883};
884
Brian Osman07c117b2019-05-23 12:51:06 -0700885class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400886public:
Brian Osman07c117b2019-05-23 12:51:06 -0700887 ByteCodeExpressionLValue(ByteCodeGenerator* generator, const Expression& expr)
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400888 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700889 , fExpression(expr) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400890
891 void load() override {
Brian Osman07c117b2019-05-23 12:51:06 -0700892 fGenerator.writeVariableExpression(fExpression);
Brian Osman1091f022019-05-16 09:42:16 -0400893 }
894
Brian Osman3e29f1d2019-05-28 09:35:05 -0400895 void store(bool discard) override {
Brian Osman07c117b2019-05-23 12:51:06 -0700896 int count = ByteCodeGenerator::SlotCount(fExpression.fType);
Brian Osman3e29f1d2019-05-28 09:35:05 -0400897 if (!discard) {
898 if (count > 4) {
899 fGenerator.write(ByteCodeInstruction::kDupN);
900 fGenerator.write8(count);
901 } else {
902 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
903 }
Brian Osman07c117b2019-05-23 12:51:06 -0700904 }
905 Variable::Storage storage;
906 int location = fGenerator.getLocation(fExpression, &storage);
907 bool isGlobal = storage == Variable::kGlobal_Storage;
908 if (location < 0 || count > 4) {
909 if (location >= 0) {
910 fGenerator.write(ByteCodeInstruction::kPushImmediate);
911 fGenerator.write32(location);
912 }
913 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreExtendedGlobal
914 : ByteCodeInstruction::kStoreExtended);
915 fGenerator.write8(count);
916 } else {
917 fGenerator.write(vector_instruction(isGlobal ? ByteCodeInstruction::kStoreGlobal
918 : ByteCodeInstruction::kStore,
919 count));
920 fGenerator.write8(location);
921 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400922 }
923
924private:
925 typedef LValue INHERITED;
926
Brian Osman07c117b2019-05-23 12:51:06 -0700927 const Expression& fExpression;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400928};
929
930std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
931 switch (e.fKind) {
Ethan Nicholas91164d12019-05-15 15:29:54 -0400932 case Expression::kExternalValue_Kind: {
933 ExternalValue* value = ((ExternalValueReference&) e).fValue;
934 int index = fOutput->fExternalValues.size();
935 fOutput->fExternalValues.push_back(value);
936 SkASSERT(index <= 255);
937 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
938 }
Brian Osman07c117b2019-05-23 12:51:06 -0700939 case Expression::kFieldAccess_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400940 case Expression::kIndex_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400941 case Expression::kVariableReference_Kind:
Brian Osman07c117b2019-05-23 12:51:06 -0700942 return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
Brian Osman0785db02019-05-24 14:19:11 -0400943 case Expression::kSwizzle_Kind: {
944 const Swizzle& s = (const Swizzle&) e;
945 return swizzle_is_simple(s)
946 ? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e))
947 : std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s));
948 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400949 case Expression::kTernary_Kind:
950 default:
951 printf("unsupported lvalue %s\n", e.description().c_str());
952 return nullptr;
953 }
954}
955
956void ByteCodeGenerator::writeBlock(const Block& b) {
957 for (const auto& s : b.fStatements) {
958 this->writeStatement(*s);
959 }
960}
961
962void ByteCodeGenerator::setBreakTargets() {
963 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
964 for (DeferredLocation& b : breaks) {
965 b.set();
966 }
967 fBreakTargets.pop();
968}
969
970void ByteCodeGenerator::setContinueTargets() {
971 std::vector<DeferredLocation>& continues = fContinueTargets.top();
972 for (DeferredLocation& c : continues) {
973 c.set();
974 }
975 fContinueTargets.pop();
976}
977
978void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
979 this->write(ByteCodeInstruction::kBranch);
980 fBreakTargets.top().emplace_back(this);
981}
982
983void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
984 this->write(ByteCodeInstruction::kBranch);
985 fContinueTargets.top().emplace_back(this);
986}
987
988void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
989 fContinueTargets.emplace();
990 fBreakTargets.emplace();
991 size_t start = fCode->size();
992 this->writeStatement(*d.fStatement);
993 this->setContinueTargets();
994 this->writeExpression(*d.fTest);
995 this->write(ByteCodeInstruction::kConditionalBranch);
996 this->write16(start);
997 this->setBreakTargets();
998}
999
1000void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
1001 fContinueTargets.emplace();
1002 fBreakTargets.emplace();
1003 if (f.fInitializer) {
1004 this->writeStatement(*f.fInitializer);
1005 }
1006 size_t start = fCode->size();
1007 if (f.fTest) {
1008 this->writeExpression(*f.fTest);
1009 this->write(ByteCodeInstruction::kNot);
1010 this->write(ByteCodeInstruction::kConditionalBranch);
1011 DeferredLocation endLocation(this);
1012 this->writeStatement(*f.fStatement);
1013 this->setContinueTargets();
1014 if (f.fNext) {
Brian Osman3e29f1d2019-05-28 09:35:05 -04001015 this->writeExpression(*f.fNext, true);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001016 }
1017 this->write(ByteCodeInstruction::kBranch);
1018 this->write16(start);
1019 endLocation.set();
1020 } else {
1021 this->writeStatement(*f.fStatement);
1022 this->setContinueTargets();
1023 if (f.fNext) {
Brian Osman3e29f1d2019-05-28 09:35:05 -04001024 this->writeExpression(*f.fNext, true);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001025 }
1026 this->write(ByteCodeInstruction::kBranch);
1027 this->write16(start);
1028 }
1029 this->setBreakTargets();
1030}
1031
1032void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001033 if (i.fIfFalse) {
Mike Kleinb45ee832019-05-17 11:11:11 -05001034 // if (test) { ..ifTrue.. } else { .. ifFalse .. }
1035 this->writeExpression(*i.fTest);
Mike Kleinb45ee832019-05-17 11:11:11 -05001036 this->write(ByteCodeInstruction::kConditionalBranch);
1037 DeferredLocation trueLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001038 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -05001039 this->write(ByteCodeInstruction::kBranch);
1040 DeferredLocation endLocation(this);
1041 trueLocation.set();
1042 this->writeStatement(*i.fIfTrue);
1043 endLocation.set();
1044 } else {
1045 // if (test) { ..ifTrue.. }
1046 this->writeExpression(*i.fTest);
1047 this->write(ByteCodeInstruction::kNot);
Mike Kleinb45ee832019-05-17 11:11:11 -05001048 this->write(ByteCodeInstruction::kConditionalBranch);
1049 DeferredLocation endLocation(this);
1050 this->writeStatement(*i.fIfTrue);
1051 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001052 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001053}
1054
1055void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -04001056 this->writeExpression(*r.fExpression);
1057 this->write(ByteCodeInstruction::kReturn);
Brian Osman07c117b2019-05-23 12:51:06 -07001058 this->write8(SlotCount(r.fExpression->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001059}
1060
1061void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
1062 // not yet implemented
1063 abort();
1064}
1065
1066void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1067 for (const auto& declStatement : v.fVars) {
1068 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
1069 // we need to grab the location even if we don't use it, to ensure it
1070 // has been allocated
1071 int location = getLocation(*decl.fVar);
1072 if (decl.fValue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001073 this->writeExpression(*decl.fValue);
Brian Osman07c117b2019-05-23 12:51:06 -07001074 int count = SlotCount(decl.fValue->fType);
1075 if (count > 4) {
1076 this->write(ByteCodeInstruction::kPushImmediate);
1077 this->write32(location);
1078 this->write(ByteCodeInstruction::kStoreExtended);
1079 this->write8(count);
1080 } else {
1081 this->write(vector_instruction(ByteCodeInstruction::kStore, count));
1082 this->write8(location);
1083 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001084 }
1085 }
1086}
1087
1088void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
1089 fContinueTargets.emplace();
1090 fBreakTargets.emplace();
1091 size_t start = fCode->size();
1092 this->writeExpression(*w.fTest);
1093 this->write(ByteCodeInstruction::kNot);
1094 this->write(ByteCodeInstruction::kConditionalBranch);
1095 DeferredLocation endLocation(this);
1096 this->writeStatement(*w.fStatement);
1097 this->setContinueTargets();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001098 this->write(ByteCodeInstruction::kBranch);
1099 this->write16(start);
1100 endLocation.set();
1101 this->setBreakTargets();
1102}
1103
1104void ByteCodeGenerator::writeStatement(const Statement& s) {
1105 switch (s.fKind) {
1106 case Statement::kBlock_Kind:
1107 this->writeBlock((Block&) s);
1108 break;
1109 case Statement::kBreak_Kind:
1110 this->writeBreakStatement((BreakStatement&) s);
1111 break;
1112 case Statement::kContinue_Kind:
1113 this->writeContinueStatement((ContinueStatement&) s);
1114 break;
1115 case Statement::kDiscard_Kind:
1116 // not yet implemented
1117 abort();
1118 case Statement::kDo_Kind:
1119 this->writeDoStatement((DoStatement&) s);
1120 break;
Brian Osman3e29f1d2019-05-28 09:35:05 -04001121 case Statement::kExpression_Kind:
1122 this->writeExpression(*((ExpressionStatement&) s).fExpression, true);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001123 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001124 case Statement::kFor_Kind:
1125 this->writeForStatement((ForStatement&) s);
1126 break;
1127 case Statement::kIf_Kind:
1128 this->writeIfStatement((IfStatement&) s);
1129 break;
1130 case Statement::kNop_Kind:
1131 break;
1132 case Statement::kReturn_Kind:
1133 this->writeReturnStatement((ReturnStatement&) s);
1134 break;
1135 case Statement::kSwitch_Kind:
1136 this->writeSwitchStatement((SwitchStatement&) s);
1137 break;
1138 case Statement::kVarDeclarations_Kind:
1139 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1140 break;
1141 case Statement::kWhile_Kind:
1142 this->writeWhileStatement((WhileStatement&) s);
1143 break;
1144 default:
1145 SkASSERT(false);
1146 }
1147}
1148
Brian Osman80164412019-06-07 13:00:23 -04001149ByteCodeFunction::ByteCodeFunction(const FunctionDeclaration* declaration)
1150 : fName(declaration->fName) {
1151 fParameterCount = 0;
1152 for (const auto& p : declaration->fParameters) {
1153 int slots = ByteCodeGenerator::SlotCount(p->fType);
1154 fParameters.push_back({ slots, (bool)(p->fModifiers.fFlags & Modifiers::kOut_Flag) });
1155 fParameterCount += slots;
1156 }
1157}
1158
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001159}