blob: e213594ed725db42db58e74be03a1cafd4a24431 [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
13static int slot_count(const Type& type) {
14 return type.columns() * type.rows();
15}
16
17bool ByteCodeGenerator::generateCode() {
18 for (const auto& e : fProgram) {
19 switch (e.fKind) {
20 case ProgramElement::kFunction_Kind: {
21 std::unique_ptr<ByteCodeFunction> f = this->writeFunction((FunctionDefinition&) e);
22 if (!f) {
23 return false;
24 }
25 fOutput->fFunctions.push_back(std::move(f));
26 break;
27 }
28 case ProgramElement::kVar_Kind: {
29 VarDeclarations& decl = (VarDeclarations&) e;
30 for (const auto& v : decl.fVars) {
31 const Variable* declVar = ((VarDeclaration&) *v).fVar;
32 if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
33 continue;
34 }
35 if (declVar->fModifiers.fFlags & Modifiers::kIn_Flag) {
36 for (int i = slot_count(declVar->fType); i > 0; --i) {
37 fOutput->fInputSlots.push_back(fOutput->fGlobalCount++);
38 }
39 } else {
40 fOutput->fGlobalCount += slot_count(declVar->fType);
41 }
42 }
43 break;
44 }
45 default:
46 ; // ignore
47 }
48 }
Brian Osman226668a2019-05-14 16:47:30 -040049 for (auto& call : fCallTargets) {
50 if (!call.set()) {
51 return false;
52 }
53 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040054 return true;
55}
56
57std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
58 fFunction = &f;
Brian Osman226668a2019-05-14 16:47:30 -040059 std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040060 fParameterCount = 0;
61 for (const auto& p : f.fDeclaration.fParameters) {
62 fParameterCount += p->fType.columns() * p->fType.rows();
63 }
64 fCode = &result->fCode;
65 this->writeStatement(*f.fBody);
Ethan Nicholas7e603db2019-05-03 12:57:47 -040066 this->write(ByteCodeInstruction::kReturn);
67 this->write8(0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040068 result->fParameterCount = fParameterCount;
69 result->fLocalCount = fLocals.size();
Ethan Nicholasdfcad062019-05-07 12:53:34 -040070 const Type& returnType = f.fDeclaration.fReturnType;
71 if (returnType != *fContext.fVoid_Type) {
72 result->fReturnCount = returnType.columns() * returnType.rows();
73 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040074 fLocals.clear();
75 fFunction = nullptr;
76 return result;
77}
78
79enum class TypeCategory {
80 kBool,
81 kSigned,
82 kUnsigned,
83 kFloat,
84};
85
86static TypeCategory type_category(const Type& type) {
87 switch (type.kind()) {
88 case Type::Kind::kVector_Kind:
89 case Type::Kind::kMatrix_Kind:
90 return type_category(type.componentType());
91 default:
92 if (type.fName == "bool") {
93 return TypeCategory::kBool;
94 } else if (type.fName == "int" || type.fName == "short") {
95 return TypeCategory::kSigned;
96 } else if (type.fName == "uint" || type.fName == "ushort") {
97 return TypeCategory::kUnsigned;
98 } else {
99 SkASSERT(type.fName == "float" || type.fName == "half");
100 return TypeCategory::kFloat;
101 }
102 ABORT("unsupported type: %s\n", type.description().c_str());
103 }
104}
105
106int ByteCodeGenerator::getLocation(const Variable& var) {
107 // given that we seldom have more than a couple of variables, linear search is probably the most
108 // efficient way to handle lookups
109 switch (var.fStorage) {
110 case Variable::kLocal_Storage: {
111 for (int i = fLocals.size() - 1; i >= 0; --i) {
112 if (fLocals[i] == &var) {
Brian Osman1091f022019-05-16 09:42:16 -0400113 SkASSERT(fParameterCount + i <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400114 return fParameterCount + i;
115 }
116 }
117 int result = fParameterCount + fLocals.size();
118 fLocals.push_back(&var);
119 for (int i = 0; i < slot_count(var.fType) - 1; ++i) {
120 fLocals.push_back(nullptr);
121 }
Brian Osman1091f022019-05-16 09:42:16 -0400122 SkASSERT(result <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400123 return result;
124 }
125 case Variable::kParameter_Storage: {
126 int offset = 0;
127 for (const auto& p : fFunction->fDeclaration.fParameters) {
128 if (p == &var) {
Brian Osman1091f022019-05-16 09:42:16 -0400129 SkASSERT(offset <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400130 return offset;
131 }
132 offset += slot_count(p->fType);
133 }
134 SkASSERT(false);
Brian Osman1091f022019-05-16 09:42:16 -0400135 return 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400136 }
137 case Variable::kGlobal_Storage: {
138 int offset = 0;
139 for (const auto& e : fProgram) {
140 if (e.fKind == ProgramElement::kVar_Kind) {
141 VarDeclarations& decl = (VarDeclarations&) e;
142 for (const auto& v : decl.fVars) {
143 const Variable* declVar = ((VarDeclaration&) *v).fVar;
144 if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
145 continue;
146 }
147 if (declVar == &var) {
Brian Osmanb7451292019-05-15 13:02:13 -0400148 SkASSERT(offset <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400149 return offset;
150 }
151 offset += slot_count(declVar->fType);
152 }
153 }
154 }
155 SkASSERT(false);
Brian Osman1091f022019-05-16 09:42:16 -0400156 return 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400157 }
158 default:
159 SkASSERT(false);
160 return 0;
161 }
162}
163
164void ByteCodeGenerator::write8(uint8_t b) {
165 fCode->push_back(b);
166}
167
168void ByteCodeGenerator::write16(uint16_t i) {
Mike Klein76346ac2019-05-17 11:57:10 -0500169 size_t n = fCode->size();
170 fCode->resize(n+2);
171 memcpy(fCode->data() + n, &i, 2);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400172}
173
174void ByteCodeGenerator::write32(uint32_t i) {
Mike Klein76346ac2019-05-17 11:57:10 -0500175 size_t n = fCode->size();
176 fCode->resize(n+4);
177 memcpy(fCode->data() + n, &i, 4);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400178}
179
180void ByteCodeGenerator::write(ByteCodeInstruction i) {
Mike Klein108e9352019-05-21 11:05:17 -0500181 this->write16((uint16_t)i);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400182}
183
Mike Klein76346ac2019-05-17 11:57:10 -0500184static ByteCodeInstruction vector_instruction(ByteCodeInstruction base, int count) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400185 return ((ByteCodeInstruction) ((int) base + count - 1));
186}
187
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400188void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400189 ByteCodeInstruction u, ByteCodeInstruction f,
190 int count) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400191 switch (type_category(type)) {
192 case TypeCategory::kSigned:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400193 this->write(vector_instruction(s, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400194 break;
195 case TypeCategory::kUnsigned:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400196 this->write(vector_instruction(u, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400197 break;
198 case TypeCategory::kFloat:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400199 this->write(vector_instruction(f, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400200 break;
201 default:
202 SkASSERT(false);
203 }
204}
205
206void ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b) {
207 if (b.fOperator == Token::Kind::EQ) {
208 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
209 this->writeExpression(*b.fRight);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400210 lvalue->store();
211 return;
212 }
213 Token::Kind op;
214 std::unique_ptr<LValue> lvalue;
215 if (is_assignment(b.fOperator)) {
216 lvalue = this->getLValue(*b.fLeft);
217 lvalue->load();
218 op = remove_assignment(b.fOperator);
219 } else {
220 this->writeExpression(*b.fLeft);
221 op = b.fOperator;
222 if (b.fLeft->fType.kind() == Type::kScalar_Kind &&
223 b.fRight->fType.kind() == Type::kVector_Kind) {
224 for (int i = b.fRight->fType.columns(); i > 1; --i) {
225 this->write(ByteCodeInstruction::kDup);
226 }
227 }
228 }
229 this->writeExpression(*b.fRight);
230 if (b.fLeft->fType.kind() == Type::kVector_Kind &&
231 b.fRight->fType.kind() == Type::kScalar_Kind) {
232 for (int i = b.fLeft->fType.columns(); i > 1; --i) {
233 this->write(ByteCodeInstruction::kDup);
234 }
235 }
236 int count = slot_count(b.fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400237 switch (op) {
238 case Token::Kind::EQEQ:
239 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareIEQ,
240 ByteCodeInstruction::kCompareIEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400241 ByteCodeInstruction::kCompareFEQ,
242 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400243 break;
244 case Token::Kind::GT:
245 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGT,
246 ByteCodeInstruction::kCompareUGT,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400247 ByteCodeInstruction::kCompareFGT,
248 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400249 break;
250 case Token::Kind::GTEQ:
251 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGTEQ,
252 ByteCodeInstruction::kCompareUGTEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400253 ByteCodeInstruction::kCompareFGTEQ,
254 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400255 break;
256 case Token::Kind::LT:
257 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLT,
258 ByteCodeInstruction::kCompareULT,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400259 ByteCodeInstruction::kCompareFLT,
260 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400261 break;
262 case Token::Kind::LTEQ:
263 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLTEQ,
264 ByteCodeInstruction::kCompareULTEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400265 ByteCodeInstruction::kCompareFLTEQ,
266 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400267 break;
268 case Token::Kind::MINUS:
269 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kSubtractI,
270 ByteCodeInstruction::kSubtractI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400271 ByteCodeInstruction::kSubtractF,
272 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400273 break;
274 case Token::Kind::NEQ:
275 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareINEQ,
276 ByteCodeInstruction::kCompareINEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400277 ByteCodeInstruction::kCompareFNEQ,
278 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400279 break;
280 case Token::Kind::PERCENT:
281 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kRemainderS,
282 ByteCodeInstruction::kRemainderU,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400283 ByteCodeInstruction::kRemainderF,
284 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400285 break;
286 case Token::Kind::PLUS:
287 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kAddI,
288 ByteCodeInstruction::kAddI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400289 ByteCodeInstruction::kAddF,
290 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400291 break;
292 case Token::Kind::SLASH:
293 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kDivideS,
294 ByteCodeInstruction::kDivideU,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400295 ByteCodeInstruction::kDivideF,
296 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400297 break;
298 case Token::Kind::STAR:
Ethan Nicholas91164d12019-05-15 15:29:54 -0400299 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kMultiplyI,
300 ByteCodeInstruction::kMultiplyI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400301 ByteCodeInstruction::kMultiplyF,
302 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400303 break;
304 default:
305 SkASSERT(false);
306 }
307 if (lvalue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400308 lvalue->store();
309 }
310}
311
312void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
313 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osman44d44762019-05-13 14:19:12 -0400314 this->write32(b.fValue ? 1 : 0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400315}
316
317void ByteCodeGenerator::writeConstructor(const Constructor& c) {
318 if (c.fArguments.size() == 1 &&
319 type_category(c.fType) == type_category(c.fArguments[0]->fType)) {
320 // cast from float to half or similar no-op
321 this->writeExpression(*c.fArguments[0]);
322 return;
323 }
324 for (const auto& arg : c.fArguments) {
325 this->writeExpression(*arg);
326 }
327 if (c.fArguments.size() == 1) {
328 TypeCategory inCategory = type_category(c.fArguments[0]->fType);
329 TypeCategory outCategory = type_category(c.fType);
330 if (inCategory != outCategory) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400331 if (inCategory == TypeCategory::kFloat) {
332 SkASSERT(outCategory == TypeCategory::kSigned ||
333 outCategory == TypeCategory::kUnsigned);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400334 this->write(vector_instruction(ByteCodeInstruction::kFloatToInt,
335 c.fType.columns()));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400336 } else if (outCategory == TypeCategory::kFloat) {
337 if (inCategory == TypeCategory::kSigned) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400338 this->write(vector_instruction(ByteCodeInstruction::kSignedToFloat,
339 c.fType.columns()));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400340 } else {
341 SkASSERT(inCategory == TypeCategory::kUnsigned);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400342 this->write(vector_instruction(ByteCodeInstruction::kUnsignedToFloat,
343 c.fType.columns()));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400344 }
345 } else {
346 SkASSERT(false);
347 }
348 }
349 }
350}
351
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400352void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f) {
353 int argumentCount = 0;
354 for (const auto& arg : f.fArguments) {
355 this->writeExpression(*arg);
356 argumentCount += slot_count(arg->fType);
357 }
358 this->write(ByteCodeInstruction::kCallExternal);
359 SkASSERT(argumentCount <= 255);
360 this->write8(argumentCount);
361 this->write8(slot_count(f.fType));
362 int index = fOutput->fExternalValues.size();
363 fOutput->fExternalValues.push_back(f.fFunction);
364 SkASSERT(index <= 255);
365 this->write8(index);
366}
367
Ethan Nicholas91164d12019-05-15 15:29:54 -0400368void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400369 this->write(vector_instruction(ByteCodeInstruction::kReadExternal,
370 slot_count(e.fValue->type())));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400371 int index = fOutput->fExternalValues.size();
372 fOutput->fExternalValues.push_back(e.fValue);
373 SkASSERT(index <= 255);
374 this->write8(index);
375}
376
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400377void ByteCodeGenerator::writeFieldAccess(const FieldAccess& f) {
378 // not yet implemented
379 abort();
380}
381
382void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
383 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400384 this->write32(Interpreter::Value((float) f.fValue).fUnsigned);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400385}
386
387void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Brian Osman226668a2019-05-14 16:47:30 -0400388 for (const auto& arg : f.fArguments) {
389 this->writeExpression(*arg);
390 }
391 this->write(ByteCodeInstruction::kCall);
392 fCallTargets.emplace_back(this, f.fFunction);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400393}
394
395void ByteCodeGenerator::writeIndexExpression(const IndexExpression& i) {
396 // not yet implemented
397 abort();
398}
399
400void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
401 this->write(ByteCodeInstruction::kPushImmediate);
402 this->write32(i.fValue);
403}
404
405void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
406 // not yet implemented
407 abort();
408}
409
410void ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p) {
411 switch (p.fOperator) {
412 case Token::Kind::PLUSPLUS: // fall through
413 case Token::Kind::MINUSMINUS: {
Brian Osmanf3fa6002019-05-17 14:26:53 -0400414 SkASSERT(slot_count(p.fOperand->fType) == 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400415 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
416 lvalue->load();
417 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400418 this->write32(type_category(p.fType) == TypeCategory::kFloat
419 ? Interpreter::Value(1.0f).fUnsigned : 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400420 if (p.fOperator == Token::Kind::PLUSPLUS) {
421 this->writeTypedInstruction(p.fType,
422 ByteCodeInstruction::kAddI,
423 ByteCodeInstruction::kAddI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400424 ByteCodeInstruction::kAddF,
425 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400426 } else {
427 this->writeTypedInstruction(p.fType,
428 ByteCodeInstruction::kSubtractI,
429 ByteCodeInstruction::kSubtractI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400430 ByteCodeInstruction::kSubtractF,
431 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400432 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400433 lvalue->store();
434 break;
435 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400436 case Token::Kind::MINUS: {
437 this->writeExpression(*p.fOperand);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400438 this->writeTypedInstruction(p.fType,
Mike Klein12710912019-05-21 11:04:59 -0500439 ByteCodeInstruction::kNegateI,
440 ByteCodeInstruction::kNegateI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400441 ByteCodeInstruction::kNegateF,
442 slot_count(p.fOperand->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400443 break;
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400444 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400445 default:
446 SkASSERT(false);
447 }
448}
449
450void ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p) {
Brian Osmanf3fa6002019-05-17 14:26:53 -0400451 switch (p.fOperator) {
452 case Token::Kind::PLUSPLUS: // fall through
453 case Token::Kind::MINUSMINUS: {
454 SkASSERT(slot_count(p.fOperand->fType) == 1);
455 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
456 lvalue->load();
457 this->write(ByteCodeInstruction::kDup);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400458 this->write(ByteCodeInstruction::kPushImmediate);
459 this->write32(type_category(p.fType) == TypeCategory::kFloat
460 ? Interpreter::Value(1.0f).fUnsigned : 1);
461 if (p.fOperator == Token::Kind::PLUSPLUS) {
462 this->writeTypedInstruction(p.fType,
463 ByteCodeInstruction::kAddI,
464 ByteCodeInstruction::kAddI,
465 ByteCodeInstruction::kAddF,
466 1);
467 } else {
468 this->writeTypedInstruction(p.fType,
469 ByteCodeInstruction::kSubtractI,
470 ByteCodeInstruction::kSubtractI,
471 ByteCodeInstruction::kSubtractF,
472 1);
473 }
474 lvalue->store();
475 this->write(ByteCodeInstruction::kPop);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400476 break;
477 }
478 default:
479 SkASSERT(false);
480 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400481}
482
483void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
484 switch (s.fBase->fKind) {
485 case Expression::kVariableReference_Kind: {
486 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
Brian Osman1091f022019-05-16 09:42:16 -0400487 this->write(var.fStorage == Variable::kGlobal_Storage
488 ? ByteCodeInstruction::kLoadSwizzleGlobal
489 : ByteCodeInstruction::kLoadSwizzle);
490 this->write8(this->getLocation(var));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400491 this->write8(s.fComponents.size());
492 for (int c : s.fComponents) {
493 this->write8(c);
494 }
495 break;
496 }
497 default:
498 this->writeExpression(*s.fBase);
499 this->write(ByteCodeInstruction::kSwizzle);
500 this->write8(s.fBase->fType.columns());
501 this->write8(s.fComponents.size());
502 for (int c : s.fComponents) {
503 this->write8(c);
504 }
505 }
506}
507
508void ByteCodeGenerator::writeVariableReference(const VariableReference& v) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400509 this->write(vector_instruction(v.fVariable.fStorage == Variable::kGlobal_Storage
510 ? ByteCodeInstruction::kLoadGlobal
511 : ByteCodeInstruction::kLoad,
512 slot_count(v.fType)));
Brian Osman1091f022019-05-16 09:42:16 -0400513 this->write8(this->getLocation(v.fVariable));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400514}
515
516void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Brian Osman4e93feb2019-05-16 15:38:00 -0400517 this->writeExpression(*t.fTest);
Brian Osman4e93feb2019-05-16 15:38:00 -0400518 this->write(ByteCodeInstruction::kConditionalBranch);
519 DeferredLocation trueLocation(this);
520 this->writeExpression(*t.fIfFalse);
Brian Osman4e93feb2019-05-16 15:38:00 -0400521 this->write(ByteCodeInstruction::kBranch);
522 DeferredLocation endLocation(this);
523 trueLocation.set();
524 this->writeExpression(*t.fIfTrue);
525 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400526}
527
528void ByteCodeGenerator::writeExpression(const Expression& e) {
529 switch (e.fKind) {
530 case Expression::kBinary_Kind:
531 this->writeBinaryExpression((BinaryExpression&) e);
532 break;
533 case Expression::kBoolLiteral_Kind:
534 this->writeBoolLiteral((BoolLiteral&) e);
535 break;
536 case Expression::kConstructor_Kind:
537 this->writeConstructor((Constructor&) e);
538 break;
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400539 case Expression::kExternalFunctionCall_Kind:
540 this->writeExternalFunctionCall((ExternalFunctionCall&) e);
541 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400542 case Expression::kExternalValue_Kind:
543 this->writeExternalValue((ExternalValueReference&) e);
544 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400545 case Expression::kFieldAccess_Kind:
546 this->writeFieldAccess((FieldAccess&) e);
547 break;
548 case Expression::kFloatLiteral_Kind:
549 this->writeFloatLiteral((FloatLiteral&) e);
550 break;
551 case Expression::kFunctionCall_Kind:
552 this->writeFunctionCall((FunctionCall&) e);
553 break;
554 case Expression::kIndex_Kind:
555 this->writeIndexExpression((IndexExpression&) e);
556 break;
557 case Expression::kIntLiteral_Kind:
558 this->writeIntLiteral((IntLiteral&) e);
559 break;
560 case Expression::kNullLiteral_Kind:
561 this->writeNullLiteral((NullLiteral&) e);
562 break;
563 case Expression::kPrefix_Kind:
564 this->writePrefixExpression((PrefixExpression&) e);
565 break;
566 case Expression::kPostfix_Kind:
567 this->writePostfixExpression((PostfixExpression&) e);
568 break;
569 case Expression::kSwizzle_Kind:
570 this->writeSwizzle((Swizzle&) e);
571 break;
572 case Expression::kVariableReference_Kind:
573 this->writeVariableReference((VariableReference&) e);
574 break;
575 case Expression::kTernary_Kind:
576 this->writeTernaryExpression((TernaryExpression&) e);
577 break;
578 default:
579 printf("unsupported expression %s\n", e.description().c_str());
580 SkASSERT(false);
581 }
582}
583
Ethan Nicholas91164d12019-05-15 15:29:54 -0400584class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
585public:
586 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
587 : INHERITED(*generator)
588 , fCount(slot_count(value.type()))
589 , fIndex(index) {}
590
591 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400592 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400593 fGenerator.write8(fIndex);
594 }
595
596 void store() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400597 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
598 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400599 fGenerator.write8(fIndex);
600 }
601
602private:
603 typedef LValue INHERITED;
604
605 int fCount;
606
607 int fIndex;
608};
609
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400610class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
611public:
612 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
613 : INHERITED(*generator)
614 , fSwizzle(swizzle) {
Brian Osman1091f022019-05-16 09:42:16 -0400615 SkASSERT(fSwizzle.fBase->fKind == Expression::kVariableReference_Kind);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400616 }
617
618 void load() override {
Brian Osman1091f022019-05-16 09:42:16 -0400619 fGenerator.writeSwizzle(fSwizzle);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400620 }
621
622 void store() override {
Brian Osman1091f022019-05-16 09:42:16 -0400623 const Variable& var = ((VariableReference&)*fSwizzle.fBase).fVariable;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400624 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup,
625 fSwizzle.fComponents.size()));
Brian Osman1091f022019-05-16 09:42:16 -0400626 fGenerator.write(var.fStorage == Variable::kGlobal_Storage
627 ? ByteCodeInstruction::kStoreSwizzleGlobal
628 : ByteCodeInstruction::kStoreSwizzle);
629 fGenerator.write8(fGenerator.getLocation(var));
630 fGenerator.write8(fSwizzle.fComponents.size());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400631 for (int c : fSwizzle.fComponents) {
632 fGenerator.write8(c);
633 }
634 }
635
636private:
637 const Swizzle& fSwizzle;
638
639 typedef LValue INHERITED;
640};
641
642class ByteCodeVariableLValue : public ByteCodeGenerator::LValue {
643public:
644 ByteCodeVariableLValue(ByteCodeGenerator* generator, const Variable& var)
645 : INHERITED(*generator)
646 , fCount(slot_count(var.fType))
Brian Osman1091f022019-05-16 09:42:16 -0400647 , fLocation(generator->getLocation(var))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400648 , fIsGlobal(var.fStorage == Variable::kGlobal_Storage) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400649 }
650
651 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400652 fGenerator.write(vector_instruction(fIsGlobal ? ByteCodeInstruction::kLoadGlobal
653 : ByteCodeInstruction::kLoad,
654 fCount));
Brian Osman1091f022019-05-16 09:42:16 -0400655 fGenerator.write8(fLocation);
656 }
657
658 void store() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400659 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
660 fGenerator.write(vector_instruction(fIsGlobal ? ByteCodeInstruction::kStoreGlobal
661 : ByteCodeInstruction::kStore,
662 fCount));
Brian Osman1091f022019-05-16 09:42:16 -0400663 fGenerator.write8(fLocation);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400664 }
665
666private:
667 typedef LValue INHERITED;
668
669 int fCount;
Brian Osman1091f022019-05-16 09:42:16 -0400670 int fLocation;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400671 bool fIsGlobal;
672};
673
674std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
675 switch (e.fKind) {
Ethan Nicholas91164d12019-05-15 15:29:54 -0400676 case Expression::kExternalValue_Kind: {
677 ExternalValue* value = ((ExternalValueReference&) e).fValue;
678 int index = fOutput->fExternalValues.size();
679 fOutput->fExternalValues.push_back(value);
680 SkASSERT(index <= 255);
681 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
682 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400683 case Expression::kIndex_Kind:
684 // not yet implemented
685 abort();
686 case Expression::kVariableReference_Kind:
687 return std::unique_ptr<LValue>(new ByteCodeVariableLValue(this,
688 ((VariableReference&) e).fVariable));
689 case Expression::kSwizzle_Kind:
690 return std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, (Swizzle&) e));
691 case Expression::kTernary_Kind:
692 default:
693 printf("unsupported lvalue %s\n", e.description().c_str());
694 return nullptr;
695 }
696}
697
698void ByteCodeGenerator::writeBlock(const Block& b) {
699 for (const auto& s : b.fStatements) {
700 this->writeStatement(*s);
701 }
702}
703
704void ByteCodeGenerator::setBreakTargets() {
705 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
706 for (DeferredLocation& b : breaks) {
707 b.set();
708 }
709 fBreakTargets.pop();
710}
711
712void ByteCodeGenerator::setContinueTargets() {
713 std::vector<DeferredLocation>& continues = fContinueTargets.top();
714 for (DeferredLocation& c : continues) {
715 c.set();
716 }
717 fContinueTargets.pop();
718}
719
720void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
721 this->write(ByteCodeInstruction::kBranch);
722 fBreakTargets.top().emplace_back(this);
723}
724
725void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
726 this->write(ByteCodeInstruction::kBranch);
727 fContinueTargets.top().emplace_back(this);
728}
729
730void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
731 fContinueTargets.emplace();
732 fBreakTargets.emplace();
733 size_t start = fCode->size();
734 this->writeStatement(*d.fStatement);
735 this->setContinueTargets();
736 this->writeExpression(*d.fTest);
737 this->write(ByteCodeInstruction::kConditionalBranch);
738 this->write16(start);
739 this->setBreakTargets();
740}
741
742void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
743 fContinueTargets.emplace();
744 fBreakTargets.emplace();
745 if (f.fInitializer) {
746 this->writeStatement(*f.fInitializer);
747 }
748 size_t start = fCode->size();
749 if (f.fTest) {
750 this->writeExpression(*f.fTest);
751 this->write(ByteCodeInstruction::kNot);
752 this->write(ByteCodeInstruction::kConditionalBranch);
753 DeferredLocation endLocation(this);
754 this->writeStatement(*f.fStatement);
755 this->setContinueTargets();
756 if (f.fNext) {
757 this->writeExpression(*f.fNext);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400758 this->write(vector_instruction(ByteCodeInstruction::kPop, slot_count(f.fNext->fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400759 }
760 this->write(ByteCodeInstruction::kBranch);
761 this->write16(start);
762 endLocation.set();
763 } else {
764 this->writeStatement(*f.fStatement);
765 this->setContinueTargets();
766 if (f.fNext) {
767 this->writeExpression(*f.fNext);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400768 this->write(vector_instruction(ByteCodeInstruction::kPop, slot_count(f.fNext->fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400769 }
770 this->write(ByteCodeInstruction::kBranch);
771 this->write16(start);
772 }
773 this->setBreakTargets();
774}
775
776void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400777 if (i.fIfFalse) {
Mike Kleinb45ee832019-05-17 11:11:11 -0500778 // if (test) { ..ifTrue.. } else { .. ifFalse .. }
779 this->writeExpression(*i.fTest);
Mike Kleinb45ee832019-05-17 11:11:11 -0500780 this->write(ByteCodeInstruction::kConditionalBranch);
781 DeferredLocation trueLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400782 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -0500783 this->write(ByteCodeInstruction::kBranch);
784 DeferredLocation endLocation(this);
785 trueLocation.set();
786 this->writeStatement(*i.fIfTrue);
787 endLocation.set();
788 } else {
789 // if (test) { ..ifTrue.. }
790 this->writeExpression(*i.fTest);
791 this->write(ByteCodeInstruction::kNot);
Mike Kleinb45ee832019-05-17 11:11:11 -0500792 this->write(ByteCodeInstruction::kConditionalBranch);
793 DeferredLocation endLocation(this);
794 this->writeStatement(*i.fIfTrue);
795 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400796 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400797}
798
799void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -0400800 this->writeExpression(*r.fExpression);
801 this->write(ByteCodeInstruction::kReturn);
802 this->write8(r.fExpression->fType.columns() * r.fExpression->fType.rows());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400803}
804
805void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
806 // not yet implemented
807 abort();
808}
809
810void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
811 for (const auto& declStatement : v.fVars) {
812 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
813 // we need to grab the location even if we don't use it, to ensure it
814 // has been allocated
815 int location = getLocation(*decl.fVar);
816 if (decl.fValue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400817 this->writeExpression(*decl.fValue);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400818 this->write(vector_instruction(ByteCodeInstruction::kStore,
819 slot_count(decl.fValue->fType)));
Brian Osman1091f022019-05-16 09:42:16 -0400820 this->write8(location);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400821 }
822 }
823}
824
825void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
826 fContinueTargets.emplace();
827 fBreakTargets.emplace();
828 size_t start = fCode->size();
829 this->writeExpression(*w.fTest);
830 this->write(ByteCodeInstruction::kNot);
831 this->write(ByteCodeInstruction::kConditionalBranch);
832 DeferredLocation endLocation(this);
833 this->writeStatement(*w.fStatement);
834 this->setContinueTargets();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400835 this->write(ByteCodeInstruction::kBranch);
836 this->write16(start);
837 endLocation.set();
838 this->setBreakTargets();
839}
840
841void ByteCodeGenerator::writeStatement(const Statement& s) {
842 switch (s.fKind) {
843 case Statement::kBlock_Kind:
844 this->writeBlock((Block&) s);
845 break;
846 case Statement::kBreak_Kind:
847 this->writeBreakStatement((BreakStatement&) s);
848 break;
849 case Statement::kContinue_Kind:
850 this->writeContinueStatement((ContinueStatement&) s);
851 break;
852 case Statement::kDiscard_Kind:
853 // not yet implemented
854 abort();
855 case Statement::kDo_Kind:
856 this->writeDoStatement((DoStatement&) s);
857 break;
858 case Statement::kExpression_Kind: {
859 const Expression& expr = *((ExpressionStatement&) s).fExpression;
860 this->writeExpression(expr);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400861 this->write(vector_instruction(ByteCodeInstruction::kPop, slot_count(expr.fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400862 break;
863 }
864 case Statement::kFor_Kind:
865 this->writeForStatement((ForStatement&) s);
866 break;
867 case Statement::kIf_Kind:
868 this->writeIfStatement((IfStatement&) s);
869 break;
870 case Statement::kNop_Kind:
871 break;
872 case Statement::kReturn_Kind:
873 this->writeReturnStatement((ReturnStatement&) s);
874 break;
875 case Statement::kSwitch_Kind:
876 this->writeSwitchStatement((SwitchStatement&) s);
877 break;
878 case Statement::kVarDeclarations_Kind:
879 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
880 break;
881 case Statement::kWhile_Kind:
882 this->writeWhileStatement((WhileStatement&) s);
883 break;
884 default:
885 SkASSERT(false);
886 }
887}
888
889}