blob: 91a2d70cd31c0c9408fe46aa698aaba1557a54b7 [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 Kleine5288362019-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 Kleine5288362019-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) {
181 this->write8((uint8_t) i);
182}
183
Mike Kleine5288362019-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 Nicholas91164d12019-05-15 15:29:54 -0400352void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400353 this->write(vector_instruction(ByteCodeInstruction::kReadExternal,
354 slot_count(e.fValue->type())));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400355 int index = fOutput->fExternalValues.size();
356 fOutput->fExternalValues.push_back(e.fValue);
357 SkASSERT(index <= 255);
358 this->write8(index);
359}
360
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400361void ByteCodeGenerator::writeFieldAccess(const FieldAccess& f) {
362 // not yet implemented
363 abort();
364}
365
366void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
367 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400368 this->write32(Interpreter::Value((float) f.fValue).fUnsigned);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400369}
370
371void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Brian Osman226668a2019-05-14 16:47:30 -0400372 for (const auto& arg : f.fArguments) {
373 this->writeExpression(*arg);
374 }
375 this->write(ByteCodeInstruction::kCall);
376 fCallTargets.emplace_back(this, f.fFunction);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400377}
378
379void ByteCodeGenerator::writeIndexExpression(const IndexExpression& i) {
380 // not yet implemented
381 abort();
382}
383
384void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
385 this->write(ByteCodeInstruction::kPushImmediate);
386 this->write32(i.fValue);
387}
388
389void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
390 // not yet implemented
391 abort();
392}
393
394void ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p) {
395 switch (p.fOperator) {
396 case Token::Kind::PLUSPLUS: // fall through
397 case Token::Kind::MINUSMINUS: {
Brian Osmanf3fa6002019-05-17 14:26:53 -0400398 SkASSERT(slot_count(p.fOperand->fType) == 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400399 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
400 lvalue->load();
401 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400402 this->write32(type_category(p.fType) == TypeCategory::kFloat
403 ? Interpreter::Value(1.0f).fUnsigned : 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400404 if (p.fOperator == Token::Kind::PLUSPLUS) {
405 this->writeTypedInstruction(p.fType,
406 ByteCodeInstruction::kAddI,
407 ByteCodeInstruction::kAddI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400408 ByteCodeInstruction::kAddF,
409 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400410 } else {
411 this->writeTypedInstruction(p.fType,
412 ByteCodeInstruction::kSubtractI,
413 ByteCodeInstruction::kSubtractI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400414 ByteCodeInstruction::kSubtractF,
415 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400416 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400417 lvalue->store();
418 break;
419 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400420 case Token::Kind::MINUS: {
421 this->writeExpression(*p.fOperand);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400422 this->writeTypedInstruction(p.fType,
423 ByteCodeInstruction::kNegateS,
424 ByteCodeInstruction::kInvalid,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400425 ByteCodeInstruction::kNegateF,
426 slot_count(p.fOperand->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400427 break;
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400428 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400429 default:
430 SkASSERT(false);
431 }
432}
433
434void ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p) {
Brian Osmanf3fa6002019-05-17 14:26:53 -0400435 switch (p.fOperator) {
436 case Token::Kind::PLUSPLUS: // fall through
437 case Token::Kind::MINUSMINUS: {
438 SkASSERT(slot_count(p.fOperand->fType) == 1);
439 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
440 lvalue->load();
441 this->write(ByteCodeInstruction::kDup);
442 this->align(4, 3);
443 this->write(ByteCodeInstruction::kPushImmediate);
444 this->write32(type_category(p.fType) == TypeCategory::kFloat
445 ? Interpreter::Value(1.0f).fUnsigned : 1);
446 if (p.fOperator == Token::Kind::PLUSPLUS) {
447 this->writeTypedInstruction(p.fType,
448 ByteCodeInstruction::kAddI,
449 ByteCodeInstruction::kAddI,
450 ByteCodeInstruction::kAddF,
451 1);
452 } else {
453 this->writeTypedInstruction(p.fType,
454 ByteCodeInstruction::kSubtractI,
455 ByteCodeInstruction::kSubtractI,
456 ByteCodeInstruction::kSubtractF,
457 1);
458 }
459 lvalue->store();
460 this->write(ByteCodeInstruction::kPop);
461 this->write8(1);
462 break;
463 }
464 default:
465 SkASSERT(false);
466 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400467}
468
469void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
470 switch (s.fBase->fKind) {
471 case Expression::kVariableReference_Kind: {
472 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
Brian Osman1091f022019-05-16 09:42:16 -0400473 this->write(var.fStorage == Variable::kGlobal_Storage
474 ? ByteCodeInstruction::kLoadSwizzleGlobal
475 : ByteCodeInstruction::kLoadSwizzle);
476 this->write8(this->getLocation(var));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400477 this->write8(s.fComponents.size());
478 for (int c : s.fComponents) {
479 this->write8(c);
480 }
481 break;
482 }
483 default:
484 this->writeExpression(*s.fBase);
485 this->write(ByteCodeInstruction::kSwizzle);
486 this->write8(s.fBase->fType.columns());
487 this->write8(s.fComponents.size());
488 for (int c : s.fComponents) {
489 this->write8(c);
490 }
491 }
492}
493
494void ByteCodeGenerator::writeVariableReference(const VariableReference& v) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400495 this->write(vector_instruction(v.fVariable.fStorage == Variable::kGlobal_Storage
496 ? ByteCodeInstruction::kLoadGlobal
497 : ByteCodeInstruction::kLoad,
498 slot_count(v.fType)));
Brian Osman1091f022019-05-16 09:42:16 -0400499 this->write8(this->getLocation(v.fVariable));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400500}
501
502void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Brian Osman4e93feb2019-05-16 15:38:00 -0400503 this->writeExpression(*t.fTest);
Brian Osman4e93feb2019-05-16 15:38:00 -0400504 this->write(ByteCodeInstruction::kConditionalBranch);
505 DeferredLocation trueLocation(this);
506 this->writeExpression(*t.fIfFalse);
Brian Osman4e93feb2019-05-16 15:38:00 -0400507 this->write(ByteCodeInstruction::kBranch);
508 DeferredLocation endLocation(this);
509 trueLocation.set();
510 this->writeExpression(*t.fIfTrue);
511 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400512}
513
514void ByteCodeGenerator::writeExpression(const Expression& e) {
515 switch (e.fKind) {
516 case Expression::kBinary_Kind:
517 this->writeBinaryExpression((BinaryExpression&) e);
518 break;
519 case Expression::kBoolLiteral_Kind:
520 this->writeBoolLiteral((BoolLiteral&) e);
521 break;
522 case Expression::kConstructor_Kind:
523 this->writeConstructor((Constructor&) e);
524 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400525 case Expression::kExternalValue_Kind:
526 this->writeExternalValue((ExternalValueReference&) e);
527 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400528 case Expression::kFieldAccess_Kind:
529 this->writeFieldAccess((FieldAccess&) e);
530 break;
531 case Expression::kFloatLiteral_Kind:
532 this->writeFloatLiteral((FloatLiteral&) e);
533 break;
534 case Expression::kFunctionCall_Kind:
535 this->writeFunctionCall((FunctionCall&) e);
536 break;
537 case Expression::kIndex_Kind:
538 this->writeIndexExpression((IndexExpression&) e);
539 break;
540 case Expression::kIntLiteral_Kind:
541 this->writeIntLiteral((IntLiteral&) e);
542 break;
543 case Expression::kNullLiteral_Kind:
544 this->writeNullLiteral((NullLiteral&) e);
545 break;
546 case Expression::kPrefix_Kind:
547 this->writePrefixExpression((PrefixExpression&) e);
548 break;
549 case Expression::kPostfix_Kind:
550 this->writePostfixExpression((PostfixExpression&) e);
551 break;
552 case Expression::kSwizzle_Kind:
553 this->writeSwizzle((Swizzle&) e);
554 break;
555 case Expression::kVariableReference_Kind:
556 this->writeVariableReference((VariableReference&) e);
557 break;
558 case Expression::kTernary_Kind:
559 this->writeTernaryExpression((TernaryExpression&) e);
560 break;
561 default:
562 printf("unsupported expression %s\n", e.description().c_str());
563 SkASSERT(false);
564 }
565}
566
Ethan Nicholas91164d12019-05-15 15:29:54 -0400567class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
568public:
569 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
570 : INHERITED(*generator)
571 , fCount(slot_count(value.type()))
572 , fIndex(index) {}
573
574 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400575 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400576 fGenerator.write8(fIndex);
577 }
578
579 void store() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400580 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
581 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400582 fGenerator.write8(fIndex);
583 }
584
585private:
586 typedef LValue INHERITED;
587
588 int fCount;
589
590 int fIndex;
591};
592
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400593class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
594public:
595 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
596 : INHERITED(*generator)
597 , fSwizzle(swizzle) {
Brian Osman1091f022019-05-16 09:42:16 -0400598 SkASSERT(fSwizzle.fBase->fKind == Expression::kVariableReference_Kind);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400599 }
600
601 void load() override {
Brian Osman1091f022019-05-16 09:42:16 -0400602 fGenerator.writeSwizzle(fSwizzle);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400603 }
604
605 void store() override {
Brian Osman1091f022019-05-16 09:42:16 -0400606 const Variable& var = ((VariableReference&)*fSwizzle.fBase).fVariable;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400607 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup,
608 fSwizzle.fComponents.size()));
Brian Osman1091f022019-05-16 09:42:16 -0400609 fGenerator.write(var.fStorage == Variable::kGlobal_Storage
610 ? ByteCodeInstruction::kStoreSwizzleGlobal
611 : ByteCodeInstruction::kStoreSwizzle);
612 fGenerator.write8(fGenerator.getLocation(var));
613 fGenerator.write8(fSwizzle.fComponents.size());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400614 for (int c : fSwizzle.fComponents) {
615 fGenerator.write8(c);
616 }
617 }
618
619private:
620 const Swizzle& fSwizzle;
621
622 typedef LValue INHERITED;
623};
624
625class ByteCodeVariableLValue : public ByteCodeGenerator::LValue {
626public:
627 ByteCodeVariableLValue(ByteCodeGenerator* generator, const Variable& var)
628 : INHERITED(*generator)
629 , fCount(slot_count(var.fType))
Brian Osman1091f022019-05-16 09:42:16 -0400630 , fLocation(generator->getLocation(var))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400631 , fIsGlobal(var.fStorage == Variable::kGlobal_Storage) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400632 }
633
634 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400635 fGenerator.write(vector_instruction(fIsGlobal ? ByteCodeInstruction::kLoadGlobal
636 : ByteCodeInstruction::kLoad,
637 fCount));
Brian Osman1091f022019-05-16 09:42:16 -0400638 fGenerator.write8(fLocation);
639 }
640
641 void store() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400642 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
643 fGenerator.write(vector_instruction(fIsGlobal ? ByteCodeInstruction::kStoreGlobal
644 : ByteCodeInstruction::kStore,
645 fCount));
Brian Osman1091f022019-05-16 09:42:16 -0400646 fGenerator.write8(fLocation);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400647 }
648
649private:
650 typedef LValue INHERITED;
651
652 int fCount;
Brian Osman1091f022019-05-16 09:42:16 -0400653 int fLocation;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400654 bool fIsGlobal;
655};
656
657std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
658 switch (e.fKind) {
Ethan Nicholas91164d12019-05-15 15:29:54 -0400659 case Expression::kExternalValue_Kind: {
660 ExternalValue* value = ((ExternalValueReference&) e).fValue;
661 int index = fOutput->fExternalValues.size();
662 fOutput->fExternalValues.push_back(value);
663 SkASSERT(index <= 255);
664 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
665 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400666 case Expression::kIndex_Kind:
667 // not yet implemented
668 abort();
669 case Expression::kVariableReference_Kind:
670 return std::unique_ptr<LValue>(new ByteCodeVariableLValue(this,
671 ((VariableReference&) e).fVariable));
672 case Expression::kSwizzle_Kind:
673 return std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, (Swizzle&) e));
674 case Expression::kTernary_Kind:
675 default:
676 printf("unsupported lvalue %s\n", e.description().c_str());
677 return nullptr;
678 }
679}
680
681void ByteCodeGenerator::writeBlock(const Block& b) {
682 for (const auto& s : b.fStatements) {
683 this->writeStatement(*s);
684 }
685}
686
687void ByteCodeGenerator::setBreakTargets() {
688 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
689 for (DeferredLocation& b : breaks) {
690 b.set();
691 }
692 fBreakTargets.pop();
693}
694
695void ByteCodeGenerator::setContinueTargets() {
696 std::vector<DeferredLocation>& continues = fContinueTargets.top();
697 for (DeferredLocation& c : continues) {
698 c.set();
699 }
700 fContinueTargets.pop();
701}
702
703void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
704 this->write(ByteCodeInstruction::kBranch);
705 fBreakTargets.top().emplace_back(this);
706}
707
708void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
709 this->write(ByteCodeInstruction::kBranch);
710 fContinueTargets.top().emplace_back(this);
711}
712
713void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
714 fContinueTargets.emplace();
715 fBreakTargets.emplace();
716 size_t start = fCode->size();
717 this->writeStatement(*d.fStatement);
718 this->setContinueTargets();
719 this->writeExpression(*d.fTest);
720 this->write(ByteCodeInstruction::kConditionalBranch);
721 this->write16(start);
722 this->setBreakTargets();
723}
724
725void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
726 fContinueTargets.emplace();
727 fBreakTargets.emplace();
728 if (f.fInitializer) {
729 this->writeStatement(*f.fInitializer);
730 }
731 size_t start = fCode->size();
732 if (f.fTest) {
733 this->writeExpression(*f.fTest);
734 this->write(ByteCodeInstruction::kNot);
735 this->write(ByteCodeInstruction::kConditionalBranch);
736 DeferredLocation endLocation(this);
737 this->writeStatement(*f.fStatement);
738 this->setContinueTargets();
739 if (f.fNext) {
740 this->writeExpression(*f.fNext);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400741 this->write(vector_instruction(ByteCodeInstruction::kPop, slot_count(f.fNext->fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400742 }
743 this->write(ByteCodeInstruction::kBranch);
744 this->write16(start);
745 endLocation.set();
746 } else {
747 this->writeStatement(*f.fStatement);
748 this->setContinueTargets();
749 if (f.fNext) {
750 this->writeExpression(*f.fNext);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400751 this->write(vector_instruction(ByteCodeInstruction::kPop, slot_count(f.fNext->fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400752 }
753 this->write(ByteCodeInstruction::kBranch);
754 this->write16(start);
755 }
756 this->setBreakTargets();
757}
758
759void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400760 if (i.fIfFalse) {
Mike Kleinb45ee832019-05-17 11:11:11 -0500761 // if (test) { ..ifTrue.. } else { .. ifFalse .. }
762 this->writeExpression(*i.fTest);
Mike Kleinb45ee832019-05-17 11:11:11 -0500763 this->write(ByteCodeInstruction::kConditionalBranch);
764 DeferredLocation trueLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400765 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -0500766 this->write(ByteCodeInstruction::kBranch);
767 DeferredLocation endLocation(this);
768 trueLocation.set();
769 this->writeStatement(*i.fIfTrue);
770 endLocation.set();
771 } else {
772 // if (test) { ..ifTrue.. }
773 this->writeExpression(*i.fTest);
774 this->write(ByteCodeInstruction::kNot);
Mike Kleinb45ee832019-05-17 11:11:11 -0500775 this->write(ByteCodeInstruction::kConditionalBranch);
776 DeferredLocation endLocation(this);
777 this->writeStatement(*i.fIfTrue);
778 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400779 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400780}
781
782void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -0400783 this->writeExpression(*r.fExpression);
784 this->write(ByteCodeInstruction::kReturn);
785 this->write8(r.fExpression->fType.columns() * r.fExpression->fType.rows());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400786}
787
788void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
789 // not yet implemented
790 abort();
791}
792
793void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
794 for (const auto& declStatement : v.fVars) {
795 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
796 // we need to grab the location even if we don't use it, to ensure it
797 // has been allocated
798 int location = getLocation(*decl.fVar);
799 if (decl.fValue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400800 this->writeExpression(*decl.fValue);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400801 this->write(vector_instruction(ByteCodeInstruction::kStore,
802 slot_count(decl.fValue->fType)));
Brian Osman1091f022019-05-16 09:42:16 -0400803 this->write8(location);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400804 }
805 }
806}
807
808void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
809 fContinueTargets.emplace();
810 fBreakTargets.emplace();
811 size_t start = fCode->size();
812 this->writeExpression(*w.fTest);
813 this->write(ByteCodeInstruction::kNot);
814 this->write(ByteCodeInstruction::kConditionalBranch);
815 DeferredLocation endLocation(this);
816 this->writeStatement(*w.fStatement);
817 this->setContinueTargets();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400818 this->write(ByteCodeInstruction::kBranch);
819 this->write16(start);
820 endLocation.set();
821 this->setBreakTargets();
822}
823
824void ByteCodeGenerator::writeStatement(const Statement& s) {
825 switch (s.fKind) {
826 case Statement::kBlock_Kind:
827 this->writeBlock((Block&) s);
828 break;
829 case Statement::kBreak_Kind:
830 this->writeBreakStatement((BreakStatement&) s);
831 break;
832 case Statement::kContinue_Kind:
833 this->writeContinueStatement((ContinueStatement&) s);
834 break;
835 case Statement::kDiscard_Kind:
836 // not yet implemented
837 abort();
838 case Statement::kDo_Kind:
839 this->writeDoStatement((DoStatement&) s);
840 break;
841 case Statement::kExpression_Kind: {
842 const Expression& expr = *((ExpressionStatement&) s).fExpression;
843 this->writeExpression(expr);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400844 this->write(vector_instruction(ByteCodeInstruction::kPop, slot_count(expr.fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400845 break;
846 }
847 case Statement::kFor_Kind:
848 this->writeForStatement((ForStatement&) s);
849 break;
850 case Statement::kIf_Kind:
851 this->writeIfStatement((IfStatement&) s);
852 break;
853 case Statement::kNop_Kind:
854 break;
855 case Statement::kReturn_Kind:
856 this->writeReturnStatement((ReturnStatement&) s);
857 break;
858 case Statement::kSwitch_Kind:
859 this->writeSwitchStatement((SwitchStatement&) s);
860 break;
861 case Statement::kVarDeclarations_Kind:
862 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
863 break;
864 case Statement::kWhile_Kind:
865 this->writeWhileStatement((WhileStatement&) s);
866 break;
867 default:
868 SkASSERT(false);
869 }
870}
871
872}