blob: 5c877a7e9c016753b4b15d38ae71e9522c683441 [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
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000164void ByteCodeGenerator::align(int divisor, int remainder) {
165 switch (remainder - (int) fCode->size() % divisor) {
166 case 0: return;
167 case 3: this->write(ByteCodeInstruction::kNop3); // fall through
168 case 2: this->write(ByteCodeInstruction::kNop2); // fall through
169 case 1: this->write(ByteCodeInstruction::kNop1);
170 break;
171 default: SkASSERT(false);
172 }
173}
174
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400175void ByteCodeGenerator::write8(uint8_t b) {
176 fCode->push_back(b);
177}
178
179void ByteCodeGenerator::write16(uint16_t i) {
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000180 SkASSERT(fCode->size() % 2 == 0);
181 this->write8(i >> 0);
182 this->write8(i >> 8);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400183}
184
185void ByteCodeGenerator::write32(uint32_t i) {
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000186 SkASSERT(fCode->size() % 4 == 0);
187 this->write8((i >> 0) & 0xFF);
188 this->write8((i >> 8) & 0xFF);
189 this->write8((i >> 16) & 0xFF);
190 this->write8((i >> 24) & 0xFF);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400191}
192
193void ByteCodeGenerator::write(ByteCodeInstruction i) {
194 this->write8((uint8_t) i);
195}
196
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000197ByteCodeInstruction vector_instruction(ByteCodeInstruction base, int count) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400198 return ((ByteCodeInstruction) ((int) base + count - 1));
199}
200
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400201void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400202 ByteCodeInstruction u, ByteCodeInstruction f,
203 int count) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400204 switch (type_category(type)) {
205 case TypeCategory::kSigned:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400206 this->write(vector_instruction(s, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400207 break;
208 case TypeCategory::kUnsigned:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400209 this->write(vector_instruction(u, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400210 break;
211 case TypeCategory::kFloat:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400212 this->write(vector_instruction(f, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400213 break;
214 default:
215 SkASSERT(false);
216 }
217}
218
219void ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b) {
220 if (b.fOperator == Token::Kind::EQ) {
221 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
222 this->writeExpression(*b.fRight);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400223 lvalue->store();
224 return;
225 }
226 Token::Kind op;
227 std::unique_ptr<LValue> lvalue;
228 if (is_assignment(b.fOperator)) {
229 lvalue = this->getLValue(*b.fLeft);
230 lvalue->load();
231 op = remove_assignment(b.fOperator);
232 } else {
233 this->writeExpression(*b.fLeft);
234 op = b.fOperator;
235 if (b.fLeft->fType.kind() == Type::kScalar_Kind &&
236 b.fRight->fType.kind() == Type::kVector_Kind) {
237 for (int i = b.fRight->fType.columns(); i > 1; --i) {
238 this->write(ByteCodeInstruction::kDup);
239 }
240 }
241 }
242 this->writeExpression(*b.fRight);
243 if (b.fLeft->fType.kind() == Type::kVector_Kind &&
244 b.fRight->fType.kind() == Type::kScalar_Kind) {
245 for (int i = b.fLeft->fType.columns(); i > 1; --i) {
246 this->write(ByteCodeInstruction::kDup);
247 }
248 }
249 int count = slot_count(b.fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400250 switch (op) {
251 case Token::Kind::EQEQ:
252 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareIEQ,
253 ByteCodeInstruction::kCompareIEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400254 ByteCodeInstruction::kCompareFEQ,
255 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400256 break;
257 case Token::Kind::GT:
258 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGT,
259 ByteCodeInstruction::kCompareUGT,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400260 ByteCodeInstruction::kCompareFGT,
261 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400262 break;
263 case Token::Kind::GTEQ:
264 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGTEQ,
265 ByteCodeInstruction::kCompareUGTEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400266 ByteCodeInstruction::kCompareFGTEQ,
267 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400268 break;
269 case Token::Kind::LT:
270 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLT,
271 ByteCodeInstruction::kCompareULT,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400272 ByteCodeInstruction::kCompareFLT,
273 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400274 break;
275 case Token::Kind::LTEQ:
276 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLTEQ,
277 ByteCodeInstruction::kCompareULTEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400278 ByteCodeInstruction::kCompareFLTEQ,
279 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400280 break;
281 case Token::Kind::MINUS:
282 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kSubtractI,
283 ByteCodeInstruction::kSubtractI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400284 ByteCodeInstruction::kSubtractF,
285 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400286 break;
287 case Token::Kind::NEQ:
288 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareINEQ,
289 ByteCodeInstruction::kCompareINEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400290 ByteCodeInstruction::kCompareFNEQ,
291 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400292 break;
293 case Token::Kind::PERCENT:
294 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kRemainderS,
295 ByteCodeInstruction::kRemainderU,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400296 ByteCodeInstruction::kRemainderF,
297 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400298 break;
299 case Token::Kind::PLUS:
300 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kAddI,
301 ByteCodeInstruction::kAddI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400302 ByteCodeInstruction::kAddF,
303 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400304 break;
305 case Token::Kind::SLASH:
306 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kDivideS,
307 ByteCodeInstruction::kDivideU,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400308 ByteCodeInstruction::kDivideF,
309 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400310 break;
311 case Token::Kind::STAR:
Ethan Nicholas91164d12019-05-15 15:29:54 -0400312 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kMultiplyI,
313 ByteCodeInstruction::kMultiplyI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400314 ByteCodeInstruction::kMultiplyF,
315 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400316 break;
317 default:
318 SkASSERT(false);
319 }
320 if (lvalue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400321 lvalue->store();
322 }
323}
324
325void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000326 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400327 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osman44d44762019-05-13 14:19:12 -0400328 this->write32(b.fValue ? 1 : 0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400329}
330
331void ByteCodeGenerator::writeConstructor(const Constructor& c) {
332 if (c.fArguments.size() == 1 &&
333 type_category(c.fType) == type_category(c.fArguments[0]->fType)) {
334 // cast from float to half or similar no-op
335 this->writeExpression(*c.fArguments[0]);
336 return;
337 }
338 for (const auto& arg : c.fArguments) {
339 this->writeExpression(*arg);
340 }
341 if (c.fArguments.size() == 1) {
342 TypeCategory inCategory = type_category(c.fArguments[0]->fType);
343 TypeCategory outCategory = type_category(c.fType);
344 if (inCategory != outCategory) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400345 if (inCategory == TypeCategory::kFloat) {
346 SkASSERT(outCategory == TypeCategory::kSigned ||
347 outCategory == TypeCategory::kUnsigned);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400348 this->write(vector_instruction(ByteCodeInstruction::kFloatToInt,
349 c.fType.columns()));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400350 } else if (outCategory == TypeCategory::kFloat) {
351 if (inCategory == TypeCategory::kSigned) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400352 this->write(vector_instruction(ByteCodeInstruction::kSignedToFloat,
353 c.fType.columns()));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400354 } else {
355 SkASSERT(inCategory == TypeCategory::kUnsigned);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400356 this->write(vector_instruction(ByteCodeInstruction::kUnsignedToFloat,
357 c.fType.columns()));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400358 }
359 } else {
360 SkASSERT(false);
361 }
362 }
363 }
364}
365
Ethan Nicholas91164d12019-05-15 15:29:54 -0400366void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400367 this->write(vector_instruction(ByteCodeInstruction::kReadExternal,
368 slot_count(e.fValue->type())));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400369 int index = fOutput->fExternalValues.size();
370 fOutput->fExternalValues.push_back(e.fValue);
371 SkASSERT(index <= 255);
372 this->write8(index);
373}
374
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400375void ByteCodeGenerator::writeFieldAccess(const FieldAccess& f) {
376 // not yet implemented
377 abort();
378}
379
380void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000381 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400382 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400383 this->write32(Interpreter::Value((float) f.fValue).fUnsigned);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400384}
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) {
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000400 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: {
Brian Osmanf3fa6002019-05-17 14:26:53 -0400414 SkASSERT(slot_count(p.fOperand->fType) == 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400415 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
416 lvalue->load();
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000417 this->align(4, 3);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400418 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400419 this->write32(type_category(p.fType) == TypeCategory::kFloat
420 ? Interpreter::Value(1.0f).fUnsigned : 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400421 if (p.fOperator == Token::Kind::PLUSPLUS) {
422 this->writeTypedInstruction(p.fType,
423 ByteCodeInstruction::kAddI,
424 ByteCodeInstruction::kAddI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400425 ByteCodeInstruction::kAddF,
426 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400427 } else {
428 this->writeTypedInstruction(p.fType,
429 ByteCodeInstruction::kSubtractI,
430 ByteCodeInstruction::kSubtractI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400431 ByteCodeInstruction::kSubtractF,
432 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400433 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400434 lvalue->store();
435 break;
436 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400437 case Token::Kind::MINUS: {
438 this->writeExpression(*p.fOperand);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400439 this->writeTypedInstruction(p.fType,
440 ByteCodeInstruction::kNegateS,
441 ByteCodeInstruction::kInvalid,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400442 ByteCodeInstruction::kNegateF,
443 slot_count(p.fOperand->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400444 break;
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400445 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400446 default:
447 SkASSERT(false);
448 }
449}
450
451void ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p) {
Brian Osmanf3fa6002019-05-17 14:26:53 -0400452 switch (p.fOperator) {
453 case Token::Kind::PLUSPLUS: // fall through
454 case Token::Kind::MINUSMINUS: {
455 SkASSERT(slot_count(p.fOperand->fType) == 1);
456 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
457 lvalue->load();
458 this->write(ByteCodeInstruction::kDup);
459 this->align(4, 3);
460 this->write(ByteCodeInstruction::kPushImmediate);
461 this->write32(type_category(p.fType) == TypeCategory::kFloat
462 ? Interpreter::Value(1.0f).fUnsigned : 1);
463 if (p.fOperator == Token::Kind::PLUSPLUS) {
464 this->writeTypedInstruction(p.fType,
465 ByteCodeInstruction::kAddI,
466 ByteCodeInstruction::kAddI,
467 ByteCodeInstruction::kAddF,
468 1);
469 } else {
470 this->writeTypedInstruction(p.fType,
471 ByteCodeInstruction::kSubtractI,
472 ByteCodeInstruction::kSubtractI,
473 ByteCodeInstruction::kSubtractF,
474 1);
475 }
476 lvalue->store();
477 this->write(ByteCodeInstruction::kPop);
478 this->write8(1);
479 break;
480 }
481 default:
482 SkASSERT(false);
483 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400484}
485
486void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
487 switch (s.fBase->fKind) {
488 case Expression::kVariableReference_Kind: {
489 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
Brian Osman1091f022019-05-16 09:42:16 -0400490 this->write(var.fStorage == Variable::kGlobal_Storage
491 ? ByteCodeInstruction::kLoadSwizzleGlobal
492 : ByteCodeInstruction::kLoadSwizzle);
493 this->write8(this->getLocation(var));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400494 this->write8(s.fComponents.size());
495 for (int c : s.fComponents) {
496 this->write8(c);
497 }
498 break;
499 }
500 default:
501 this->writeExpression(*s.fBase);
502 this->write(ByteCodeInstruction::kSwizzle);
503 this->write8(s.fBase->fType.columns());
504 this->write8(s.fComponents.size());
505 for (int c : s.fComponents) {
506 this->write8(c);
507 }
508 }
509}
510
511void ByteCodeGenerator::writeVariableReference(const VariableReference& v) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400512 this->write(vector_instruction(v.fVariable.fStorage == Variable::kGlobal_Storage
513 ? ByteCodeInstruction::kLoadGlobal
514 : ByteCodeInstruction::kLoad,
515 slot_count(v.fType)));
Brian Osman1091f022019-05-16 09:42:16 -0400516 this->write8(this->getLocation(v.fVariable));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400517}
518
519void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Brian Osman4e93feb2019-05-16 15:38:00 -0400520 this->writeExpression(*t.fTest);
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000521 this->align(2, 1);
Brian Osman4e93feb2019-05-16 15:38:00 -0400522 this->write(ByteCodeInstruction::kConditionalBranch);
523 DeferredLocation trueLocation(this);
524 this->writeExpression(*t.fIfFalse);
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000525 this->align(2, 1);
Brian Osman4e93feb2019-05-16 15:38:00 -0400526 this->write(ByteCodeInstruction::kBranch);
527 DeferredLocation endLocation(this);
528 trueLocation.set();
529 this->writeExpression(*t.fIfTrue);
530 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400531}
532
533void ByteCodeGenerator::writeExpression(const Expression& e) {
534 switch (e.fKind) {
535 case Expression::kBinary_Kind:
536 this->writeBinaryExpression((BinaryExpression&) e);
537 break;
538 case Expression::kBoolLiteral_Kind:
539 this->writeBoolLiteral((BoolLiteral&) e);
540 break;
541 case Expression::kConstructor_Kind:
542 this->writeConstructor((Constructor&) e);
543 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400544 case Expression::kExternalValue_Kind:
545 this->writeExternalValue((ExternalValueReference&) e);
546 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400547 case Expression::kFieldAccess_Kind:
548 this->writeFieldAccess((FieldAccess&) e);
549 break;
550 case Expression::kFloatLiteral_Kind:
551 this->writeFloatLiteral((FloatLiteral&) e);
552 break;
553 case Expression::kFunctionCall_Kind:
554 this->writeFunctionCall((FunctionCall&) e);
555 break;
556 case Expression::kIndex_Kind:
557 this->writeIndexExpression((IndexExpression&) e);
558 break;
559 case Expression::kIntLiteral_Kind:
560 this->writeIntLiteral((IntLiteral&) e);
561 break;
562 case Expression::kNullLiteral_Kind:
563 this->writeNullLiteral((NullLiteral&) e);
564 break;
565 case Expression::kPrefix_Kind:
566 this->writePrefixExpression((PrefixExpression&) e);
567 break;
568 case Expression::kPostfix_Kind:
569 this->writePostfixExpression((PostfixExpression&) e);
570 break;
571 case Expression::kSwizzle_Kind:
572 this->writeSwizzle((Swizzle&) e);
573 break;
574 case Expression::kVariableReference_Kind:
575 this->writeVariableReference((VariableReference&) e);
576 break;
577 case Expression::kTernary_Kind:
578 this->writeTernaryExpression((TernaryExpression&) e);
579 break;
580 default:
581 printf("unsupported expression %s\n", e.description().c_str());
582 SkASSERT(false);
583 }
584}
585
Ethan Nicholas91164d12019-05-15 15:29:54 -0400586class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
587public:
588 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
589 : INHERITED(*generator)
590 , fCount(slot_count(value.type()))
591 , fIndex(index) {}
592
593 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400594 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400595 fGenerator.write8(fIndex);
596 }
597
598 void store() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400599 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
600 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400601 fGenerator.write8(fIndex);
602 }
603
604private:
605 typedef LValue INHERITED;
606
607 int fCount;
608
609 int fIndex;
610};
611
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400612class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
613public:
614 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
615 : INHERITED(*generator)
616 , fSwizzle(swizzle) {
Brian Osman1091f022019-05-16 09:42:16 -0400617 SkASSERT(fSwizzle.fBase->fKind == Expression::kVariableReference_Kind);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400618 }
619
620 void load() override {
Brian Osman1091f022019-05-16 09:42:16 -0400621 fGenerator.writeSwizzle(fSwizzle);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400622 }
623
624 void store() override {
Brian Osman1091f022019-05-16 09:42:16 -0400625 const Variable& var = ((VariableReference&)*fSwizzle.fBase).fVariable;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400626 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup,
627 fSwizzle.fComponents.size()));
Brian Osman1091f022019-05-16 09:42:16 -0400628 fGenerator.write(var.fStorage == Variable::kGlobal_Storage
629 ? ByteCodeInstruction::kStoreSwizzleGlobal
630 : ByteCodeInstruction::kStoreSwizzle);
631 fGenerator.write8(fGenerator.getLocation(var));
632 fGenerator.write8(fSwizzle.fComponents.size());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400633 for (int c : fSwizzle.fComponents) {
634 fGenerator.write8(c);
635 }
636 }
637
638private:
639 const Swizzle& fSwizzle;
640
641 typedef LValue INHERITED;
642};
643
644class ByteCodeVariableLValue : public ByteCodeGenerator::LValue {
645public:
646 ByteCodeVariableLValue(ByteCodeGenerator* generator, const Variable& var)
647 : INHERITED(*generator)
648 , fCount(slot_count(var.fType))
Brian Osman1091f022019-05-16 09:42:16 -0400649 , fLocation(generator->getLocation(var))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400650 , fIsGlobal(var.fStorage == Variable::kGlobal_Storage) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400651 }
652
653 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400654 fGenerator.write(vector_instruction(fIsGlobal ? ByteCodeInstruction::kLoadGlobal
655 : ByteCodeInstruction::kLoad,
656 fCount));
Brian Osman1091f022019-05-16 09:42:16 -0400657 fGenerator.write8(fLocation);
658 }
659
660 void store() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400661 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
662 fGenerator.write(vector_instruction(fIsGlobal ? ByteCodeInstruction::kStoreGlobal
663 : ByteCodeInstruction::kStore,
664 fCount));
Brian Osman1091f022019-05-16 09:42:16 -0400665 fGenerator.write8(fLocation);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400666 }
667
668private:
669 typedef LValue INHERITED;
670
671 int fCount;
Brian Osman1091f022019-05-16 09:42:16 -0400672 int fLocation;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400673 bool fIsGlobal;
674};
675
676std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
677 switch (e.fKind) {
Ethan Nicholas91164d12019-05-15 15:29:54 -0400678 case Expression::kExternalValue_Kind: {
679 ExternalValue* value = ((ExternalValueReference&) e).fValue;
680 int index = fOutput->fExternalValues.size();
681 fOutput->fExternalValues.push_back(value);
682 SkASSERT(index <= 255);
683 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
684 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400685 case Expression::kIndex_Kind:
686 // not yet implemented
687 abort();
688 case Expression::kVariableReference_Kind:
689 return std::unique_ptr<LValue>(new ByteCodeVariableLValue(this,
690 ((VariableReference&) e).fVariable));
691 case Expression::kSwizzle_Kind:
692 return std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, (Swizzle&) e));
693 case Expression::kTernary_Kind:
694 default:
695 printf("unsupported lvalue %s\n", e.description().c_str());
696 return nullptr;
697 }
698}
699
700void ByteCodeGenerator::writeBlock(const Block& b) {
701 for (const auto& s : b.fStatements) {
702 this->writeStatement(*s);
703 }
704}
705
706void ByteCodeGenerator::setBreakTargets() {
707 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
708 for (DeferredLocation& b : breaks) {
709 b.set();
710 }
711 fBreakTargets.pop();
712}
713
714void ByteCodeGenerator::setContinueTargets() {
715 std::vector<DeferredLocation>& continues = fContinueTargets.top();
716 for (DeferredLocation& c : continues) {
717 c.set();
718 }
719 fContinueTargets.pop();
720}
721
722void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000723 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400724 this->write(ByteCodeInstruction::kBranch);
725 fBreakTargets.top().emplace_back(this);
726}
727
728void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000729 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400730 this->write(ByteCodeInstruction::kBranch);
731 fContinueTargets.top().emplace_back(this);
732}
733
734void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
735 fContinueTargets.emplace();
736 fBreakTargets.emplace();
737 size_t start = fCode->size();
738 this->writeStatement(*d.fStatement);
739 this->setContinueTargets();
740 this->writeExpression(*d.fTest);
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000741 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400742 this->write(ByteCodeInstruction::kConditionalBranch);
743 this->write16(start);
744 this->setBreakTargets();
745}
746
747void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
748 fContinueTargets.emplace();
749 fBreakTargets.emplace();
750 if (f.fInitializer) {
751 this->writeStatement(*f.fInitializer);
752 }
753 size_t start = fCode->size();
754 if (f.fTest) {
755 this->writeExpression(*f.fTest);
756 this->write(ByteCodeInstruction::kNot);
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000757 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400758 this->write(ByteCodeInstruction::kConditionalBranch);
759 DeferredLocation endLocation(this);
760 this->writeStatement(*f.fStatement);
761 this->setContinueTargets();
762 if (f.fNext) {
763 this->writeExpression(*f.fNext);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400764 this->write(vector_instruction(ByteCodeInstruction::kPop, slot_count(f.fNext->fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400765 }
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000766 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400767 this->write(ByteCodeInstruction::kBranch);
768 this->write16(start);
769 endLocation.set();
770 } else {
771 this->writeStatement(*f.fStatement);
772 this->setContinueTargets();
773 if (f.fNext) {
774 this->writeExpression(*f.fNext);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400775 this->write(vector_instruction(ByteCodeInstruction::kPop, slot_count(f.fNext->fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400776 }
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000777 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400778 this->write(ByteCodeInstruction::kBranch);
779 this->write16(start);
780 }
781 this->setBreakTargets();
782}
783
784void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400785 if (i.fIfFalse) {
Mike Kleinb45ee832019-05-17 11:11:11 -0500786 // if (test) { ..ifTrue.. } else { .. ifFalse .. }
787 this->writeExpression(*i.fTest);
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000788 this->align(2, 1);
Mike Kleinb45ee832019-05-17 11:11:11 -0500789 this->write(ByteCodeInstruction::kConditionalBranch);
790 DeferredLocation trueLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400791 this->writeStatement(*i.fIfFalse);
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000792 this->align(2, 1);
Mike Kleinb45ee832019-05-17 11:11:11 -0500793 this->write(ByteCodeInstruction::kBranch);
794 DeferredLocation endLocation(this);
795 trueLocation.set();
796 this->writeStatement(*i.fIfTrue);
797 endLocation.set();
798 } else {
799 // if (test) { ..ifTrue.. }
800 this->writeExpression(*i.fTest);
801 this->write(ByteCodeInstruction::kNot);
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000802 this->align(2, 1);
Mike Kleinb45ee832019-05-17 11:11:11 -0500803 this->write(ByteCodeInstruction::kConditionalBranch);
804 DeferredLocation endLocation(this);
805 this->writeStatement(*i.fIfTrue);
806 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400807 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400808}
809
810void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -0400811 this->writeExpression(*r.fExpression);
812 this->write(ByteCodeInstruction::kReturn);
813 this->write8(r.fExpression->fType.columns() * r.fExpression->fType.rows());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400814}
815
816void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
817 // not yet implemented
818 abort();
819}
820
821void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
822 for (const auto& declStatement : v.fVars) {
823 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
824 // we need to grab the location even if we don't use it, to ensure it
825 // has been allocated
826 int location = getLocation(*decl.fVar);
827 if (decl.fValue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400828 this->writeExpression(*decl.fValue);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400829 this->write(vector_instruction(ByteCodeInstruction::kStore,
830 slot_count(decl.fValue->fType)));
Brian Osman1091f022019-05-16 09:42:16 -0400831 this->write8(location);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400832 }
833 }
834}
835
836void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
837 fContinueTargets.emplace();
838 fBreakTargets.emplace();
839 size_t start = fCode->size();
840 this->writeExpression(*w.fTest);
841 this->write(ByteCodeInstruction::kNot);
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000842 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400843 this->write(ByteCodeInstruction::kConditionalBranch);
844 DeferredLocation endLocation(this);
845 this->writeStatement(*w.fStatement);
846 this->setContinueTargets();
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000847 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400848 this->write(ByteCodeInstruction::kBranch);
849 this->write16(start);
850 endLocation.set();
851 this->setBreakTargets();
852}
853
854void ByteCodeGenerator::writeStatement(const Statement& s) {
855 switch (s.fKind) {
856 case Statement::kBlock_Kind:
857 this->writeBlock((Block&) s);
858 break;
859 case Statement::kBreak_Kind:
860 this->writeBreakStatement((BreakStatement&) s);
861 break;
862 case Statement::kContinue_Kind:
863 this->writeContinueStatement((ContinueStatement&) s);
864 break;
865 case Statement::kDiscard_Kind:
866 // not yet implemented
867 abort();
868 case Statement::kDo_Kind:
869 this->writeDoStatement((DoStatement&) s);
870 break;
871 case Statement::kExpression_Kind: {
872 const Expression& expr = *((ExpressionStatement&) s).fExpression;
873 this->writeExpression(expr);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400874 this->write(vector_instruction(ByteCodeInstruction::kPop, slot_count(expr.fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400875 break;
876 }
877 case Statement::kFor_Kind:
878 this->writeForStatement((ForStatement&) s);
879 break;
880 case Statement::kIf_Kind:
881 this->writeIfStatement((IfStatement&) s);
882 break;
883 case Statement::kNop_Kind:
884 break;
885 case Statement::kReturn_Kind:
886 this->writeReturnStatement((ReturnStatement&) s);
887 break;
888 case Statement::kSwitch_Kind:
889 this->writeSwitchStatement((SwitchStatement&) s);
890 break;
891 case Statement::kVarDeclarations_Kind:
892 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
893 break;
894 case Statement::kWhile_Kind:
895 this->writeWhileStatement((WhileStatement&) s);
896 break;
897 default:
898 SkASSERT(false);
899 }
900}
901
902}