blob: 16d43f4fb24413a26510b9d6cc8e6120e61f1bf8 [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
137int ByteCodeGenerator::getLocation(const Variable& var) {
138 // given that we seldom have more than a couple of variables, linear search is probably the most
139 // efficient way to handle lookups
140 switch (var.fStorage) {
141 case Variable::kLocal_Storage: {
142 for (int i = fLocals.size() - 1; i >= 0; --i) {
143 if (fLocals[i] == &var) {
Brian Osman1091f022019-05-16 09:42:16 -0400144 SkASSERT(fParameterCount + i <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400145 return fParameterCount + i;
146 }
147 }
148 int result = fParameterCount + fLocals.size();
149 fLocals.push_back(&var);
Brian Osman07c117b2019-05-23 12:51:06 -0700150 for (int i = 0; i < SlotCount(var.fType) - 1; ++i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400151 fLocals.push_back(nullptr);
152 }
Brian Osman1091f022019-05-16 09:42:16 -0400153 SkASSERT(result <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400154 return result;
155 }
156 case Variable::kParameter_Storage: {
157 int offset = 0;
158 for (const auto& p : fFunction->fDeclaration.fParameters) {
159 if (p == &var) {
Brian Osman1091f022019-05-16 09:42:16 -0400160 SkASSERT(offset <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400161 return offset;
162 }
Brian Osman07c117b2019-05-23 12:51:06 -0700163 offset += SlotCount(p->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400164 }
165 SkASSERT(false);
Brian Osman1091f022019-05-16 09:42:16 -0400166 return 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400167 }
168 case Variable::kGlobal_Storage: {
169 int offset = 0;
170 for (const auto& e : fProgram) {
171 if (e.fKind == ProgramElement::kVar_Kind) {
172 VarDeclarations& decl = (VarDeclarations&) e;
173 for (const auto& v : decl.fVars) {
174 const Variable* declVar = ((VarDeclaration&) *v).fVar;
175 if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
176 continue;
177 }
178 if (declVar == &var) {
Brian Osmanb7451292019-05-15 13:02:13 -0400179 SkASSERT(offset <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400180 return offset;
181 }
Brian Osman07c117b2019-05-23 12:51:06 -0700182 offset += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400183 }
184 }
185 }
186 SkASSERT(false);
Brian Osman1091f022019-05-16 09:42:16 -0400187 return 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400188 }
189 default:
190 SkASSERT(false);
191 return 0;
192 }
193}
194
Brian Osman07c117b2019-05-23 12:51:06 -0700195int ByteCodeGenerator::getLocation(const Expression& expr, Variable::Storage* storage) {
196 switch (expr.fKind) {
197 case Expression::kFieldAccess_Kind: {
198 const FieldAccess& f = (const FieldAccess&)expr;
199 int baseAddr = this->getLocation(*f.fBase, storage);
200 int offset = 0;
201 for (int i = 0; i < f.fFieldIndex; ++i) {
202 offset += SlotCount(*f.fBase->fType.fields()[i].fType);
203 }
204 if (baseAddr < 0) {
205 this->write(ByteCodeInstruction::kPushImmediate);
206 this->write32(offset);
207 this->write(ByteCodeInstruction::kAddI);
208 return -1;
209 } else {
210 return baseAddr + offset;
211 }
212 }
213 case Expression::kIndex_Kind: {
214 const IndexExpression& i = (const IndexExpression&)expr;
215 int stride = SlotCount(i.fType);
216 int offset = -1;
217 if (i.fIndex->isConstant()) {
218 offset = i.fIndex->getConstantInt() * stride;
219 } else {
220 this->writeExpression(*i.fIndex);
221 this->write(ByteCodeInstruction::kPushImmediate);
222 this->write32(stride);
223 this->write(ByteCodeInstruction::kMultiplyI);
224 }
225 int baseAddr = this->getLocation(*i.fBase, storage);
226 if (baseAddr >= 0 && offset >= 0) {
227 return baseAddr + offset;
228 }
229 if (baseAddr >= 0) {
230 this->write(ByteCodeInstruction::kPushImmediate);
231 this->write32(baseAddr);
232 }
233 if (offset >= 0) {
234 this->write(ByteCodeInstruction::kPushImmediate);
235 this->write32(offset);
236 }
237 this->write(ByteCodeInstruction::kAddI);
238 return -1;
239 }
240 case Expression::kVariableReference_Kind: {
241 const Variable& var = ((const VariableReference&)expr).fVariable;
242 *storage = var.fStorage;
243 return this->getLocation(var);
244 }
245 default:
246 SkASSERT(false);
247 return 0;
248 }
249}
250
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400251void ByteCodeGenerator::write8(uint8_t b) {
252 fCode->push_back(b);
253}
254
255void ByteCodeGenerator::write16(uint16_t i) {
Mike Klein76346ac2019-05-17 11:57:10 -0500256 size_t n = fCode->size();
257 fCode->resize(n+2);
258 memcpy(fCode->data() + n, &i, 2);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400259}
260
261void ByteCodeGenerator::write32(uint32_t i) {
Mike Klein76346ac2019-05-17 11:57:10 -0500262 size_t n = fCode->size();
263 fCode->resize(n+4);
264 memcpy(fCode->data() + n, &i, 4);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400265}
266
267void ByteCodeGenerator::write(ByteCodeInstruction i) {
Mike Klein108e9352019-05-21 11:05:17 -0500268 this->write16((uint16_t)i);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400269}
270
Mike Klein76346ac2019-05-17 11:57:10 -0500271static ByteCodeInstruction vector_instruction(ByteCodeInstruction base, int count) {
Brian Osman07c117b2019-05-23 12:51:06 -0700272 SkASSERT(count >= 1 && count <= 4);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400273 return ((ByteCodeInstruction) ((int) base + count - 1));
274}
275
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400276void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400277 ByteCodeInstruction u, ByteCodeInstruction f,
278 int count) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400279 switch (type_category(type)) {
280 case TypeCategory::kSigned:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400281 this->write(vector_instruction(s, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400282 break;
283 case TypeCategory::kUnsigned:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400284 this->write(vector_instruction(u, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400285 break;
286 case TypeCategory::kFloat:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400287 this->write(vector_instruction(f, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400288 break;
289 default:
290 SkASSERT(false);
291 }
292}
293
294void ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b) {
295 if (b.fOperator == Token::Kind::EQ) {
296 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
297 this->writeExpression(*b.fRight);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400298 lvalue->store();
299 return;
300 }
301 Token::Kind op;
302 std::unique_ptr<LValue> lvalue;
303 if (is_assignment(b.fOperator)) {
304 lvalue = this->getLValue(*b.fLeft);
305 lvalue->load();
306 op = remove_assignment(b.fOperator);
307 } else {
308 this->writeExpression(*b.fLeft);
309 op = b.fOperator;
310 if (b.fLeft->fType.kind() == Type::kScalar_Kind &&
311 b.fRight->fType.kind() == Type::kVector_Kind) {
312 for (int i = b.fRight->fType.columns(); i > 1; --i) {
313 this->write(ByteCodeInstruction::kDup);
314 }
315 }
316 }
317 this->writeExpression(*b.fRight);
318 if (b.fLeft->fType.kind() == Type::kVector_Kind &&
319 b.fRight->fType.kind() == Type::kScalar_Kind) {
320 for (int i = b.fLeft->fType.columns(); i > 1; --i) {
321 this->write(ByteCodeInstruction::kDup);
322 }
323 }
Brian Osman07c117b2019-05-23 12:51:06 -0700324 int count = SlotCount(b.fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400325 switch (op) {
326 case Token::Kind::EQEQ:
327 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareIEQ,
328 ByteCodeInstruction::kCompareIEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400329 ByteCodeInstruction::kCompareFEQ,
330 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400331 break;
332 case Token::Kind::GT:
333 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGT,
334 ByteCodeInstruction::kCompareUGT,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400335 ByteCodeInstruction::kCompareFGT,
336 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400337 break;
338 case Token::Kind::GTEQ:
339 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGTEQ,
340 ByteCodeInstruction::kCompareUGTEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400341 ByteCodeInstruction::kCompareFGTEQ,
342 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400343 break;
344 case Token::Kind::LT:
345 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLT,
346 ByteCodeInstruction::kCompareULT,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400347 ByteCodeInstruction::kCompareFLT,
348 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400349 break;
350 case Token::Kind::LTEQ:
351 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLTEQ,
352 ByteCodeInstruction::kCompareULTEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400353 ByteCodeInstruction::kCompareFLTEQ,
354 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400355 break;
356 case Token::Kind::MINUS:
357 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kSubtractI,
358 ByteCodeInstruction::kSubtractI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400359 ByteCodeInstruction::kSubtractF,
360 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400361 break;
362 case Token::Kind::NEQ:
363 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareINEQ,
364 ByteCodeInstruction::kCompareINEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400365 ByteCodeInstruction::kCompareFNEQ,
366 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400367 break;
368 case Token::Kind::PERCENT:
369 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kRemainderS,
370 ByteCodeInstruction::kRemainderU,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400371 ByteCodeInstruction::kRemainderF,
372 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400373 break;
374 case Token::Kind::PLUS:
375 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kAddI,
376 ByteCodeInstruction::kAddI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400377 ByteCodeInstruction::kAddF,
378 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400379 break;
380 case Token::Kind::SLASH:
381 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kDivideS,
382 ByteCodeInstruction::kDivideU,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400383 ByteCodeInstruction::kDivideF,
384 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400385 break;
386 case Token::Kind::STAR:
Ethan Nicholas91164d12019-05-15 15:29:54 -0400387 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kMultiplyI,
388 ByteCodeInstruction::kMultiplyI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400389 ByteCodeInstruction::kMultiplyF,
390 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400391 break;
392 default:
393 SkASSERT(false);
394 }
395 if (lvalue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400396 lvalue->store();
397 }
398}
399
400void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
401 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osman44d44762019-05-13 14:19:12 -0400402 this->write32(b.fValue ? 1 : 0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400403}
404
405void ByteCodeGenerator::writeConstructor(const Constructor& c) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400406 for (const auto& arg : c.fArguments) {
407 this->writeExpression(*arg);
408 }
409 if (c.fArguments.size() == 1) {
410 TypeCategory inCategory = type_category(c.fArguments[0]->fType);
411 TypeCategory outCategory = type_category(c.fType);
Brian Osmanc51d7912019-05-22 15:16:16 -0700412 int inCount = c.fArguments[0]->fType.columns();
413 int outCount = c.fType.columns();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400414 if (inCategory != outCategory) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700415 SkASSERT(inCount == outCount);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400416 if (inCategory == TypeCategory::kFloat) {
417 SkASSERT(outCategory == TypeCategory::kSigned ||
418 outCategory == TypeCategory::kUnsigned);
Brian Osmanc51d7912019-05-22 15:16:16 -0700419 this->write(vector_instruction(ByteCodeInstruction::kConvertFtoI, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400420 } else if (outCategory == TypeCategory::kFloat) {
421 if (inCategory == TypeCategory::kSigned) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700422 this->write(vector_instruction(ByteCodeInstruction::kConvertStoF, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400423 } else {
424 SkASSERT(inCategory == TypeCategory::kUnsigned);
Brian Osmanc51d7912019-05-22 15:16:16 -0700425 this->write(vector_instruction(ByteCodeInstruction::kConvertUtoF, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400426 }
427 } else {
428 SkASSERT(false);
429 }
430 }
Brian Osmanc51d7912019-05-22 15:16:16 -0700431 if (inCount != outCount) {
432 SkASSERT(inCount == 1);
433 for (; inCount != outCount; ++inCount) {
434 this->write(ByteCodeInstruction::kDup);
435 }
436 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400437 }
438}
439
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400440void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f) {
441 int argumentCount = 0;
442 for (const auto& arg : f.fArguments) {
443 this->writeExpression(*arg);
Brian Osman07c117b2019-05-23 12:51:06 -0700444 argumentCount += SlotCount(arg->fType);
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400445 }
446 this->write(ByteCodeInstruction::kCallExternal);
447 SkASSERT(argumentCount <= 255);
448 this->write8(argumentCount);
Brian Osman07c117b2019-05-23 12:51:06 -0700449 this->write8(SlotCount(f.fType));
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400450 int index = fOutput->fExternalValues.size();
451 fOutput->fExternalValues.push_back(f.fFunction);
452 SkASSERT(index <= 255);
453 this->write8(index);
454}
455
Ethan Nicholas91164d12019-05-15 15:29:54 -0400456void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400457 this->write(vector_instruction(ByteCodeInstruction::kReadExternal,
Brian Osman07c117b2019-05-23 12:51:06 -0700458 SlotCount(e.fValue->type())));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400459 int index = fOutput->fExternalValues.size();
460 fOutput->fExternalValues.push_back(e.fValue);
461 SkASSERT(index <= 255);
462 this->write8(index);
463}
464
Brian Osman07c117b2019-05-23 12:51:06 -0700465void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
466 Variable::Storage storage;
467 int location = this->getLocation(expr, &storage);
468 bool isGlobal = storage == Variable::kGlobal_Storage;
469 int count = SlotCount(expr.fType);
470 if (location < 0 || count > 4) {
471 if (location >= 0) {
472 this->write(ByteCodeInstruction::kPushImmediate);
473 this->write32(location);
474 }
475 this->write(isGlobal ? ByteCodeInstruction::kLoadExtendedGlobal
476 : ByteCodeInstruction::kLoadExtended);
477 this->write8(count);
478 } else {
479 this->write(vector_instruction(isGlobal ? ByteCodeInstruction::kLoadGlobal
480 : ByteCodeInstruction::kLoad,
481 count));
482 this->write8(location);
483 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400484}
485
486void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
487 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400488 this->write32(Interpreter::Value((float) f.fValue).fUnsigned);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400489}
490
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400491void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
492 auto found = fIntrinsics.find(c.fFunction.fName);
493 if (found == fIntrinsics.end()) {
494 fErrors.error(c.fOffset, "unsupported intrinsic function");
495 return;
496 }
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400497 if (found->second.fIsSpecial) {
498 SkASSERT(found->second.fValue.fSpecial == SpecialIntrinsic::kDot);
499 SkASSERT(c.fArguments.size() == 2);
500 SkASSERT(SlotCount(c.fArguments[0]->fType) == SlotCount(c.fArguments[1]->fType));
501 this->write((ByteCodeInstruction) ((int) ByteCodeInstruction::kMultiplyF +
502 SlotCount(c.fArguments[0]->fType) - 1));
503 for (int i = SlotCount(c.fArguments[0]->fType); i > 1; --i) {
504 this->write(ByteCodeInstruction::kAddF);
505 }
506 } else {
507 switch (found->second.fValue.fInstruction) {
508 case ByteCodeInstruction::kCos:
509 case ByteCodeInstruction::kMix:
510 case ByteCodeInstruction::kSin:
511 case ByteCodeInstruction::kSqrt:
512 case ByteCodeInstruction::kTan:
513 SkASSERT(c.fArguments.size() > 0);
514 this->write((ByteCodeInstruction) ((int) found->second.fValue.fInstruction +
515 SlotCount(c.fArguments[0]->fType) - 1));
516 break;
517 case ByteCodeInstruction::kCross:
518 this->write(found->second.fValue.fInstruction);
519 break;
520 default:
521 SkASSERT(false);
522 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400523 }
524}
525
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400526void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400527 for (const auto& arg : f.fArguments) {
528 this->writeExpression(*arg);
529 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400530 if (f.fFunction.fBuiltin) {
531 this->writeIntrinsicCall(f);
532 return;
533 }
Brian Osman226668a2019-05-14 16:47:30 -0400534 this->write(ByteCodeInstruction::kCall);
535 fCallTargets.emplace_back(this, f.fFunction);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400536}
537
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400538void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
539 this->write(ByteCodeInstruction::kPushImmediate);
540 this->write32(i.fValue);
541}
542
543void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
544 // not yet implemented
545 abort();
546}
547
548void ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p) {
549 switch (p.fOperator) {
550 case Token::Kind::PLUSPLUS: // fall through
551 case Token::Kind::MINUSMINUS: {
Brian Osman07c117b2019-05-23 12:51:06 -0700552 SkASSERT(SlotCount(p.fOperand->fType) == 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400553 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
554 lvalue->load();
555 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400556 this->write32(type_category(p.fType) == TypeCategory::kFloat
557 ? Interpreter::Value(1.0f).fUnsigned : 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400558 if (p.fOperator == Token::Kind::PLUSPLUS) {
559 this->writeTypedInstruction(p.fType,
560 ByteCodeInstruction::kAddI,
561 ByteCodeInstruction::kAddI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400562 ByteCodeInstruction::kAddF,
563 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400564 } else {
565 this->writeTypedInstruction(p.fType,
566 ByteCodeInstruction::kSubtractI,
567 ByteCodeInstruction::kSubtractI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400568 ByteCodeInstruction::kSubtractF,
569 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400570 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400571 lvalue->store();
572 break;
573 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400574 case Token::Kind::MINUS: {
575 this->writeExpression(*p.fOperand);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400576 this->writeTypedInstruction(p.fType,
Mike Klein12710912019-05-21 11:04:59 -0500577 ByteCodeInstruction::kNegateI,
578 ByteCodeInstruction::kNegateI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400579 ByteCodeInstruction::kNegateF,
Brian Osman07c117b2019-05-23 12:51:06 -0700580 SlotCount(p.fOperand->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400581 break;
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400582 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400583 default:
584 SkASSERT(false);
585 }
586}
587
588void ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p) {
Brian Osmanf3fa6002019-05-17 14:26:53 -0400589 switch (p.fOperator) {
590 case Token::Kind::PLUSPLUS: // fall through
591 case Token::Kind::MINUSMINUS: {
Brian Osman07c117b2019-05-23 12:51:06 -0700592 SkASSERT(SlotCount(p.fOperand->fType) == 1);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400593 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
594 lvalue->load();
595 this->write(ByteCodeInstruction::kDup);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400596 this->write(ByteCodeInstruction::kPushImmediate);
597 this->write32(type_category(p.fType) == TypeCategory::kFloat
598 ? Interpreter::Value(1.0f).fUnsigned : 1);
599 if (p.fOperator == Token::Kind::PLUSPLUS) {
600 this->writeTypedInstruction(p.fType,
601 ByteCodeInstruction::kAddI,
602 ByteCodeInstruction::kAddI,
603 ByteCodeInstruction::kAddF,
604 1);
605 } else {
606 this->writeTypedInstruction(p.fType,
607 ByteCodeInstruction::kSubtractI,
608 ByteCodeInstruction::kSubtractI,
609 ByteCodeInstruction::kSubtractF,
610 1);
611 }
612 lvalue->store();
613 this->write(ByteCodeInstruction::kPop);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400614 break;
615 }
616 default:
617 SkASSERT(false);
618 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400619}
620
621void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
622 switch (s.fBase->fKind) {
623 case Expression::kVariableReference_Kind: {
624 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
Brian Osman1091f022019-05-16 09:42:16 -0400625 this->write(var.fStorage == Variable::kGlobal_Storage
626 ? ByteCodeInstruction::kLoadSwizzleGlobal
627 : ByteCodeInstruction::kLoadSwizzle);
628 this->write8(this->getLocation(var));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400629 this->write8(s.fComponents.size());
630 for (int c : s.fComponents) {
631 this->write8(c);
632 }
633 break;
634 }
635 default:
636 this->writeExpression(*s.fBase);
637 this->write(ByteCodeInstruction::kSwizzle);
638 this->write8(s.fBase->fType.columns());
639 this->write8(s.fComponents.size());
640 for (int c : s.fComponents) {
641 this->write8(c);
642 }
643 }
644}
645
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400646void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Brian Osman4e93feb2019-05-16 15:38:00 -0400647 this->writeExpression(*t.fTest);
Brian Osman4e93feb2019-05-16 15:38:00 -0400648 this->write(ByteCodeInstruction::kConditionalBranch);
649 DeferredLocation trueLocation(this);
650 this->writeExpression(*t.fIfFalse);
Brian Osman4e93feb2019-05-16 15:38:00 -0400651 this->write(ByteCodeInstruction::kBranch);
652 DeferredLocation endLocation(this);
653 trueLocation.set();
654 this->writeExpression(*t.fIfTrue);
655 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400656}
657
658void ByteCodeGenerator::writeExpression(const Expression& e) {
659 switch (e.fKind) {
660 case Expression::kBinary_Kind:
661 this->writeBinaryExpression((BinaryExpression&) e);
662 break;
663 case Expression::kBoolLiteral_Kind:
664 this->writeBoolLiteral((BoolLiteral&) e);
665 break;
666 case Expression::kConstructor_Kind:
667 this->writeConstructor((Constructor&) e);
668 break;
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400669 case Expression::kExternalFunctionCall_Kind:
670 this->writeExternalFunctionCall((ExternalFunctionCall&) e);
671 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400672 case Expression::kExternalValue_Kind:
673 this->writeExternalValue((ExternalValueReference&) e);
674 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400675 case Expression::kFieldAccess_Kind:
Brian Osman07c117b2019-05-23 12:51:06 -0700676 case Expression::kIndex_Kind:
677 case Expression::kVariableReference_Kind:
678 this->writeVariableExpression(e);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400679 break;
680 case Expression::kFloatLiteral_Kind:
681 this->writeFloatLiteral((FloatLiteral&) e);
682 break;
683 case Expression::kFunctionCall_Kind:
684 this->writeFunctionCall((FunctionCall&) e);
685 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400686 case Expression::kIntLiteral_Kind:
687 this->writeIntLiteral((IntLiteral&) e);
688 break;
689 case Expression::kNullLiteral_Kind:
690 this->writeNullLiteral((NullLiteral&) e);
691 break;
692 case Expression::kPrefix_Kind:
693 this->writePrefixExpression((PrefixExpression&) e);
694 break;
695 case Expression::kPostfix_Kind:
696 this->writePostfixExpression((PostfixExpression&) e);
697 break;
698 case Expression::kSwizzle_Kind:
699 this->writeSwizzle((Swizzle&) e);
700 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400701 case Expression::kTernary_Kind:
702 this->writeTernaryExpression((TernaryExpression&) e);
703 break;
704 default:
705 printf("unsupported expression %s\n", e.description().c_str());
706 SkASSERT(false);
707 }
708}
709
Ethan Nicholas91164d12019-05-15 15:29:54 -0400710class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
711public:
712 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
713 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700714 , fCount(ByteCodeGenerator::SlotCount(value.type()))
Ethan Nicholas91164d12019-05-15 15:29:54 -0400715 , fIndex(index) {}
716
717 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400718 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400719 fGenerator.write8(fIndex);
720 }
721
722 void store() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400723 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
724 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400725 fGenerator.write8(fIndex);
726 }
727
728private:
729 typedef LValue INHERITED;
730
731 int fCount;
732
733 int fIndex;
734};
735
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400736class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
737public:
738 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
739 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700740 , fSwizzle(swizzle) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400741
742 void load() override {
Brian Osman1091f022019-05-16 09:42:16 -0400743 fGenerator.writeSwizzle(fSwizzle);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400744 }
745
746 void store() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400747 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup,
748 fSwizzle.fComponents.size()));
Brian Osman07c117b2019-05-23 12:51:06 -0700749 Variable::Storage storage;
750 int location = fGenerator.getLocation(*fSwizzle.fBase, &storage);
751 bool isGlobal = storage == Variable::kGlobal_Storage;
752 if (location < 0) {
753 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleIndirectGlobal
754 : ByteCodeInstruction::kStoreSwizzleIndirect);
755 } else {
756 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleGlobal
757 : ByteCodeInstruction::kStoreSwizzle);
758 fGenerator.write8(location);
759 }
Brian Osman1091f022019-05-16 09:42:16 -0400760 fGenerator.write8(fSwizzle.fComponents.size());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400761 for (int c : fSwizzle.fComponents) {
762 fGenerator.write8(c);
763 }
764 }
765
766private:
767 const Swizzle& fSwizzle;
768
769 typedef LValue INHERITED;
770};
771
Brian Osman07c117b2019-05-23 12:51:06 -0700772class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400773public:
Brian Osman07c117b2019-05-23 12:51:06 -0700774 ByteCodeExpressionLValue(ByteCodeGenerator* generator, const Expression& expr)
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400775 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700776 , fExpression(expr) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400777
778 void load() override {
Brian Osman07c117b2019-05-23 12:51:06 -0700779 fGenerator.writeVariableExpression(fExpression);
Brian Osman1091f022019-05-16 09:42:16 -0400780 }
781
782 void store() override {
Brian Osman07c117b2019-05-23 12:51:06 -0700783 int count = ByteCodeGenerator::SlotCount(fExpression.fType);
784 if (count > 4) {
785 fGenerator.write(ByteCodeInstruction::kDupN);
786 fGenerator.write8(count);
787 } else {
788 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
789 }
790 Variable::Storage storage;
791 int location = fGenerator.getLocation(fExpression, &storage);
792 bool isGlobal = storage == Variable::kGlobal_Storage;
793 if (location < 0 || count > 4) {
794 if (location >= 0) {
795 fGenerator.write(ByteCodeInstruction::kPushImmediate);
796 fGenerator.write32(location);
797 }
798 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreExtendedGlobal
799 : ByteCodeInstruction::kStoreExtended);
800 fGenerator.write8(count);
801 } else {
802 fGenerator.write(vector_instruction(isGlobal ? ByteCodeInstruction::kStoreGlobal
803 : ByteCodeInstruction::kStore,
804 count));
805 fGenerator.write8(location);
806 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400807 }
808
809private:
810 typedef LValue INHERITED;
811
Brian Osman07c117b2019-05-23 12:51:06 -0700812 const Expression& fExpression;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400813};
814
815std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
816 switch (e.fKind) {
Ethan Nicholas91164d12019-05-15 15:29:54 -0400817 case Expression::kExternalValue_Kind: {
818 ExternalValue* value = ((ExternalValueReference&) e).fValue;
819 int index = fOutput->fExternalValues.size();
820 fOutput->fExternalValues.push_back(value);
821 SkASSERT(index <= 255);
822 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
823 }
Brian Osman07c117b2019-05-23 12:51:06 -0700824 case Expression::kFieldAccess_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400825 case Expression::kIndex_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400826 case Expression::kVariableReference_Kind:
Brian Osman07c117b2019-05-23 12:51:06 -0700827 return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400828 case Expression::kSwizzle_Kind:
829 return std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, (Swizzle&) e));
830 case Expression::kTernary_Kind:
831 default:
832 printf("unsupported lvalue %s\n", e.description().c_str());
833 return nullptr;
834 }
835}
836
837void ByteCodeGenerator::writeBlock(const Block& b) {
838 for (const auto& s : b.fStatements) {
839 this->writeStatement(*s);
840 }
841}
842
843void ByteCodeGenerator::setBreakTargets() {
844 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
845 for (DeferredLocation& b : breaks) {
846 b.set();
847 }
848 fBreakTargets.pop();
849}
850
851void ByteCodeGenerator::setContinueTargets() {
852 std::vector<DeferredLocation>& continues = fContinueTargets.top();
853 for (DeferredLocation& c : continues) {
854 c.set();
855 }
856 fContinueTargets.pop();
857}
858
859void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
860 this->write(ByteCodeInstruction::kBranch);
861 fBreakTargets.top().emplace_back(this);
862}
863
864void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
865 this->write(ByteCodeInstruction::kBranch);
866 fContinueTargets.top().emplace_back(this);
867}
868
869void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
870 fContinueTargets.emplace();
871 fBreakTargets.emplace();
872 size_t start = fCode->size();
873 this->writeStatement(*d.fStatement);
874 this->setContinueTargets();
875 this->writeExpression(*d.fTest);
876 this->write(ByteCodeInstruction::kConditionalBranch);
877 this->write16(start);
878 this->setBreakTargets();
879}
880
881void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
882 fContinueTargets.emplace();
883 fBreakTargets.emplace();
884 if (f.fInitializer) {
885 this->writeStatement(*f.fInitializer);
886 }
887 size_t start = fCode->size();
888 if (f.fTest) {
889 this->writeExpression(*f.fTest);
890 this->write(ByteCodeInstruction::kNot);
891 this->write(ByteCodeInstruction::kConditionalBranch);
892 DeferredLocation endLocation(this);
893 this->writeStatement(*f.fStatement);
894 this->setContinueTargets();
895 if (f.fNext) {
896 this->writeExpression(*f.fNext);
Brian Osman07c117b2019-05-23 12:51:06 -0700897 this->write(vector_instruction(ByteCodeInstruction::kPop, SlotCount(f.fNext->fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400898 }
899 this->write(ByteCodeInstruction::kBranch);
900 this->write16(start);
901 endLocation.set();
902 } else {
903 this->writeStatement(*f.fStatement);
904 this->setContinueTargets();
905 if (f.fNext) {
906 this->writeExpression(*f.fNext);
Brian Osman07c117b2019-05-23 12:51:06 -0700907 this->write(vector_instruction(ByteCodeInstruction::kPop, SlotCount(f.fNext->fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400908 }
909 this->write(ByteCodeInstruction::kBranch);
910 this->write16(start);
911 }
912 this->setBreakTargets();
913}
914
915void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400916 if (i.fIfFalse) {
Mike Kleinb45ee832019-05-17 11:11:11 -0500917 // if (test) { ..ifTrue.. } else { .. ifFalse .. }
918 this->writeExpression(*i.fTest);
Mike Kleinb45ee832019-05-17 11:11:11 -0500919 this->write(ByteCodeInstruction::kConditionalBranch);
920 DeferredLocation trueLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400921 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -0500922 this->write(ByteCodeInstruction::kBranch);
923 DeferredLocation endLocation(this);
924 trueLocation.set();
925 this->writeStatement(*i.fIfTrue);
926 endLocation.set();
927 } else {
928 // if (test) { ..ifTrue.. }
929 this->writeExpression(*i.fTest);
930 this->write(ByteCodeInstruction::kNot);
Mike Kleinb45ee832019-05-17 11:11:11 -0500931 this->write(ByteCodeInstruction::kConditionalBranch);
932 DeferredLocation endLocation(this);
933 this->writeStatement(*i.fIfTrue);
934 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400935 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400936}
937
938void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -0400939 this->writeExpression(*r.fExpression);
940 this->write(ByteCodeInstruction::kReturn);
Brian Osman07c117b2019-05-23 12:51:06 -0700941 this->write8(SlotCount(r.fExpression->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400942}
943
944void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
945 // not yet implemented
946 abort();
947}
948
949void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
950 for (const auto& declStatement : v.fVars) {
951 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
952 // we need to grab the location even if we don't use it, to ensure it
953 // has been allocated
954 int location = getLocation(*decl.fVar);
955 if (decl.fValue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400956 this->writeExpression(*decl.fValue);
Brian Osman07c117b2019-05-23 12:51:06 -0700957 int count = SlotCount(decl.fValue->fType);
958 if (count > 4) {
959 this->write(ByteCodeInstruction::kPushImmediate);
960 this->write32(location);
961 this->write(ByteCodeInstruction::kStoreExtended);
962 this->write8(count);
963 } else {
964 this->write(vector_instruction(ByteCodeInstruction::kStore, count));
965 this->write8(location);
966 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400967 }
968 }
969}
970
971void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
972 fContinueTargets.emplace();
973 fBreakTargets.emplace();
974 size_t start = fCode->size();
975 this->writeExpression(*w.fTest);
976 this->write(ByteCodeInstruction::kNot);
977 this->write(ByteCodeInstruction::kConditionalBranch);
978 DeferredLocation endLocation(this);
979 this->writeStatement(*w.fStatement);
980 this->setContinueTargets();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400981 this->write(ByteCodeInstruction::kBranch);
982 this->write16(start);
983 endLocation.set();
984 this->setBreakTargets();
985}
986
987void ByteCodeGenerator::writeStatement(const Statement& s) {
988 switch (s.fKind) {
989 case Statement::kBlock_Kind:
990 this->writeBlock((Block&) s);
991 break;
992 case Statement::kBreak_Kind:
993 this->writeBreakStatement((BreakStatement&) s);
994 break;
995 case Statement::kContinue_Kind:
996 this->writeContinueStatement((ContinueStatement&) s);
997 break;
998 case Statement::kDiscard_Kind:
999 // not yet implemented
1000 abort();
1001 case Statement::kDo_Kind:
1002 this->writeDoStatement((DoStatement&) s);
1003 break;
1004 case Statement::kExpression_Kind: {
1005 const Expression& expr = *((ExpressionStatement&) s).fExpression;
1006 this->writeExpression(expr);
Brian Osman07c117b2019-05-23 12:51:06 -07001007 int count = SlotCount(expr.fType);
1008 if (count > 4) {
1009 this->write(ByteCodeInstruction::kPopN);
1010 this->write8(count);
1011 } else {
1012 this->write(vector_instruction(ByteCodeInstruction::kPop, count));
1013 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001014 break;
1015 }
1016 case Statement::kFor_Kind:
1017 this->writeForStatement((ForStatement&) s);
1018 break;
1019 case Statement::kIf_Kind:
1020 this->writeIfStatement((IfStatement&) s);
1021 break;
1022 case Statement::kNop_Kind:
1023 break;
1024 case Statement::kReturn_Kind:
1025 this->writeReturnStatement((ReturnStatement&) s);
1026 break;
1027 case Statement::kSwitch_Kind:
1028 this->writeSwitchStatement((SwitchStatement&) s);
1029 break;
1030 case Statement::kVarDeclarations_Kind:
1031 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1032 break;
1033 case Statement::kWhile_Kind:
1034 this->writeWhileStatement((WhileStatement&) s);
1035 break;
1036 default:
1037 SkASSERT(false);
1038 }
1039}
1040
1041}