blob: 6a88c85d55833dc4fd3f293e8c313958161f4fc8 [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;
322 case TypeCategory::kFloat:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400323 this->write(vector_instruction(f, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400324 break;
325 default:
326 SkASSERT(false);
327 }
328}
329
330void ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b) {
331 if (b.fOperator == Token::Kind::EQ) {
332 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
333 this->writeExpression(*b.fRight);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400334 lvalue->store();
335 return;
336 }
Brian Osman16e6fd52019-05-29 11:19:00 -0400337 const Type& lType = b.fLeft->fType;
338 const Type& rType = b.fRight->fType;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400339 Token::Kind op;
340 std::unique_ptr<LValue> lvalue;
341 if (is_assignment(b.fOperator)) {
342 lvalue = this->getLValue(*b.fLeft);
343 lvalue->load();
344 op = remove_assignment(b.fOperator);
345 } else {
346 this->writeExpression(*b.fLeft);
347 op = b.fOperator;
Brian Osman16e6fd52019-05-29 11:19:00 -0400348 if (lType.kind() == Type::kScalar_Kind &&
349 (rType.kind() == Type::kVector_Kind || rType.kind() == Type::kMatrix_Kind)) {
350 for (int i = SlotCount(rType); i > 1; --i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400351 this->write(ByteCodeInstruction::kDup);
352 }
353 }
354 }
355 this->writeExpression(*b.fRight);
Brian Osman16e6fd52019-05-29 11:19:00 -0400356 if ((lType.kind() == Type::kVector_Kind || lType.kind() == Type::kMatrix_Kind) &&
357 rType.kind() == Type::kScalar_Kind) {
358 for (int i = SlotCount(lType); i > 1; --i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400359 this->write(ByteCodeInstruction::kDup);
360 }
361 }
Brian Osman7df8fff2019-05-29 14:33:57 -0400362 int count = std::max(SlotCount(lType), SlotCount(rType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400363 switch (op) {
364 case Token::Kind::EQEQ:
365 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareIEQ,
366 ByteCodeInstruction::kCompareIEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400367 ByteCodeInstruction::kCompareFEQ,
368 count);
Brian Osman16e6fd52019-05-29 11:19:00 -0400369 // Collapse to a single bool
370 for (int i = count; i > 1; --i) {
371 this->write(ByteCodeInstruction::kAndB);
372 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400373 break;
374 case Token::Kind::GT:
375 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGT,
376 ByteCodeInstruction::kCompareUGT,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400377 ByteCodeInstruction::kCompareFGT,
378 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400379 break;
380 case Token::Kind::GTEQ:
381 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGTEQ,
382 ByteCodeInstruction::kCompareUGTEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400383 ByteCodeInstruction::kCompareFGTEQ,
384 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400385 break;
386 case Token::Kind::LT:
387 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLT,
388 ByteCodeInstruction::kCompareULT,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400389 ByteCodeInstruction::kCompareFLT,
390 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400391 break;
392 case Token::Kind::LTEQ:
393 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLTEQ,
394 ByteCodeInstruction::kCompareULTEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400395 ByteCodeInstruction::kCompareFLTEQ,
396 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400397 break;
398 case Token::Kind::MINUS:
399 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kSubtractI,
400 ByteCodeInstruction::kSubtractI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400401 ByteCodeInstruction::kSubtractF,
402 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400403 break;
404 case Token::Kind::NEQ:
405 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareINEQ,
406 ByteCodeInstruction::kCompareINEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400407 ByteCodeInstruction::kCompareFNEQ,
408 count);
Brian Osman16e6fd52019-05-29 11:19:00 -0400409 // Collapse to a single bool
410 for (int i = count; i > 1; --i) {
411 this->write(ByteCodeInstruction::kOrB);
412 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400413 break;
414 case Token::Kind::PERCENT:
415 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kRemainderS,
416 ByteCodeInstruction::kRemainderU,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400417 ByteCodeInstruction::kRemainderF,
418 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400419 break;
420 case Token::Kind::PLUS:
421 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kAddI,
422 ByteCodeInstruction::kAddI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400423 ByteCodeInstruction::kAddF,
424 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400425 break;
426 case Token::Kind::SLASH:
427 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kDivideS,
428 ByteCodeInstruction::kDivideU,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400429 ByteCodeInstruction::kDivideF,
430 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400431 break;
432 case Token::Kind::STAR:
Ethan Nicholas91164d12019-05-15 15:29:54 -0400433 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kMultiplyI,
434 ByteCodeInstruction::kMultiplyI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400435 ByteCodeInstruction::kMultiplyF,
436 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400437 break;
438 default:
439 SkASSERT(false);
440 }
441 if (lvalue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400442 lvalue->store();
443 }
444}
445
446void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
447 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osman44d44762019-05-13 14:19:12 -0400448 this->write32(b.fValue ? 1 : 0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400449}
450
451void ByteCodeGenerator::writeConstructor(const Constructor& c) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400452 for (const auto& arg : c.fArguments) {
453 this->writeExpression(*arg);
454 }
455 if (c.fArguments.size() == 1) {
Brian Osman29e013d2019-05-28 17:16:03 -0400456 const Type& inType = c.fArguments[0]->fType;
457 const Type& outType = c.fType;
458 TypeCategory inCategory = type_category(inType);
459 TypeCategory outCategory = type_category(outType);
460 int inCount = SlotCount(inType);
461 int outCount = SlotCount(outType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400462 if (inCategory != outCategory) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700463 SkASSERT(inCount == outCount);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400464 if (inCategory == TypeCategory::kFloat) {
465 SkASSERT(outCategory == TypeCategory::kSigned ||
466 outCategory == TypeCategory::kUnsigned);
Brian Osmanc51d7912019-05-22 15:16:16 -0700467 this->write(vector_instruction(ByteCodeInstruction::kConvertFtoI, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400468 } else if (outCategory == TypeCategory::kFloat) {
469 if (inCategory == TypeCategory::kSigned) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700470 this->write(vector_instruction(ByteCodeInstruction::kConvertStoF, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400471 } else {
472 SkASSERT(inCategory == TypeCategory::kUnsigned);
Brian Osmanc51d7912019-05-22 15:16:16 -0700473 this->write(vector_instruction(ByteCodeInstruction::kConvertUtoF, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400474 }
475 } else {
476 SkASSERT(false);
477 }
478 }
Brian Osman29e013d2019-05-28 17:16:03 -0400479 if (inType.kind() == Type::kMatrix_Kind && outType.kind() == Type::kMatrix_Kind) {
480 this->write(ByteCodeInstruction::kMatrixToMatrix);
481 this->write8(inType.columns());
482 this->write8(inType.rows());
483 this->write8(outType.columns());
484 this->write8(outType.rows());
485 } else if (inCount != outCount) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700486 SkASSERT(inCount == 1);
Brian Osman29e013d2019-05-28 17:16:03 -0400487 if (outType.kind() == Type::kMatrix_Kind) {
488 this->write(ByteCodeInstruction::kScalarToMatrix);
489 this->write8(outType.columns());
490 this->write8(outType.rows());
491 } else {
492 SkASSERT(outType.kind() == Type::kVector_Kind);
493 for (; inCount != outCount; ++inCount) {
494 this->write(ByteCodeInstruction::kDup);
495 }
Brian Osmanc51d7912019-05-22 15:16:16 -0700496 }
497 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400498 }
499}
500
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400501void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f) {
502 int argumentCount = 0;
503 for (const auto& arg : f.fArguments) {
504 this->writeExpression(*arg);
Brian Osman07c117b2019-05-23 12:51:06 -0700505 argumentCount += SlotCount(arg->fType);
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400506 }
507 this->write(ByteCodeInstruction::kCallExternal);
508 SkASSERT(argumentCount <= 255);
509 this->write8(argumentCount);
Brian Osman07c117b2019-05-23 12:51:06 -0700510 this->write8(SlotCount(f.fType));
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400511 int index = fOutput->fExternalValues.size();
512 fOutput->fExternalValues.push_back(f.fFunction);
513 SkASSERT(index <= 255);
514 this->write8(index);
515}
516
Ethan Nicholas91164d12019-05-15 15:29:54 -0400517void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400518 this->write(vector_instruction(ByteCodeInstruction::kReadExternal,
Brian Osman07c117b2019-05-23 12:51:06 -0700519 SlotCount(e.fValue->type())));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400520 int index = fOutput->fExternalValues.size();
521 fOutput->fExternalValues.push_back(e.fValue);
522 SkASSERT(index <= 255);
523 this->write8(index);
524}
525
Brian Osman07c117b2019-05-23 12:51:06 -0700526void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
527 Variable::Storage storage;
528 int location = this->getLocation(expr, &storage);
529 bool isGlobal = storage == Variable::kGlobal_Storage;
530 int count = SlotCount(expr.fType);
531 if (location < 0 || count > 4) {
532 if (location >= 0) {
533 this->write(ByteCodeInstruction::kPushImmediate);
534 this->write32(location);
535 }
536 this->write(isGlobal ? ByteCodeInstruction::kLoadExtendedGlobal
537 : ByteCodeInstruction::kLoadExtended);
538 this->write8(count);
539 } else {
540 this->write(vector_instruction(isGlobal ? ByteCodeInstruction::kLoadGlobal
541 : ByteCodeInstruction::kLoad,
542 count));
543 this->write8(location);
544 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400545}
546
547void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
548 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400549 this->write32(Interpreter::Value((float) f.fValue).fUnsigned);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400550}
551
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400552void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
553 auto found = fIntrinsics.find(c.fFunction.fName);
554 if (found == fIntrinsics.end()) {
555 fErrors.error(c.fOffset, "unsupported intrinsic function");
556 return;
557 }
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400558 if (found->second.fIsSpecial) {
559 SkASSERT(found->second.fValue.fSpecial == SpecialIntrinsic::kDot);
560 SkASSERT(c.fArguments.size() == 2);
561 SkASSERT(SlotCount(c.fArguments[0]->fType) == SlotCount(c.fArguments[1]->fType));
562 this->write((ByteCodeInstruction) ((int) ByteCodeInstruction::kMultiplyF +
563 SlotCount(c.fArguments[0]->fType) - 1));
564 for (int i = SlotCount(c.fArguments[0]->fType); i > 1; --i) {
565 this->write(ByteCodeInstruction::kAddF);
566 }
567 } else {
568 switch (found->second.fValue.fInstruction) {
569 case ByteCodeInstruction::kCos:
570 case ByteCodeInstruction::kMix:
571 case ByteCodeInstruction::kSin:
572 case ByteCodeInstruction::kSqrt:
573 case ByteCodeInstruction::kTan:
574 SkASSERT(c.fArguments.size() > 0);
575 this->write((ByteCodeInstruction) ((int) found->second.fValue.fInstruction +
576 SlotCount(c.fArguments[0]->fType) - 1));
577 break;
578 case ByteCodeInstruction::kCross:
579 this->write(found->second.fValue.fInstruction);
580 break;
581 default:
582 SkASSERT(false);
583 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400584 }
585}
586
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400587void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400588 for (const auto& arg : f.fArguments) {
589 this->writeExpression(*arg);
590 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400591 if (f.fFunction.fBuiltin) {
592 this->writeIntrinsicCall(f);
593 return;
594 }
Brian Osman226668a2019-05-14 16:47:30 -0400595 this->write(ByteCodeInstruction::kCall);
596 fCallTargets.emplace_back(this, f.fFunction);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400597}
598
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400599void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
600 this->write(ByteCodeInstruction::kPushImmediate);
601 this->write32(i.fValue);
602}
603
604void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
605 // not yet implemented
606 abort();
607}
608
609void ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p) {
610 switch (p.fOperator) {
611 case Token::Kind::PLUSPLUS: // fall through
612 case Token::Kind::MINUSMINUS: {
Brian Osman07c117b2019-05-23 12:51:06 -0700613 SkASSERT(SlotCount(p.fOperand->fType) == 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400614 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
615 lvalue->load();
616 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400617 this->write32(type_category(p.fType) == TypeCategory::kFloat
618 ? Interpreter::Value(1.0f).fUnsigned : 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400619 if (p.fOperator == Token::Kind::PLUSPLUS) {
620 this->writeTypedInstruction(p.fType,
621 ByteCodeInstruction::kAddI,
622 ByteCodeInstruction::kAddI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400623 ByteCodeInstruction::kAddF,
624 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400625 } else {
626 this->writeTypedInstruction(p.fType,
627 ByteCodeInstruction::kSubtractI,
628 ByteCodeInstruction::kSubtractI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400629 ByteCodeInstruction::kSubtractF,
630 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400631 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400632 lvalue->store();
633 break;
634 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400635 case Token::Kind::MINUS: {
636 this->writeExpression(*p.fOperand);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400637 this->writeTypedInstruction(p.fType,
Mike Klein12710912019-05-21 11:04:59 -0500638 ByteCodeInstruction::kNegateI,
639 ByteCodeInstruction::kNegateI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400640 ByteCodeInstruction::kNegateF,
Brian Osman07c117b2019-05-23 12:51:06 -0700641 SlotCount(p.fOperand->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400642 break;
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400643 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400644 default:
645 SkASSERT(false);
646 }
647}
648
649void ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p) {
Brian Osmanf3fa6002019-05-17 14:26:53 -0400650 switch (p.fOperator) {
651 case Token::Kind::PLUSPLUS: // fall through
652 case Token::Kind::MINUSMINUS: {
Brian Osman07c117b2019-05-23 12:51:06 -0700653 SkASSERT(SlotCount(p.fOperand->fType) == 1);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400654 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
655 lvalue->load();
656 this->write(ByteCodeInstruction::kDup);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400657 this->write(ByteCodeInstruction::kPushImmediate);
658 this->write32(type_category(p.fType) == TypeCategory::kFloat
659 ? Interpreter::Value(1.0f).fUnsigned : 1);
660 if (p.fOperator == Token::Kind::PLUSPLUS) {
661 this->writeTypedInstruction(p.fType,
662 ByteCodeInstruction::kAddI,
663 ByteCodeInstruction::kAddI,
664 ByteCodeInstruction::kAddF,
665 1);
666 } else {
667 this->writeTypedInstruction(p.fType,
668 ByteCodeInstruction::kSubtractI,
669 ByteCodeInstruction::kSubtractI,
670 ByteCodeInstruction::kSubtractF,
671 1);
672 }
673 lvalue->store();
674 this->write(ByteCodeInstruction::kPop);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400675 break;
676 }
677 default:
678 SkASSERT(false);
679 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400680}
681
682void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
Brian Osman0785db02019-05-24 14:19:11 -0400683 if (swizzle_is_simple(s)) {
684 this->writeVariableExpression(s);
685 return;
686 }
687
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400688 switch (s.fBase->fKind) {
689 case Expression::kVariableReference_Kind: {
690 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
Brian Osman1091f022019-05-16 09:42:16 -0400691 this->write(var.fStorage == Variable::kGlobal_Storage
692 ? ByteCodeInstruction::kLoadSwizzleGlobal
693 : ByteCodeInstruction::kLoadSwizzle);
694 this->write8(this->getLocation(var));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400695 this->write8(s.fComponents.size());
696 for (int c : s.fComponents) {
697 this->write8(c);
698 }
699 break;
700 }
701 default:
702 this->writeExpression(*s.fBase);
703 this->write(ByteCodeInstruction::kSwizzle);
704 this->write8(s.fBase->fType.columns());
705 this->write8(s.fComponents.size());
706 for (int c : s.fComponents) {
707 this->write8(c);
708 }
709 }
710}
711
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400712void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Brian Osman4e93feb2019-05-16 15:38:00 -0400713 this->writeExpression(*t.fTest);
Brian Osman4e93feb2019-05-16 15:38:00 -0400714 this->write(ByteCodeInstruction::kConditionalBranch);
715 DeferredLocation trueLocation(this);
716 this->writeExpression(*t.fIfFalse);
Brian Osman4e93feb2019-05-16 15:38:00 -0400717 this->write(ByteCodeInstruction::kBranch);
718 DeferredLocation endLocation(this);
719 trueLocation.set();
720 this->writeExpression(*t.fIfTrue);
721 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400722}
723
724void ByteCodeGenerator::writeExpression(const Expression& e) {
725 switch (e.fKind) {
726 case Expression::kBinary_Kind:
727 this->writeBinaryExpression((BinaryExpression&) e);
728 break;
729 case Expression::kBoolLiteral_Kind:
730 this->writeBoolLiteral((BoolLiteral&) e);
731 break;
732 case Expression::kConstructor_Kind:
733 this->writeConstructor((Constructor&) e);
734 break;
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400735 case Expression::kExternalFunctionCall_Kind:
736 this->writeExternalFunctionCall((ExternalFunctionCall&) e);
737 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400738 case Expression::kExternalValue_Kind:
739 this->writeExternalValue((ExternalValueReference&) e);
740 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400741 case Expression::kFieldAccess_Kind:
Brian Osman07c117b2019-05-23 12:51:06 -0700742 case Expression::kIndex_Kind:
743 case Expression::kVariableReference_Kind:
744 this->writeVariableExpression(e);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400745 break;
746 case Expression::kFloatLiteral_Kind:
747 this->writeFloatLiteral((FloatLiteral&) e);
748 break;
749 case Expression::kFunctionCall_Kind:
750 this->writeFunctionCall((FunctionCall&) e);
751 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400752 case Expression::kIntLiteral_Kind:
753 this->writeIntLiteral((IntLiteral&) e);
754 break;
755 case Expression::kNullLiteral_Kind:
756 this->writeNullLiteral((NullLiteral&) e);
757 break;
758 case Expression::kPrefix_Kind:
759 this->writePrefixExpression((PrefixExpression&) e);
760 break;
761 case Expression::kPostfix_Kind:
762 this->writePostfixExpression((PostfixExpression&) e);
763 break;
764 case Expression::kSwizzle_Kind:
765 this->writeSwizzle((Swizzle&) e);
766 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400767 case Expression::kTernary_Kind:
768 this->writeTernaryExpression((TernaryExpression&) e);
769 break;
770 default:
771 printf("unsupported expression %s\n", e.description().c_str());
772 SkASSERT(false);
773 }
774}
775
Ethan Nicholas91164d12019-05-15 15:29:54 -0400776class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
777public:
778 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
779 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700780 , fCount(ByteCodeGenerator::SlotCount(value.type()))
Ethan Nicholas91164d12019-05-15 15:29:54 -0400781 , fIndex(index) {}
782
783 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400784 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400785 fGenerator.write8(fIndex);
786 }
787
788 void store() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400789 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
790 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400791 fGenerator.write8(fIndex);
792 }
793
794private:
795 typedef LValue INHERITED;
796
797 int fCount;
798
799 int fIndex;
800};
801
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400802class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
803public:
804 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
805 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700806 , fSwizzle(swizzle) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400807
808 void load() override {
Brian Osman1091f022019-05-16 09:42:16 -0400809 fGenerator.writeSwizzle(fSwizzle);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400810 }
811
812 void store() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400813 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup,
814 fSwizzle.fComponents.size()));
Brian Osman07c117b2019-05-23 12:51:06 -0700815 Variable::Storage storage;
816 int location = fGenerator.getLocation(*fSwizzle.fBase, &storage);
817 bool isGlobal = storage == Variable::kGlobal_Storage;
818 if (location < 0) {
819 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleIndirectGlobal
820 : ByteCodeInstruction::kStoreSwizzleIndirect);
821 } else {
822 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleGlobal
823 : ByteCodeInstruction::kStoreSwizzle);
824 fGenerator.write8(location);
825 }
Brian Osman1091f022019-05-16 09:42:16 -0400826 fGenerator.write8(fSwizzle.fComponents.size());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400827 for (int c : fSwizzle.fComponents) {
828 fGenerator.write8(c);
829 }
830 }
831
832private:
833 const Swizzle& fSwizzle;
834
835 typedef LValue INHERITED;
836};
837
Brian Osman07c117b2019-05-23 12:51:06 -0700838class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400839public:
Brian Osman07c117b2019-05-23 12:51:06 -0700840 ByteCodeExpressionLValue(ByteCodeGenerator* generator, const Expression& expr)
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400841 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700842 , fExpression(expr) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400843
844 void load() override {
Brian Osman07c117b2019-05-23 12:51:06 -0700845 fGenerator.writeVariableExpression(fExpression);
Brian Osman1091f022019-05-16 09:42:16 -0400846 }
847
848 void store() override {
Brian Osman07c117b2019-05-23 12:51:06 -0700849 int count = ByteCodeGenerator::SlotCount(fExpression.fType);
850 if (count > 4) {
851 fGenerator.write(ByteCodeInstruction::kDupN);
852 fGenerator.write8(count);
853 } else {
854 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
855 }
856 Variable::Storage storage;
857 int location = fGenerator.getLocation(fExpression, &storage);
858 bool isGlobal = storage == Variable::kGlobal_Storage;
859 if (location < 0 || count > 4) {
860 if (location >= 0) {
861 fGenerator.write(ByteCodeInstruction::kPushImmediate);
862 fGenerator.write32(location);
863 }
864 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreExtendedGlobal
865 : ByteCodeInstruction::kStoreExtended);
866 fGenerator.write8(count);
867 } else {
868 fGenerator.write(vector_instruction(isGlobal ? ByteCodeInstruction::kStoreGlobal
869 : ByteCodeInstruction::kStore,
870 count));
871 fGenerator.write8(location);
872 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400873 }
874
875private:
876 typedef LValue INHERITED;
877
Brian Osman07c117b2019-05-23 12:51:06 -0700878 const Expression& fExpression;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400879};
880
881std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
882 switch (e.fKind) {
Ethan Nicholas91164d12019-05-15 15:29:54 -0400883 case Expression::kExternalValue_Kind: {
884 ExternalValue* value = ((ExternalValueReference&) e).fValue;
885 int index = fOutput->fExternalValues.size();
886 fOutput->fExternalValues.push_back(value);
887 SkASSERT(index <= 255);
888 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
889 }
Brian Osman07c117b2019-05-23 12:51:06 -0700890 case Expression::kFieldAccess_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400891 case Expression::kIndex_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400892 case Expression::kVariableReference_Kind:
Brian Osman07c117b2019-05-23 12:51:06 -0700893 return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
Brian Osman0785db02019-05-24 14:19:11 -0400894 case Expression::kSwizzle_Kind: {
895 const Swizzle& s = (const Swizzle&) e;
896 return swizzle_is_simple(s)
897 ? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e))
898 : std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s));
899 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400900 case Expression::kTernary_Kind:
901 default:
902 printf("unsupported lvalue %s\n", e.description().c_str());
903 return nullptr;
904 }
905}
906
907void ByteCodeGenerator::writeBlock(const Block& b) {
908 for (const auto& s : b.fStatements) {
909 this->writeStatement(*s);
910 }
911}
912
913void ByteCodeGenerator::setBreakTargets() {
914 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
915 for (DeferredLocation& b : breaks) {
916 b.set();
917 }
918 fBreakTargets.pop();
919}
920
921void ByteCodeGenerator::setContinueTargets() {
922 std::vector<DeferredLocation>& continues = fContinueTargets.top();
923 for (DeferredLocation& c : continues) {
924 c.set();
925 }
926 fContinueTargets.pop();
927}
928
929void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
930 this->write(ByteCodeInstruction::kBranch);
931 fBreakTargets.top().emplace_back(this);
932}
933
934void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
935 this->write(ByteCodeInstruction::kBranch);
936 fContinueTargets.top().emplace_back(this);
937}
938
939void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
940 fContinueTargets.emplace();
941 fBreakTargets.emplace();
942 size_t start = fCode->size();
943 this->writeStatement(*d.fStatement);
944 this->setContinueTargets();
945 this->writeExpression(*d.fTest);
946 this->write(ByteCodeInstruction::kConditionalBranch);
947 this->write16(start);
948 this->setBreakTargets();
949}
950
951void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
952 fContinueTargets.emplace();
953 fBreakTargets.emplace();
954 if (f.fInitializer) {
955 this->writeStatement(*f.fInitializer);
956 }
957 size_t start = fCode->size();
958 if (f.fTest) {
959 this->writeExpression(*f.fTest);
960 this->write(ByteCodeInstruction::kNot);
961 this->write(ByteCodeInstruction::kConditionalBranch);
962 DeferredLocation endLocation(this);
963 this->writeStatement(*f.fStatement);
964 this->setContinueTargets();
965 if (f.fNext) {
966 this->writeExpression(*f.fNext);
Brian Osman07c117b2019-05-23 12:51:06 -0700967 this->write(vector_instruction(ByteCodeInstruction::kPop, SlotCount(f.fNext->fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400968 }
969 this->write(ByteCodeInstruction::kBranch);
970 this->write16(start);
971 endLocation.set();
972 } else {
973 this->writeStatement(*f.fStatement);
974 this->setContinueTargets();
975 if (f.fNext) {
976 this->writeExpression(*f.fNext);
Brian Osman07c117b2019-05-23 12:51:06 -0700977 this->write(vector_instruction(ByteCodeInstruction::kPop, SlotCount(f.fNext->fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400978 }
979 this->write(ByteCodeInstruction::kBranch);
980 this->write16(start);
981 }
982 this->setBreakTargets();
983}
984
985void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400986 if (i.fIfFalse) {
Mike Kleinb45ee832019-05-17 11:11:11 -0500987 // if (test) { ..ifTrue.. } else { .. ifFalse .. }
988 this->writeExpression(*i.fTest);
Mike Kleinb45ee832019-05-17 11:11:11 -0500989 this->write(ByteCodeInstruction::kConditionalBranch);
990 DeferredLocation trueLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400991 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -0500992 this->write(ByteCodeInstruction::kBranch);
993 DeferredLocation endLocation(this);
994 trueLocation.set();
995 this->writeStatement(*i.fIfTrue);
996 endLocation.set();
997 } else {
998 // if (test) { ..ifTrue.. }
999 this->writeExpression(*i.fTest);
1000 this->write(ByteCodeInstruction::kNot);
Mike Kleinb45ee832019-05-17 11:11:11 -05001001 this->write(ByteCodeInstruction::kConditionalBranch);
1002 DeferredLocation endLocation(this);
1003 this->writeStatement(*i.fIfTrue);
1004 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001005 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001006}
1007
1008void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -04001009 this->writeExpression(*r.fExpression);
1010 this->write(ByteCodeInstruction::kReturn);
Brian Osman07c117b2019-05-23 12:51:06 -07001011 this->write8(SlotCount(r.fExpression->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001012}
1013
1014void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
1015 // not yet implemented
1016 abort();
1017}
1018
1019void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1020 for (const auto& declStatement : v.fVars) {
1021 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
1022 // we need to grab the location even if we don't use it, to ensure it
1023 // has been allocated
1024 int location = getLocation(*decl.fVar);
1025 if (decl.fValue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001026 this->writeExpression(*decl.fValue);
Brian Osman07c117b2019-05-23 12:51:06 -07001027 int count = SlotCount(decl.fValue->fType);
1028 if (count > 4) {
1029 this->write(ByteCodeInstruction::kPushImmediate);
1030 this->write32(location);
1031 this->write(ByteCodeInstruction::kStoreExtended);
1032 this->write8(count);
1033 } else {
1034 this->write(vector_instruction(ByteCodeInstruction::kStore, count));
1035 this->write8(location);
1036 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001037 }
1038 }
1039}
1040
1041void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
1042 fContinueTargets.emplace();
1043 fBreakTargets.emplace();
1044 size_t start = fCode->size();
1045 this->writeExpression(*w.fTest);
1046 this->write(ByteCodeInstruction::kNot);
1047 this->write(ByteCodeInstruction::kConditionalBranch);
1048 DeferredLocation endLocation(this);
1049 this->writeStatement(*w.fStatement);
1050 this->setContinueTargets();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001051 this->write(ByteCodeInstruction::kBranch);
1052 this->write16(start);
1053 endLocation.set();
1054 this->setBreakTargets();
1055}
1056
1057void ByteCodeGenerator::writeStatement(const Statement& s) {
1058 switch (s.fKind) {
1059 case Statement::kBlock_Kind:
1060 this->writeBlock((Block&) s);
1061 break;
1062 case Statement::kBreak_Kind:
1063 this->writeBreakStatement((BreakStatement&) s);
1064 break;
1065 case Statement::kContinue_Kind:
1066 this->writeContinueStatement((ContinueStatement&) s);
1067 break;
1068 case Statement::kDiscard_Kind:
1069 // not yet implemented
1070 abort();
1071 case Statement::kDo_Kind:
1072 this->writeDoStatement((DoStatement&) s);
1073 break;
1074 case Statement::kExpression_Kind: {
1075 const Expression& expr = *((ExpressionStatement&) s).fExpression;
1076 this->writeExpression(expr);
Brian Osman07c117b2019-05-23 12:51:06 -07001077 int count = SlotCount(expr.fType);
1078 if (count > 4) {
1079 this->write(ByteCodeInstruction::kPopN);
1080 this->write8(count);
1081 } else {
1082 this->write(vector_instruction(ByteCodeInstruction::kPop, count));
1083 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001084 break;
1085 }
1086 case Statement::kFor_Kind:
1087 this->writeForStatement((ForStatement&) s);
1088 break;
1089 case Statement::kIf_Kind:
1090 this->writeIfStatement((IfStatement&) s);
1091 break;
1092 case Statement::kNop_Kind:
1093 break;
1094 case Statement::kReturn_Kind:
1095 this->writeReturnStatement((ReturnStatement&) s);
1096 break;
1097 case Statement::kSwitch_Kind:
1098 this->writeSwitchStatement((SwitchStatement&) s);
1099 break;
1100 case Statement::kVarDeclarations_Kind:
1101 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1102 break;
1103 case Statement::kWhile_Kind:
1104 this->writeWhileStatement((WhileStatement&) s);
1105 break;
1106 default:
1107 SkASSERT(false);
1108 }
1109}
1110
1111}