blob: 5f737ebc2ffc462405c69e94ecac706e6d951e9a [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
11namespace SkSL {
12
Ethan Nicholas82162ee2019-05-21 16:05:08 -040013ByteCodeGenerator::ByteCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
14 ByteCode* output)
15 : INHERITED(program, errors, nullptr)
16 , fContext(*context)
Ethan Nicholasae9633b2019-05-24 12:46:34 -040017 , fOutput(output)
18 , fIntrinsics {
19 { "cos", ByteCodeInstruction::kCos },
20 { "cross", ByteCodeInstruction::kCross },
21 { "dot", SpecialIntrinsic::kDot },
22 { "sin", ByteCodeInstruction::kSin },
23 { "sqrt", ByteCodeInstruction::kSqrt },
24 { "tan", ByteCodeInstruction::kTan },
25 { "mix", ByteCodeInstruction::kMix },
26 } {}
27
Ethan Nicholas82162ee2019-05-21 16:05:08 -040028
Brian Osman07c117b2019-05-23 12:51:06 -070029int ByteCodeGenerator::SlotCount(const Type& type) {
30 if (type.kind() == Type::kStruct_Kind) {
31 int slots = 0;
32 for (const auto& f : type.fields()) {
33 slots += SlotCount(*f.fType);
34 }
35 SkASSERT(slots <= 255);
36 return slots;
37 } else if (type.kind() == Type::kArray_Kind) {
38 int columns = type.columns();
39 SkASSERT(columns >= 0);
40 int slots = columns * SlotCount(type.componentType());
41 SkASSERT(slots <= 255);
42 return slots;
43 } else {
44 return type.columns() * type.rows();
45 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040046}
47
48bool ByteCodeGenerator::generateCode() {
49 for (const auto& e : fProgram) {
50 switch (e.fKind) {
51 case ProgramElement::kFunction_Kind: {
52 std::unique_ptr<ByteCodeFunction> f = this->writeFunction((FunctionDefinition&) e);
53 if (!f) {
54 return false;
55 }
56 fOutput->fFunctions.push_back(std::move(f));
57 break;
58 }
59 case ProgramElement::kVar_Kind: {
60 VarDeclarations& decl = (VarDeclarations&) e;
61 for (const auto& v : decl.fVars) {
62 const Variable* declVar = ((VarDeclaration&) *v).fVar;
63 if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
64 continue;
65 }
66 if (declVar->fModifiers.fFlags & Modifiers::kIn_Flag) {
Brian Osman07c117b2019-05-23 12:51:06 -070067 for (int i = SlotCount(declVar->fType); i > 0; --i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040068 fOutput->fInputSlots.push_back(fOutput->fGlobalCount++);
69 }
70 } else {
Brian Osman07c117b2019-05-23 12:51:06 -070071 fOutput->fGlobalCount += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040072 }
73 }
74 break;
75 }
76 default:
77 ; // ignore
78 }
79 }
Brian Osman226668a2019-05-14 16:47:30 -040080 for (auto& call : fCallTargets) {
81 if (!call.set()) {
82 return false;
83 }
84 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040085 return true;
86}
87
88std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
89 fFunction = &f;
Brian Osman226668a2019-05-14 16:47:30 -040090 std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040091 fParameterCount = 0;
92 for (const auto& p : f.fDeclaration.fParameters) {
Brian Osman07c117b2019-05-23 12:51:06 -070093 fParameterCount += SlotCount(p->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040094 }
95 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->fParameterCount = fParameterCount;
100 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;
463 default:
464 SkASSERT(false);
465 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400466 }
467 if (lvalue) {
Brian Osman3e29f1d2019-05-28 09:35:05 -0400468 lvalue->store(discard);
469 discard = false;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400470 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400471 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400472}
473
474void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
475 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osman44d44762019-05-13 14:19:12 -0400476 this->write32(b.fValue ? 1 : 0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400477}
478
479void ByteCodeGenerator::writeConstructor(const Constructor& c) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400480 for (const auto& arg : c.fArguments) {
481 this->writeExpression(*arg);
482 }
483 if (c.fArguments.size() == 1) {
Brian Osman29e013d2019-05-28 17:16:03 -0400484 const Type& inType = c.fArguments[0]->fType;
485 const Type& outType = c.fType;
486 TypeCategory inCategory = type_category(inType);
487 TypeCategory outCategory = type_category(outType);
488 int inCount = SlotCount(inType);
489 int outCount = SlotCount(outType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400490 if (inCategory != outCategory) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700491 SkASSERT(inCount == outCount);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400492 if (inCategory == TypeCategory::kFloat) {
493 SkASSERT(outCategory == TypeCategory::kSigned ||
494 outCategory == TypeCategory::kUnsigned);
Brian Osmanc51d7912019-05-22 15:16:16 -0700495 this->write(vector_instruction(ByteCodeInstruction::kConvertFtoI, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400496 } else if (outCategory == TypeCategory::kFloat) {
497 if (inCategory == TypeCategory::kSigned) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700498 this->write(vector_instruction(ByteCodeInstruction::kConvertStoF, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400499 } else {
500 SkASSERT(inCategory == TypeCategory::kUnsigned);
Brian Osmanc51d7912019-05-22 15:16:16 -0700501 this->write(vector_instruction(ByteCodeInstruction::kConvertUtoF, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400502 }
503 } else {
504 SkASSERT(false);
505 }
506 }
Brian Osman29e013d2019-05-28 17:16:03 -0400507 if (inType.kind() == Type::kMatrix_Kind && outType.kind() == Type::kMatrix_Kind) {
508 this->write(ByteCodeInstruction::kMatrixToMatrix);
509 this->write8(inType.columns());
510 this->write8(inType.rows());
511 this->write8(outType.columns());
512 this->write8(outType.rows());
513 } else if (inCount != outCount) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700514 SkASSERT(inCount == 1);
Brian Osman29e013d2019-05-28 17:16:03 -0400515 if (outType.kind() == Type::kMatrix_Kind) {
516 this->write(ByteCodeInstruction::kScalarToMatrix);
517 this->write8(outType.columns());
518 this->write8(outType.rows());
519 } else {
520 SkASSERT(outType.kind() == Type::kVector_Kind);
521 for (; inCount != outCount; ++inCount) {
522 this->write(ByteCodeInstruction::kDup);
523 }
Brian Osmanc51d7912019-05-22 15:16:16 -0700524 }
525 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400526 }
527}
528
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400529void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f) {
530 int argumentCount = 0;
531 for (const auto& arg : f.fArguments) {
532 this->writeExpression(*arg);
Brian Osman07c117b2019-05-23 12:51:06 -0700533 argumentCount += SlotCount(arg->fType);
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400534 }
535 this->write(ByteCodeInstruction::kCallExternal);
536 SkASSERT(argumentCount <= 255);
537 this->write8(argumentCount);
Brian Osman07c117b2019-05-23 12:51:06 -0700538 this->write8(SlotCount(f.fType));
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400539 int index = fOutput->fExternalValues.size();
540 fOutput->fExternalValues.push_back(f.fFunction);
541 SkASSERT(index <= 255);
542 this->write8(index);
543}
544
Ethan Nicholas91164d12019-05-15 15:29:54 -0400545void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400546 this->write(vector_instruction(ByteCodeInstruction::kReadExternal,
Brian Osman07c117b2019-05-23 12:51:06 -0700547 SlotCount(e.fValue->type())));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400548 int index = fOutput->fExternalValues.size();
549 fOutput->fExternalValues.push_back(e.fValue);
550 SkASSERT(index <= 255);
551 this->write8(index);
552}
553
Brian Osman07c117b2019-05-23 12:51:06 -0700554void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
555 Variable::Storage storage;
556 int location = this->getLocation(expr, &storage);
557 bool isGlobal = storage == Variable::kGlobal_Storage;
558 int count = SlotCount(expr.fType);
559 if (location < 0 || count > 4) {
560 if (location >= 0) {
561 this->write(ByteCodeInstruction::kPushImmediate);
562 this->write32(location);
563 }
564 this->write(isGlobal ? ByteCodeInstruction::kLoadExtendedGlobal
565 : ByteCodeInstruction::kLoadExtended);
566 this->write8(count);
567 } else {
568 this->write(vector_instruction(isGlobal ? ByteCodeInstruction::kLoadGlobal
569 : ByteCodeInstruction::kLoad,
570 count));
571 this->write8(location);
572 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400573}
574
575void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
576 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400577 this->write32(Interpreter::Value((float) f.fValue).fUnsigned);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400578}
579
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400580void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
581 auto found = fIntrinsics.find(c.fFunction.fName);
582 if (found == fIntrinsics.end()) {
583 fErrors.error(c.fOffset, "unsupported intrinsic function");
584 return;
585 }
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400586 if (found->second.fIsSpecial) {
587 SkASSERT(found->second.fValue.fSpecial == SpecialIntrinsic::kDot);
588 SkASSERT(c.fArguments.size() == 2);
589 SkASSERT(SlotCount(c.fArguments[0]->fType) == SlotCount(c.fArguments[1]->fType));
590 this->write((ByteCodeInstruction) ((int) ByteCodeInstruction::kMultiplyF +
591 SlotCount(c.fArguments[0]->fType) - 1));
592 for (int i = SlotCount(c.fArguments[0]->fType); i > 1; --i) {
593 this->write(ByteCodeInstruction::kAddF);
594 }
595 } else {
596 switch (found->second.fValue.fInstruction) {
597 case ByteCodeInstruction::kCos:
598 case ByteCodeInstruction::kMix:
599 case ByteCodeInstruction::kSin:
600 case ByteCodeInstruction::kSqrt:
601 case ByteCodeInstruction::kTan:
602 SkASSERT(c.fArguments.size() > 0);
603 this->write((ByteCodeInstruction) ((int) found->second.fValue.fInstruction +
604 SlotCount(c.fArguments[0]->fType) - 1));
605 break;
606 case ByteCodeInstruction::kCross:
607 this->write(found->second.fValue.fInstruction);
608 break;
609 default:
610 SkASSERT(false);
611 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400612 }
613}
614
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400615void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400616 for (const auto& arg : f.fArguments) {
617 this->writeExpression(*arg);
618 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400619 if (f.fFunction.fBuiltin) {
620 this->writeIntrinsicCall(f);
621 return;
622 }
Brian Osman226668a2019-05-14 16:47:30 -0400623 this->write(ByteCodeInstruction::kCall);
624 fCallTargets.emplace_back(this, f.fFunction);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400625}
626
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400627void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
628 this->write(ByteCodeInstruction::kPushImmediate);
629 this->write32(i.fValue);
630}
631
632void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
633 // not yet implemented
634 abort();
635}
636
Brian Osman3e29f1d2019-05-28 09:35:05 -0400637bool ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p, bool discard) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400638 switch (p.fOperator) {
639 case Token::Kind::PLUSPLUS: // fall through
640 case Token::Kind::MINUSMINUS: {
Brian Osman07c117b2019-05-23 12:51:06 -0700641 SkASSERT(SlotCount(p.fOperand->fType) == 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400642 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
643 lvalue->load();
644 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400645 this->write32(type_category(p.fType) == TypeCategory::kFloat
646 ? Interpreter::Value(1.0f).fUnsigned : 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400647 if (p.fOperator == Token::Kind::PLUSPLUS) {
648 this->writeTypedInstruction(p.fType,
649 ByteCodeInstruction::kAddI,
650 ByteCodeInstruction::kAddI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400651 ByteCodeInstruction::kAddF,
652 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400653 } else {
654 this->writeTypedInstruction(p.fType,
655 ByteCodeInstruction::kSubtractI,
656 ByteCodeInstruction::kSubtractI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400657 ByteCodeInstruction::kSubtractF,
658 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400659 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400660 lvalue->store(discard);
661 discard = false;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400662 break;
663 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400664 case Token::Kind::MINUS: {
665 this->writeExpression(*p.fOperand);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400666 this->writeTypedInstruction(p.fType,
Mike Klein12710912019-05-21 11:04:59 -0500667 ByteCodeInstruction::kNegateI,
668 ByteCodeInstruction::kNegateI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400669 ByteCodeInstruction::kNegateF,
Brian Osman07c117b2019-05-23 12:51:06 -0700670 SlotCount(p.fOperand->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400671 break;
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400672 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400673 default:
674 SkASSERT(false);
675 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400676 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400677}
678
Brian Osman3e29f1d2019-05-28 09:35:05 -0400679bool ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p, bool discard) {
Brian Osmanf3fa6002019-05-17 14:26:53 -0400680 switch (p.fOperator) {
681 case Token::Kind::PLUSPLUS: // fall through
682 case Token::Kind::MINUSMINUS: {
Brian Osman07c117b2019-05-23 12:51:06 -0700683 SkASSERT(SlotCount(p.fOperand->fType) == 1);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400684 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
685 lvalue->load();
Brian Osman3e29f1d2019-05-28 09:35:05 -0400686 if (!discard) {
687 this->write(ByteCodeInstruction::kDup);
688 }
Brian Osmanf3fa6002019-05-17 14:26:53 -0400689 this->write(ByteCodeInstruction::kPushImmediate);
690 this->write32(type_category(p.fType) == TypeCategory::kFloat
691 ? Interpreter::Value(1.0f).fUnsigned : 1);
692 if (p.fOperator == Token::Kind::PLUSPLUS) {
693 this->writeTypedInstruction(p.fType,
694 ByteCodeInstruction::kAddI,
695 ByteCodeInstruction::kAddI,
696 ByteCodeInstruction::kAddF,
697 1);
698 } else {
699 this->writeTypedInstruction(p.fType,
700 ByteCodeInstruction::kSubtractI,
701 ByteCodeInstruction::kSubtractI,
702 ByteCodeInstruction::kSubtractF,
703 1);
704 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400705 lvalue->store(discard);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400706 this->write(ByteCodeInstruction::kPop);
Brian Osman3e29f1d2019-05-28 09:35:05 -0400707 discard = false;
Brian Osmanf3fa6002019-05-17 14:26:53 -0400708 break;
709 }
710 default:
711 SkASSERT(false);
712 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400713 return discard;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400714}
715
716void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
Brian Osman0785db02019-05-24 14:19:11 -0400717 if (swizzle_is_simple(s)) {
718 this->writeVariableExpression(s);
719 return;
720 }
721
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400722 switch (s.fBase->fKind) {
723 case Expression::kVariableReference_Kind: {
724 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
Brian Osman1091f022019-05-16 09:42:16 -0400725 this->write(var.fStorage == Variable::kGlobal_Storage
726 ? ByteCodeInstruction::kLoadSwizzleGlobal
727 : ByteCodeInstruction::kLoadSwizzle);
728 this->write8(this->getLocation(var));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400729 this->write8(s.fComponents.size());
730 for (int c : s.fComponents) {
731 this->write8(c);
732 }
733 break;
734 }
735 default:
736 this->writeExpression(*s.fBase);
737 this->write(ByteCodeInstruction::kSwizzle);
738 this->write8(s.fBase->fType.columns());
739 this->write8(s.fComponents.size());
740 for (int c : s.fComponents) {
741 this->write8(c);
742 }
743 }
744}
745
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400746void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Brian Osman4e93feb2019-05-16 15:38:00 -0400747 this->writeExpression(*t.fTest);
Brian Osman4e93feb2019-05-16 15:38:00 -0400748 this->write(ByteCodeInstruction::kConditionalBranch);
749 DeferredLocation trueLocation(this);
750 this->writeExpression(*t.fIfFalse);
Brian Osman4e93feb2019-05-16 15:38:00 -0400751 this->write(ByteCodeInstruction::kBranch);
752 DeferredLocation endLocation(this);
753 trueLocation.set();
754 this->writeExpression(*t.fIfTrue);
755 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400756}
757
Brian Osman3e29f1d2019-05-28 09:35:05 -0400758void ByteCodeGenerator::writeExpression(const Expression& e, bool discard) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400759 switch (e.fKind) {
760 case Expression::kBinary_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400761 discard = this->writeBinaryExpression((BinaryExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400762 break;
763 case Expression::kBoolLiteral_Kind:
764 this->writeBoolLiteral((BoolLiteral&) e);
765 break;
766 case Expression::kConstructor_Kind:
767 this->writeConstructor((Constructor&) e);
768 break;
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400769 case Expression::kExternalFunctionCall_Kind:
770 this->writeExternalFunctionCall((ExternalFunctionCall&) e);
771 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400772 case Expression::kExternalValue_Kind:
773 this->writeExternalValue((ExternalValueReference&) e);
774 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400775 case Expression::kFieldAccess_Kind:
Brian Osman07c117b2019-05-23 12:51:06 -0700776 case Expression::kIndex_Kind:
777 case Expression::kVariableReference_Kind:
778 this->writeVariableExpression(e);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400779 break;
780 case Expression::kFloatLiteral_Kind:
781 this->writeFloatLiteral((FloatLiteral&) e);
782 break;
783 case Expression::kFunctionCall_Kind:
784 this->writeFunctionCall((FunctionCall&) e);
785 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400786 case Expression::kIntLiteral_Kind:
787 this->writeIntLiteral((IntLiteral&) e);
788 break;
789 case Expression::kNullLiteral_Kind:
790 this->writeNullLiteral((NullLiteral&) e);
791 break;
792 case Expression::kPrefix_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400793 discard = this->writePrefixExpression((PrefixExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400794 break;
795 case Expression::kPostfix_Kind:
Brian Osman3e29f1d2019-05-28 09:35:05 -0400796 discard = this->writePostfixExpression((PostfixExpression&) e, discard);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400797 break;
798 case Expression::kSwizzle_Kind:
799 this->writeSwizzle((Swizzle&) e);
800 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400801 case Expression::kTernary_Kind:
802 this->writeTernaryExpression((TernaryExpression&) e);
803 break;
804 default:
805 printf("unsupported expression %s\n", e.description().c_str());
806 SkASSERT(false);
807 }
Brian Osman3e29f1d2019-05-28 09:35:05 -0400808 if (discard) {
809 int count = SlotCount(e.fType);
810 if (count > 4) {
811 this->write(ByteCodeInstruction::kPopN);
812 this->write8(count);
813 } else {
814 this->write(vector_instruction(ByteCodeInstruction::kPop, count));
815 }
816 discard = false;
817 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400818}
819
Ethan Nicholas91164d12019-05-15 15:29:54 -0400820class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
821public:
822 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
823 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700824 , fCount(ByteCodeGenerator::SlotCount(value.type()))
Ethan Nicholas91164d12019-05-15 15:29:54 -0400825 , fIndex(index) {}
826
827 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400828 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400829 fGenerator.write8(fIndex);
830 }
831
Brian Osman3e29f1d2019-05-28 09:35:05 -0400832 void store(bool discard) override {
833 if (!discard) {
834 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
835 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400836 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400837 fGenerator.write8(fIndex);
838 }
839
840private:
841 typedef LValue INHERITED;
842
843 int fCount;
844
845 int fIndex;
846};
847
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400848class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
849public:
850 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
851 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700852 , fSwizzle(swizzle) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400853
854 void load() override {
Brian Osman1091f022019-05-16 09:42:16 -0400855 fGenerator.writeSwizzle(fSwizzle);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400856 }
857
Brian Osman3e29f1d2019-05-28 09:35:05 -0400858 void store(bool discard) override {
859 if (!discard) {
860 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup,
861 fSwizzle.fComponents.size()));
862 }
Brian Osman07c117b2019-05-23 12:51:06 -0700863 Variable::Storage storage;
864 int location = fGenerator.getLocation(*fSwizzle.fBase, &storage);
865 bool isGlobal = storage == Variable::kGlobal_Storage;
866 if (location < 0) {
867 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleIndirectGlobal
868 : ByteCodeInstruction::kStoreSwizzleIndirect);
869 } else {
870 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleGlobal
871 : ByteCodeInstruction::kStoreSwizzle);
872 fGenerator.write8(location);
873 }
Brian Osman1091f022019-05-16 09:42:16 -0400874 fGenerator.write8(fSwizzle.fComponents.size());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400875 for (int c : fSwizzle.fComponents) {
876 fGenerator.write8(c);
877 }
878 }
879
880private:
881 const Swizzle& fSwizzle;
882
883 typedef LValue INHERITED;
884};
885
Brian Osman07c117b2019-05-23 12:51:06 -0700886class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400887public:
Brian Osman07c117b2019-05-23 12:51:06 -0700888 ByteCodeExpressionLValue(ByteCodeGenerator* generator, const Expression& expr)
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400889 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700890 , fExpression(expr) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400891
892 void load() override {
Brian Osman07c117b2019-05-23 12:51:06 -0700893 fGenerator.writeVariableExpression(fExpression);
Brian Osman1091f022019-05-16 09:42:16 -0400894 }
895
Brian Osman3e29f1d2019-05-28 09:35:05 -0400896 void store(bool discard) override {
Brian Osman07c117b2019-05-23 12:51:06 -0700897 int count = ByteCodeGenerator::SlotCount(fExpression.fType);
Brian Osman3e29f1d2019-05-28 09:35:05 -0400898 if (!discard) {
899 if (count > 4) {
900 fGenerator.write(ByteCodeInstruction::kDupN);
901 fGenerator.write8(count);
902 } else {
903 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
904 }
Brian Osman07c117b2019-05-23 12:51:06 -0700905 }
906 Variable::Storage storage;
907 int location = fGenerator.getLocation(fExpression, &storage);
908 bool isGlobal = storage == Variable::kGlobal_Storage;
909 if (location < 0 || count > 4) {
910 if (location >= 0) {
911 fGenerator.write(ByteCodeInstruction::kPushImmediate);
912 fGenerator.write32(location);
913 }
914 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreExtendedGlobal
915 : ByteCodeInstruction::kStoreExtended);
916 fGenerator.write8(count);
917 } else {
918 fGenerator.write(vector_instruction(isGlobal ? ByteCodeInstruction::kStoreGlobal
919 : ByteCodeInstruction::kStore,
920 count));
921 fGenerator.write8(location);
922 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400923 }
924
925private:
926 typedef LValue INHERITED;
927
Brian Osman07c117b2019-05-23 12:51:06 -0700928 const Expression& fExpression;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400929};
930
931std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
932 switch (e.fKind) {
Ethan Nicholas91164d12019-05-15 15:29:54 -0400933 case Expression::kExternalValue_Kind: {
934 ExternalValue* value = ((ExternalValueReference&) e).fValue;
935 int index = fOutput->fExternalValues.size();
936 fOutput->fExternalValues.push_back(value);
937 SkASSERT(index <= 255);
938 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
939 }
Brian Osman07c117b2019-05-23 12:51:06 -0700940 case Expression::kFieldAccess_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400941 case Expression::kIndex_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400942 case Expression::kVariableReference_Kind:
Brian Osman07c117b2019-05-23 12:51:06 -0700943 return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
Brian Osman0785db02019-05-24 14:19:11 -0400944 case Expression::kSwizzle_Kind: {
945 const Swizzle& s = (const Swizzle&) e;
946 return swizzle_is_simple(s)
947 ? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e))
948 : std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s));
949 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400950 case Expression::kTernary_Kind:
951 default:
952 printf("unsupported lvalue %s\n", e.description().c_str());
953 return nullptr;
954 }
955}
956
957void ByteCodeGenerator::writeBlock(const Block& b) {
958 for (const auto& s : b.fStatements) {
959 this->writeStatement(*s);
960 }
961}
962
963void ByteCodeGenerator::setBreakTargets() {
964 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
965 for (DeferredLocation& b : breaks) {
966 b.set();
967 }
968 fBreakTargets.pop();
969}
970
971void ByteCodeGenerator::setContinueTargets() {
972 std::vector<DeferredLocation>& continues = fContinueTargets.top();
973 for (DeferredLocation& c : continues) {
974 c.set();
975 }
976 fContinueTargets.pop();
977}
978
979void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
980 this->write(ByteCodeInstruction::kBranch);
981 fBreakTargets.top().emplace_back(this);
982}
983
984void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
985 this->write(ByteCodeInstruction::kBranch);
986 fContinueTargets.top().emplace_back(this);
987}
988
989void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
990 fContinueTargets.emplace();
991 fBreakTargets.emplace();
992 size_t start = fCode->size();
993 this->writeStatement(*d.fStatement);
994 this->setContinueTargets();
995 this->writeExpression(*d.fTest);
996 this->write(ByteCodeInstruction::kConditionalBranch);
997 this->write16(start);
998 this->setBreakTargets();
999}
1000
1001void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
1002 fContinueTargets.emplace();
1003 fBreakTargets.emplace();
1004 if (f.fInitializer) {
1005 this->writeStatement(*f.fInitializer);
1006 }
1007 size_t start = fCode->size();
1008 if (f.fTest) {
1009 this->writeExpression(*f.fTest);
1010 this->write(ByteCodeInstruction::kNot);
1011 this->write(ByteCodeInstruction::kConditionalBranch);
1012 DeferredLocation endLocation(this);
1013 this->writeStatement(*f.fStatement);
1014 this->setContinueTargets();
1015 if (f.fNext) {
Brian Osman3e29f1d2019-05-28 09:35:05 -04001016 this->writeExpression(*f.fNext, true);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001017 }
1018 this->write(ByteCodeInstruction::kBranch);
1019 this->write16(start);
1020 endLocation.set();
1021 } else {
1022 this->writeStatement(*f.fStatement);
1023 this->setContinueTargets();
1024 if (f.fNext) {
Brian Osman3e29f1d2019-05-28 09:35:05 -04001025 this->writeExpression(*f.fNext, true);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001026 }
1027 this->write(ByteCodeInstruction::kBranch);
1028 this->write16(start);
1029 }
1030 this->setBreakTargets();
1031}
1032
1033void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001034 if (i.fIfFalse) {
Mike Kleinb45ee832019-05-17 11:11:11 -05001035 // if (test) { ..ifTrue.. } else { .. ifFalse .. }
1036 this->writeExpression(*i.fTest);
Mike Kleinb45ee832019-05-17 11:11:11 -05001037 this->write(ByteCodeInstruction::kConditionalBranch);
1038 DeferredLocation trueLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001039 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -05001040 this->write(ByteCodeInstruction::kBranch);
1041 DeferredLocation endLocation(this);
1042 trueLocation.set();
1043 this->writeStatement(*i.fIfTrue);
1044 endLocation.set();
1045 } else {
1046 // if (test) { ..ifTrue.. }
1047 this->writeExpression(*i.fTest);
1048 this->write(ByteCodeInstruction::kNot);
Mike Kleinb45ee832019-05-17 11:11:11 -05001049 this->write(ByteCodeInstruction::kConditionalBranch);
1050 DeferredLocation endLocation(this);
1051 this->writeStatement(*i.fIfTrue);
1052 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001053 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001054}
1055
1056void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -04001057 this->writeExpression(*r.fExpression);
1058 this->write(ByteCodeInstruction::kReturn);
Brian Osman07c117b2019-05-23 12:51:06 -07001059 this->write8(SlotCount(r.fExpression->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001060}
1061
1062void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
1063 // not yet implemented
1064 abort();
1065}
1066
1067void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1068 for (const auto& declStatement : v.fVars) {
1069 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
1070 // we need to grab the location even if we don't use it, to ensure it
1071 // has been allocated
1072 int location = getLocation(*decl.fVar);
1073 if (decl.fValue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001074 this->writeExpression(*decl.fValue);
Brian Osman07c117b2019-05-23 12:51:06 -07001075 int count = SlotCount(decl.fValue->fType);
1076 if (count > 4) {
1077 this->write(ByteCodeInstruction::kPushImmediate);
1078 this->write32(location);
1079 this->write(ByteCodeInstruction::kStoreExtended);
1080 this->write8(count);
1081 } else {
1082 this->write(vector_instruction(ByteCodeInstruction::kStore, count));
1083 this->write8(location);
1084 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001085 }
1086 }
1087}
1088
1089void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
1090 fContinueTargets.emplace();
1091 fBreakTargets.emplace();
1092 size_t start = fCode->size();
1093 this->writeExpression(*w.fTest);
1094 this->write(ByteCodeInstruction::kNot);
1095 this->write(ByteCodeInstruction::kConditionalBranch);
1096 DeferredLocation endLocation(this);
1097 this->writeStatement(*w.fStatement);
1098 this->setContinueTargets();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001099 this->write(ByteCodeInstruction::kBranch);
1100 this->write16(start);
1101 endLocation.set();
1102 this->setBreakTargets();
1103}
1104
1105void ByteCodeGenerator::writeStatement(const Statement& s) {
1106 switch (s.fKind) {
1107 case Statement::kBlock_Kind:
1108 this->writeBlock((Block&) s);
1109 break;
1110 case Statement::kBreak_Kind:
1111 this->writeBreakStatement((BreakStatement&) s);
1112 break;
1113 case Statement::kContinue_Kind:
1114 this->writeContinueStatement((ContinueStatement&) s);
1115 break;
1116 case Statement::kDiscard_Kind:
1117 // not yet implemented
1118 abort();
1119 case Statement::kDo_Kind:
1120 this->writeDoStatement((DoStatement&) s);
1121 break;
Brian Osman3e29f1d2019-05-28 09:35:05 -04001122 case Statement::kExpression_Kind:
1123 this->writeExpression(*((ExpressionStatement&) s).fExpression, true);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001124 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001125 case Statement::kFor_Kind:
1126 this->writeForStatement((ForStatement&) s);
1127 break;
1128 case Statement::kIf_Kind:
1129 this->writeIfStatement((IfStatement&) s);
1130 break;
1131 case Statement::kNop_Kind:
1132 break;
1133 case Statement::kReturn_Kind:
1134 this->writeReturnStatement((ReturnStatement&) s);
1135 break;
1136 case Statement::kSwitch_Kind:
1137 this->writeSwitchStatement((SwitchStatement&) s);
1138 break;
1139 case Statement::kVarDeclarations_Kind:
1140 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1141 break;
1142 case Statement::kWhile_Kind:
1143 this->writeWhileStatement((WhileStatement&) s);
1144 break;
1145 default:
1146 SkASSERT(false);
1147 }
1148}
1149
1150}