blob: 0070674003ad9c38b3589c8ceaaca1ee5165aedb [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)
17 , fOutput(output) {
18 fIntrinsics["cos"] = ByteCodeInstruction::kCos;
19 fIntrinsics["sin"] = ByteCodeInstruction::kSin;
20 fIntrinsics["sqrt"] = ByteCodeInstruction::kSqrt;
21 fIntrinsics["tan"] = ByteCodeInstruction::kTan;
22}
23
Brian Osman07c117b2019-05-23 12:51:06 -070024int ByteCodeGenerator::SlotCount(const Type& type) {
25 if (type.kind() == Type::kStruct_Kind) {
26 int slots = 0;
27 for (const auto& f : type.fields()) {
28 slots += SlotCount(*f.fType);
29 }
30 SkASSERT(slots <= 255);
31 return slots;
32 } else if (type.kind() == Type::kArray_Kind) {
33 int columns = type.columns();
34 SkASSERT(columns >= 0);
35 int slots = columns * SlotCount(type.componentType());
36 SkASSERT(slots <= 255);
37 return slots;
38 } else {
39 return type.columns() * type.rows();
40 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040041}
42
43bool ByteCodeGenerator::generateCode() {
44 for (const auto& e : fProgram) {
45 switch (e.fKind) {
46 case ProgramElement::kFunction_Kind: {
47 std::unique_ptr<ByteCodeFunction> f = this->writeFunction((FunctionDefinition&) e);
48 if (!f) {
49 return false;
50 }
51 fOutput->fFunctions.push_back(std::move(f));
52 break;
53 }
54 case ProgramElement::kVar_Kind: {
55 VarDeclarations& decl = (VarDeclarations&) e;
56 for (const auto& v : decl.fVars) {
57 const Variable* declVar = ((VarDeclaration&) *v).fVar;
58 if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
59 continue;
60 }
61 if (declVar->fModifiers.fFlags & Modifiers::kIn_Flag) {
Brian Osman07c117b2019-05-23 12:51:06 -070062 for (int i = SlotCount(declVar->fType); i > 0; --i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040063 fOutput->fInputSlots.push_back(fOutput->fGlobalCount++);
64 }
65 } else {
Brian Osman07c117b2019-05-23 12:51:06 -070066 fOutput->fGlobalCount += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040067 }
68 }
69 break;
70 }
71 default:
72 ; // ignore
73 }
74 }
Brian Osman226668a2019-05-14 16:47:30 -040075 for (auto& call : fCallTargets) {
76 if (!call.set()) {
77 return false;
78 }
79 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040080 return true;
81}
82
83std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
84 fFunction = &f;
Brian Osman226668a2019-05-14 16:47:30 -040085 std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040086 fParameterCount = 0;
87 for (const auto& p : f.fDeclaration.fParameters) {
Brian Osman07c117b2019-05-23 12:51:06 -070088 fParameterCount += SlotCount(p->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040089 }
90 fCode = &result->fCode;
91 this->writeStatement(*f.fBody);
Ethan Nicholas7e603db2019-05-03 12:57:47 -040092 this->write(ByteCodeInstruction::kReturn);
93 this->write8(0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040094 result->fParameterCount = fParameterCount;
95 result->fLocalCount = fLocals.size();
Ethan Nicholasdfcad062019-05-07 12:53:34 -040096 const Type& returnType = f.fDeclaration.fReturnType;
97 if (returnType != *fContext.fVoid_Type) {
Brian Osman07c117b2019-05-23 12:51:06 -070098 result->fReturnCount = SlotCount(returnType);
Ethan Nicholasdfcad062019-05-07 12:53:34 -040099 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400100 fLocals.clear();
101 fFunction = nullptr;
102 return result;
103}
104
105enum class TypeCategory {
106 kBool,
107 kSigned,
108 kUnsigned,
109 kFloat,
110};
111
112static TypeCategory type_category(const Type& type) {
113 switch (type.kind()) {
114 case Type::Kind::kVector_Kind:
115 case Type::Kind::kMatrix_Kind:
116 return type_category(type.componentType());
117 default:
118 if (type.fName == "bool") {
119 return TypeCategory::kBool;
120 } else if (type.fName == "int" || type.fName == "short") {
121 return TypeCategory::kSigned;
122 } else if (type.fName == "uint" || type.fName == "ushort") {
123 return TypeCategory::kUnsigned;
124 } else {
125 SkASSERT(type.fName == "float" || type.fName == "half");
126 return TypeCategory::kFloat;
127 }
128 ABORT("unsupported type: %s\n", type.description().c_str());
129 }
130}
131
132int ByteCodeGenerator::getLocation(const Variable& var) {
133 // given that we seldom have more than a couple of variables, linear search is probably the most
134 // efficient way to handle lookups
135 switch (var.fStorage) {
136 case Variable::kLocal_Storage: {
137 for (int i = fLocals.size() - 1; i >= 0; --i) {
138 if (fLocals[i] == &var) {
Brian Osman1091f022019-05-16 09:42:16 -0400139 SkASSERT(fParameterCount + i <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400140 return fParameterCount + i;
141 }
142 }
143 int result = fParameterCount + fLocals.size();
144 fLocals.push_back(&var);
Brian Osman07c117b2019-05-23 12:51:06 -0700145 for (int i = 0; i < SlotCount(var.fType) - 1; ++i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400146 fLocals.push_back(nullptr);
147 }
Brian Osman1091f022019-05-16 09:42:16 -0400148 SkASSERT(result <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400149 return result;
150 }
151 case Variable::kParameter_Storage: {
152 int offset = 0;
153 for (const auto& p : fFunction->fDeclaration.fParameters) {
154 if (p == &var) {
Brian Osman1091f022019-05-16 09:42:16 -0400155 SkASSERT(offset <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400156 return offset;
157 }
Brian Osman07c117b2019-05-23 12:51:06 -0700158 offset += SlotCount(p->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400159 }
160 SkASSERT(false);
Brian Osman1091f022019-05-16 09:42:16 -0400161 return 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400162 }
163 case Variable::kGlobal_Storage: {
164 int offset = 0;
165 for (const auto& e : fProgram) {
166 if (e.fKind == ProgramElement::kVar_Kind) {
167 VarDeclarations& decl = (VarDeclarations&) e;
168 for (const auto& v : decl.fVars) {
169 const Variable* declVar = ((VarDeclaration&) *v).fVar;
170 if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
171 continue;
172 }
173 if (declVar == &var) {
Brian Osmanb7451292019-05-15 13:02:13 -0400174 SkASSERT(offset <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400175 return offset;
176 }
Brian Osman07c117b2019-05-23 12:51:06 -0700177 offset += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400178 }
179 }
180 }
181 SkASSERT(false);
Brian Osman1091f022019-05-16 09:42:16 -0400182 return 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400183 }
184 default:
185 SkASSERT(false);
186 return 0;
187 }
188}
189
Brian Osman07c117b2019-05-23 12:51:06 -0700190int ByteCodeGenerator::getLocation(const Expression& expr, Variable::Storage* storage) {
191 switch (expr.fKind) {
192 case Expression::kFieldAccess_Kind: {
193 const FieldAccess& f = (const FieldAccess&)expr;
194 int baseAddr = this->getLocation(*f.fBase, storage);
195 int offset = 0;
196 for (int i = 0; i < f.fFieldIndex; ++i) {
197 offset += SlotCount(*f.fBase->fType.fields()[i].fType);
198 }
199 if (baseAddr < 0) {
200 this->write(ByteCodeInstruction::kPushImmediate);
201 this->write32(offset);
202 this->write(ByteCodeInstruction::kAddI);
203 return -1;
204 } else {
205 return baseAddr + offset;
206 }
207 }
208 case Expression::kIndex_Kind: {
209 const IndexExpression& i = (const IndexExpression&)expr;
210 int stride = SlotCount(i.fType);
211 int offset = -1;
212 if (i.fIndex->isConstant()) {
213 offset = i.fIndex->getConstantInt() * stride;
214 } else {
215 this->writeExpression(*i.fIndex);
216 this->write(ByteCodeInstruction::kPushImmediate);
217 this->write32(stride);
218 this->write(ByteCodeInstruction::kMultiplyI);
219 }
220 int baseAddr = this->getLocation(*i.fBase, storage);
221 if (baseAddr >= 0 && offset >= 0) {
222 return baseAddr + offset;
223 }
224 if (baseAddr >= 0) {
225 this->write(ByteCodeInstruction::kPushImmediate);
226 this->write32(baseAddr);
227 }
228 if (offset >= 0) {
229 this->write(ByteCodeInstruction::kPushImmediate);
230 this->write32(offset);
231 }
232 this->write(ByteCodeInstruction::kAddI);
233 return -1;
234 }
235 case Expression::kVariableReference_Kind: {
236 const Variable& var = ((const VariableReference&)expr).fVariable;
237 *storage = var.fStorage;
238 return this->getLocation(var);
239 }
240 default:
241 SkASSERT(false);
242 return 0;
243 }
244}
245
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400246void ByteCodeGenerator::write8(uint8_t b) {
247 fCode->push_back(b);
248}
249
250void ByteCodeGenerator::write16(uint16_t i) {
Mike Klein76346ac2019-05-17 11:57:10 -0500251 size_t n = fCode->size();
252 fCode->resize(n+2);
253 memcpy(fCode->data() + n, &i, 2);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400254}
255
256void ByteCodeGenerator::write32(uint32_t i) {
Mike Klein76346ac2019-05-17 11:57:10 -0500257 size_t n = fCode->size();
258 fCode->resize(n+4);
259 memcpy(fCode->data() + n, &i, 4);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400260}
261
262void ByteCodeGenerator::write(ByteCodeInstruction i) {
Mike Klein108e9352019-05-21 11:05:17 -0500263 this->write16((uint16_t)i);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400264}
265
Mike Klein76346ac2019-05-17 11:57:10 -0500266static ByteCodeInstruction vector_instruction(ByteCodeInstruction base, int count) {
Brian Osman07c117b2019-05-23 12:51:06 -0700267 SkASSERT(count >= 1 && count <= 4);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400268 return ((ByteCodeInstruction) ((int) base + count - 1));
269}
270
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400271void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400272 ByteCodeInstruction u, ByteCodeInstruction f,
273 int count) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400274 switch (type_category(type)) {
275 case TypeCategory::kSigned:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400276 this->write(vector_instruction(s, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400277 break;
278 case TypeCategory::kUnsigned:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400279 this->write(vector_instruction(u, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400280 break;
281 case TypeCategory::kFloat:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400282 this->write(vector_instruction(f, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400283 break;
284 default:
285 SkASSERT(false);
286 }
287}
288
289void ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b) {
290 if (b.fOperator == Token::Kind::EQ) {
291 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
292 this->writeExpression(*b.fRight);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400293 lvalue->store();
294 return;
295 }
296 Token::Kind op;
297 std::unique_ptr<LValue> lvalue;
298 if (is_assignment(b.fOperator)) {
299 lvalue = this->getLValue(*b.fLeft);
300 lvalue->load();
301 op = remove_assignment(b.fOperator);
302 } else {
303 this->writeExpression(*b.fLeft);
304 op = b.fOperator;
305 if (b.fLeft->fType.kind() == Type::kScalar_Kind &&
306 b.fRight->fType.kind() == Type::kVector_Kind) {
307 for (int i = b.fRight->fType.columns(); i > 1; --i) {
308 this->write(ByteCodeInstruction::kDup);
309 }
310 }
311 }
312 this->writeExpression(*b.fRight);
313 if (b.fLeft->fType.kind() == Type::kVector_Kind &&
314 b.fRight->fType.kind() == Type::kScalar_Kind) {
315 for (int i = b.fLeft->fType.columns(); i > 1; --i) {
316 this->write(ByteCodeInstruction::kDup);
317 }
318 }
Brian Osman07c117b2019-05-23 12:51:06 -0700319 int count = SlotCount(b.fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400320 switch (op) {
321 case Token::Kind::EQEQ:
322 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareIEQ,
323 ByteCodeInstruction::kCompareIEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400324 ByteCodeInstruction::kCompareFEQ,
325 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400326 break;
327 case Token::Kind::GT:
328 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGT,
329 ByteCodeInstruction::kCompareUGT,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400330 ByteCodeInstruction::kCompareFGT,
331 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400332 break;
333 case Token::Kind::GTEQ:
334 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGTEQ,
335 ByteCodeInstruction::kCompareUGTEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400336 ByteCodeInstruction::kCompareFGTEQ,
337 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400338 break;
339 case Token::Kind::LT:
340 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLT,
341 ByteCodeInstruction::kCompareULT,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400342 ByteCodeInstruction::kCompareFLT,
343 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400344 break;
345 case Token::Kind::LTEQ:
346 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLTEQ,
347 ByteCodeInstruction::kCompareULTEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400348 ByteCodeInstruction::kCompareFLTEQ,
349 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400350 break;
351 case Token::Kind::MINUS:
352 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kSubtractI,
353 ByteCodeInstruction::kSubtractI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400354 ByteCodeInstruction::kSubtractF,
355 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400356 break;
357 case Token::Kind::NEQ:
358 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareINEQ,
359 ByteCodeInstruction::kCompareINEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400360 ByteCodeInstruction::kCompareFNEQ,
361 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400362 break;
363 case Token::Kind::PERCENT:
364 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kRemainderS,
365 ByteCodeInstruction::kRemainderU,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400366 ByteCodeInstruction::kRemainderF,
367 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400368 break;
369 case Token::Kind::PLUS:
370 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kAddI,
371 ByteCodeInstruction::kAddI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400372 ByteCodeInstruction::kAddF,
373 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400374 break;
375 case Token::Kind::SLASH:
376 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kDivideS,
377 ByteCodeInstruction::kDivideU,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400378 ByteCodeInstruction::kDivideF,
379 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400380 break;
381 case Token::Kind::STAR:
Ethan Nicholas91164d12019-05-15 15:29:54 -0400382 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kMultiplyI,
383 ByteCodeInstruction::kMultiplyI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400384 ByteCodeInstruction::kMultiplyF,
385 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400386 break;
387 default:
388 SkASSERT(false);
389 }
390 if (lvalue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400391 lvalue->store();
392 }
393}
394
395void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
396 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osman44d44762019-05-13 14:19:12 -0400397 this->write32(b.fValue ? 1 : 0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400398}
399
400void ByteCodeGenerator::writeConstructor(const Constructor& c) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400401 for (const auto& arg : c.fArguments) {
402 this->writeExpression(*arg);
403 }
404 if (c.fArguments.size() == 1) {
405 TypeCategory inCategory = type_category(c.fArguments[0]->fType);
406 TypeCategory outCategory = type_category(c.fType);
Brian Osmanc51d7912019-05-22 15:16:16 -0700407 int inCount = c.fArguments[0]->fType.columns();
408 int outCount = c.fType.columns();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400409 if (inCategory != outCategory) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700410 SkASSERT(inCount == outCount);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400411 if (inCategory == TypeCategory::kFloat) {
412 SkASSERT(outCategory == TypeCategory::kSigned ||
413 outCategory == TypeCategory::kUnsigned);
Brian Osmanc51d7912019-05-22 15:16:16 -0700414 this->write(vector_instruction(ByteCodeInstruction::kConvertFtoI, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400415 } else if (outCategory == TypeCategory::kFloat) {
416 if (inCategory == TypeCategory::kSigned) {
Brian Osmanc51d7912019-05-22 15:16:16 -0700417 this->write(vector_instruction(ByteCodeInstruction::kConvertStoF, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400418 } else {
419 SkASSERT(inCategory == TypeCategory::kUnsigned);
Brian Osmanc51d7912019-05-22 15:16:16 -0700420 this->write(vector_instruction(ByteCodeInstruction::kConvertUtoF, outCount));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400421 }
422 } else {
423 SkASSERT(false);
424 }
425 }
Brian Osmanc51d7912019-05-22 15:16:16 -0700426 if (inCount != outCount) {
427 SkASSERT(inCount == 1);
428 for (; inCount != outCount; ++inCount) {
429 this->write(ByteCodeInstruction::kDup);
430 }
431 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400432 }
433}
434
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400435void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f) {
436 int argumentCount = 0;
437 for (const auto& arg : f.fArguments) {
438 this->writeExpression(*arg);
Brian Osman07c117b2019-05-23 12:51:06 -0700439 argumentCount += SlotCount(arg->fType);
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400440 }
441 this->write(ByteCodeInstruction::kCallExternal);
442 SkASSERT(argumentCount <= 255);
443 this->write8(argumentCount);
Brian Osman07c117b2019-05-23 12:51:06 -0700444 this->write8(SlotCount(f.fType));
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400445 int index = fOutput->fExternalValues.size();
446 fOutput->fExternalValues.push_back(f.fFunction);
447 SkASSERT(index <= 255);
448 this->write8(index);
449}
450
Ethan Nicholas91164d12019-05-15 15:29:54 -0400451void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400452 this->write(vector_instruction(ByteCodeInstruction::kReadExternal,
Brian Osman07c117b2019-05-23 12:51:06 -0700453 SlotCount(e.fValue->type())));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400454 int index = fOutput->fExternalValues.size();
455 fOutput->fExternalValues.push_back(e.fValue);
456 SkASSERT(index <= 255);
457 this->write8(index);
458}
459
Brian Osman07c117b2019-05-23 12:51:06 -0700460void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
461 Variable::Storage storage;
462 int location = this->getLocation(expr, &storage);
463 bool isGlobal = storage == Variable::kGlobal_Storage;
464 int count = SlotCount(expr.fType);
465 if (location < 0 || count > 4) {
466 if (location >= 0) {
467 this->write(ByteCodeInstruction::kPushImmediate);
468 this->write32(location);
469 }
470 this->write(isGlobal ? ByteCodeInstruction::kLoadExtendedGlobal
471 : ByteCodeInstruction::kLoadExtended);
472 this->write8(count);
473 } else {
474 this->write(vector_instruction(isGlobal ? ByteCodeInstruction::kLoadGlobal
475 : ByteCodeInstruction::kLoad,
476 count));
477 this->write8(location);
478 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400479}
480
481void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
482 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400483 this->write32(Interpreter::Value((float) f.fValue).fUnsigned);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400484}
485
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400486void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
487 auto found = fIntrinsics.find(c.fFunction.fName);
488 if (found == fIntrinsics.end()) {
489 fErrors.error(c.fOffset, "unsupported intrinsic function");
490 return;
491 }
492 switch (found->second) {
493 case ByteCodeInstruction::kCos: // fall through
494 case ByteCodeInstruction::kSin: // fall through
495 case ByteCodeInstruction::kSqrt: // fall through
496 case ByteCodeInstruction::kTan:
497 SkASSERT(c.fArguments.size() == 1);
498 this->write((ByteCodeInstruction) ((int) found->second +
Brian Osman07c117b2019-05-23 12:51:06 -0700499 SlotCount(c.fArguments[0]->fType) - 1));
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400500 break;
501 default:
502 SkASSERT(false);
503 }
504}
505
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400506void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400507 if (f.fFunction.fBuiltin) {
508 this->writeIntrinsicCall(f);
509 return;
510 }
Brian Osman226668a2019-05-14 16:47:30 -0400511 for (const auto& arg : f.fArguments) {
512 this->writeExpression(*arg);
513 }
514 this->write(ByteCodeInstruction::kCall);
515 fCallTargets.emplace_back(this, f.fFunction);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400516}
517
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400518void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
519 this->write(ByteCodeInstruction::kPushImmediate);
520 this->write32(i.fValue);
521}
522
523void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
524 // not yet implemented
525 abort();
526}
527
528void ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p) {
529 switch (p.fOperator) {
530 case Token::Kind::PLUSPLUS: // fall through
531 case Token::Kind::MINUSMINUS: {
Brian Osman07c117b2019-05-23 12:51:06 -0700532 SkASSERT(SlotCount(p.fOperand->fType) == 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400533 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
534 lvalue->load();
535 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400536 this->write32(type_category(p.fType) == TypeCategory::kFloat
537 ? Interpreter::Value(1.0f).fUnsigned : 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400538 if (p.fOperator == Token::Kind::PLUSPLUS) {
539 this->writeTypedInstruction(p.fType,
540 ByteCodeInstruction::kAddI,
541 ByteCodeInstruction::kAddI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400542 ByteCodeInstruction::kAddF,
543 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400544 } else {
545 this->writeTypedInstruction(p.fType,
546 ByteCodeInstruction::kSubtractI,
547 ByteCodeInstruction::kSubtractI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400548 ByteCodeInstruction::kSubtractF,
549 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400550 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400551 lvalue->store();
552 break;
553 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400554 case Token::Kind::MINUS: {
555 this->writeExpression(*p.fOperand);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400556 this->writeTypedInstruction(p.fType,
Mike Klein12710912019-05-21 11:04:59 -0500557 ByteCodeInstruction::kNegateI,
558 ByteCodeInstruction::kNegateI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400559 ByteCodeInstruction::kNegateF,
Brian Osman07c117b2019-05-23 12:51:06 -0700560 SlotCount(p.fOperand->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400561 break;
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400562 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400563 default:
564 SkASSERT(false);
565 }
566}
567
568void ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p) {
Brian Osmanf3fa6002019-05-17 14:26:53 -0400569 switch (p.fOperator) {
570 case Token::Kind::PLUSPLUS: // fall through
571 case Token::Kind::MINUSMINUS: {
Brian Osman07c117b2019-05-23 12:51:06 -0700572 SkASSERT(SlotCount(p.fOperand->fType) == 1);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400573 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
574 lvalue->load();
575 this->write(ByteCodeInstruction::kDup);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400576 this->write(ByteCodeInstruction::kPushImmediate);
577 this->write32(type_category(p.fType) == TypeCategory::kFloat
578 ? Interpreter::Value(1.0f).fUnsigned : 1);
579 if (p.fOperator == Token::Kind::PLUSPLUS) {
580 this->writeTypedInstruction(p.fType,
581 ByteCodeInstruction::kAddI,
582 ByteCodeInstruction::kAddI,
583 ByteCodeInstruction::kAddF,
584 1);
585 } else {
586 this->writeTypedInstruction(p.fType,
587 ByteCodeInstruction::kSubtractI,
588 ByteCodeInstruction::kSubtractI,
589 ByteCodeInstruction::kSubtractF,
590 1);
591 }
592 lvalue->store();
593 this->write(ByteCodeInstruction::kPop);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400594 break;
595 }
596 default:
597 SkASSERT(false);
598 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400599}
600
601void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
602 switch (s.fBase->fKind) {
603 case Expression::kVariableReference_Kind: {
604 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
Brian Osman1091f022019-05-16 09:42:16 -0400605 this->write(var.fStorage == Variable::kGlobal_Storage
606 ? ByteCodeInstruction::kLoadSwizzleGlobal
607 : ByteCodeInstruction::kLoadSwizzle);
608 this->write8(this->getLocation(var));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400609 this->write8(s.fComponents.size());
610 for (int c : s.fComponents) {
611 this->write8(c);
612 }
613 break;
614 }
615 default:
616 this->writeExpression(*s.fBase);
617 this->write(ByteCodeInstruction::kSwizzle);
618 this->write8(s.fBase->fType.columns());
619 this->write8(s.fComponents.size());
620 for (int c : s.fComponents) {
621 this->write8(c);
622 }
623 }
624}
625
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400626void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Brian Osman4e93feb2019-05-16 15:38:00 -0400627 this->writeExpression(*t.fTest);
Brian Osman4e93feb2019-05-16 15:38:00 -0400628 this->write(ByteCodeInstruction::kConditionalBranch);
629 DeferredLocation trueLocation(this);
630 this->writeExpression(*t.fIfFalse);
Brian Osman4e93feb2019-05-16 15:38:00 -0400631 this->write(ByteCodeInstruction::kBranch);
632 DeferredLocation endLocation(this);
633 trueLocation.set();
634 this->writeExpression(*t.fIfTrue);
635 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400636}
637
638void ByteCodeGenerator::writeExpression(const Expression& e) {
639 switch (e.fKind) {
640 case Expression::kBinary_Kind:
641 this->writeBinaryExpression((BinaryExpression&) e);
642 break;
643 case Expression::kBoolLiteral_Kind:
644 this->writeBoolLiteral((BoolLiteral&) e);
645 break;
646 case Expression::kConstructor_Kind:
647 this->writeConstructor((Constructor&) e);
648 break;
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400649 case Expression::kExternalFunctionCall_Kind:
650 this->writeExternalFunctionCall((ExternalFunctionCall&) e);
651 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400652 case Expression::kExternalValue_Kind:
653 this->writeExternalValue((ExternalValueReference&) e);
654 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400655 case Expression::kFieldAccess_Kind:
Brian Osman07c117b2019-05-23 12:51:06 -0700656 case Expression::kIndex_Kind:
657 case Expression::kVariableReference_Kind:
658 this->writeVariableExpression(e);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400659 break;
660 case Expression::kFloatLiteral_Kind:
661 this->writeFloatLiteral((FloatLiteral&) e);
662 break;
663 case Expression::kFunctionCall_Kind:
664 this->writeFunctionCall((FunctionCall&) e);
665 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400666 case Expression::kIntLiteral_Kind:
667 this->writeIntLiteral((IntLiteral&) e);
668 break;
669 case Expression::kNullLiteral_Kind:
670 this->writeNullLiteral((NullLiteral&) e);
671 break;
672 case Expression::kPrefix_Kind:
673 this->writePrefixExpression((PrefixExpression&) e);
674 break;
675 case Expression::kPostfix_Kind:
676 this->writePostfixExpression((PostfixExpression&) e);
677 break;
678 case Expression::kSwizzle_Kind:
679 this->writeSwizzle((Swizzle&) e);
680 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400681 case Expression::kTernary_Kind:
682 this->writeTernaryExpression((TernaryExpression&) e);
683 break;
684 default:
685 printf("unsupported expression %s\n", e.description().c_str());
686 SkASSERT(false);
687 }
688}
689
Ethan Nicholas91164d12019-05-15 15:29:54 -0400690class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
691public:
692 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
693 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700694 , fCount(ByteCodeGenerator::SlotCount(value.type()))
Ethan Nicholas91164d12019-05-15 15:29:54 -0400695 , fIndex(index) {}
696
697 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400698 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400699 fGenerator.write8(fIndex);
700 }
701
702 void store() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400703 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
704 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400705 fGenerator.write8(fIndex);
706 }
707
708private:
709 typedef LValue INHERITED;
710
711 int fCount;
712
713 int fIndex;
714};
715
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400716class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
717public:
718 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
719 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700720 , fSwizzle(swizzle) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400721
722 void load() override {
Brian Osman1091f022019-05-16 09:42:16 -0400723 fGenerator.writeSwizzle(fSwizzle);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400724 }
725
726 void store() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400727 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup,
728 fSwizzle.fComponents.size()));
Brian Osman07c117b2019-05-23 12:51:06 -0700729 Variable::Storage storage;
730 int location = fGenerator.getLocation(*fSwizzle.fBase, &storage);
731 bool isGlobal = storage == Variable::kGlobal_Storage;
732 if (location < 0) {
733 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleIndirectGlobal
734 : ByteCodeInstruction::kStoreSwizzleIndirect);
735 } else {
736 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleGlobal
737 : ByteCodeInstruction::kStoreSwizzle);
738 fGenerator.write8(location);
739 }
Brian Osman1091f022019-05-16 09:42:16 -0400740 fGenerator.write8(fSwizzle.fComponents.size());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400741 for (int c : fSwizzle.fComponents) {
742 fGenerator.write8(c);
743 }
744 }
745
746private:
747 const Swizzle& fSwizzle;
748
749 typedef LValue INHERITED;
750};
751
Brian Osman07c117b2019-05-23 12:51:06 -0700752class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400753public:
Brian Osman07c117b2019-05-23 12:51:06 -0700754 ByteCodeExpressionLValue(ByteCodeGenerator* generator, const Expression& expr)
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400755 : INHERITED(*generator)
Brian Osman07c117b2019-05-23 12:51:06 -0700756 , fExpression(expr) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400757
758 void load() override {
Brian Osman07c117b2019-05-23 12:51:06 -0700759 fGenerator.writeVariableExpression(fExpression);
Brian Osman1091f022019-05-16 09:42:16 -0400760 }
761
762 void store() override {
Brian Osman07c117b2019-05-23 12:51:06 -0700763 int count = ByteCodeGenerator::SlotCount(fExpression.fType);
764 if (count > 4) {
765 fGenerator.write(ByteCodeInstruction::kDupN);
766 fGenerator.write8(count);
767 } else {
768 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
769 }
770 Variable::Storage storage;
771 int location = fGenerator.getLocation(fExpression, &storage);
772 bool isGlobal = storage == Variable::kGlobal_Storage;
773 if (location < 0 || count > 4) {
774 if (location >= 0) {
775 fGenerator.write(ByteCodeInstruction::kPushImmediate);
776 fGenerator.write32(location);
777 }
778 fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreExtendedGlobal
779 : ByteCodeInstruction::kStoreExtended);
780 fGenerator.write8(count);
781 } else {
782 fGenerator.write(vector_instruction(isGlobal ? ByteCodeInstruction::kStoreGlobal
783 : ByteCodeInstruction::kStore,
784 count));
785 fGenerator.write8(location);
786 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400787 }
788
789private:
790 typedef LValue INHERITED;
791
Brian Osman07c117b2019-05-23 12:51:06 -0700792 const Expression& fExpression;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400793};
794
795std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
796 switch (e.fKind) {
Ethan Nicholas91164d12019-05-15 15:29:54 -0400797 case Expression::kExternalValue_Kind: {
798 ExternalValue* value = ((ExternalValueReference&) e).fValue;
799 int index = fOutput->fExternalValues.size();
800 fOutput->fExternalValues.push_back(value);
801 SkASSERT(index <= 255);
802 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
803 }
Brian Osman07c117b2019-05-23 12:51:06 -0700804 case Expression::kFieldAccess_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400805 case Expression::kIndex_Kind:
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400806 case Expression::kVariableReference_Kind:
Brian Osman07c117b2019-05-23 12:51:06 -0700807 return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400808 case Expression::kSwizzle_Kind:
809 return std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, (Swizzle&) e));
810 case Expression::kTernary_Kind:
811 default:
812 printf("unsupported lvalue %s\n", e.description().c_str());
813 return nullptr;
814 }
815}
816
817void ByteCodeGenerator::writeBlock(const Block& b) {
818 for (const auto& s : b.fStatements) {
819 this->writeStatement(*s);
820 }
821}
822
823void ByteCodeGenerator::setBreakTargets() {
824 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
825 for (DeferredLocation& b : breaks) {
826 b.set();
827 }
828 fBreakTargets.pop();
829}
830
831void ByteCodeGenerator::setContinueTargets() {
832 std::vector<DeferredLocation>& continues = fContinueTargets.top();
833 for (DeferredLocation& c : continues) {
834 c.set();
835 }
836 fContinueTargets.pop();
837}
838
839void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
840 this->write(ByteCodeInstruction::kBranch);
841 fBreakTargets.top().emplace_back(this);
842}
843
844void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
845 this->write(ByteCodeInstruction::kBranch);
846 fContinueTargets.top().emplace_back(this);
847}
848
849void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
850 fContinueTargets.emplace();
851 fBreakTargets.emplace();
852 size_t start = fCode->size();
853 this->writeStatement(*d.fStatement);
854 this->setContinueTargets();
855 this->writeExpression(*d.fTest);
856 this->write(ByteCodeInstruction::kConditionalBranch);
857 this->write16(start);
858 this->setBreakTargets();
859}
860
861void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
862 fContinueTargets.emplace();
863 fBreakTargets.emplace();
864 if (f.fInitializer) {
865 this->writeStatement(*f.fInitializer);
866 }
867 size_t start = fCode->size();
868 if (f.fTest) {
869 this->writeExpression(*f.fTest);
870 this->write(ByteCodeInstruction::kNot);
871 this->write(ByteCodeInstruction::kConditionalBranch);
872 DeferredLocation endLocation(this);
873 this->writeStatement(*f.fStatement);
874 this->setContinueTargets();
875 if (f.fNext) {
876 this->writeExpression(*f.fNext);
Brian Osman07c117b2019-05-23 12:51:06 -0700877 this->write(vector_instruction(ByteCodeInstruction::kPop, SlotCount(f.fNext->fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400878 }
879 this->write(ByteCodeInstruction::kBranch);
880 this->write16(start);
881 endLocation.set();
882 } else {
883 this->writeStatement(*f.fStatement);
884 this->setContinueTargets();
885 if (f.fNext) {
886 this->writeExpression(*f.fNext);
Brian Osman07c117b2019-05-23 12:51:06 -0700887 this->write(vector_instruction(ByteCodeInstruction::kPop, SlotCount(f.fNext->fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400888 }
889 this->write(ByteCodeInstruction::kBranch);
890 this->write16(start);
891 }
892 this->setBreakTargets();
893}
894
895void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400896 if (i.fIfFalse) {
Mike Kleinb45ee832019-05-17 11:11:11 -0500897 // if (test) { ..ifTrue.. } else { .. ifFalse .. }
898 this->writeExpression(*i.fTest);
Mike Kleinb45ee832019-05-17 11:11:11 -0500899 this->write(ByteCodeInstruction::kConditionalBranch);
900 DeferredLocation trueLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400901 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -0500902 this->write(ByteCodeInstruction::kBranch);
903 DeferredLocation endLocation(this);
904 trueLocation.set();
905 this->writeStatement(*i.fIfTrue);
906 endLocation.set();
907 } else {
908 // if (test) { ..ifTrue.. }
909 this->writeExpression(*i.fTest);
910 this->write(ByteCodeInstruction::kNot);
Mike Kleinb45ee832019-05-17 11:11:11 -0500911 this->write(ByteCodeInstruction::kConditionalBranch);
912 DeferredLocation endLocation(this);
913 this->writeStatement(*i.fIfTrue);
914 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400915 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400916}
917
918void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -0400919 this->writeExpression(*r.fExpression);
920 this->write(ByteCodeInstruction::kReturn);
Brian Osman07c117b2019-05-23 12:51:06 -0700921 this->write8(SlotCount(r.fExpression->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400922}
923
924void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
925 // not yet implemented
926 abort();
927}
928
929void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
930 for (const auto& declStatement : v.fVars) {
931 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
932 // we need to grab the location even if we don't use it, to ensure it
933 // has been allocated
934 int location = getLocation(*decl.fVar);
935 if (decl.fValue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400936 this->writeExpression(*decl.fValue);
Brian Osman07c117b2019-05-23 12:51:06 -0700937 int count = SlotCount(decl.fValue->fType);
938 if (count > 4) {
939 this->write(ByteCodeInstruction::kPushImmediate);
940 this->write32(location);
941 this->write(ByteCodeInstruction::kStoreExtended);
942 this->write8(count);
943 } else {
944 this->write(vector_instruction(ByteCodeInstruction::kStore, count));
945 this->write8(location);
946 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400947 }
948 }
949}
950
951void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
952 fContinueTargets.emplace();
953 fBreakTargets.emplace();
954 size_t start = fCode->size();
955 this->writeExpression(*w.fTest);
956 this->write(ByteCodeInstruction::kNot);
957 this->write(ByteCodeInstruction::kConditionalBranch);
958 DeferredLocation endLocation(this);
959 this->writeStatement(*w.fStatement);
960 this->setContinueTargets();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400961 this->write(ByteCodeInstruction::kBranch);
962 this->write16(start);
963 endLocation.set();
964 this->setBreakTargets();
965}
966
967void ByteCodeGenerator::writeStatement(const Statement& s) {
968 switch (s.fKind) {
969 case Statement::kBlock_Kind:
970 this->writeBlock((Block&) s);
971 break;
972 case Statement::kBreak_Kind:
973 this->writeBreakStatement((BreakStatement&) s);
974 break;
975 case Statement::kContinue_Kind:
976 this->writeContinueStatement((ContinueStatement&) s);
977 break;
978 case Statement::kDiscard_Kind:
979 // not yet implemented
980 abort();
981 case Statement::kDo_Kind:
982 this->writeDoStatement((DoStatement&) s);
983 break;
984 case Statement::kExpression_Kind: {
985 const Expression& expr = *((ExpressionStatement&) s).fExpression;
986 this->writeExpression(expr);
Brian Osman07c117b2019-05-23 12:51:06 -0700987 int count = SlotCount(expr.fType);
988 if (count > 4) {
989 this->write(ByteCodeInstruction::kPopN);
990 this->write8(count);
991 } else {
992 this->write(vector_instruction(ByteCodeInstruction::kPop, count));
993 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400994 break;
995 }
996 case Statement::kFor_Kind:
997 this->writeForStatement((ForStatement&) s);
998 break;
999 case Statement::kIf_Kind:
1000 this->writeIfStatement((IfStatement&) s);
1001 break;
1002 case Statement::kNop_Kind:
1003 break;
1004 case Statement::kReturn_Kind:
1005 this->writeReturnStatement((ReturnStatement&) s);
1006 break;
1007 case Statement::kSwitch_Kind:
1008 this->writeSwitchStatement((SwitchStatement&) s);
1009 break;
1010 case Statement::kVarDeclarations_Kind:
1011 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1012 break;
1013 case Statement::kWhile_Kind:
1014 this->writeWhileStatement((WhileStatement&) s);
1015 break;
1016 default:
1017 SkASSERT(false);
1018 }
1019}
1020
1021}