blob: b53fe477749972a3b55bdbd397fe6b3b0556e2c2 [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
Ethan Nicholas82162ee2019-05-21 16:05:08 -040013ByteCodeGenerator::ByteCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
14 ByteCode* output)
15 : INHERITED(program, errors, nullptr)
16 , fContext(*context)
17 , fOutput(output) {
18 fIntrinsics["cos"] = ByteCodeInstruction::kCos;
19 fIntrinsics["sin"] = ByteCodeInstruction::kSin;
20 fIntrinsics["sqrt"] = ByteCodeInstruction::kSqrt;
21 fIntrinsics["tan"] = ByteCodeInstruction::kTan;
22}
23
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040024static int slot_count(const Type& type) {
25 return type.columns() * type.rows();
26}
27
28bool ByteCodeGenerator::generateCode() {
29 for (const auto& e : fProgram) {
30 switch (e.fKind) {
31 case ProgramElement::kFunction_Kind: {
32 std::unique_ptr<ByteCodeFunction> f = this->writeFunction((FunctionDefinition&) e);
33 if (!f) {
34 return false;
35 }
36 fOutput->fFunctions.push_back(std::move(f));
37 break;
38 }
39 case ProgramElement::kVar_Kind: {
40 VarDeclarations& decl = (VarDeclarations&) e;
41 for (const auto& v : decl.fVars) {
42 const Variable* declVar = ((VarDeclaration&) *v).fVar;
43 if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
44 continue;
45 }
46 if (declVar->fModifiers.fFlags & Modifiers::kIn_Flag) {
47 for (int i = slot_count(declVar->fType); i > 0; --i) {
48 fOutput->fInputSlots.push_back(fOutput->fGlobalCount++);
49 }
50 } else {
51 fOutput->fGlobalCount += slot_count(declVar->fType);
52 }
53 }
54 break;
55 }
56 default:
57 ; // ignore
58 }
59 }
Brian Osman226668a2019-05-14 16:47:30 -040060 for (auto& call : fCallTargets) {
61 if (!call.set()) {
62 return false;
63 }
64 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040065 return true;
66}
67
68std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
69 fFunction = &f;
Brian Osman226668a2019-05-14 16:47:30 -040070 std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040071 fParameterCount = 0;
72 for (const auto& p : f.fDeclaration.fParameters) {
73 fParameterCount += p->fType.columns() * p->fType.rows();
74 }
75 fCode = &result->fCode;
76 this->writeStatement(*f.fBody);
Ethan Nicholas7e603db2019-05-03 12:57:47 -040077 this->write(ByteCodeInstruction::kReturn);
78 this->write8(0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040079 result->fParameterCount = fParameterCount;
80 result->fLocalCount = fLocals.size();
Ethan Nicholasdfcad062019-05-07 12:53:34 -040081 const Type& returnType = f.fDeclaration.fReturnType;
82 if (returnType != *fContext.fVoid_Type) {
83 result->fReturnCount = returnType.columns() * returnType.rows();
84 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040085 fLocals.clear();
86 fFunction = nullptr;
87 return result;
88}
89
90enum class TypeCategory {
91 kBool,
92 kSigned,
93 kUnsigned,
94 kFloat,
95};
96
97static TypeCategory type_category(const Type& type) {
98 switch (type.kind()) {
99 case Type::Kind::kVector_Kind:
100 case Type::Kind::kMatrix_Kind:
101 return type_category(type.componentType());
102 default:
103 if (type.fName == "bool") {
104 return TypeCategory::kBool;
105 } else if (type.fName == "int" || type.fName == "short") {
106 return TypeCategory::kSigned;
107 } else if (type.fName == "uint" || type.fName == "ushort") {
108 return TypeCategory::kUnsigned;
109 } else {
110 SkASSERT(type.fName == "float" || type.fName == "half");
111 return TypeCategory::kFloat;
112 }
113 ABORT("unsupported type: %s\n", type.description().c_str());
114 }
115}
116
117int ByteCodeGenerator::getLocation(const Variable& var) {
118 // given that we seldom have more than a couple of variables, linear search is probably the most
119 // efficient way to handle lookups
120 switch (var.fStorage) {
121 case Variable::kLocal_Storage: {
122 for (int i = fLocals.size() - 1; i >= 0; --i) {
123 if (fLocals[i] == &var) {
Brian Osman1091f022019-05-16 09:42:16 -0400124 SkASSERT(fParameterCount + i <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400125 return fParameterCount + i;
126 }
127 }
128 int result = fParameterCount + fLocals.size();
129 fLocals.push_back(&var);
130 for (int i = 0; i < slot_count(var.fType) - 1; ++i) {
131 fLocals.push_back(nullptr);
132 }
Brian Osman1091f022019-05-16 09:42:16 -0400133 SkASSERT(result <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400134 return result;
135 }
136 case Variable::kParameter_Storage: {
137 int offset = 0;
138 for (const auto& p : fFunction->fDeclaration.fParameters) {
139 if (p == &var) {
Brian Osman1091f022019-05-16 09:42:16 -0400140 SkASSERT(offset <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400141 return offset;
142 }
143 offset += slot_count(p->fType);
144 }
145 SkASSERT(false);
Brian Osman1091f022019-05-16 09:42:16 -0400146 return 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400147 }
148 case Variable::kGlobal_Storage: {
149 int offset = 0;
150 for (const auto& e : fProgram) {
151 if (e.fKind == ProgramElement::kVar_Kind) {
152 VarDeclarations& decl = (VarDeclarations&) e;
153 for (const auto& v : decl.fVars) {
154 const Variable* declVar = ((VarDeclaration&) *v).fVar;
155 if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
156 continue;
157 }
158 if (declVar == &var) {
Brian Osmanb7451292019-05-15 13:02:13 -0400159 SkASSERT(offset <= 255);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400160 return offset;
161 }
162 offset += slot_count(declVar->fType);
163 }
164 }
165 }
166 SkASSERT(false);
Brian Osman1091f022019-05-16 09:42:16 -0400167 return 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400168 }
169 default:
170 SkASSERT(false);
171 return 0;
172 }
173}
174
175void ByteCodeGenerator::write8(uint8_t b) {
176 fCode->push_back(b);
177}
178
179void ByteCodeGenerator::write16(uint16_t i) {
Mike Klein76346ac2019-05-17 11:57:10 -0500180 size_t n = fCode->size();
181 fCode->resize(n+2);
182 memcpy(fCode->data() + n, &i, 2);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400183}
184
185void ByteCodeGenerator::write32(uint32_t i) {
Mike Klein76346ac2019-05-17 11:57:10 -0500186 size_t n = fCode->size();
187 fCode->resize(n+4);
188 memcpy(fCode->data() + n, &i, 4);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400189}
190
191void ByteCodeGenerator::write(ByteCodeInstruction i) {
Mike Klein108e9352019-05-21 11:05:17 -0500192 this->write16((uint16_t)i);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400193}
194
Mike Klein76346ac2019-05-17 11:57:10 -0500195static ByteCodeInstruction vector_instruction(ByteCodeInstruction base, int count) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400196 return ((ByteCodeInstruction) ((int) base + count - 1));
197}
198
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400199void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400200 ByteCodeInstruction u, ByteCodeInstruction f,
201 int count) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400202 switch (type_category(type)) {
203 case TypeCategory::kSigned:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400204 this->write(vector_instruction(s, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400205 break;
206 case TypeCategory::kUnsigned:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400207 this->write(vector_instruction(u, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400208 break;
209 case TypeCategory::kFloat:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400210 this->write(vector_instruction(f, count));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400211 break;
212 default:
213 SkASSERT(false);
214 }
215}
216
217void ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b) {
218 if (b.fOperator == Token::Kind::EQ) {
219 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
220 this->writeExpression(*b.fRight);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400221 lvalue->store();
222 return;
223 }
224 Token::Kind op;
225 std::unique_ptr<LValue> lvalue;
226 if (is_assignment(b.fOperator)) {
227 lvalue = this->getLValue(*b.fLeft);
228 lvalue->load();
229 op = remove_assignment(b.fOperator);
230 } else {
231 this->writeExpression(*b.fLeft);
232 op = b.fOperator;
233 if (b.fLeft->fType.kind() == Type::kScalar_Kind &&
234 b.fRight->fType.kind() == Type::kVector_Kind) {
235 for (int i = b.fRight->fType.columns(); i > 1; --i) {
236 this->write(ByteCodeInstruction::kDup);
237 }
238 }
239 }
240 this->writeExpression(*b.fRight);
241 if (b.fLeft->fType.kind() == Type::kVector_Kind &&
242 b.fRight->fType.kind() == Type::kScalar_Kind) {
243 for (int i = b.fLeft->fType.columns(); i > 1; --i) {
244 this->write(ByteCodeInstruction::kDup);
245 }
246 }
247 int count = slot_count(b.fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400248 switch (op) {
249 case Token::Kind::EQEQ:
250 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareIEQ,
251 ByteCodeInstruction::kCompareIEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400252 ByteCodeInstruction::kCompareFEQ,
253 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400254 break;
255 case Token::Kind::GT:
256 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGT,
257 ByteCodeInstruction::kCompareUGT,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400258 ByteCodeInstruction::kCompareFGT,
259 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400260 break;
261 case Token::Kind::GTEQ:
262 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSGTEQ,
263 ByteCodeInstruction::kCompareUGTEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400264 ByteCodeInstruction::kCompareFGTEQ,
265 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400266 break;
267 case Token::Kind::LT:
268 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLT,
269 ByteCodeInstruction::kCompareULT,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400270 ByteCodeInstruction::kCompareFLT,
271 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400272 break;
273 case Token::Kind::LTEQ:
274 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareSLTEQ,
275 ByteCodeInstruction::kCompareULTEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400276 ByteCodeInstruction::kCompareFLTEQ,
277 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400278 break;
279 case Token::Kind::MINUS:
280 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kSubtractI,
281 ByteCodeInstruction::kSubtractI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400282 ByteCodeInstruction::kSubtractF,
283 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400284 break;
285 case Token::Kind::NEQ:
286 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kCompareINEQ,
287 ByteCodeInstruction::kCompareINEQ,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400288 ByteCodeInstruction::kCompareFNEQ,
289 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400290 break;
291 case Token::Kind::PERCENT:
292 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kRemainderS,
293 ByteCodeInstruction::kRemainderU,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400294 ByteCodeInstruction::kRemainderF,
295 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400296 break;
297 case Token::Kind::PLUS:
298 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kAddI,
299 ByteCodeInstruction::kAddI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400300 ByteCodeInstruction::kAddF,
301 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400302 break;
303 case Token::Kind::SLASH:
304 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kDivideS,
305 ByteCodeInstruction::kDivideU,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400306 ByteCodeInstruction::kDivideF,
307 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400308 break;
309 case Token::Kind::STAR:
Ethan Nicholas91164d12019-05-15 15:29:54 -0400310 this->writeTypedInstruction(b.fLeft->fType, ByteCodeInstruction::kMultiplyI,
311 ByteCodeInstruction::kMultiplyI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400312 ByteCodeInstruction::kMultiplyF,
313 count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400314 break;
315 default:
316 SkASSERT(false);
317 }
318 if (lvalue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400319 lvalue->store();
320 }
321}
322
323void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
324 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osman44d44762019-05-13 14:19:12 -0400325 this->write32(b.fValue ? 1 : 0);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400326}
327
328void ByteCodeGenerator::writeConstructor(const Constructor& c) {
329 if (c.fArguments.size() == 1 &&
330 type_category(c.fType) == type_category(c.fArguments[0]->fType)) {
331 // cast from float to half or similar no-op
332 this->writeExpression(*c.fArguments[0]);
333 return;
334 }
335 for (const auto& arg : c.fArguments) {
336 this->writeExpression(*arg);
337 }
338 if (c.fArguments.size() == 1) {
339 TypeCategory inCategory = type_category(c.fArguments[0]->fType);
340 TypeCategory outCategory = type_category(c.fType);
341 if (inCategory != outCategory) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400342 if (inCategory == TypeCategory::kFloat) {
343 SkASSERT(outCategory == TypeCategory::kSigned ||
344 outCategory == TypeCategory::kUnsigned);
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400345 this->write(vector_instruction(ByteCodeInstruction::kConvertFtoI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400346 c.fType.columns()));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400347 } else if (outCategory == TypeCategory::kFloat) {
348 if (inCategory == TypeCategory::kSigned) {
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400349 this->write(vector_instruction(ByteCodeInstruction::kConvertStoF,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400350 c.fType.columns()));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400351 } else {
352 SkASSERT(inCategory == TypeCategory::kUnsigned);
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400353 this->write(vector_instruction(ByteCodeInstruction::kConvertUtoF,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400354 c.fType.columns()));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400355 }
356 } else {
357 SkASSERT(false);
358 }
359 }
360 }
361}
362
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400363void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f) {
364 int argumentCount = 0;
365 for (const auto& arg : f.fArguments) {
366 this->writeExpression(*arg);
367 argumentCount += slot_count(arg->fType);
368 }
369 this->write(ByteCodeInstruction::kCallExternal);
370 SkASSERT(argumentCount <= 255);
371 this->write8(argumentCount);
372 this->write8(slot_count(f.fType));
373 int index = fOutput->fExternalValues.size();
374 fOutput->fExternalValues.push_back(f.fFunction);
375 SkASSERT(index <= 255);
376 this->write8(index);
377}
378
Ethan Nicholas91164d12019-05-15 15:29:54 -0400379void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400380 this->write(vector_instruction(ByteCodeInstruction::kReadExternal,
381 slot_count(e.fValue->type())));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400382 int index = fOutput->fExternalValues.size();
383 fOutput->fExternalValues.push_back(e.fValue);
384 SkASSERT(index <= 255);
385 this->write8(index);
386}
387
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400388void ByteCodeGenerator::writeFieldAccess(const FieldAccess& f) {
389 // not yet implemented
390 abort();
391}
392
393void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
394 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400395 this->write32(Interpreter::Value((float) f.fValue).fUnsigned);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400396}
397
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400398void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
399 auto found = fIntrinsics.find(c.fFunction.fName);
400 if (found == fIntrinsics.end()) {
401 fErrors.error(c.fOffset, "unsupported intrinsic function");
402 return;
403 }
404 switch (found->second) {
405 case ByteCodeInstruction::kCos: // fall through
406 case ByteCodeInstruction::kSin: // fall through
407 case ByteCodeInstruction::kSqrt: // fall through
408 case ByteCodeInstruction::kTan:
409 SkASSERT(c.fArguments.size() == 1);
410 this->write((ByteCodeInstruction) ((int) found->second +
411 slot_count(c.fArguments[0]->fType) - 1));
412 break;
413 default:
414 SkASSERT(false);
415 }
416}
417
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400418void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400419 if (f.fFunction.fBuiltin) {
420 this->writeIntrinsicCall(f);
421 return;
422 }
Brian Osman226668a2019-05-14 16:47:30 -0400423 for (const auto& arg : f.fArguments) {
424 this->writeExpression(*arg);
425 }
426 this->write(ByteCodeInstruction::kCall);
427 fCallTargets.emplace_back(this, f.fFunction);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400428}
429
430void ByteCodeGenerator::writeIndexExpression(const IndexExpression& i) {
431 // not yet implemented
432 abort();
433}
434
435void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
436 this->write(ByteCodeInstruction::kPushImmediate);
437 this->write32(i.fValue);
438}
439
440void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
441 // not yet implemented
442 abort();
443}
444
445void ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p) {
446 switch (p.fOperator) {
447 case Token::Kind::PLUSPLUS: // fall through
448 case Token::Kind::MINUSMINUS: {
Brian Osmanf3fa6002019-05-17 14:26:53 -0400449 SkASSERT(slot_count(p.fOperand->fType) == 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400450 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
451 lvalue->load();
452 this->write(ByteCodeInstruction::kPushImmediate);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400453 this->write32(type_category(p.fType) == TypeCategory::kFloat
454 ? Interpreter::Value(1.0f).fUnsigned : 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400455 if (p.fOperator == Token::Kind::PLUSPLUS) {
456 this->writeTypedInstruction(p.fType,
457 ByteCodeInstruction::kAddI,
458 ByteCodeInstruction::kAddI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400459 ByteCodeInstruction::kAddF,
460 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400461 } else {
462 this->writeTypedInstruction(p.fType,
463 ByteCodeInstruction::kSubtractI,
464 ByteCodeInstruction::kSubtractI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400465 ByteCodeInstruction::kSubtractF,
466 1);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400467 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400468 lvalue->store();
469 break;
470 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400471 case Token::Kind::MINUS: {
472 this->writeExpression(*p.fOperand);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400473 this->writeTypedInstruction(p.fType,
Mike Klein12710912019-05-21 11:04:59 -0500474 ByteCodeInstruction::kNegateI,
475 ByteCodeInstruction::kNegateI,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400476 ByteCodeInstruction::kNegateF,
477 slot_count(p.fOperand->fType));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400478 break;
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400479 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400480 default:
481 SkASSERT(false);
482 }
483}
484
485void ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p) {
Brian Osmanf3fa6002019-05-17 14:26:53 -0400486 switch (p.fOperator) {
487 case Token::Kind::PLUSPLUS: // fall through
488 case Token::Kind::MINUSMINUS: {
489 SkASSERT(slot_count(p.fOperand->fType) == 1);
490 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
491 lvalue->load();
492 this->write(ByteCodeInstruction::kDup);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400493 this->write(ByteCodeInstruction::kPushImmediate);
494 this->write32(type_category(p.fType) == TypeCategory::kFloat
495 ? Interpreter::Value(1.0f).fUnsigned : 1);
496 if (p.fOperator == Token::Kind::PLUSPLUS) {
497 this->writeTypedInstruction(p.fType,
498 ByteCodeInstruction::kAddI,
499 ByteCodeInstruction::kAddI,
500 ByteCodeInstruction::kAddF,
501 1);
502 } else {
503 this->writeTypedInstruction(p.fType,
504 ByteCodeInstruction::kSubtractI,
505 ByteCodeInstruction::kSubtractI,
506 ByteCodeInstruction::kSubtractF,
507 1);
508 }
509 lvalue->store();
510 this->write(ByteCodeInstruction::kPop);
Brian Osmanf3fa6002019-05-17 14:26:53 -0400511 break;
512 }
513 default:
514 SkASSERT(false);
515 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400516}
517
518void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
519 switch (s.fBase->fKind) {
520 case Expression::kVariableReference_Kind: {
521 const Variable& var = ((VariableReference&) *s.fBase).fVariable;
Brian Osman1091f022019-05-16 09:42:16 -0400522 this->write(var.fStorage == Variable::kGlobal_Storage
523 ? ByteCodeInstruction::kLoadSwizzleGlobal
524 : ByteCodeInstruction::kLoadSwizzle);
525 this->write8(this->getLocation(var));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400526 this->write8(s.fComponents.size());
527 for (int c : s.fComponents) {
528 this->write8(c);
529 }
530 break;
531 }
532 default:
533 this->writeExpression(*s.fBase);
534 this->write(ByteCodeInstruction::kSwizzle);
535 this->write8(s.fBase->fType.columns());
536 this->write8(s.fComponents.size());
537 for (int c : s.fComponents) {
538 this->write8(c);
539 }
540 }
541}
542
543void ByteCodeGenerator::writeVariableReference(const VariableReference& v) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400544 this->write(vector_instruction(v.fVariable.fStorage == Variable::kGlobal_Storage
545 ? ByteCodeInstruction::kLoadGlobal
546 : ByteCodeInstruction::kLoad,
547 slot_count(v.fType)));
Brian Osman1091f022019-05-16 09:42:16 -0400548 this->write8(this->getLocation(v.fVariable));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400549}
550
551void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Brian Osman4e93feb2019-05-16 15:38:00 -0400552 this->writeExpression(*t.fTest);
Brian Osman4e93feb2019-05-16 15:38:00 -0400553 this->write(ByteCodeInstruction::kConditionalBranch);
554 DeferredLocation trueLocation(this);
555 this->writeExpression(*t.fIfFalse);
Brian Osman4e93feb2019-05-16 15:38:00 -0400556 this->write(ByteCodeInstruction::kBranch);
557 DeferredLocation endLocation(this);
558 trueLocation.set();
559 this->writeExpression(*t.fIfTrue);
560 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400561}
562
563void ByteCodeGenerator::writeExpression(const Expression& e) {
564 switch (e.fKind) {
565 case Expression::kBinary_Kind:
566 this->writeBinaryExpression((BinaryExpression&) e);
567 break;
568 case Expression::kBoolLiteral_Kind:
569 this->writeBoolLiteral((BoolLiteral&) e);
570 break;
571 case Expression::kConstructor_Kind:
572 this->writeConstructor((Constructor&) e);
573 break;
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400574 case Expression::kExternalFunctionCall_Kind:
575 this->writeExternalFunctionCall((ExternalFunctionCall&) e);
576 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400577 case Expression::kExternalValue_Kind:
578 this->writeExternalValue((ExternalValueReference&) e);
579 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400580 case Expression::kFieldAccess_Kind:
581 this->writeFieldAccess((FieldAccess&) e);
582 break;
583 case Expression::kFloatLiteral_Kind:
584 this->writeFloatLiteral((FloatLiteral&) e);
585 break;
586 case Expression::kFunctionCall_Kind:
587 this->writeFunctionCall((FunctionCall&) e);
588 break;
589 case Expression::kIndex_Kind:
590 this->writeIndexExpression((IndexExpression&) e);
591 break;
592 case Expression::kIntLiteral_Kind:
593 this->writeIntLiteral((IntLiteral&) e);
594 break;
595 case Expression::kNullLiteral_Kind:
596 this->writeNullLiteral((NullLiteral&) e);
597 break;
598 case Expression::kPrefix_Kind:
599 this->writePrefixExpression((PrefixExpression&) e);
600 break;
601 case Expression::kPostfix_Kind:
602 this->writePostfixExpression((PostfixExpression&) e);
603 break;
604 case Expression::kSwizzle_Kind:
605 this->writeSwizzle((Swizzle&) e);
606 break;
607 case Expression::kVariableReference_Kind:
608 this->writeVariableReference((VariableReference&) e);
609 break;
610 case Expression::kTernary_Kind:
611 this->writeTernaryExpression((TernaryExpression&) e);
612 break;
613 default:
614 printf("unsupported expression %s\n", e.description().c_str());
615 SkASSERT(false);
616 }
617}
618
Ethan Nicholas91164d12019-05-15 15:29:54 -0400619class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
620public:
621 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
622 : INHERITED(*generator)
623 , fCount(slot_count(value.type()))
624 , fIndex(index) {}
625
626 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400627 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400628 fGenerator.write8(fIndex);
629 }
630
631 void store() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400632 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
633 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Ethan Nicholas91164d12019-05-15 15:29:54 -0400634 fGenerator.write8(fIndex);
635 }
636
637private:
638 typedef LValue INHERITED;
639
640 int fCount;
641
642 int fIndex;
643};
644
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400645class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
646public:
647 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
648 : INHERITED(*generator)
649 , fSwizzle(swizzle) {
Brian Osman1091f022019-05-16 09:42:16 -0400650 SkASSERT(fSwizzle.fBase->fKind == Expression::kVariableReference_Kind);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400651 }
652
653 void load() override {
Brian Osman1091f022019-05-16 09:42:16 -0400654 fGenerator.writeSwizzle(fSwizzle);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400655 }
656
657 void store() override {
Brian Osman1091f022019-05-16 09:42:16 -0400658 const Variable& var = ((VariableReference&)*fSwizzle.fBase).fVariable;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400659 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup,
660 fSwizzle.fComponents.size()));
Brian Osman1091f022019-05-16 09:42:16 -0400661 fGenerator.write(var.fStorage == Variable::kGlobal_Storage
662 ? ByteCodeInstruction::kStoreSwizzleGlobal
663 : ByteCodeInstruction::kStoreSwizzle);
664 fGenerator.write8(fGenerator.getLocation(var));
665 fGenerator.write8(fSwizzle.fComponents.size());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400666 for (int c : fSwizzle.fComponents) {
667 fGenerator.write8(c);
668 }
669 }
670
671private:
672 const Swizzle& fSwizzle;
673
674 typedef LValue INHERITED;
675};
676
677class ByteCodeVariableLValue : public ByteCodeGenerator::LValue {
678public:
679 ByteCodeVariableLValue(ByteCodeGenerator* generator, const Variable& var)
680 : INHERITED(*generator)
681 , fCount(slot_count(var.fType))
Brian Osman1091f022019-05-16 09:42:16 -0400682 , fLocation(generator->getLocation(var))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400683 , fIsGlobal(var.fStorage == Variable::kGlobal_Storage) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400684 }
685
686 void load() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400687 fGenerator.write(vector_instruction(fIsGlobal ? ByteCodeInstruction::kLoadGlobal
688 : ByteCodeInstruction::kLoad,
689 fCount));
Brian Osman1091f022019-05-16 09:42:16 -0400690 fGenerator.write8(fLocation);
691 }
692
693 void store() override {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400694 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
695 fGenerator.write(vector_instruction(fIsGlobal ? ByteCodeInstruction::kStoreGlobal
696 : ByteCodeInstruction::kStore,
697 fCount));
Brian Osman1091f022019-05-16 09:42:16 -0400698 fGenerator.write8(fLocation);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400699 }
700
701private:
702 typedef LValue INHERITED;
703
704 int fCount;
Brian Osman1091f022019-05-16 09:42:16 -0400705 int fLocation;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400706 bool fIsGlobal;
707};
708
709std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
710 switch (e.fKind) {
Ethan Nicholas91164d12019-05-15 15:29:54 -0400711 case Expression::kExternalValue_Kind: {
712 ExternalValue* value = ((ExternalValueReference&) e).fValue;
713 int index = fOutput->fExternalValues.size();
714 fOutput->fExternalValues.push_back(value);
715 SkASSERT(index <= 255);
716 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
717 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400718 case Expression::kIndex_Kind:
719 // not yet implemented
720 abort();
721 case Expression::kVariableReference_Kind:
722 return std::unique_ptr<LValue>(new ByteCodeVariableLValue(this,
723 ((VariableReference&) e).fVariable));
724 case Expression::kSwizzle_Kind:
725 return std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, (Swizzle&) e));
726 case Expression::kTernary_Kind:
727 default:
728 printf("unsupported lvalue %s\n", e.description().c_str());
729 return nullptr;
730 }
731}
732
733void ByteCodeGenerator::writeBlock(const Block& b) {
734 for (const auto& s : b.fStatements) {
735 this->writeStatement(*s);
736 }
737}
738
739void ByteCodeGenerator::setBreakTargets() {
740 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
741 for (DeferredLocation& b : breaks) {
742 b.set();
743 }
744 fBreakTargets.pop();
745}
746
747void ByteCodeGenerator::setContinueTargets() {
748 std::vector<DeferredLocation>& continues = fContinueTargets.top();
749 for (DeferredLocation& c : continues) {
750 c.set();
751 }
752 fContinueTargets.pop();
753}
754
755void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
756 this->write(ByteCodeInstruction::kBranch);
757 fBreakTargets.top().emplace_back(this);
758}
759
760void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
761 this->write(ByteCodeInstruction::kBranch);
762 fContinueTargets.top().emplace_back(this);
763}
764
765void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
766 fContinueTargets.emplace();
767 fBreakTargets.emplace();
768 size_t start = fCode->size();
769 this->writeStatement(*d.fStatement);
770 this->setContinueTargets();
771 this->writeExpression(*d.fTest);
772 this->write(ByteCodeInstruction::kConditionalBranch);
773 this->write16(start);
774 this->setBreakTargets();
775}
776
777void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
778 fContinueTargets.emplace();
779 fBreakTargets.emplace();
780 if (f.fInitializer) {
781 this->writeStatement(*f.fInitializer);
782 }
783 size_t start = fCode->size();
784 if (f.fTest) {
785 this->writeExpression(*f.fTest);
786 this->write(ByteCodeInstruction::kNot);
787 this->write(ByteCodeInstruction::kConditionalBranch);
788 DeferredLocation endLocation(this);
789 this->writeStatement(*f.fStatement);
790 this->setContinueTargets();
791 if (f.fNext) {
792 this->writeExpression(*f.fNext);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400793 this->write(vector_instruction(ByteCodeInstruction::kPop, slot_count(f.fNext->fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400794 }
795 this->write(ByteCodeInstruction::kBranch);
796 this->write16(start);
797 endLocation.set();
798 } else {
799 this->writeStatement(*f.fStatement);
800 this->setContinueTargets();
801 if (f.fNext) {
802 this->writeExpression(*f.fNext);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400803 this->write(vector_instruction(ByteCodeInstruction::kPop, slot_count(f.fNext->fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400804 }
805 this->write(ByteCodeInstruction::kBranch);
806 this->write16(start);
807 }
808 this->setBreakTargets();
809}
810
811void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400812 if (i.fIfFalse) {
Mike Kleinb45ee832019-05-17 11:11:11 -0500813 // if (test) { ..ifTrue.. } else { .. ifFalse .. }
814 this->writeExpression(*i.fTest);
Mike Kleinb45ee832019-05-17 11:11:11 -0500815 this->write(ByteCodeInstruction::kConditionalBranch);
816 DeferredLocation trueLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400817 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -0500818 this->write(ByteCodeInstruction::kBranch);
819 DeferredLocation endLocation(this);
820 trueLocation.set();
821 this->writeStatement(*i.fIfTrue);
822 endLocation.set();
823 } else {
824 // if (test) { ..ifTrue.. }
825 this->writeExpression(*i.fTest);
826 this->write(ByteCodeInstruction::kNot);
Mike Kleinb45ee832019-05-17 11:11:11 -0500827 this->write(ByteCodeInstruction::kConditionalBranch);
828 DeferredLocation endLocation(this);
829 this->writeStatement(*i.fIfTrue);
830 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400831 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400832}
833
834void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
Ethan Nicholas746035a2019-04-23 13:31:09 -0400835 this->writeExpression(*r.fExpression);
836 this->write(ByteCodeInstruction::kReturn);
837 this->write8(r.fExpression->fType.columns() * r.fExpression->fType.rows());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400838}
839
840void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
841 // not yet implemented
842 abort();
843}
844
845void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
846 for (const auto& declStatement : v.fVars) {
847 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
848 // we need to grab the location even if we don't use it, to ensure it
849 // has been allocated
850 int location = getLocation(*decl.fVar);
851 if (decl.fValue) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400852 this->writeExpression(*decl.fValue);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400853 this->write(vector_instruction(ByteCodeInstruction::kStore,
854 slot_count(decl.fValue->fType)));
Brian Osman1091f022019-05-16 09:42:16 -0400855 this->write8(location);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400856 }
857 }
858}
859
860void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
861 fContinueTargets.emplace();
862 fBreakTargets.emplace();
863 size_t start = fCode->size();
864 this->writeExpression(*w.fTest);
865 this->write(ByteCodeInstruction::kNot);
866 this->write(ByteCodeInstruction::kConditionalBranch);
867 DeferredLocation endLocation(this);
868 this->writeStatement(*w.fStatement);
869 this->setContinueTargets();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400870 this->write(ByteCodeInstruction::kBranch);
871 this->write16(start);
872 endLocation.set();
873 this->setBreakTargets();
874}
875
876void ByteCodeGenerator::writeStatement(const Statement& s) {
877 switch (s.fKind) {
878 case Statement::kBlock_Kind:
879 this->writeBlock((Block&) s);
880 break;
881 case Statement::kBreak_Kind:
882 this->writeBreakStatement((BreakStatement&) s);
883 break;
884 case Statement::kContinue_Kind:
885 this->writeContinueStatement((ContinueStatement&) s);
886 break;
887 case Statement::kDiscard_Kind:
888 // not yet implemented
889 abort();
890 case Statement::kDo_Kind:
891 this->writeDoStatement((DoStatement&) s);
892 break;
893 case Statement::kExpression_Kind: {
894 const Expression& expr = *((ExpressionStatement&) s).fExpression;
895 this->writeExpression(expr);
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400896 this->write(vector_instruction(ByteCodeInstruction::kPop, slot_count(expr.fType)));
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400897 break;
898 }
899 case Statement::kFor_Kind:
900 this->writeForStatement((ForStatement&) s);
901 break;
902 case Statement::kIf_Kind:
903 this->writeIfStatement((IfStatement&) s);
904 break;
905 case Statement::kNop_Kind:
906 break;
907 case Statement::kReturn_Kind:
908 this->writeReturnStatement((ReturnStatement&) s);
909 break;
910 case Statement::kSwitch_Kind:
911 this->writeSwitchStatement((SwitchStatement&) s);
912 break;
913 case Statement::kVarDeclarations_Kind:
914 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
915 break;
916 case Statement::kWhile_Kind:
917 this->writeWhileStatement((WhileStatement&) s);
918 break;
919 default:
920 SkASSERT(false);
921 }
922}
923
924}