blob: 9958466814c979c2d4fcc0080de57c823d58f01f [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 }
337 Token::Kind op;
338 std::unique_ptr<LValue> lvalue;
339 if (is_assignment(b.fOperator)) {
340 lvalue = this->getLValue(*b.fLeft);
341 lvalue->load();
342 op = remove_assignment(b.fOperator);
343 } else {
344 this->writeExpression(*b.fLeft);
345 op = b.fOperator;
346 if (b.fLeft->fType.kind() == Type::kScalar_Kind &&
347 b.fRight->fType.kind() == Type::kVector_Kind) {
348 for (int i = b.fRight->fType.columns(); i > 1; --i) {
349 this->write(ByteCodeInstruction::kDup);
350 }
351 }
352 }
353 this->writeExpression(*b.fRight);
354 if (b.fLeft->fType.kind() == Type::kVector_Kind &&
355 b.fRight->fType.kind() == Type::kScalar_Kind) {
356 for (int i = b.fLeft->fType.columns(); i > 1; --i) {
357 this->write(ByteCodeInstruction::kDup);
358 }
359 }
Brian Osman07c117b2019-05-23 12:51:06 -0700360 int count = SlotCount(b.fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400361 switch (op) {
362 case Token::Kind::EQEQ:
363 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareIEQ,
364 ByteCodeInstruction::kCompareIEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400365 ByteCodeInstruction::kCompareFEQ,
366 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400367 break;
368 case Token::Kind::GT:
369 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGT,
370 ByteCodeInstruction::kCompareUGT,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400371 ByteCodeInstruction::kCompareFGT,
372 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400373 break;
374 case Token::Kind::GTEQ:
375 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGTEQ,
376 ByteCodeInstruction::kCompareUGTEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400377 ByteCodeInstruction::kCompareFGTEQ,
378 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400379 break;
380 case Token::Kind::LT:
381 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLT,
382 ByteCodeInstruction::kCompareULT,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400383 ByteCodeInstruction::kCompareFLT,
384 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400385 break;
386 case Token::Kind::LTEQ:
387 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLTEQ,
388 ByteCodeInstruction::kCompareULTEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400389 ByteCodeInstruction::kCompareFLTEQ,
390 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400391 break;
392 case Token::Kind::MINUS:
393 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kSubtractI,
394 ByteCodeInstruction::kSubtractI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400395 ByteCodeInstruction::kSubtractF,
396 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400397 break;
398 case Token::Kind::NEQ:
399 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareINEQ,
400 ByteCodeInstruction::kCompareINEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400401 ByteCodeInstruction::kCompareFNEQ,
402 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400403 break;
404 case Token::Kind::PERCENT:
405 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kRemainderS,
406 ByteCodeInstruction::kRemainderU,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400407 ByteCodeInstruction::kRemainderF,
408 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400409 break;
410 case Token::Kind::PLUS:
411 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kAddI,
412 ByteCodeInstruction::kAddI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400413 ByteCodeInstruction::kAddF,
414 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400415 break;
416 case Token::Kind::SLASH:
417 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kDivideS,
418 ByteCodeInstruction::kDivideU,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400419 ByteCodeInstruction::kDivideF,
420 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400421 break;
422 case Token::Kind::STAR:
Ethan Nicholas91164d12019-05-15 15:29:54 -0400423 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kMultiplyI,
424 ByteCodeInstruction::kMultiplyI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400425 ByteCodeInstruction::kMultiplyF,
426 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400427 break;
428 default:
429 SkASSERT(false);
430 }
431 if (lvalue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400432 lvalue->store();
433 }
434}
435
436void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
437 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osman44d44762019-05-13 14:19:12 -0400438 this->write32(b.fValue ? 1 : 0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400439}
440
441void ByteCodeGenerator::writeConstructor(const Constructor& c) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400442 for (const auto& arg : c.fArguments) {
443 this->writeExpression(*arg);
444 }
445 if (c.fArguments.size() == 1) {
Brian Osman29e013d2019-05-28 17:16:03 -0400446 const Type& inType = c.fArguments[0]->fType;
447 const Type& outType = c.fType;
448 TypeCategory inCategory = type_category(inType);
449 TypeCategory outCategory = type_category(outType);
450 int inCount = SlotCount(inType);
451 int outCount = SlotCount(outType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400452 if (inCategory != outCategory) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700453 SkASSERT(inCount == outCount);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400454 if (inCategory == TypeCategory::kFloat) {
455 SkASSERT(outCategory == TypeCategory::kSigned ||
456 outCategory == TypeCategory::kUnsigned);
Brian Osmanc51d7912019-05-22 15:16:16 -0700457 this->write(vector_instruction(ByteCodeInstruction::kConvertFtoI, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400458 } else if (outCategory == TypeCategory::kFloat) {
459 if (inCategory == TypeCategory::kSigned) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700460 this->write(vector_instruction(ByteCodeInstruction::kConvertStoF, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400461 } else {
462 SkASSERT(inCategory == TypeCategory::kUnsigned);
Brian Osmanc51d7912019-05-22 15:16:16 -0700463 this->write(vector_instruction(ByteCodeInstruction::kConvertUtoF, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400464 }
465 } else {
466 SkASSERT(false);
467 }
468 }
Brian Osman29e013d2019-05-28 17:16:03 -0400469 if (inType.kind() == Type::kMatrix_Kind && outType.kind() == Type::kMatrix_Kind) {
470 this->write(ByteCodeInstruction::kMatrixToMatrix);
471 this->write8(inType.columns());
472 this->write8(inType.rows());
473 this->write8(outType.columns());
474 this->write8(outType.rows());
475 } else if (inCount != outCount) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700476 SkASSERT(inCount == 1);
Brian Osman29e013d2019-05-28 17:16:03 -0400477 if (outType.kind() == Type::kMatrix_Kind) {
478 this->write(ByteCodeInstruction::kScalarToMatrix);
479 this->write8(outType.columns());
480 this->write8(outType.rows());
481 } else {
482 SkASSERT(outType.kind() == Type::kVector_Kind);
483 for (; inCount != outCount; ++inCount) {
484 this->write(ByteCodeInstruction::kDup);
485 }
Brian Osmanc51d7912019-05-22 15:16:16 -0700486 }
487 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400488 }
489}
490
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400491void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f) {
492 int argumentCount = 0;
493 for (const auto& arg : f.fArguments) {
494 this->writeExpression(*arg);
Brian Osman07c117b2019-05-23 12:51:06 -0700495 argumentCount += SlotCount(arg->fType);
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400496 }
497 this->write(ByteCodeInstruction::kCallExternal);
498 SkASSERT(argumentCount <= 255);
499 this->write8(argumentCount);
Brian Osman07c117b2019-05-23 12:51:06 -0700500 this->write8(SlotCount(f.fType));
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400501 int index = fOutput->fExternalValues.size();
502 fOutput->fExternalValues.push_back(f.fFunction);
503 SkASSERT(index <= 255);
504 this->write8(index);
505}
506
Ethan Nicholas91164d12019-05-15 15:29:54 -0400507void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400508 this->write(vector_instruction(ByteCodeInstruction::kReadExternal,
Brian Osman07c117b2019-05-23 12:51:06 -0700509 SlotCount(e.fValue->type())));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400510 int index = fOutput->fExternalValues.size();
511 fOutput->fExternalValues.push_back(e.fValue);
512 SkASSERT(index <= 255);
513 this->write8(index);
514}
515
Brian Osman07c117b2019-05-23 12:51:06 -0700516void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
517 Variable::Storage storage;
518 int location = this->getLocation(expr, &storage);
519 bool isGlobal = storage == Variable::kGlobal_Storage;
520 int count = SlotCount(expr.fType);
521 if (location < 0 || count > 4) {
522 if (location >= 0) {
523 this->write(ByteCodeInstruction::kPushImmediate);
524 this->write32(location);
525 }
526 this->write(isGlobal ? ByteCodeInstruction::kLoadExtendedGlobal
527 : ByteCodeInstruction::kLoadExtended);
528 this->write8(count);
529 } else {
530 this->write(vector_instruction(isGlobal ? ByteCodeInstruction::kLoadGlobal
531 : ByteCodeInstruction::kLoad,
532 count));
533 this->write8(location);
534 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400535}
536
537void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
538 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400539 this->write32(Interpreter::Value((float) f.fValue).fUnsigned);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400540}
541
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400542void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
543 auto found = fIntrinsics.find(c.fFunction.fName);
544 if (found == fIntrinsics.end()) {
545 fErrors.error(c.fOffset, "unsupported intrinsic function");
546 return;
547 }
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400548 if (found->second.fIsSpecial) {
549 SkASSERT(found->second.fValue.fSpecial == SpecialIntrinsic::kDot);
550 SkASSERT(c.fArguments.size() == 2);
551 SkASSERT(SlotCount(c.fArguments[0]->fType) == SlotCount(c.fArguments[1]->fType));
552 this->write((ByteCodeInstruction) ((int) ByteCodeInstruction::kMultiplyF +
553 SlotCount(c.fArguments[0]->fType) - 1));
554 for (int i = SlotCount(c.fArguments[0]->fType); i > 1; --i) {
555 this->write(ByteCodeInstruction::kAddF);
556 }
557 } else {
558 switch (found->second.fValue.fInstruction) {
559 case ByteCodeInstruction::kCos:
560 case ByteCodeInstruction::kMix:
561 case ByteCodeInstruction::kSin:
562 case ByteCodeInstruction::kSqrt:
563 case ByteCodeInstruction::kTan:
564 SkASSERT(c.fArguments.size() > 0);
565 this->write((ByteCodeInstruction) ((int) found->second.fValue.fInstruction +
566 SlotCount(c.fArguments[0]->fType) - 1));
567 break;
568 case ByteCodeInstruction::kCross:
569 this->write(found->second.fValue.fInstruction);
570 break;
571 default:
572 SkASSERT(false);
573 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400574 }
575}
576
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400577void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400578 for (const auto& arg : f.fArguments) {
579 this->writeExpression(*arg);
580 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400581 if (f.fFunction.fBuiltin) {
582 this->writeIntrinsicCall(f);
583 return;
584 }
Brian Osman226668a2019-05-14 16:47:30 -0400585 this->write(ByteCodeInstruction::kCall);
586 fCallTargets.emplace_back(this, f.fFunction);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400587}
588
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400589void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
590 this->write(ByteCodeInstruction::kPushImmediate);
591 this->write32(i.fValue);
592}
593
594void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
595 // not yet implemented
596 abort();
597}
598
599void ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p) {
600 switch (p.fOperator) {
601 case Token::Kind::PLUSPLUS: // fall through
602 case Token::Kind::MINUSMINUS: {
Brian Osman07c117b2019-05-23 12:51:06 -0700603 SkASSERT(SlotCount(p.fOperand->fType) == 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400604 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
605 lvalue->load();
606 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400607 this->write32(type_category(p.fType) == TypeCategory::kFloat
608 ? Interpreter::Value(1.0f).fUnsigned : 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400609 if (p.fOperator == Token::Kind::PLUSPLUS) {
610 this->writeTypedInstruction(p.fType,
611 ByteCodeInstruction::kAddI,
612 ByteCodeInstruction::kAddI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400613 ByteCodeInstruction::kAddF,
614 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400615 } else {
616 this->writeTypedInstruction(p.fType,
617 ByteCodeInstruction::kSubtractI,
618 ByteCodeInstruction::kSubtractI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400619 ByteCodeInstruction::kSubtractF,
620 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400621 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400622 lvalue->store();
623 break;
624 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400625 case Token::Kind::MINUS: {
626 this->writeExpression(*p.fOperand);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400627 this->writeTypedInstruction(p.fType,
Mike Klein12710912019-05-21 11:04:59 -0500628 ByteCodeInstruction::kNegateI,
629 ByteCodeInstruction::kNegateI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400630 ByteCodeInstruction::kNegateF,
Brian Osman07c117b2019-05-23 12:51:06 -0700631 SlotCount(p.fOperand->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400632 break;
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400633 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400634 default:
635 SkASSERT(false);
636 }
637}
638
639void ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p) {
Brian Osmanf3fa6002019-05-17 14:26:53 -0400640 switch (p.fOperator) {
641 case Token::Kind::PLUSPLUS: // fall through
642 case Token::Kind::MINUSMINUS: {
Brian Osman07c117b2019-05-23 12:51:06 -0700643 SkASSERT(SlotCount(p.fOperand->fType) == 1);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400644 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
645 lvalue->load();
646 this->write(ByteCodeInstruction::kDup);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400647 this->write(ByteCodeInstruction::kPushImmediate);
648 this->write32(type_category(p.fType) == TypeCategory::kFloat
649 ? Interpreter::Value(1.0f).fUnsigned : 1);
650 if (p.fOperator == Token::Kind::PLUSPLUS) {
651 this->writeTypedInstruction(p.fType,
652 ByteCodeInstruction::kAddI,
653 ByteCodeInstruction::kAddI,
654 ByteCodeInstruction::kAddF,
655 1);
656 } else {
657 this->writeTypedInstruction(p.fType,
658 ByteCodeInstruction::kSubtractI,
659 ByteCodeInstruction::kSubtractI,
660 ByteCodeInstruction::kSubtractF,
661 1);
662 }
663 lvalue->store();
664 this->write(ByteCodeInstruction::kPop);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400665 break;
666 }
667 default:
668 SkASSERT(false);
669 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400670}
671
672void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
Brian Osman0785db02019-05-24 14:19:11 -0400673 if (swizzle_is_simple(s)) {
674 this->writeVariableExpression(s);
675 return;
676 }
677
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400678 switch (s.fBase->fKind) {
679 case Expression::kVariableReference_Kind: {
680 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
Brian Osman1091f022019-05-16 09:42:16 -0400681 this->write(var.fStorage == Variable::kGlobal_Storage
682 ? ByteCodeInstruction::kLoadSwizzleGlobal
683 : ByteCodeInstruction::kLoadSwizzle);
684 this->write8(this->getLocation(var));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400685 this->write8(s.fComponents.size());
686 for (int c : s.fComponents) {
687 this->write8(c);
688 }
689 break;
690 }
691 default:
692 this->writeExpression(*s.fBase);
693 this->write(ByteCodeInstruction::kSwizzle);
694 this->write8(s.fBase->fType.columns());
695 this->write8(s.fComponents.size());
696 for (int c : s.fComponents) {
697 this->write8(c);
698 }
699 }
700}
701
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400702void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Brian Osman4e93feb2019-05-16 15:38:00 -0400703 this->writeExpression(*t.fTest);
Brian Osman4e93feb2019-05-16 15:38:00 -0400704 this->write(ByteCodeInstruction::kConditionalBranch);
705 DeferredLocation trueLocation(this);
706 this->writeExpression(*t.fIfFalse);
Brian Osman4e93feb2019-05-16 15:38:00 -0400707 this->write(ByteCodeInstruction::kBranch);
708 DeferredLocation endLocation(this);
709 trueLocation.set();
710 this->writeExpression(*t.fIfTrue);
711 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400712}
713
714void ByteCodeGenerator::writeExpression(const Expression& e) {
715 switch (e.fKind) {
716 case Expression::kBinary_Kind:
717 this->writeBinaryExpression((BinaryExpression&) e);
718 break;
719 case Expression::kBoolLiteral_Kind:
720 this->writeBoolLiteral((BoolLiteral&) e);
721 break;
722 case Expression::kConstructor_Kind:
723 this->writeConstructor((Constructor&) e);
724 break;
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400725 case Expression::kExternalFunctionCall_Kind:
726 this->writeExternalFunctionCall((ExternalFunctionCall&) e);
727 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400728 case Expression::kExternalValue_Kind:
729 this->writeExternalValue((ExternalValueReference&) e);
730 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400731 case Expression::kFieldAccess_Kind:
Brian Osman07c117b2019-05-23 12:51:06 -0700732 case Expression::kIndex_Kind:
733 case Expression::kVariableReference_Kind:
734 this->writeVariableExpression(e);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400735 break;
736 case Expression::kFloatLiteral_Kind:
737 this->writeFloatLiteral((FloatLiteral&) e);
738 break;
739 case Expression::kFunctionCall_Kind:
740 this->writeFunctionCall((FunctionCall&) e);
741 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400742 case Expression::kIntLiteral_Kind:
743 this->writeIntLiteral((IntLiteral&) e);
744 break;
745 case Expression::kNullLiteral_Kind:
746 this->writeNullLiteral((NullLiteral&) e);
747 break;
748 case Expression::kPrefix_Kind:
749 this->writePrefixExpression((PrefixExpression&) e);
750 break;
751 case Expression::kPostfix_Kind:
752 this->writePostfixExpression((PostfixExpression&) e);
753 break;
754 case Expression::kSwizzle_Kind:
755 this->writeSwizzle((Swizzle&) e);
756 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400757 case Expression::kTernary_Kind:
758 this->writeTernaryExpression((TernaryExpression&) e);
759 break;
760 default:
761 printf("unsupported expression %s\n", e.description().c_str());
762 SkASSERT(false);
763 }
764}
765
Ethan Nicholas91164d12019-05-15 15:29:54 -0400766class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
767public:
768 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
769 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700770 , fCount(ByteCodeGenerator::SlotCount(value.type()))
Ethan Nicholas91164d12019-05-15 15:29:54 -0400771 , fIndex(index) {}
772
773 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400774 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400775 fGenerator.write8(fIndex);
776 }
777
778 void store() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400779 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
780 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400781 fGenerator.write8(fIndex);
782 }
783
784private:
785 typedef LValue INHERITED;
786
787 int fCount;
788
789 int fIndex;
790};
791
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400792class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
793public:
794 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
795 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700796 , fSwizzle(swizzle) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400797
798 void load() override {
Brian Osman1091f022019-05-16 09:42:16 -0400799 fGenerator.writeSwizzle(fSwizzle);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400800 }
801
802 void store() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400803 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup,
804 fSwizzle.fComponents.size()));
Brian Osman07c117b2019-05-23 12:51:06 -0700805 Variable::Storage storage;
806 int location = fGenerator.getLocation(*fSwizzle.fBase, &storage);
807 bool isGlobal = storage == Variable::kGlobal_Storage;
808 if (location < 0) {
809 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleIndirectGlobal
810 : ByteCodeInstruction::kStoreSwizzleIndirect);
811 } else {
812 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleGlobal
813 : ByteCodeInstruction::kStoreSwizzle);
814 fGenerator.write8(location);
815 }
Brian Osman1091f022019-05-16 09:42:16 -0400816 fGenerator.write8(fSwizzle.fComponents.size());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400817 for (int c : fSwizzle.fComponents) {
818 fGenerator.write8(c);
819 }
820 }
821
822private:
823 const Swizzle& fSwizzle;
824
825 typedef LValue INHERITED;
826};
827
Brian Osman07c117b2019-05-23 12:51:06 -0700828class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400829public:
Brian Osman07c117b2019-05-23 12:51:06 -0700830 ByteCodeExpressionLValue(ByteCodeGenerator* generator, const Expression& expr)
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400831 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700832 , fExpression(expr) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400833
834 void load() override {
Brian Osman07c117b2019-05-23 12:51:06 -0700835 fGenerator.writeVariableExpression(fExpression);
Brian Osman1091f022019-05-16 09:42:16 -0400836 }
837
838 void store() override {
Brian Osman07c117b2019-05-23 12:51:06 -0700839 int count = ByteCodeGenerator::SlotCount(fExpression.fType);
840 if (count > 4) {
841 fGenerator.write(ByteCodeInstruction::kDupN);
842 fGenerator.write8(count);
843 } else {
844 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
845 }
846 Variable::Storage storage;
847 int location = fGenerator.getLocation(fExpression, &storage);
848 bool isGlobal = storage == Variable::kGlobal_Storage;
849 if (location < 0 || count > 4) {
850 if (location >= 0) {
851 fGenerator.write(ByteCodeInstruction::kPushImmediate);
852 fGenerator.write32(location);
853 }
854 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreExtendedGlobal
855 : ByteCodeInstruction::kStoreExtended);
856 fGenerator.write8(count);
857 } else {
858 fGenerator.write(vector_instruction(isGlobal ? ByteCodeInstruction::kStoreGlobal
859 : ByteCodeInstruction::kStore,
860 count));
861 fGenerator.write8(location);
862 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400863 }
864
865private:
866 typedef LValue INHERITED;
867
Brian Osman07c117b2019-05-23 12:51:06 -0700868 const Expression& fExpression;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400869};
870
871std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
872 switch (e.fKind) {
Ethan Nicholas91164d12019-05-15 15:29:54 -0400873 case Expression::kExternalValue_Kind: {
874 ExternalValue* value = ((ExternalValueReference&) e).fValue;
875 int index = fOutput->fExternalValues.size();
876 fOutput->fExternalValues.push_back(value);
877 SkASSERT(index <= 255);
878 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
879 }
Brian Osman07c117b2019-05-23 12:51:06 -0700880 case Expression::kFieldAccess_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400881 case Expression::kIndex_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400882 case Expression::kVariableReference_Kind:
Brian Osman07c117b2019-05-23 12:51:06 -0700883 return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
Brian Osman0785db02019-05-24 14:19:11 -0400884 case Expression::kSwizzle_Kind: {
885 const Swizzle& s = (const Swizzle&) e;
886 return swizzle_is_simple(s)
887 ? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e))
888 : std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s));
889 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400890 case Expression::kTernary_Kind:
891 default:
892 printf("unsupported lvalue %s\n", e.description().c_str());
893 return nullptr;
894 }
895}
896
897void ByteCodeGenerator::writeBlock(const Block& b) {
898 for (const auto& s : b.fStatements) {
899 this->writeStatement(*s);
900 }
901}
902
903void ByteCodeGenerator::setBreakTargets() {
904 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
905 for (DeferredLocation& b : breaks) {
906 b.set();
907 }
908 fBreakTargets.pop();
909}
910
911void ByteCodeGenerator::setContinueTargets() {
912 std::vector<DeferredLocation>& continues = fContinueTargets.top();
913 for (DeferredLocation& c : continues) {
914 c.set();
915 }
916 fContinueTargets.pop();
917}
918
919void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
920 this->write(ByteCodeInstruction::kBranch);
921 fBreakTargets.top().emplace_back(this);
922}
923
924void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
925 this->write(ByteCodeInstruction::kBranch);
926 fContinueTargets.top().emplace_back(this);
927}
928
929void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
930 fContinueTargets.emplace();
931 fBreakTargets.emplace();
932 size_t start = fCode->size();
933 this->writeStatement(*d.fStatement);
934 this->setContinueTargets();
935 this->writeExpression(*d.fTest);
936 this->write(ByteCodeInstruction::kConditionalBranch);
937 this->write16(start);
938 this->setBreakTargets();
939}
940
941void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
942 fContinueTargets.emplace();
943 fBreakTargets.emplace();
944 if (f.fInitializer) {
945 this->writeStatement(*f.fInitializer);
946 }
947 size_t start = fCode->size();
948 if (f.fTest) {
949 this->writeExpression(*f.fTest);
950 this->write(ByteCodeInstruction::kNot);
951 this->write(ByteCodeInstruction::kConditionalBranch);
952 DeferredLocation endLocation(this);
953 this->writeStatement(*f.fStatement);
954 this->setContinueTargets();
955 if (f.fNext) {
956 this->writeExpression(*f.fNext);
Brian Osman07c117b2019-05-23 12:51:06 -0700957 this->write(vector_instruction(ByteCodeInstruction::kPop, SlotCount(f.fNext->fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400958 }
959 this->write(ByteCodeInstruction::kBranch);
960 this->write16(start);
961 endLocation.set();
962 } else {
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 }
972 this->setBreakTargets();
973}
974
975void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400976 if (i.fIfFalse) {
Mike Kleinb45ee832019-05-17 11:11:11 -0500977 // if (test) { ..ifTrue.. } else { .. ifFalse .. }
978 this->writeExpression(*i.fTest);
Mike Kleinb45ee832019-05-17 11:11:11 -0500979 this->write(ByteCodeInstruction::kConditionalBranch);
980 DeferredLocation trueLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400981 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -0500982 this->write(ByteCodeInstruction::kBranch);
983 DeferredLocation endLocation(this);
984 trueLocation.set();
985 this->writeStatement(*i.fIfTrue);
986 endLocation.set();
987 } else {
988 // if (test) { ..ifTrue.. }
989 this->writeExpression(*i.fTest);
990 this->write(ByteCodeInstruction::kNot);
Mike Kleinb45ee832019-05-17 11:11:11 -0500991 this->write(ByteCodeInstruction::kConditionalBranch);
992 DeferredLocation endLocation(this);
993 this->writeStatement(*i.fIfTrue);
994 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400995 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400996}
997
998void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -0400999 this->writeExpression(*r.fExpression);
1000 this->write(ByteCodeInstruction::kReturn);
Brian Osman07c117b2019-05-23 12:51:06 -07001001 this->write8(SlotCount(r.fExpression->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001002}
1003
1004void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
1005 // not yet implemented
1006 abort();
1007}
1008
1009void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1010 for (const auto& declStatement : v.fVars) {
1011 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
1012 // we need to grab the location even if we don't use it, to ensure it
1013 // has been allocated
1014 int location = getLocation(*decl.fVar);
1015 if (decl.fValue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001016 this->writeExpression(*decl.fValue);
Brian Osman07c117b2019-05-23 12:51:06 -07001017 int count = SlotCount(decl.fValue->fType);
1018 if (count > 4) {
1019 this->write(ByteCodeInstruction::kPushImmediate);
1020 this->write32(location);
1021 this->write(ByteCodeInstruction::kStoreExtended);
1022 this->write8(count);
1023 } else {
1024 this->write(vector_instruction(ByteCodeInstruction::kStore, count));
1025 this->write8(location);
1026 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001027 }
1028 }
1029}
1030
1031void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
1032 fContinueTargets.emplace();
1033 fBreakTargets.emplace();
1034 size_t start = fCode->size();
1035 this->writeExpression(*w.fTest);
1036 this->write(ByteCodeInstruction::kNot);
1037 this->write(ByteCodeInstruction::kConditionalBranch);
1038 DeferredLocation endLocation(this);
1039 this->writeStatement(*w.fStatement);
1040 this->setContinueTargets();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001041 this->write(ByteCodeInstruction::kBranch);
1042 this->write16(start);
1043 endLocation.set();
1044 this->setBreakTargets();
1045}
1046
1047void ByteCodeGenerator::writeStatement(const Statement& s) {
1048 switch (s.fKind) {
1049 case Statement::kBlock_Kind:
1050 this->writeBlock((Block&) s);
1051 break;
1052 case Statement::kBreak_Kind:
1053 this->writeBreakStatement((BreakStatement&) s);
1054 break;
1055 case Statement::kContinue_Kind:
1056 this->writeContinueStatement((ContinueStatement&) s);
1057 break;
1058 case Statement::kDiscard_Kind:
1059 // not yet implemented
1060 abort();
1061 case Statement::kDo_Kind:
1062 this->writeDoStatement((DoStatement&) s);
1063 break;
1064 case Statement::kExpression_Kind: {
1065 const Expression& expr = *((ExpressionStatement&) s).fExpression;
1066 this->writeExpression(expr);
Brian Osman07c117b2019-05-23 12:51:06 -07001067 int count = SlotCount(expr.fType);
1068 if (count > 4) {
1069 this->write(ByteCodeInstruction::kPopN);
1070 this->write8(count);
1071 } else {
1072 this->write(vector_instruction(ByteCodeInstruction::kPop, count));
1073 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001074 break;
1075 }
1076 case Statement::kFor_Kind:
1077 this->writeForStatement((ForStatement&) s);
1078 break;
1079 case Statement::kIf_Kind:
1080 this->writeIfStatement((IfStatement&) s);
1081 break;
1082 case Statement::kNop_Kind:
1083 break;
1084 case Statement::kReturn_Kind:
1085 this->writeReturnStatement((ReturnStatement&) s);
1086 break;
1087 case Statement::kSwitch_Kind:
1088 this->writeSwitchStatement((SwitchStatement&) s);
1089 break;
1090 case Statement::kVarDeclarations_Kind:
1091 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1092 break;
1093 case Statement::kWhile_Kind:
1094 this->writeWhileStatement((WhileStatement&) s);
1095 break;
1096 default:
1097 SkASSERT(false);
1098 }
1099}
1100
1101}