blob: 4f69a411bf36370e0793600d8f303af1c48f8036 [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) {
Brian Osman4e93feb2019-05-16 15:38:00 -0400489 this->writeExpression(*t.fTest);
490 this->align(2, 1);
491 this->write(ByteCodeInstruction::kConditionalBranch);
492 DeferredLocation trueLocation(this);
493 this->writeExpression(*t.fIfFalse);
494 this->align(2, 1);
495 this->write(ByteCodeInstruction::kBranch);
496 DeferredLocation endLocation(this);
497 trueLocation.set();
498 this->writeExpression(*t.fIfTrue);
499 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400500}
501
502void ByteCodeGenerator::writeExpression(const Expression& e) {
503 switch (e.fKind) {
504 case Expression::kBinary_Kind:
505 this->writeBinaryExpression((BinaryExpression&) e);
506 break;
507 case Expression::kBoolLiteral_Kind:
508 this->writeBoolLiteral((BoolLiteral&) e);
509 break;
510 case Expression::kConstructor_Kind:
511 this->writeConstructor((Constructor&) e);
512 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400513 case Expression::kExternalValue_Kind:
514 this->writeExternalValue((ExternalValueReference&) e);
515 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400516 case Expression::kFieldAccess_Kind:
517 this->writeFieldAccess((FieldAccess&) e);
518 break;
519 case Expression::kFloatLiteral_Kind:
520 this->writeFloatLiteral((FloatLiteral&) e);
521 break;
522 case Expression::kFunctionCall_Kind:
523 this->writeFunctionCall((FunctionCall&) e);
524 break;
525 case Expression::kIndex_Kind:
526 this->writeIndexExpression((IndexExpression&) e);
527 break;
528 case Expression::kIntLiteral_Kind:
529 this->writeIntLiteral((IntLiteral&) e);
530 break;
531 case Expression::kNullLiteral_Kind:
532 this->writeNullLiteral((NullLiteral&) e);
533 break;
534 case Expression::kPrefix_Kind:
535 this->writePrefixExpression((PrefixExpression&) e);
536 break;
537 case Expression::kPostfix_Kind:
538 this->writePostfixExpression((PostfixExpression&) e);
539 break;
540 case Expression::kSwizzle_Kind:
541 this->writeSwizzle((Swizzle&) e);
542 break;
543 case Expression::kVariableReference_Kind:
544 this->writeVariableReference((VariableReference&) e);
545 break;
546 case Expression::kTernary_Kind:
547 this->writeTernaryExpression((TernaryExpression&) e);
548 break;
549 default:
550 printf("unsupported expression %s\n", e.description().c_str());
551 SkASSERT(false);
552 }
553}
554
Ethan Nicholas91164d12019-05-15 15:29:54 -0400555class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
556public:
557 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
558 : INHERITED(*generator)
559 , fCount(slot_count(value.type()))
560 , fIndex(index) {}
561
562 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400563 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400564 fGenerator.write8(fIndex);
565 }
566
567 void store() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400568 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
569 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400570 fGenerator.write8(fIndex);
571 }
572
573private:
574 typedef LValue INHERITED;
575
576 int fCount;
577
578 int fIndex;
579};
580
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400581class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
582public:
583 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
584 : INHERITED(*generator)
585 , fSwizzle(swizzle) {
Brian Osman1091f022019-05-16 09:42:16 -0400586 SkASSERT(fSwizzle.fBase->fKind == Expression::kVariableReference_Kind);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400587 }
588
589 void load() override {
Brian Osman1091f022019-05-16 09:42:16 -0400590 fGenerator.writeSwizzle(fSwizzle);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400591 }
592
593 void store() override {
Brian Osman1091f022019-05-16 09:42:16 -0400594 const Variable& var = ((VariableReference&)*fSwizzle.fBase).fVariable;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400595 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup,
596 fSwizzle.fComponents.size()));
Brian Osman1091f022019-05-16 09:42:16 -0400597 fGenerator.write(var.fStorage == Variable::kGlobal_Storage
598 ? ByteCodeInstruction::kStoreSwizzleGlobal
599 : ByteCodeInstruction::kStoreSwizzle);
600 fGenerator.write8(fGenerator.getLocation(var));
601 fGenerator.write8(fSwizzle.fComponents.size());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400602 for (int c : fSwizzle.fComponents) {
603 fGenerator.write8(c);
604 }
605 }
606
607private:
608 const Swizzle& fSwizzle;
609
610 typedef LValue INHERITED;
611};
612
613class ByteCodeVariableLValue : public ByteCodeGenerator::LValue {
614public:
615 ByteCodeVariableLValue(ByteCodeGenerator* generator, const Variable& var)
616 : INHERITED(*generator)
617 , fCount(slot_count(var.fType))
Brian Osman1091f022019-05-16 09:42:16 -0400618 , fLocation(generator->getLocation(var))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400619 , fIsGlobal(var.fStorage == Variable::kGlobal_Storage) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400620 }
621
622 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400623 fGenerator.write(vector_instruction(fIsGlobal ? ByteCodeInstruction::kLoadGlobal
624 : ByteCodeInstruction::kLoad,
625 fCount));
Brian Osman1091f022019-05-16 09:42:16 -0400626 fGenerator.write8(fLocation);
627 }
628
629 void store() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400630 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
631 fGenerator.write(vector_instruction(fIsGlobal ? ByteCodeInstruction::kStoreGlobal
632 : ByteCodeInstruction::kStore,
633 fCount));
Brian Osman1091f022019-05-16 09:42:16 -0400634 fGenerator.write8(fLocation);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400635 }
636
637private:
638 typedef LValue INHERITED;
639
640 int fCount;
Brian Osman1091f022019-05-16 09:42:16 -0400641 int fLocation;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400642 bool fIsGlobal;
643};
644
645std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
646 switch (e.fKind) {
Ethan Nicholas91164d12019-05-15 15:29:54 -0400647 case Expression::kExternalValue_Kind: {
648 ExternalValue* value = ((ExternalValueReference&) e).fValue;
649 int index = fOutput->fExternalValues.size();
650 fOutput->fExternalValues.push_back(value);
651 SkASSERT(index <= 255);
652 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
653 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400654 case Expression::kIndex_Kind:
655 // not yet implemented
656 abort();
657 case Expression::kVariableReference_Kind:
658 return std::unique_ptr<LValue>(new ByteCodeVariableLValue(this,
659 ((VariableReference&) e).fVariable));
660 case Expression::kSwizzle_Kind:
661 return std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, (Swizzle&) e));
662 case Expression::kTernary_Kind:
663 default:
664 printf("unsupported lvalue %s\n", e.description().c_str());
665 return nullptr;
666 }
667}
668
669void ByteCodeGenerator::writeBlock(const Block& b) {
670 for (const auto& s : b.fStatements) {
671 this->writeStatement(*s);
672 }
673}
674
675void ByteCodeGenerator::setBreakTargets() {
676 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
677 for (DeferredLocation& b : breaks) {
678 b.set();
679 }
680 fBreakTargets.pop();
681}
682
683void ByteCodeGenerator::setContinueTargets() {
684 std::vector<DeferredLocation>& continues = fContinueTargets.top();
685 for (DeferredLocation& c : continues) {
686 c.set();
687 }
688 fContinueTargets.pop();
689}
690
691void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400692 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400693 this->write(ByteCodeInstruction::kBranch);
694 fBreakTargets.top().emplace_back(this);
695}
696
697void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400698 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400699 this->write(ByteCodeInstruction::kBranch);
700 fContinueTargets.top().emplace_back(this);
701}
702
703void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
704 fContinueTargets.emplace();
705 fBreakTargets.emplace();
706 size_t start = fCode->size();
707 this->writeStatement(*d.fStatement);
708 this->setContinueTargets();
709 this->writeExpression(*d.fTest);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400710 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400711 this->write(ByteCodeInstruction::kConditionalBranch);
712 this->write16(start);
713 this->setBreakTargets();
714}
715
716void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
717 fContinueTargets.emplace();
718 fBreakTargets.emplace();
719 if (f.fInitializer) {
720 this->writeStatement(*f.fInitializer);
721 }
722 size_t start = fCode->size();
723 if (f.fTest) {
724 this->writeExpression(*f.fTest);
725 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400726 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400727 this->write(ByteCodeInstruction::kConditionalBranch);
728 DeferredLocation endLocation(this);
729 this->writeStatement(*f.fStatement);
730 this->setContinueTargets();
731 if (f.fNext) {
732 this->writeExpression(*f.fNext);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400733 this->write(vector_instruction(ByteCodeInstruction::kPop, slot_count(f.fNext->fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400734 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400735 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400736 this->write(ByteCodeInstruction::kBranch);
737 this->write16(start);
738 endLocation.set();
739 } else {
740 this->writeStatement(*f.fStatement);
741 this->setContinueTargets();
742 if (f.fNext) {
743 this->writeExpression(*f.fNext);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400744 this->write(vector_instruction(ByteCodeInstruction::kPop, slot_count(f.fNext->fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400745 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400746 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400747 this->write(ByteCodeInstruction::kBranch);
748 this->write16(start);
749 }
750 this->setBreakTargets();
751}
752
753void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Brian Osman4e93feb2019-05-16 15:38:00 -0400754 // TODO: For if-else, reorder the statements to remove kNot.
755 // For if w/o else, remove the trailing branch.
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400756 this->writeExpression(*i.fTest);
757 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400758 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400759 this->write(ByteCodeInstruction::kConditionalBranch);
760 DeferredLocation elseLocation(this);
761 this->writeStatement(*i.fIfTrue);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400762 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400763 this->write(ByteCodeInstruction::kBranch);
764 DeferredLocation endLocation(this);
765 elseLocation.set();
766 if (i.fIfFalse) {
767 this->writeStatement(*i.fIfFalse);
768 }
769 endLocation.set();
770}
771
772void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -0400773 this->writeExpression(*r.fExpression);
774 this->write(ByteCodeInstruction::kReturn);
775 this->write8(r.fExpression->fType.columns() * r.fExpression->fType.rows());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400776}
777
778void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
779 // not yet implemented
780 abort();
781}
782
783void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
784 for (const auto& declStatement : v.fVars) {
785 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
786 // we need to grab the location even if we don't use it, to ensure it
787 // has been allocated
788 int location = getLocation(*decl.fVar);
789 if (decl.fValue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400790 this->writeExpression(*decl.fValue);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400791 this->write(vector_instruction(ByteCodeInstruction::kStore,
792 slot_count(decl.fValue->fType)));
Brian Osman1091f022019-05-16 09:42:16 -0400793 this->write8(location);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400794 }
795 }
796}
797
798void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
799 fContinueTargets.emplace();
800 fBreakTargets.emplace();
801 size_t start = fCode->size();
802 this->writeExpression(*w.fTest);
803 this->write(ByteCodeInstruction::kNot);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400804 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400805 this->write(ByteCodeInstruction::kConditionalBranch);
806 DeferredLocation endLocation(this);
807 this->writeStatement(*w.fStatement);
808 this->setContinueTargets();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400809 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400810 this->write(ByteCodeInstruction::kBranch);
811 this->write16(start);
812 endLocation.set();
813 this->setBreakTargets();
814}
815
816void ByteCodeGenerator::writeStatement(const Statement& s) {
817 switch (s.fKind) {
818 case Statement::kBlock_Kind:
819 this->writeBlock((Block&) s);
820 break;
821 case Statement::kBreak_Kind:
822 this->writeBreakStatement((BreakStatement&) s);
823 break;
824 case Statement::kContinue_Kind:
825 this->writeContinueStatement((ContinueStatement&) s);
826 break;
827 case Statement::kDiscard_Kind:
828 // not yet implemented
829 abort();
830 case Statement::kDo_Kind:
831 this->writeDoStatement((DoStatement&) s);
832 break;
833 case Statement::kExpression_Kind: {
834 const Expression& expr = *((ExpressionStatement&) s).fExpression;
835 this->writeExpression(expr);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400836 this->write(vector_instruction(ByteCodeInstruction::kPop, slot_count(expr.fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400837 break;
838 }
839 case Statement::kFor_Kind:
840 this->writeForStatement((ForStatement&) s);
841 break;
842 case Statement::kIf_Kind:
843 this->writeIfStatement((IfStatement&) s);
844 break;
845 case Statement::kNop_Kind:
846 break;
847 case Statement::kReturn_Kind:
848 this->writeReturnStatement((ReturnStatement&) s);
849 break;
850 case Statement::kSwitch_Kind:
851 this->writeSwitchStatement((SwitchStatement&) s);
852 break;
853 case Statement::kVarDeclarations_Kind:
854 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
855 break;
856 case Statement::kWhile_Kind:
857 this->writeWhileStatement((WhileStatement&) s);
858 break;
859 default:
860 SkASSERT(false);
861 }
862}
863
864}