blob: 1b0890560dbac4db8aad66321613f4a5c6c02fe6 [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) {
181 this->write8((uint8_t) i);
182}
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 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);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400442 this->write(ByteCodeInstruction::kPushImmediate);
443 this->write32(type_category(p.fType) == TypeCategory::kFloat
444 ? Interpreter::Value(1.0f).fUnsigned : 1);
445 if (p.fOperator == Token::Kind::PLUSPLUS) {
446 this->writeTypedInstruction(p.fType,
447 ByteCodeInstruction::kAddI,
448 ByteCodeInstruction::kAddI,
449 ByteCodeInstruction::kAddF,
450 1);
451 } else {
452 this->writeTypedInstruction(p.fType,
453 ByteCodeInstruction::kSubtractI,
454 ByteCodeInstruction::kSubtractI,
455 ByteCodeInstruction::kSubtractF,
456 1);
457 }
458 lvalue->store();
459 this->write(ByteCodeInstruction::kPop);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400460 break;
461 }
462 default:
463 SkASSERT(false);
464 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400465}
466
467void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
468 switch (s.fBase->fKind) {
469 case Expression::kVariableReference_Kind: {
470 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
Brian Osman1091f022019-05-16 09:42:16 -0400471 this->write(var.fStorage == Variable::kGlobal_Storage
472 ? ByteCodeInstruction::kLoadSwizzleGlobal
473 : ByteCodeInstruction::kLoadSwizzle);
474 this->write8(this->getLocation(var));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400475 this->write8(s.fComponents.size());
476 for (int c : s.fComponents) {
477 this->write8(c);
478 }
479 break;
480 }
481 default:
482 this->writeExpression(*s.fBase);
483 this->write(ByteCodeInstruction::kSwizzle);
484 this->write8(s.fBase->fType.columns());
485 this->write8(s.fComponents.size());
486 for (int c : s.fComponents) {
487 this->write8(c);
488 }
489 }
490}
491
492void ByteCodeGenerator::writeVariableReference(const VariableReference& v) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400493 this->write(vector_instruction(v.fVariable.fStorage == Variable::kGlobal_Storage
494 ? ByteCodeInstruction::kLoadGlobal
495 : ByteCodeInstruction::kLoad,
496 slot_count(v.fType)));
Brian Osman1091f022019-05-16 09:42:16 -0400497 this->write8(this->getLocation(v.fVariable));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400498}
499
500void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Brian Osman4e93feb2019-05-16 15:38:00 -0400501 this->writeExpression(*t.fTest);
Brian Osman4e93feb2019-05-16 15:38:00 -0400502 this->write(ByteCodeInstruction::kConditionalBranch);
503 DeferredLocation trueLocation(this);
504 this->writeExpression(*t.fIfFalse);
Brian Osman4e93feb2019-05-16 15:38:00 -0400505 this->write(ByteCodeInstruction::kBranch);
506 DeferredLocation endLocation(this);
507 trueLocation.set();
508 this->writeExpression(*t.fIfTrue);
509 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400510}
511
512void ByteCodeGenerator::writeExpression(const Expression& e) {
513 switch (e.fKind) {
514 case Expression::kBinary_Kind:
515 this->writeBinaryExpression((BinaryExpression&) e);
516 break;
517 case Expression::kBoolLiteral_Kind:
518 this->writeBoolLiteral((BoolLiteral&) e);
519 break;
520 case Expression::kConstructor_Kind:
521 this->writeConstructor((Constructor&) e);
522 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400523 case Expression::kExternalValue_Kind:
524 this->writeExternalValue((ExternalValueReference&) e);
525 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400526 case Expression::kFieldAccess_Kind:
527 this->writeFieldAccess((FieldAccess&) e);
528 break;
529 case Expression::kFloatLiteral_Kind:
530 this->writeFloatLiteral((FloatLiteral&) e);
531 break;
532 case Expression::kFunctionCall_Kind:
533 this->writeFunctionCall((FunctionCall&) e);
534 break;
535 case Expression::kIndex_Kind:
536 this->writeIndexExpression((IndexExpression&) e);
537 break;
538 case Expression::kIntLiteral_Kind:
539 this->writeIntLiteral((IntLiteral&) e);
540 break;
541 case Expression::kNullLiteral_Kind:
542 this->writeNullLiteral((NullLiteral&) e);
543 break;
544 case Expression::kPrefix_Kind:
545 this->writePrefixExpression((PrefixExpression&) e);
546 break;
547 case Expression::kPostfix_Kind:
548 this->writePostfixExpression((PostfixExpression&) e);
549 break;
550 case Expression::kSwizzle_Kind:
551 this->writeSwizzle((Swizzle&) e);
552 break;
553 case Expression::kVariableReference_Kind:
554 this->writeVariableReference((VariableReference&) e);
555 break;
556 case Expression::kTernary_Kind:
557 this->writeTernaryExpression((TernaryExpression&) e);
558 break;
559 default:
560 printf("unsupported expression %s\n", e.description().c_str());
561 SkASSERT(false);
562 }
563}
564
Ethan Nicholas91164d12019-05-15 15:29:54 -0400565class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
566public:
567 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
568 : INHERITED(*generator)
569 , fCount(slot_count(value.type()))
570 , fIndex(index) {}
571
572 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400573 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400574 fGenerator.write8(fIndex);
575 }
576
577 void store() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400578 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
579 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400580 fGenerator.write8(fIndex);
581 }
582
583private:
584 typedef LValue INHERITED;
585
586 int fCount;
587
588 int fIndex;
589};
590
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400591class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
592public:
593 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
594 : INHERITED(*generator)
595 , fSwizzle(swizzle) {
Brian Osman1091f022019-05-16 09:42:16 -0400596 SkASSERT(fSwizzle.fBase->fKind == Expression::kVariableReference_Kind);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400597 }
598
599 void load() override {
Brian Osman1091f022019-05-16 09:42:16 -0400600 fGenerator.writeSwizzle(fSwizzle);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400601 }
602
603 void store() override {
Brian Osman1091f022019-05-16 09:42:16 -0400604 const Variable& var = ((VariableReference&)*fSwizzle.fBase).fVariable;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400605 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup,
606 fSwizzle.fComponents.size()));
Brian Osman1091f022019-05-16 09:42:16 -0400607 fGenerator.write(var.fStorage == Variable::kGlobal_Storage
608 ? ByteCodeInstruction::kStoreSwizzleGlobal
609 : ByteCodeInstruction::kStoreSwizzle);
610 fGenerator.write8(fGenerator.getLocation(var));
611 fGenerator.write8(fSwizzle.fComponents.size());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400612 for (int c : fSwizzle.fComponents) {
613 fGenerator.write8(c);
614 }
615 }
616
617private:
618 const Swizzle& fSwizzle;
619
620 typedef LValue INHERITED;
621};
622
623class ByteCodeVariableLValue : public ByteCodeGenerator::LValue {
624public:
625 ByteCodeVariableLValue(ByteCodeGenerator* generator, const Variable& var)
626 : INHERITED(*generator)
627 , fCount(slot_count(var.fType))
Brian Osman1091f022019-05-16 09:42:16 -0400628 , fLocation(generator->getLocation(var))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400629 , fIsGlobal(var.fStorage == Variable::kGlobal_Storage) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400630 }
631
632 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400633 fGenerator.write(vector_instruction(fIsGlobal ? ByteCodeInstruction::kLoadGlobal
634 : ByteCodeInstruction::kLoad,
635 fCount));
Brian Osman1091f022019-05-16 09:42:16 -0400636 fGenerator.write8(fLocation);
637 }
638
639 void store() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400640 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
641 fGenerator.write(vector_instruction(fIsGlobal ? ByteCodeInstruction::kStoreGlobal
642 : ByteCodeInstruction::kStore,
643 fCount));
Brian Osman1091f022019-05-16 09:42:16 -0400644 fGenerator.write8(fLocation);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400645 }
646
647private:
648 typedef LValue INHERITED;
649
650 int fCount;
Brian Osman1091f022019-05-16 09:42:16 -0400651 int fLocation;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400652 bool fIsGlobal;
653};
654
655std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
656 switch (e.fKind) {
Ethan Nicholas91164d12019-05-15 15:29:54 -0400657 case Expression::kExternalValue_Kind: {
658 ExternalValue* value = ((ExternalValueReference&) e).fValue;
659 int index = fOutput->fExternalValues.size();
660 fOutput->fExternalValues.push_back(value);
661 SkASSERT(index <= 255);
662 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
663 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400664 case Expression::kIndex_Kind:
665 // not yet implemented
666 abort();
667 case Expression::kVariableReference_Kind:
668 return std::unique_ptr<LValue>(new ByteCodeVariableLValue(this,
669 ((VariableReference&) e).fVariable));
670 case Expression::kSwizzle_Kind:
671 return std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, (Swizzle&) e));
672 case Expression::kTernary_Kind:
673 default:
674 printf("unsupported lvalue %s\n", e.description().c_str());
675 return nullptr;
676 }
677}
678
679void ByteCodeGenerator::writeBlock(const Block& b) {
680 for (const auto& s : b.fStatements) {
681 this->writeStatement(*s);
682 }
683}
684
685void ByteCodeGenerator::setBreakTargets() {
686 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
687 for (DeferredLocation& b : breaks) {
688 b.set();
689 }
690 fBreakTargets.pop();
691}
692
693void ByteCodeGenerator::setContinueTargets() {
694 std::vector<DeferredLocation>& continues = fContinueTargets.top();
695 for (DeferredLocation& c : continues) {
696 c.set();
697 }
698 fContinueTargets.pop();
699}
700
701void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
702 this->write(ByteCodeInstruction::kBranch);
703 fBreakTargets.top().emplace_back(this);
704}
705
706void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
707 this->write(ByteCodeInstruction::kBranch);
708 fContinueTargets.top().emplace_back(this);
709}
710
711void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
712 fContinueTargets.emplace();
713 fBreakTargets.emplace();
714 size_t start = fCode->size();
715 this->writeStatement(*d.fStatement);
716 this->setContinueTargets();
717 this->writeExpression(*d.fTest);
718 this->write(ByteCodeInstruction::kConditionalBranch);
719 this->write16(start);
720 this->setBreakTargets();
721}
722
723void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
724 fContinueTargets.emplace();
725 fBreakTargets.emplace();
726 if (f.fInitializer) {
727 this->writeStatement(*f.fInitializer);
728 }
729 size_t start = fCode->size();
730 if (f.fTest) {
731 this->writeExpression(*f.fTest);
732 this->write(ByteCodeInstruction::kNot);
733 this->write(ByteCodeInstruction::kConditionalBranch);
734 DeferredLocation endLocation(this);
735 this->writeStatement(*f.fStatement);
736 this->setContinueTargets();
737 if (f.fNext) {
738 this->writeExpression(*f.fNext);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400739 this->write(vector_instruction(ByteCodeInstruction::kPop, slot_count(f.fNext->fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400740 }
741 this->write(ByteCodeInstruction::kBranch);
742 this->write16(start);
743 endLocation.set();
744 } else {
745 this->writeStatement(*f.fStatement);
746 this->setContinueTargets();
747 if (f.fNext) {
748 this->writeExpression(*f.fNext);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400749 this->write(vector_instruction(ByteCodeInstruction::kPop, slot_count(f.fNext->fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400750 }
751 this->write(ByteCodeInstruction::kBranch);
752 this->write16(start);
753 }
754 this->setBreakTargets();
755}
756
757void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400758 if (i.fIfFalse) {
Mike Kleinb45ee832019-05-17 11:11:11 -0500759 // if (test) { ..ifTrue.. } else { .. ifFalse .. }
760 this->writeExpression(*i.fTest);
Mike Kleinb45ee832019-05-17 11:11:11 -0500761 this->write(ByteCodeInstruction::kConditionalBranch);
762 DeferredLocation trueLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400763 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -0500764 this->write(ByteCodeInstruction::kBranch);
765 DeferredLocation endLocation(this);
766 trueLocation.set();
767 this->writeStatement(*i.fIfTrue);
768 endLocation.set();
769 } else {
770 // if (test) { ..ifTrue.. }
771 this->writeExpression(*i.fTest);
772 this->write(ByteCodeInstruction::kNot);
Mike Kleinb45ee832019-05-17 11:11:11 -0500773 this->write(ByteCodeInstruction::kConditionalBranch);
774 DeferredLocation endLocation(this);
775 this->writeStatement(*i.fIfTrue);
776 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400777 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400778}
779
780void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -0400781 this->writeExpression(*r.fExpression);
782 this->write(ByteCodeInstruction::kReturn);
783 this->write8(r.fExpression->fType.columns() * r.fExpression->fType.rows());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400784}
785
786void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
787 // not yet implemented
788 abort();
789}
790
791void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
792 for (const auto& declStatement : v.fVars) {
793 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
794 // we need to grab the location even if we don't use it, to ensure it
795 // has been allocated
796 int location = getLocation(*decl.fVar);
797 if (decl.fValue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400798 this->writeExpression(*decl.fValue);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400799 this->write(vector_instruction(ByteCodeInstruction::kStore,
800 slot_count(decl.fValue->fType)));
Brian Osman1091f022019-05-16 09:42:16 -0400801 this->write8(location);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400802 }
803 }
804}
805
806void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
807 fContinueTargets.emplace();
808 fBreakTargets.emplace();
809 size_t start = fCode->size();
810 this->writeExpression(*w.fTest);
811 this->write(ByteCodeInstruction::kNot);
812 this->write(ByteCodeInstruction::kConditionalBranch);
813 DeferredLocation endLocation(this);
814 this->writeStatement(*w.fStatement);
815 this->setContinueTargets();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400816 this->write(ByteCodeInstruction::kBranch);
817 this->write16(start);
818 endLocation.set();
819 this->setBreakTargets();
820}
821
822void ByteCodeGenerator::writeStatement(const Statement& s) {
823 switch (s.fKind) {
824 case Statement::kBlock_Kind:
825 this->writeBlock((Block&) s);
826 break;
827 case Statement::kBreak_Kind:
828 this->writeBreakStatement((BreakStatement&) s);
829 break;
830 case Statement::kContinue_Kind:
831 this->writeContinueStatement((ContinueStatement&) s);
832 break;
833 case Statement::kDiscard_Kind:
834 // not yet implemented
835 abort();
836 case Statement::kDo_Kind:
837 this->writeDoStatement((DoStatement&) s);
838 break;
839 case Statement::kExpression_Kind: {
840 const Expression& expr = *((ExpressionStatement&) s).fExpression;
841 this->writeExpression(expr);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400842 this->write(vector_instruction(ByteCodeInstruction::kPop, slot_count(expr.fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400843 break;
844 }
845 case Statement::kFor_Kind:
846 this->writeForStatement((ForStatement&) s);
847 break;
848 case Statement::kIf_Kind:
849 this->writeIfStatement((IfStatement&) s);
850 break;
851 case Statement::kNop_Kind:
852 break;
853 case Statement::kReturn_Kind:
854 this->writeReturnStatement((ReturnStatement&) s);
855 break;
856 case Statement::kSwitch_Kind:
857 this->writeSwitchStatement((SwitchStatement&) s);
858 break;
859 case Statement::kVarDeclarations_Kind:
860 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
861 break;
862 case Statement::kWhile_Kind:
863 this->writeWhileStatement((WhileStatement&) s);
864 break;
865 default:
866 SkASSERT(false);
867 }
868}
869
870}