blob: 52df945d17af3eeaaa14708dbaa44f47dc3e6162 [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"
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04009
10namespace SkSL {
11
12static int slot_count(const Type& type) {
13 return type.columns() * type.rows();
14}
15
16bool ByteCodeGenerator::generateCode() {
17 for (const auto& e : fProgram) {
18 switch (e.fKind) {
19 case ProgramElement::kFunction_Kind: {
20 std::unique_ptr<ByteCodeFunction> f = this->writeFunction((FunctionDefinition&) e);
21 if (!f) {
22 return false;
23 }
24 fOutput->fFunctions.push_back(std::move(f));
25 break;
26 }
27 case ProgramElement::kVar_Kind: {
28 VarDeclarations& decl = (VarDeclarations&) e;
29 for (const auto& v : decl.fVars) {
30 const Variable* declVar = ((VarDeclaration&) *v).fVar;
31 if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
32 continue;
33 }
34 if (declVar->fModifiers.fFlags & Modifiers::kIn_Flag) {
35 for (int i = slot_count(declVar->fType); i > 0; --i) {
36 fOutput->fInputSlots.push_back(fOutput->fGlobalCount++);
37 }
38 } else {
39 fOutput->fGlobalCount += slot_count(declVar->fType);
40 }
41 }
42 break;
43 }
44 default:
45 ; // ignore
46 }
47 }
Brian Osman226668a2019-05-14 16:47:30 -040048 for (auto& call : fCallTargets) {
49 if (!call.set()) {
50 return false;
51 }
52 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040053 return true;
54}
55
56std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
57 fFunction = &f;
Brian Osman226668a2019-05-14 16:47:30 -040058 std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040059 fParameterCount = 0;
60 for (const auto& p : f.fDeclaration.fParameters) {
61 fParameterCount += p->fType.columns() * p->fType.rows();
62 }
63 fCode = &result->fCode;
64 this->writeStatement(*f.fBody);
Ethan Nicholas7e603db2019-05-03 12:57:47 -040065 this->write(ByteCodeInstruction::kReturn);
66 this->write8(0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040067 result->fParameterCount = fParameterCount;
68 result->fLocalCount = fLocals.size();
Ethan Nicholasdfcad062019-05-07 12:53:34 -040069 const Type& returnType = f.fDeclaration.fReturnType;
70 if (returnType != *fContext.fVoid_Type) {
71 result->fReturnCount = returnType.columns() * returnType.rows();
72 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040073 fLocals.clear();
74 fFunction = nullptr;
75 return result;
76}
77
78enum class TypeCategory {
79 kBool,
80 kSigned,
81 kUnsigned,
82 kFloat,
83};
84
85static TypeCategory type_category(const Type& type) {
86 switch (type.kind()) {
87 case Type::Kind::kVector_Kind:
88 case Type::Kind::kMatrix_Kind:
89 return type_category(type.componentType());
90 default:
91 if (type.fName == "bool") {
92 return TypeCategory::kBool;
93 } else if (type.fName == "int" || type.fName == "short") {
94 return TypeCategory::kSigned;
95 } else if (type.fName == "uint" || type.fName == "ushort") {
96 return TypeCategory::kUnsigned;
97 } else {
98 SkASSERT(type.fName == "float" || type.fName == "half");
99 return TypeCategory::kFloat;
100 }
101 ABORT("unsupported type: %s\n", type.description().c_str());
102 }
103}
104
105int ByteCodeGenerator::getLocation(const Variable& var) {
106 // given that we seldom have more than a couple of variables, linear search is probably the most
107 // efficient way to handle lookups
108 switch (var.fStorage) {
109 case Variable::kLocal_Storage: {
110 for (int i = fLocals.size() - 1; i >= 0; --i) {
111 if (fLocals[i] == &var) {
Brian Osman1091f022019-05-16 09:42:16 -0400112 SkASSERT(fParameterCount + i <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400113 return fParameterCount + i;
114 }
115 }
116 int result = fParameterCount + fLocals.size();
117 fLocals.push_back(&var);
118 for (int i = 0; i < slot_count(var.fType) - 1; ++i) {
119 fLocals.push_back(nullptr);
120 }
Brian Osman1091f022019-05-16 09:42:16 -0400121 SkASSERT(result <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400122 return result;
123 }
124 case Variable::kParameter_Storage: {
125 int offset = 0;
126 for (const auto& p : fFunction->fDeclaration.fParameters) {
127 if (p == &var) {
Brian Osman1091f022019-05-16 09:42:16 -0400128 SkASSERT(offset <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400129 return offset;
130 }
131 offset += slot_count(p->fType);
132 }
133 SkASSERT(false);
Brian Osman1091f022019-05-16 09:42:16 -0400134 return 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400135 }
136 case Variable::kGlobal_Storage: {
137 int offset = 0;
138 for (const auto& e : fProgram) {
139 if (e.fKind == ProgramElement::kVar_Kind) {
140 VarDeclarations& decl = (VarDeclarations&) e;
141 for (const auto& v : decl.fVars) {
142 const Variable* declVar = ((VarDeclaration&) *v).fVar;
143 if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
144 continue;
145 }
146 if (declVar == &var) {
Brian Osmanb7451292019-05-15 13:02:13 -0400147 SkASSERT(offset <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400148 return offset;
149 }
150 offset += slot_count(declVar->fType);
151 }
152 }
153 }
154 SkASSERT(false);
Brian Osman1091f022019-05-16 09:42:16 -0400155 return 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400156 }
157 default:
158 SkASSERT(false);
159 return 0;
160 }
161}
162
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400163void ByteCodeGenerator::align(int divisor, int remainder) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400164 switch (remainder - (int) fCode->size() % divisor) {
165 case 0: return;
166 case 3: this->write(ByteCodeInstruction::kNop3); // fall through
167 case 2: this->write(ByteCodeInstruction::kNop2); // fall through
168 case 1: this->write(ByteCodeInstruction::kNop1);
169 break;
170 default: SkASSERT(false);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400171 }
172}
173
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400174void ByteCodeGenerator::write8(uint8_t b) {
175 fCode->push_back(b);
176}
177
178void ByteCodeGenerator::write16(uint16_t i) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400179 SkASSERT(fCode->size() % 2 == 0);
180 this->write8(i >> 0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400181 this->write8(i >> 8);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400182}
183
184void ByteCodeGenerator::write32(uint32_t i) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400185 SkASSERT(fCode->size() % 4 == 0);
Brian Osmane1e988d2019-03-21 14:06:24 -0400186 this->write8((i >> 0) & 0xFF);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400187 this->write8((i >> 8) & 0xFF);
188 this->write8((i >> 16) & 0xFF);
189 this->write8((i >> 24) & 0xFF);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400190}
191
192void ByteCodeGenerator::write(ByteCodeInstruction i) {
193 this->write8((uint8_t) i);
194}
195
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400196ByteCodeInstruction vector_instruction(ByteCodeInstruction base, int count) {
197 return ((ByteCodeInstruction) ((int) base + count - 1));
198}
199
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400200void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400201 ByteCodeInstruction u, ByteCodeInstruction f,
202 int count) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400203 switch (type_category(type)) {
204 case TypeCategory::kSigned:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400205 this->write(vector_instruction(s, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400206 break;
207 case TypeCategory::kUnsigned:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400208 this->write(vector_instruction(u, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400209 break;
210 case TypeCategory::kFloat:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400211 this->write(vector_instruction(f, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400212 break;
213 default:
214 SkASSERT(false);
215 }
216}
217
218void ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b) {
219 if (b.fOperator == Token::Kind::EQ) {
220 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
221 this->writeExpression(*b.fRight);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400222 lvalue->store();
223 return;
224 }
225 Token::Kind op;
226 std::unique_ptr<LValue> lvalue;
227 if (is_assignment(b.fOperator)) {
228 lvalue = this->getLValue(*b.fLeft);
229 lvalue->load();
230 op = remove_assignment(b.fOperator);
231 } else {
232 this->writeExpression(*b.fLeft);
233 op = b.fOperator;
234 if (b.fLeft->fType.kind() == Type::kScalar_Kind &&
235 b.fRight->fType.kind() == Type::kVector_Kind) {
236 for (int i = b.fRight->fType.columns(); i > 1; --i) {
237 this->write(ByteCodeInstruction::kDup);
238 }
239 }
240 }
241 this->writeExpression(*b.fRight);
242 if (b.fLeft->fType.kind() == Type::kVector_Kind &&
243 b.fRight->fType.kind() == Type::kScalar_Kind) {
244 for (int i = b.fLeft->fType.columns(); i > 1; --i) {
245 this->write(ByteCodeInstruction::kDup);
246 }
247 }
248 int count = slot_count(b.fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400249 switch (op) {
250 case Token::Kind::EQEQ:
251 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareIEQ,
252 ByteCodeInstruction::kCompareIEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400253 ByteCodeInstruction::kCompareFEQ,
254 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400255 break;
256 case Token::Kind::GT:
257 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGT,
258 ByteCodeInstruction::kCompareUGT,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400259 ByteCodeInstruction::kCompareFGT,
260 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400261 break;
262 case Token::Kind::GTEQ:
263 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGTEQ,
264 ByteCodeInstruction::kCompareUGTEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400265 ByteCodeInstruction::kCompareFGTEQ,
266 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400267 break;
268 case Token::Kind::LT:
269 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLT,
270 ByteCodeInstruction::kCompareULT,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400271 ByteCodeInstruction::kCompareFLT,
272 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400273 break;
274 case Token::Kind::LTEQ:
275 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLTEQ,
276 ByteCodeInstruction::kCompareULTEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400277 ByteCodeInstruction::kCompareFLTEQ,
278 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400279 break;
280 case Token::Kind::MINUS:
281 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kSubtractI,
282 ByteCodeInstruction::kSubtractI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400283 ByteCodeInstruction::kSubtractF,
284 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400285 break;
286 case Token::Kind::NEQ:
287 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareINEQ,
288 ByteCodeInstruction::kCompareINEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400289 ByteCodeInstruction::kCompareFNEQ,
290 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400291 break;
292 case Token::Kind::PERCENT:
293 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kRemainderS,
294 ByteCodeInstruction::kRemainderU,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400295 ByteCodeInstruction::kRemainderF,
296 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400297 break;
298 case Token::Kind::PLUS:
299 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kAddI,
300 ByteCodeInstruction::kAddI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400301 ByteCodeInstruction::kAddF,
302 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400303 break;
304 case Token::Kind::SLASH:
305 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kDivideS,
306 ByteCodeInstruction::kDivideU,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400307 ByteCodeInstruction::kDivideF,
308 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400309 break;
310 case Token::Kind::STAR:
Ethan Nicholas91164d12019-05-15 15:29:54 -0400311 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kMultiplyI,
312 ByteCodeInstruction::kMultiplyI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400313 ByteCodeInstruction::kMultiplyF,
314 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400315 break;
316 default:
317 SkASSERT(false);
318 }
319 if (lvalue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400320 lvalue->store();
321 }
322}
323
324void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400325 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400326 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osman44d44762019-05-13 14:19:12 -0400327 this->write32(b.fValue ? 1 : 0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400328}
329
330void ByteCodeGenerator::writeConstructor(const Constructor& c) {
331 if (c.fArguments.size() == 1 &&
332 type_category(c.fType) == type_category(c.fArguments[0]->fType)) {
333 // cast from float to half or similar no-op
334 this->writeExpression(*c.fArguments[0]);
335 return;
336 }
337 for (const auto& arg : c.fArguments) {
338 this->writeExpression(*arg);
339 }
340 if (c.fArguments.size() == 1) {
341 TypeCategory inCategory = type_category(c.fArguments[0]->fType);
342 TypeCategory outCategory = type_category(c.fType);
343 if (inCategory != outCategory) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400344 if (inCategory == TypeCategory::kFloat) {
345 SkASSERT(outCategory == TypeCategory::kSigned ||
346 outCategory == TypeCategory::kUnsigned);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400347 this->write(vector_instruction(ByteCodeInstruction::kFloatToInt,
348 c.fType.columns()));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400349 } else if (outCategory == TypeCategory::kFloat) {
350 if (inCategory == TypeCategory::kSigned) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400351 this->write(vector_instruction(ByteCodeInstruction::kSignedToFloat,
352 c.fType.columns()));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400353 } else {
354 SkASSERT(inCategory == TypeCategory::kUnsigned);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400355 this->write(vector_instruction(ByteCodeInstruction::kUnsignedToFloat,
356 c.fType.columns()));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400357 }
358 } else {
359 SkASSERT(false);
360 }
361 }
362 }
363}
364
Ethan Nicholas91164d12019-05-15 15:29:54 -0400365void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400366 this->write(vector_instruction(ByteCodeInstruction::kReadExternal,
367 slot_count(e.fValue->type())));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400368 int index = fOutput->fExternalValues.size();
369 fOutput->fExternalValues.push_back(e.fValue);
370 SkASSERT(index <= 255);
371 this->write8(index);
372}
373
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400374void ByteCodeGenerator::writeFieldAccess(const FieldAccess& f) {
375 // not yet implemented
376 abort();
377}
378
379void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400380 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400381 this->write(ByteCodeInstruction::kPushImmediate);
382 union { float f; uint32_t u; } pun = { (float) f.fValue };
383 this->write32(pun.u);
384}
385
386void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Brian Osman226668a2019-05-14 16:47:30 -0400387 for (const auto& arg : f.fArguments) {
388 this->writeExpression(*arg);
389 }
390 this->write(ByteCodeInstruction::kCall);
391 fCallTargets.emplace_back(this, f.fFunction);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400392}
393
394void ByteCodeGenerator::writeIndexExpression(const IndexExpression& i) {
395 // not yet implemented
396 abort();
397}
398
399void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400400 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400401 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: {
414 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
415 lvalue->load();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400416 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400417 this->write(ByteCodeInstruction::kPushImmediate);
418 this->write32(1);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400419 SkASSERT(slot_count(p.fOperand->fType) == 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,
439 ByteCodeInstruction::kNegateS,
440 ByteCodeInstruction::kInvalid,
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) {
451 // not yet implemented
452 abort();
453}
454
455void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
456 switch (s.fBase->fKind) {
457 case Expression::kVariableReference_Kind: {
458 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
Brian Osman1091f022019-05-16 09:42:16 -0400459 this->write(var.fStorage == Variable::kGlobal_Storage
460 ? ByteCodeInstruction::kLoadSwizzleGlobal
461 : ByteCodeInstruction::kLoadSwizzle);
462 this->write8(this->getLocation(var));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400463 this->write8(s.fComponents.size());
464 for (int c : s.fComponents) {
465 this->write8(c);
466 }
467 break;
468 }
469 default:
470 this->writeExpression(*s.fBase);
471 this->write(ByteCodeInstruction::kSwizzle);
472 this->write8(s.fBase->fType.columns());
473 this->write8(s.fComponents.size());
474 for (int c : s.fComponents) {
475 this->write8(c);
476 }
477 }
478}
479
480void ByteCodeGenerator::writeVariableReference(const VariableReference& v) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400481 this->write(vector_instruction(v.fVariable.fStorage == Variable::kGlobal_Storage
482 ? ByteCodeInstruction::kLoadGlobal
483 : ByteCodeInstruction::kLoad,
484 slot_count(v.fType)));
Brian Osman1091f022019-05-16 09:42:16 -0400485 this->write8(this->getLocation(v.fVariable));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400486}
487
488void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
489 // not yet implemented
490 abort();
491}
492
493void ByteCodeGenerator::writeExpression(const Expression& e) {
494 switch (e.fKind) {
495 case Expression::kBinary_Kind:
496 this->writeBinaryExpression((BinaryExpression&) e);
497 break;
498 case Expression::kBoolLiteral_Kind:
499 this->writeBoolLiteral((BoolLiteral&) e);
500 break;
501 case Expression::kConstructor_Kind:
502 this->writeConstructor((Constructor&) e);
503 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400504 case Expression::kExternalValue_Kind:
505 this->writeExternalValue((ExternalValueReference&) e);
506 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400507 case Expression::kFieldAccess_Kind:
508 this->writeFieldAccess((FieldAccess&) e);
509 break;
510 case Expression::kFloatLiteral_Kind:
511 this->writeFloatLiteral((FloatLiteral&) e);
512 break;
513 case Expression::kFunctionCall_Kind:
514 this->writeFunctionCall((FunctionCall&) e);
515 break;
516 case Expression::kIndex_Kind:
517 this->writeIndexExpression((IndexExpression&) e);
518 break;
519 case Expression::kIntLiteral_Kind:
520 this->writeIntLiteral((IntLiteral&) e);
521 break;
522 case Expression::kNullLiteral_Kind:
523 this->writeNullLiteral((NullLiteral&) e);
524 break;
525 case Expression::kPrefix_Kind:
526 this->writePrefixExpression((PrefixExpression&) e);
527 break;
528 case Expression::kPostfix_Kind:
529 this->writePostfixExpression((PostfixExpression&) e);
530 break;
531 case Expression::kSwizzle_Kind:
532 this->writeSwizzle((Swizzle&) e);
533 break;
534 case Expression::kVariableReference_Kind:
535 this->writeVariableReference((VariableReference&) e);
536 break;
537 case Expression::kTernary_Kind:
538 this->writeTernaryExpression((TernaryExpression&) e);
539 break;
540 default:
541 printf("unsupported expression %s\n", e.description().c_str());
542 SkASSERT(false);
543 }
544}
545
Ethan Nicholas91164d12019-05-15 15:29:54 -0400546class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
547public:
548 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
549 : INHERITED(*generator)
550 , fCount(slot_count(value.type()))
551 , fIndex(index) {}
552
553 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400554 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400555 fGenerator.write8(fIndex);
556 }
557
558 void store() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400559 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
560 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400561 fGenerator.write8(fIndex);
562 }
563
564private:
565 typedef LValue INHERITED;
566
567 int fCount;
568
569 int fIndex;
570};
571
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400572class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
573public:
574 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
575 : INHERITED(*generator)
576 , fSwizzle(swizzle) {
Brian Osman1091f022019-05-16 09:42:16 -0400577 SkASSERT(fSwizzle.fBase->fKind == Expression::kVariableReference_Kind);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400578 }
579
580 void load() override {
Brian Osman1091f022019-05-16 09:42:16 -0400581 fGenerator.writeSwizzle(fSwizzle);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400582 }
583
584 void store() override {
Brian Osman1091f022019-05-16 09:42:16 -0400585 const Variable& var = ((VariableReference&)*fSwizzle.fBase).fVariable;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400586 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup,
587 fSwizzle.fComponents.size()));
Brian Osman1091f022019-05-16 09:42:16 -0400588 fGenerator.write(var.fStorage == Variable::kGlobal_Storage
589 ? ByteCodeInstruction::kStoreSwizzleGlobal
590 : ByteCodeInstruction::kStoreSwizzle);
591 fGenerator.write8(fGenerator.getLocation(var));
592 fGenerator.write8(fSwizzle.fComponents.size());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400593 for (int c : fSwizzle.fComponents) {
594 fGenerator.write8(c);
595 }
596 }
597
598private:
599 const Swizzle& fSwizzle;
600
601 typedef LValue INHERITED;
602};
603
604class ByteCodeVariableLValue : public ByteCodeGenerator::LValue {
605public:
606 ByteCodeVariableLValue(ByteCodeGenerator* generator, const Variable& var)
607 : INHERITED(*generator)
608 , fCount(slot_count(var.fType))
Brian Osman1091f022019-05-16 09:42:16 -0400609 , fLocation(generator->getLocation(var))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400610 , fIsGlobal(var.fStorage == Variable::kGlobal_Storage) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400611 }
612
613 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400614 fGenerator.write(vector_instruction(fIsGlobal ? ByteCodeInstruction::kLoadGlobal
615 : ByteCodeInstruction::kLoad,
616 fCount));
Brian Osman1091f022019-05-16 09:42:16 -0400617 fGenerator.write8(fLocation);
618 }
619
620 void store() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400621 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
622 fGenerator.write(vector_instruction(fIsGlobal ? ByteCodeInstruction::kStoreGlobal
623 : ByteCodeInstruction::kStore,
624 fCount));
Brian Osman1091f022019-05-16 09:42:16 -0400625 fGenerator.write8(fLocation);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400626 }
627
628private:
629 typedef LValue INHERITED;
630
631 int fCount;
Brian Osman1091f022019-05-16 09:42:16 -0400632 int fLocation;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400633 bool fIsGlobal;
634};
635
636std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
637 switch (e.fKind) {
Ethan Nicholas91164d12019-05-15 15:29:54 -0400638 case Expression::kExternalValue_Kind: {
639 ExternalValue* value = ((ExternalValueReference&) e).fValue;
640 int index = fOutput->fExternalValues.size();
641 fOutput->fExternalValues.push_back(value);
642 SkASSERT(index <= 255);
643 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
644 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400645 case Expression::kIndex_Kind:
646 // not yet implemented
647 abort();
648 case Expression::kVariableReference_Kind:
649 return std::unique_ptr<LValue>(new ByteCodeVariableLValue(this,
650 ((VariableReference&) e).fVariable));
651 case Expression::kSwizzle_Kind:
652 return std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, (Swizzle&) e));
653 case Expression::kTernary_Kind:
654 default:
655 printf("unsupported lvalue %s\n", e.description().c_str());
656 return nullptr;
657 }
658}
659
660void ByteCodeGenerator::writeBlock(const Block& b) {
661 for (const auto& s : b.fStatements) {
662 this->writeStatement(*s);
663 }
664}
665
666void ByteCodeGenerator::setBreakTargets() {
667 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
668 for (DeferredLocation& b : breaks) {
669 b.set();
670 }
671 fBreakTargets.pop();
672}
673
674void ByteCodeGenerator::setContinueTargets() {
675 std::vector<DeferredLocation>& continues = fContinueTargets.top();
676 for (DeferredLocation& c : continues) {
677 c.set();
678 }
679 fContinueTargets.pop();
680}
681
682void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400683 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400684 this->write(ByteCodeInstruction::kBranch);
685 fBreakTargets.top().emplace_back(this);
686}
687
688void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400689 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400690 this->write(ByteCodeInstruction::kBranch);
691 fContinueTargets.top().emplace_back(this);
692}
693
694void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
695 fContinueTargets.emplace();
696 fBreakTargets.emplace();
697 size_t start = fCode->size();
698 this->writeStatement(*d.fStatement);
699 this->setContinueTargets();
700 this->writeExpression(*d.fTest);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400701 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400702 this->write(ByteCodeInstruction::kConditionalBranch);
703 this->write16(start);
704 this->setBreakTargets();
705}
706
707void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
708 fContinueTargets.emplace();
709 fBreakTargets.emplace();
710 if (f.fInitializer) {
711 this->writeStatement(*f.fInitializer);
712 }
713 size_t start = fCode->size();
714 if (f.fTest) {
715 this->writeExpression(*f.fTest);
716 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400717 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400718 this->write(ByteCodeInstruction::kConditionalBranch);
719 DeferredLocation endLocation(this);
720 this->writeStatement(*f.fStatement);
721 this->setContinueTargets();
722 if (f.fNext) {
723 this->writeExpression(*f.fNext);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400724 this->write(vector_instruction(ByteCodeInstruction::kPop, slot_count(f.fNext->fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400725 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400726 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400727 this->write(ByteCodeInstruction::kBranch);
728 this->write16(start);
729 endLocation.set();
730 } else {
731 this->writeStatement(*f.fStatement);
732 this->setContinueTargets();
733 if (f.fNext) {
734 this->writeExpression(*f.fNext);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400735 this->write(vector_instruction(ByteCodeInstruction::kPop, slot_count(f.fNext->fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400736 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400737 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400738 this->write(ByteCodeInstruction::kBranch);
739 this->write16(start);
740 }
741 this->setBreakTargets();
742}
743
744void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
745 this->writeExpression(*i.fTest);
746 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400747 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400748 this->write(ByteCodeInstruction::kConditionalBranch);
749 DeferredLocation elseLocation(this);
750 this->writeStatement(*i.fIfTrue);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400751 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400752 this->write(ByteCodeInstruction::kBranch);
753 DeferredLocation endLocation(this);
754 elseLocation.set();
755 if (i.fIfFalse) {
756 this->writeStatement(*i.fIfFalse);
757 }
758 endLocation.set();
759}
760
761void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -0400762 this->writeExpression(*r.fExpression);
763 this->write(ByteCodeInstruction::kReturn);
764 this->write8(r.fExpression->fType.columns() * r.fExpression->fType.rows());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400765}
766
767void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
768 // not yet implemented
769 abort();
770}
771
772void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
773 for (const auto& declStatement : v.fVars) {
774 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
775 // we need to grab the location even if we don't use it, to ensure it
776 // has been allocated
777 int location = getLocation(*decl.fVar);
778 if (decl.fValue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400779 this->writeExpression(*decl.fValue);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400780 this->write(vector_instruction(ByteCodeInstruction::kStore,
781 slot_count(decl.fValue->fType)));
Brian Osman1091f022019-05-16 09:42:16 -0400782 this->write8(location);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400783 }
784 }
785}
786
787void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
788 fContinueTargets.emplace();
789 fBreakTargets.emplace();
790 size_t start = fCode->size();
791 this->writeExpression(*w.fTest);
792 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400793 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400794 this->write(ByteCodeInstruction::kConditionalBranch);
795 DeferredLocation endLocation(this);
796 this->writeStatement(*w.fStatement);
797 this->setContinueTargets();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400798 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400799 this->write(ByteCodeInstruction::kBranch);
800 this->write16(start);
801 endLocation.set();
802 this->setBreakTargets();
803}
804
805void ByteCodeGenerator::writeStatement(const Statement& s) {
806 switch (s.fKind) {
807 case Statement::kBlock_Kind:
808 this->writeBlock((Block&) s);
809 break;
810 case Statement::kBreak_Kind:
811 this->writeBreakStatement((BreakStatement&) s);
812 break;
813 case Statement::kContinue_Kind:
814 this->writeContinueStatement((ContinueStatement&) s);
815 break;
816 case Statement::kDiscard_Kind:
817 // not yet implemented
818 abort();
819 case Statement::kDo_Kind:
820 this->writeDoStatement((DoStatement&) s);
821 break;
822 case Statement::kExpression_Kind: {
823 const Expression& expr = *((ExpressionStatement&) s).fExpression;
824 this->writeExpression(expr);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400825 this->write(vector_instruction(ByteCodeInstruction::kPop, slot_count(expr.fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400826 break;
827 }
828 case Statement::kFor_Kind:
829 this->writeForStatement((ForStatement&) s);
830 break;
831 case Statement::kIf_Kind:
832 this->writeIfStatement((IfStatement&) s);
833 break;
834 case Statement::kNop_Kind:
835 break;
836 case Statement::kReturn_Kind:
837 this->writeReturnStatement((ReturnStatement&) s);
838 break;
839 case Statement::kSwitch_Kind:
840 this->writeSwitchStatement((SwitchStatement&) s);
841 break;
842 case Statement::kVarDeclarations_Kind:
843 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
844 break;
845 case Statement::kWhile_Kind:
846 this->writeWhileStatement((WhileStatement&) s);
847 break;
848 default:
849 SkASSERT(false);
850 }
851}
852
853}