blob: 1e9ea5c7c627f40d5102bb787ecd1aaea197f522 [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);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400478 break;
479 }
480 default:
481 SkASSERT(false);
482 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400483}
484
485void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
486 switch (s.fBase->fKind) {
487 case Expression::kVariableReference_Kind: {
488 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
Brian Osman1091f022019-05-16 09:42:16 -0400489 this->write(var.fStorage == Variable::kGlobal_Storage
490 ? ByteCodeInstruction::kLoadSwizzleGlobal
491 : ByteCodeInstruction::kLoadSwizzle);
492 this->write8(this->getLocation(var));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400493 this->write8(s.fComponents.size());
494 for (int c : s.fComponents) {
495 this->write8(c);
496 }
497 break;
498 }
499 default:
500 this->writeExpression(*s.fBase);
501 this->write(ByteCodeInstruction::kSwizzle);
502 this->write8(s.fBase->fType.columns());
503 this->write8(s.fComponents.size());
504 for (int c : s.fComponents) {
505 this->write8(c);
506 }
507 }
508}
509
510void ByteCodeGenerator::writeVariableReference(const VariableReference& v) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400511 this->write(vector_instruction(v.fVariable.fStorage == Variable::kGlobal_Storage
512 ? ByteCodeInstruction::kLoadGlobal
513 : ByteCodeInstruction::kLoad,
514 slot_count(v.fType)));
Brian Osman1091f022019-05-16 09:42:16 -0400515 this->write8(this->getLocation(v.fVariable));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400516}
517
518void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Brian Osman4e93feb2019-05-16 15:38:00 -0400519 this->writeExpression(*t.fTest);
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000520 this->align(2, 1);
Brian Osman4e93feb2019-05-16 15:38:00 -0400521 this->write(ByteCodeInstruction::kConditionalBranch);
522 DeferredLocation trueLocation(this);
523 this->writeExpression(*t.fIfFalse);
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000524 this->align(2, 1);
Brian Osman4e93feb2019-05-16 15:38:00 -0400525 this->write(ByteCodeInstruction::kBranch);
526 DeferredLocation endLocation(this);
527 trueLocation.set();
528 this->writeExpression(*t.fIfTrue);
529 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400530}
531
532void ByteCodeGenerator::writeExpression(const Expression& e) {
533 switch (e.fKind) {
534 case Expression::kBinary_Kind:
535 this->writeBinaryExpression((BinaryExpression&) e);
536 break;
537 case Expression::kBoolLiteral_Kind:
538 this->writeBoolLiteral((BoolLiteral&) e);
539 break;
540 case Expression::kConstructor_Kind:
541 this->writeConstructor((Constructor&) e);
542 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400543 case Expression::kExternalValue_Kind:
544 this->writeExternalValue((ExternalValueReference&) e);
545 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400546 case Expression::kFieldAccess_Kind:
547 this->writeFieldAccess((FieldAccess&) e);
548 break;
549 case Expression::kFloatLiteral_Kind:
550 this->writeFloatLiteral((FloatLiteral&) e);
551 break;
552 case Expression::kFunctionCall_Kind:
553 this->writeFunctionCall((FunctionCall&) e);
554 break;
555 case Expression::kIndex_Kind:
556 this->writeIndexExpression((IndexExpression&) e);
557 break;
558 case Expression::kIntLiteral_Kind:
559 this->writeIntLiteral((IntLiteral&) e);
560 break;
561 case Expression::kNullLiteral_Kind:
562 this->writeNullLiteral((NullLiteral&) e);
563 break;
564 case Expression::kPrefix_Kind:
565 this->writePrefixExpression((PrefixExpression&) e);
566 break;
567 case Expression::kPostfix_Kind:
568 this->writePostfixExpression((PostfixExpression&) e);
569 break;
570 case Expression::kSwizzle_Kind:
571 this->writeSwizzle((Swizzle&) e);
572 break;
573 case Expression::kVariableReference_Kind:
574 this->writeVariableReference((VariableReference&) e);
575 break;
576 case Expression::kTernary_Kind:
577 this->writeTernaryExpression((TernaryExpression&) e);
578 break;
579 default:
580 printf("unsupported expression %s\n", e.description().c_str());
581 SkASSERT(false);
582 }
583}
584
Ethan Nicholas91164d12019-05-15 15:29:54 -0400585class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
586public:
587 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
588 : INHERITED(*generator)
589 , fCount(slot_count(value.type()))
590 , fIndex(index) {}
591
592 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400593 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400594 fGenerator.write8(fIndex);
595 }
596
597 void store() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400598 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
599 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400600 fGenerator.write8(fIndex);
601 }
602
603private:
604 typedef LValue INHERITED;
605
606 int fCount;
607
608 int fIndex;
609};
610
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400611class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
612public:
613 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
614 : INHERITED(*generator)
615 , fSwizzle(swizzle) {
Brian Osman1091f022019-05-16 09:42:16 -0400616 SkASSERT(fSwizzle.fBase->fKind == Expression::kVariableReference_Kind);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400617 }
618
619 void load() override {
Brian Osman1091f022019-05-16 09:42:16 -0400620 fGenerator.writeSwizzle(fSwizzle);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400621 }
622
623 void store() override {
Brian Osman1091f022019-05-16 09:42:16 -0400624 const Variable& var = ((VariableReference&)*fSwizzle.fBase).fVariable;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400625 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup,
626 fSwizzle.fComponents.size()));
Brian Osman1091f022019-05-16 09:42:16 -0400627 fGenerator.write(var.fStorage == Variable::kGlobal_Storage
628 ? ByteCodeInstruction::kStoreSwizzleGlobal
629 : ByteCodeInstruction::kStoreSwizzle);
630 fGenerator.write8(fGenerator.getLocation(var));
631 fGenerator.write8(fSwizzle.fComponents.size());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400632 for (int c : fSwizzle.fComponents) {
633 fGenerator.write8(c);
634 }
635 }
636
637private:
638 const Swizzle& fSwizzle;
639
640 typedef LValue INHERITED;
641};
642
643class ByteCodeVariableLValue : public ByteCodeGenerator::LValue {
644public:
645 ByteCodeVariableLValue(ByteCodeGenerator* generator, const Variable& var)
646 : INHERITED(*generator)
647 , fCount(slot_count(var.fType))
Brian Osman1091f022019-05-16 09:42:16 -0400648 , fLocation(generator->getLocation(var))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400649 , fIsGlobal(var.fStorage == Variable::kGlobal_Storage) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400650 }
651
652 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400653 fGenerator.write(vector_instruction(fIsGlobal ? ByteCodeInstruction::kLoadGlobal
654 : ByteCodeInstruction::kLoad,
655 fCount));
Brian Osman1091f022019-05-16 09:42:16 -0400656 fGenerator.write8(fLocation);
657 }
658
659 void store() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400660 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
661 fGenerator.write(vector_instruction(fIsGlobal ? ByteCodeInstruction::kStoreGlobal
662 : ByteCodeInstruction::kStore,
663 fCount));
Brian Osman1091f022019-05-16 09:42:16 -0400664 fGenerator.write8(fLocation);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400665 }
666
667private:
668 typedef LValue INHERITED;
669
670 int fCount;
Brian Osman1091f022019-05-16 09:42:16 -0400671 int fLocation;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400672 bool fIsGlobal;
673};
674
675std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
676 switch (e.fKind) {
Ethan Nicholas91164d12019-05-15 15:29:54 -0400677 case Expression::kExternalValue_Kind: {
678 ExternalValue* value = ((ExternalValueReference&) e).fValue;
679 int index = fOutput->fExternalValues.size();
680 fOutput->fExternalValues.push_back(value);
681 SkASSERT(index <= 255);
682 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
683 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400684 case Expression::kIndex_Kind:
685 // not yet implemented
686 abort();
687 case Expression::kVariableReference_Kind:
688 return std::unique_ptr<LValue>(new ByteCodeVariableLValue(this,
689 ((VariableReference&) e).fVariable));
690 case Expression::kSwizzle_Kind:
691 return std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, (Swizzle&) e));
692 case Expression::kTernary_Kind:
693 default:
694 printf("unsupported lvalue %s\n", e.description().c_str());
695 return nullptr;
696 }
697}
698
699void ByteCodeGenerator::writeBlock(const Block& b) {
700 for (const auto& s : b.fStatements) {
701 this->writeStatement(*s);
702 }
703}
704
705void ByteCodeGenerator::setBreakTargets() {
706 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
707 for (DeferredLocation& b : breaks) {
708 b.set();
709 }
710 fBreakTargets.pop();
711}
712
713void ByteCodeGenerator::setContinueTargets() {
714 std::vector<DeferredLocation>& continues = fContinueTargets.top();
715 for (DeferredLocation& c : continues) {
716 c.set();
717 }
718 fContinueTargets.pop();
719}
720
721void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000722 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400723 this->write(ByteCodeInstruction::kBranch);
724 fBreakTargets.top().emplace_back(this);
725}
726
727void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000728 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400729 this->write(ByteCodeInstruction::kBranch);
730 fContinueTargets.top().emplace_back(this);
731}
732
733void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
734 fContinueTargets.emplace();
735 fBreakTargets.emplace();
736 size_t start = fCode->size();
737 this->writeStatement(*d.fStatement);
738 this->setContinueTargets();
739 this->writeExpression(*d.fTest);
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000740 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400741 this->write(ByteCodeInstruction::kConditionalBranch);
742 this->write16(start);
743 this->setBreakTargets();
744}
745
746void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
747 fContinueTargets.emplace();
748 fBreakTargets.emplace();
749 if (f.fInitializer) {
750 this->writeStatement(*f.fInitializer);
751 }
752 size_t start = fCode->size();
753 if (f.fTest) {
754 this->writeExpression(*f.fTest);
755 this->write(ByteCodeInstruction::kNot);
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000756 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400757 this->write(ByteCodeInstruction::kConditionalBranch);
758 DeferredLocation endLocation(this);
759 this->writeStatement(*f.fStatement);
760 this->setContinueTargets();
761 if (f.fNext) {
762 this->writeExpression(*f.fNext);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400763 this->write(vector_instruction(ByteCodeInstruction::kPop, slot_count(f.fNext->fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400764 }
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000765 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400766 this->write(ByteCodeInstruction::kBranch);
767 this->write16(start);
768 endLocation.set();
769 } else {
770 this->writeStatement(*f.fStatement);
771 this->setContinueTargets();
772 if (f.fNext) {
773 this->writeExpression(*f.fNext);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400774 this->write(vector_instruction(ByteCodeInstruction::kPop, slot_count(f.fNext->fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400775 }
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000776 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400777 this->write(ByteCodeInstruction::kBranch);
778 this->write16(start);
779 }
780 this->setBreakTargets();
781}
782
783void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400784 if (i.fIfFalse) {
Mike Kleinb45ee832019-05-17 11:11:11 -0500785 // if (test) { ..ifTrue.. } else { .. ifFalse .. }
786 this->writeExpression(*i.fTest);
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000787 this->align(2, 1);
Mike Kleinb45ee832019-05-17 11:11:11 -0500788 this->write(ByteCodeInstruction::kConditionalBranch);
789 DeferredLocation trueLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400790 this->writeStatement(*i.fIfFalse);
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000791 this->align(2, 1);
Mike Kleinb45ee832019-05-17 11:11:11 -0500792 this->write(ByteCodeInstruction::kBranch);
793 DeferredLocation endLocation(this);
794 trueLocation.set();
795 this->writeStatement(*i.fIfTrue);
796 endLocation.set();
797 } else {
798 // if (test) { ..ifTrue.. }
799 this->writeExpression(*i.fTest);
800 this->write(ByteCodeInstruction::kNot);
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000801 this->align(2, 1);
Mike Kleinb45ee832019-05-17 11:11:11 -0500802 this->write(ByteCodeInstruction::kConditionalBranch);
803 DeferredLocation endLocation(this);
804 this->writeStatement(*i.fIfTrue);
805 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400806 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400807}
808
809void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -0400810 this->writeExpression(*r.fExpression);
811 this->write(ByteCodeInstruction::kReturn);
812 this->write8(r.fExpression->fType.columns() * r.fExpression->fType.rows());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400813}
814
815void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
816 // not yet implemented
817 abort();
818}
819
820void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
821 for (const auto& declStatement : v.fVars) {
822 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
823 // we need to grab the location even if we don't use it, to ensure it
824 // has been allocated
825 int location = getLocation(*decl.fVar);
826 if (decl.fValue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400827 this->writeExpression(*decl.fValue);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400828 this->write(vector_instruction(ByteCodeInstruction::kStore,
829 slot_count(decl.fValue->fType)));
Brian Osman1091f022019-05-16 09:42:16 -0400830 this->write8(location);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400831 }
832 }
833}
834
835void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
836 fContinueTargets.emplace();
837 fBreakTargets.emplace();
838 size_t start = fCode->size();
839 this->writeExpression(*w.fTest);
840 this->write(ByteCodeInstruction::kNot);
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000841 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400842 this->write(ByteCodeInstruction::kConditionalBranch);
843 DeferredLocation endLocation(this);
844 this->writeStatement(*w.fStatement);
845 this->setContinueTargets();
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000846 this->align(2, 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400847 this->write(ByteCodeInstruction::kBranch);
848 this->write16(start);
849 endLocation.set();
850 this->setBreakTargets();
851}
852
853void ByteCodeGenerator::writeStatement(const Statement& s) {
854 switch (s.fKind) {
855 case Statement::kBlock_Kind:
856 this->writeBlock((Block&) s);
857 break;
858 case Statement::kBreak_Kind:
859 this->writeBreakStatement((BreakStatement&) s);
860 break;
861 case Statement::kContinue_Kind:
862 this->writeContinueStatement((ContinueStatement&) s);
863 break;
864 case Statement::kDiscard_Kind:
865 // not yet implemented
866 abort();
867 case Statement::kDo_Kind:
868 this->writeDoStatement((DoStatement&) s);
869 break;
870 case Statement::kExpression_Kind: {
871 const Expression& expr = *((ExpressionStatement&) s).fExpression;
872 this->writeExpression(expr);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400873 this->write(vector_instruction(ByteCodeInstruction::kPop, slot_count(expr.fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400874 break;
875 }
876 case Statement::kFor_Kind:
877 this->writeForStatement((ForStatement&) s);
878 break;
879 case Statement::kIf_Kind:
880 this->writeIfStatement((IfStatement&) s);
881 break;
882 case Statement::kNop_Kind:
883 break;
884 case Statement::kReturn_Kind:
885 this->writeReturnStatement((ReturnStatement&) s);
886 break;
887 case Statement::kSwitch_Kind:
888 this->writeSwitchStatement((SwitchStatement&) s);
889 break;
890 case Statement::kVarDeclarations_Kind:
891 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
892 break;
893 case Statement::kWhile_Kind:
894 this->writeWhileStatement((WhileStatement&) s);
895 break;
896 default:
897 SkASSERT(false);
898 }
899}
900
901}