blob: 210b54e2a707f871412e225fc763136fe27129d7 [file] [log] [blame]
Brian Osmanb380e712019-07-24 17:02:39 -04001/*
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04002 * Copyright 2019 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/sksl/SkSLByteCodeGenerator.h"
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04009
Brian Osmanb08cc022020-04-02 11:38:40 -040010#include <algorithm>
11
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040012namespace SkSL {
13
Brian Osmanb08cc022020-04-02 11:38:40 -040014static TypeCategory type_category(const Type& type) {
15 switch (type.kind()) {
16 case Type::Kind::kVector_Kind:
17 case Type::Kind::kMatrix_Kind:
18 return type_category(type.componentType());
19 default:
20 if (type.fName == "bool") {
21 return TypeCategory::kBool;
22 } else if (type.fName == "int" ||
23 type.fName == "short" ||
24 type.fName == "$intLiteral") {
25 return TypeCategory::kSigned;
26 } else if (type.fName == "uint" ||
27 type.fName == "ushort") {
28 return TypeCategory::kUnsigned;
29 } else {
30 SkASSERT(type.fName == "float" ||
31 type.fName == "half" ||
32 type.fName == "$floatLiteral");
33 return TypeCategory::kFloat;
34 }
35 ABORT("unsupported type: %s\n", type.displayName().c_str());
36 }
37}
38
39
40ByteCodeGenerator::ByteCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
41 ByteCode* output)
Ethan Nicholas82162ee2019-05-21 16:05:08 -040042 : INHERITED(program, errors, nullptr)
Brian Osmanb08cc022020-04-02 11:38:40 -040043 , fContext(*context)
Ethan Nicholasae9633b2019-05-24 12:46:34 -040044 , fOutput(output)
45 , fIntrinsics {
Brian Osmanb08cc022020-04-02 11:38:40 -040046 { "cos", ByteCodeInstruction::kCos },
Brian Osman15c98cb2020-02-27 18:36:57 +000047 { "dot", SpecialIntrinsic::kDot },
Brian Osmanb08cc022020-04-02 11:38:40 -040048 { "inverse", ByteCodeInstruction::kInverse2x2 },
49 { "sin", ByteCodeInstruction::kSin },
50 { "sqrt", ByteCodeInstruction::kSqrt },
51 { "tan", ByteCodeInstruction::kTan },
52 } {}
53
Ethan Nicholas82162ee2019-05-21 16:05:08 -040054
Brian Osman07c117b2019-05-23 12:51:06 -070055int ByteCodeGenerator::SlotCount(const Type& type) {
Brian Osmanfba386b2019-06-20 14:54:15 -040056 if (type.kind() == Type::kOther_Kind) {
57 return 0;
58 } else if (type.kind() == Type::kStruct_Kind) {
Brian Osman07c117b2019-05-23 12:51:06 -070059 int slots = 0;
60 for (const auto& f : type.fields()) {
61 slots += SlotCount(*f.fType);
62 }
63 SkASSERT(slots <= 255);
64 return slots;
65 } else if (type.kind() == Type::kArray_Kind) {
66 int columns = type.columns();
67 SkASSERT(columns >= 0);
68 int slots = columns * SlotCount(type.componentType());
69 SkASSERT(slots <= 255);
70 return slots;
71 } else {
72 return type.columns() * type.rows();
73 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040074}
75
Brian Osman1c110a02019-10-01 14:53:32 -040076static inline bool is_uniform(const SkSL::Variable& var) {
77 return var.fModifiers.fFlags & Modifiers::kUniform_Flag;
78}
79
Brian Osmaneadfeb92020-01-09 12:43:03 -050080static inline bool is_in(const SkSL::Variable& var) {
81 return var.fModifiers.fFlags & Modifiers::kIn_Flag;
82}
Brian Osmanb08cc022020-04-02 11:38:40 -040083
84void ByteCodeGenerator::gatherUniforms(const Type& type, const String& name) {
85 if (type.kind() == Type::kOther_Kind) {
86 return;
87 } else if (type.kind() == Type::kStruct_Kind) {
88 for (const auto& f : type.fields()) {
89 this->gatherUniforms(*f.fType, name + "." + f.fName);
Ethan Nicholasb962eff2020-01-23 16:49:41 -050090 }
Brian Osmanb08cc022020-04-02 11:38:40 -040091 } else if (type.kind() == Type::kArray_Kind) {
92 for (int i = 0; i < type.columns(); ++i) {
93 this->gatherUniforms(type.componentType(), String::printf("%s[%d]", name.c_str(), i));
Ethan Nicholasb962eff2020-01-23 16:49:41 -050094 }
Brian Osmanb08cc022020-04-02 11:38:40 -040095 } else {
96 fOutput->fUniforms.push_back({ name, type_category(type), type.rows(), type.columns(),
97 fOutput->fUniformSlotCount });
98 fOutput->fUniformSlotCount += type.columns() * type.rows();
99 }
100}
101
102bool ByteCodeGenerator::generateCode() {
103 for (const auto& e : fProgram) {
104 switch (e.fKind) {
105 case ProgramElement::kFunction_Kind: {
106 std::unique_ptr<ByteCodeFunction> f = this->writeFunction((FunctionDefinition&) e);
107 if (!f) {
108 return false;
109 }
110 fOutput->fFunctions.push_back(std::move(f));
111 fFunctions.push_back(&(FunctionDefinition&)e);
112 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500113 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400114 case ProgramElement::kVar_Kind: {
115 VarDeclarations& decl = (VarDeclarations&) e;
116 for (const auto& v : decl.fVars) {
117 const Variable* declVar = ((VarDeclaration&) *v).fVar;
118 if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
119 continue;
120 }
121 if (is_uniform(*declVar)) {
122 this->gatherUniforms(declVar->fType, declVar->fName);
123 } else {
124 fOutput->fGlobalSlotCount += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400125 }
126 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400127 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400128 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400129 default:
130 ; // ignore
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400131 }
132 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400133 return 0 == fErrors.errorCount();
134}
135
136std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
137 fFunction = &f;
138 std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
139 fParameterCount = result->fParameterCount;
140 fLoopCount = fMaxLoopCount = 0;
141 fConditionCount = fMaxConditionCount = 0;
142 fStackCount = fMaxStackCount = 0;
143 fCode = &result->fCode;
144
145 this->writeStatement(*f.fBody);
146 if (0 == fErrors.errorCount()) {
147 SkASSERT(fLoopCount == 0);
148 SkASSERT(fConditionCount == 0);
149 SkASSERT(fStackCount == 0);
150 }
151 this->write(ByteCodeInstruction::kReturn, 0);
152 this->write8(0);
153
154 result->fLocalCount = fLocals.size();
155 result->fConditionCount = fMaxConditionCount;
156 result->fLoopCount = fMaxLoopCount;
157 result->fStackCount = fMaxStackCount;
158
159 const Type& returnType = f.fDeclaration.fReturnType;
160 if (returnType != *fContext.fVoid_Type) {
161 result->fReturnCount = SlotCount(returnType);
162 }
163 fLocals.clear();
164 fFunction = nullptr;
165 return result;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400166}
167
Brian Osman0785db02019-05-24 14:19:11 -0400168// A "simple" Swizzle is based on a variable (or a compound variable like a struct or array), and
169// that references consecutive values, such that it can be implemented using normal load/store ops
170// with an offset. Note that all single-component swizzles (of suitable base types) are simple.
171static bool swizzle_is_simple(const Swizzle& s) {
172 switch (s.fBase->fKind) {
173 case Expression::kFieldAccess_Kind:
174 case Expression::kIndex_Kind:
175 case Expression::kVariableReference_Kind:
176 break;
177 default:
178 return false;
179 }
180
181 for (size_t i = 1; i < s.fComponents.size(); ++i) {
182 if (s.fComponents[i] != s.fComponents[i - 1] + 1) {
183 return false;
184 }
185 }
186 return true;
187}
188
Brian Osmanb08cc022020-04-02 11:38:40 -0400189int ByteCodeGenerator::StackUsage(ByteCodeInstruction inst, int count_) {
190 // Ensures that we use count iff we're passed a non-default value. Most instructions have an
191 // implicit count, so the caller shouldn't need to worry about it (or count makes no sense).
192 // The asserts avoids callers thinking they're supplying useful information in that scenario,
193 // or failing to supply necessary information for the ops that need a count.
194 struct CountValue {
195 operator int() {
196 SkASSERT(val != ByteCodeGenerator::kUnusedStackCount);
197 SkDEBUGCODE(used = true);
198 return val;
199 }
200 ~CountValue() {
201 SkASSERT(used || val == ByteCodeGenerator::kUnusedStackCount);
202 }
203 int val;
204 SkDEBUGCODE(bool used = false;)
205 } count = { count_ };
206
207 switch (inst) {
208 // Unary functions/operators that don't change stack depth at all:
209#define VECTOR_UNARY_OP(base) \
210 case ByteCodeInstruction::base: \
211 case ByteCodeInstruction::base ## 2: \
212 case ByteCodeInstruction::base ## 3: \
213 case ByteCodeInstruction::base ## 4: \
214 return 0;
215
216 VECTOR_UNARY_OP(kConvertFtoI)
217 VECTOR_UNARY_OP(kConvertStoF)
218 VECTOR_UNARY_OP(kConvertUtoF)
219
220 VECTOR_UNARY_OP(kCos)
221 VECTOR_UNARY_OP(kSin)
222 VECTOR_UNARY_OP(kSqrt)
223 VECTOR_UNARY_OP(kTan)
224
225 VECTOR_UNARY_OP(kNegateF)
226 VECTOR_UNARY_OP(kNegateI)
227
228 case ByteCodeInstruction::kInverse2x2:
229 case ByteCodeInstruction::kInverse3x3:
230 case ByteCodeInstruction::kInverse4x4: return 0;
231
232 case ByteCodeInstruction::kClampIndex: return 0;
233 case ByteCodeInstruction::kNotB: return 0;
234 case ByteCodeInstruction::kNegateFN: return 0;
235 case ByteCodeInstruction::kShiftLeft: return 0;
236 case ByteCodeInstruction::kShiftRightS: return 0;
237 case ByteCodeInstruction::kShiftRightU: return 0;
238
239#undef VECTOR_UNARY_OP
240
241 // Binary functions/operators that do a 2 -> 1 reduction (possibly N times)
242#define VECTOR_BINARY_OP(base) \
243 case ByteCodeInstruction::base: return -1; \
244 case ByteCodeInstruction::base ## 2: return -2; \
245 case ByteCodeInstruction::base ## 3: return -3; \
246 case ByteCodeInstruction::base ## 4: return -4;
247
248#define VECTOR_MATRIX_BINARY_OP(base) \
249 VECTOR_BINARY_OP(base) \
250 case ByteCodeInstruction::base ## N: return -count;
251
252 case ByteCodeInstruction::kAndB: return -1;
253 case ByteCodeInstruction::kOrB: return -1;
254 case ByteCodeInstruction::kXorB: return -1;
255
256 VECTOR_BINARY_OP(kAddI)
257 VECTOR_MATRIX_BINARY_OP(kAddF)
258
259 VECTOR_BINARY_OP(kCompareIEQ)
260 VECTOR_MATRIX_BINARY_OP(kCompareFEQ)
261 VECTOR_BINARY_OP(kCompareINEQ)
262 VECTOR_MATRIX_BINARY_OP(kCompareFNEQ)
263 VECTOR_BINARY_OP(kCompareSGT)
264 VECTOR_BINARY_OP(kCompareUGT)
265 VECTOR_BINARY_OP(kCompareFGT)
266 VECTOR_BINARY_OP(kCompareSGTEQ)
267 VECTOR_BINARY_OP(kCompareUGTEQ)
268 VECTOR_BINARY_OP(kCompareFGTEQ)
269 VECTOR_BINARY_OP(kCompareSLT)
270 VECTOR_BINARY_OP(kCompareULT)
271 VECTOR_BINARY_OP(kCompareFLT)
272 VECTOR_BINARY_OP(kCompareSLTEQ)
273 VECTOR_BINARY_OP(kCompareULTEQ)
274 VECTOR_BINARY_OP(kCompareFLTEQ)
275
276 VECTOR_BINARY_OP(kDivideS)
277 VECTOR_BINARY_OP(kDivideU)
278 VECTOR_MATRIX_BINARY_OP(kDivideF)
279 VECTOR_BINARY_OP(kMultiplyI)
280 VECTOR_MATRIX_BINARY_OP(kMultiplyF)
281 VECTOR_BINARY_OP(kRemainderF)
282 VECTOR_BINARY_OP(kRemainderS)
283 VECTOR_BINARY_OP(kRemainderU)
284 VECTOR_BINARY_OP(kSubtractI)
285 VECTOR_MATRIX_BINARY_OP(kSubtractF)
286
287#undef VECTOR_BINARY_OP
288#undef VECTOR_MATRIX_BINARY_OP
289
290 // Ops that push or load data to grow the stack:
291 case ByteCodeInstruction::kDup:
292 case ByteCodeInstruction::kLoad:
293 case ByteCodeInstruction::kLoadGlobal:
294 case ByteCodeInstruction::kLoadUniform:
295 case ByteCodeInstruction::kReadExternal:
296 case ByteCodeInstruction::kPushImmediate:
297 return 1;
298
299 case ByteCodeInstruction::kDup2:
300 case ByteCodeInstruction::kLoad2:
301 case ByteCodeInstruction::kLoadGlobal2:
302 case ByteCodeInstruction::kLoadUniform2:
303 case ByteCodeInstruction::kReadExternal2:
304 return 2;
305
306 case ByteCodeInstruction::kDup3:
307 case ByteCodeInstruction::kLoad3:
308 case ByteCodeInstruction::kLoadGlobal3:
309 case ByteCodeInstruction::kLoadUniform3:
310 case ByteCodeInstruction::kReadExternal3:
311 return 3;
312
313 case ByteCodeInstruction::kDup4:
314 case ByteCodeInstruction::kLoad4:
315 case ByteCodeInstruction::kLoadGlobal4:
316 case ByteCodeInstruction::kLoadUniform4:
317 case ByteCodeInstruction::kReadExternal4:
318 return 4;
319
320 case ByteCodeInstruction::kDupN:
321 case ByteCodeInstruction::kLoadSwizzle:
322 case ByteCodeInstruction::kLoadSwizzleGlobal:
323 case ByteCodeInstruction::kLoadSwizzleUniform:
324 return count;
325
326 // Pushes 'count' values, minus one for the 'address' that's consumed first
327 case ByteCodeInstruction::kLoadExtended:
328 case ByteCodeInstruction::kLoadExtendedGlobal:
329 case ByteCodeInstruction::kLoadExtendedUniform:
330 return count - 1;
331
332 // Ops that pop or store data to shrink the stack:
333 case ByteCodeInstruction::kPop:
334 case ByteCodeInstruction::kStore:
335 case ByteCodeInstruction::kStoreGlobal:
336 case ByteCodeInstruction::kWriteExternal:
337 return -1;
338
339 case ByteCodeInstruction::kPop2:
340 case ByteCodeInstruction::kStore2:
341 case ByteCodeInstruction::kStoreGlobal2:
342 case ByteCodeInstruction::kWriteExternal2:
343 return -2;
344
345 case ByteCodeInstruction::kPop3:
346 case ByteCodeInstruction::kStore3:
347 case ByteCodeInstruction::kStoreGlobal3:
348 case ByteCodeInstruction::kWriteExternal3:
349 return -3;
350
351 case ByteCodeInstruction::kPop4:
352 case ByteCodeInstruction::kStore4:
353 case ByteCodeInstruction::kStoreGlobal4:
354 case ByteCodeInstruction::kWriteExternal4:
355 return -4;
356
357 case ByteCodeInstruction::kPopN:
358 case ByteCodeInstruction::kStoreSwizzle:
359 case ByteCodeInstruction::kStoreSwizzleGlobal:
360 return -count;
361
362 // Consumes 'count' values, plus one for the 'address'
363 case ByteCodeInstruction::kStoreExtended:
364 case ByteCodeInstruction::kStoreExtendedGlobal:
365 case ByteCodeInstruction::kStoreSwizzleIndirect:
366 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal:
367 return -count - 1;
368
369 // Strange ops where the caller computes the delta for us:
370 case ByteCodeInstruction::kCallExternal:
371 case ByteCodeInstruction::kMatrixToMatrix:
372 case ByteCodeInstruction::kMatrixMultiply:
373 case ByteCodeInstruction::kReserve:
374 case ByteCodeInstruction::kReturn:
375 case ByteCodeInstruction::kScalarToMatrix:
376 case ByteCodeInstruction::kSwizzle:
377 return count;
378
379 // Miscellaneous
380
381 // kCall is net-zero. Max stack depth is adjusted in writeFunctionCall.
382 case ByteCodeInstruction::kCall: return 0;
383 case ByteCodeInstruction::kBranch: return 0;
384 case ByteCodeInstruction::kBranchIfAllFalse: return 0;
385
386 case ByteCodeInstruction::kMaskPush: return -1;
387 case ByteCodeInstruction::kMaskPop: return 0;
388 case ByteCodeInstruction::kMaskNegate: return 0;
389 case ByteCodeInstruction::kMaskBlend: return -count;
390
391 case ByteCodeInstruction::kLoopBegin: return 0;
392 case ByteCodeInstruction::kLoopNext: return 0;
393 case ByteCodeInstruction::kLoopMask: return -1;
394 case ByteCodeInstruction::kLoopEnd: return 0;
395 case ByteCodeInstruction::kLoopBreak: return 0;
396 case ByteCodeInstruction::kLoopContinue: return 0;
397
398 default:
399 ABORT("unsupported instruction %d\n", (int)inst);
400 return 0;
401 }
402}
403
404ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var) {
405 // given that we seldom have more than a couple of variables, linear search is probably the most
406 // efficient way to handle lookups
407 switch (var.fStorage) {
408 case Variable::kLocal_Storage: {
409 for (int i = fLocals.size() - 1; i >= 0; --i) {
410 if (fLocals[i] == &var) {
411 SkASSERT(fParameterCount + i <= 255);
412 return { fParameterCount + i, Storage::kLocal };
413 }
414 }
415 int result = fParameterCount + fLocals.size();
416 fLocals.push_back(&var);
417 for (int i = 0; i < SlotCount(var.fType) - 1; ++i) {
418 fLocals.push_back(nullptr);
419 }
420 SkASSERT(result <= 255);
421 return { result, Storage::kLocal };
422 }
423 case Variable::kParameter_Storage: {
424 int offset = 0;
425 for (const auto& p : fFunction->fDeclaration.fParameters) {
426 if (p == &var) {
427 SkASSERT(offset <= 255);
428 return { offset, Storage::kLocal };
429 }
430 offset += SlotCount(p->fType);
431 }
432 SkASSERT(false);
433 return Location::MakeInvalid();
434 }
435 case Variable::kGlobal_Storage: {
436 if (is_in(var)) {
437 // If you see this error, it means the program is using raw 'in' variables. You
438 // should either specialize the program (Compiler::specialize) to bake in the final
439 // values of the 'in' variables, or not use 'in' variables (maybe you meant to use
440 // 'uniform' instead?).
441 fErrors.error(var.fOffset,
442 "'in' variable is not specialized or has unsupported type");
443 return Location::MakeInvalid();
444 }
445 int offset = 0;
446 bool isUniform = is_uniform(var);
447 for (const auto& e : fProgram) {
448 if (e.fKind == ProgramElement::kVar_Kind) {
449 VarDeclarations& decl = (VarDeclarations&) e;
450 for (const auto& v : decl.fVars) {
451 const Variable* declVar = ((VarDeclaration&) *v).fVar;
452 if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
453 continue;
454 }
455 if (isUniform != is_uniform(*declVar)) {
456 continue;
457 }
458 if (declVar == &var) {
459 SkASSERT(offset <= 255);
460 return { offset, isUniform ? Storage::kUniform : Storage::kGlobal };
461 }
462 offset += SlotCount(declVar->fType);
463 }
464 }
465 }
466 SkASSERT(false);
467 return Location::MakeInvalid();
468 }
469 default:
470 SkASSERT(false);
471 return Location::MakeInvalid();
472 }
473}
474
Brian Osman1c110a02019-10-01 14:53:32 -0400475ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Expression& expr) {
Brian Osman07c117b2019-05-23 12:51:06 -0700476 switch (expr.fKind) {
477 case Expression::kFieldAccess_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400478 const FieldAccess& f = (const FieldAccess&)expr;
479 Location baseLoc = this->getLocation(*f.fBase);
Brian Osman07c117b2019-05-23 12:51:06 -0700480 int offset = 0;
481 for (int i = 0; i < f.fFieldIndex; ++i) {
482 offset += SlotCount(*f.fBase->fType.fields()[i].fType);
483 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400484 if (baseLoc.isOnStack()) {
485 if (offset != 0) {
486 this->write(ByteCodeInstruction::kPushImmediate);
487 this->write32(offset);
488 this->write(ByteCodeInstruction::kAddI);
Ben Wagner470e0ac2020-01-22 16:59:21 -0500489 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400490 return baseLoc;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500491 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400492 return baseLoc + offset;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500493 }
Ben Wagner470e0ac2020-01-22 16:59:21 -0500494 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400495 case Expression::kIndex_Kind: {
496 const IndexExpression& i = (const IndexExpression&)expr;
497 int stride = SlotCount(i.fType);
498 int length = i.fBase->fType.columns();
499 SkASSERT(length <= 255);
500 int offset = -1;
501 if (i.fIndex->isConstant()) {
502 int64_t index = i.fIndex->getConstantInt();
503 if (index < 0 || index >= length) {
504 fErrors.error(i.fIndex->fOffset, "Array index out of bounds.");
505 return Location::MakeInvalid();
506 }
507 offset = index * stride;
508 } else {
509 if (i.fIndex->hasSideEffects()) {
510 // Having a side-effect in an indexer is technically safe for an rvalue,
511 // but with lvalues we have to evaluate the indexer twice, so make it an error.
512 fErrors.error(i.fIndex->fOffset,
513 "Index expressions with side-effects not supported in byte code.");
514 return Location::MakeInvalid();
515 }
516 this->writeExpression(*i.fIndex);
517 this->write(ByteCodeInstruction::kClampIndex);
518 this->write8(length);
519 if (stride != 1) {
520 this->write(ByteCodeInstruction::kPushImmediate);
521 this->write32(stride);
522 this->write(ByteCodeInstruction::kMultiplyI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400523 }
524 }
525 Location baseLoc = this->getLocation(*i.fBase);
526
527 // Are both components known statically?
528 if (!baseLoc.isOnStack() && offset >= 0) {
529 return baseLoc + offset;
530 }
531
532 // At least one component is dynamic (and on the stack).
533
534 // If the other component is zero, we're done
535 if (baseLoc.fSlot == 0 || offset == 0) {
536 return baseLoc.makeOnStack();
537 }
538
539 // Push the non-dynamic component (if any) to the stack, then add the two
540 if (!baseLoc.isOnStack()) {
541 this->write(ByteCodeInstruction::kPushImmediate);
542 this->write32(baseLoc.fSlot);
543 }
544 if (offset >= 0) {
545 this->write(ByteCodeInstruction::kPushImmediate);
546 this->write32(offset);
547 }
548 this->write(ByteCodeInstruction::kAddI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400549 return baseLoc.makeOnStack();
550 }
Brian Osman0785db02019-05-24 14:19:11 -0400551 case Expression::kSwizzle_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400552 const Swizzle& s = (const Swizzle&)expr;
Brian Osman0785db02019-05-24 14:19:11 -0400553 SkASSERT(swizzle_is_simple(s));
Brian Osmanb08cc022020-04-02 11:38:40 -0400554 Location baseLoc = this->getLocation(*s.fBase);
555 int offset = s.fComponents[0];
556 if (baseLoc.isOnStack()) {
557 if (offset != 0) {
558 this->write(ByteCodeInstruction::kPushImmediate);
559 this->write32(offset);
560 this->write(ByteCodeInstruction::kAddI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400561 }
562 return baseLoc;
563 } else {
564 return baseLoc + offset;
565 }
Brian Osman0785db02019-05-24 14:19:11 -0400566 }
Brian Osman07c117b2019-05-23 12:51:06 -0700567 case Expression::kVariableReference_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400568 const Variable& var = ((const VariableReference&)expr).fVariable;
Brian Osman07c117b2019-05-23 12:51:06 -0700569 return this->getLocation(var);
570 }
571 default:
572 SkASSERT(false);
Brian Osmanb08cc022020-04-02 11:38:40 -0400573 return Location::MakeInvalid();
Brian Osman07c117b2019-05-23 12:51:06 -0700574 }
575}
576
Brian Osmanb08cc022020-04-02 11:38:40 -0400577void ByteCodeGenerator::write8(uint8_t b) {
578 fCode->push_back(b);
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500579}
580
Brian Osmanb08cc022020-04-02 11:38:40 -0400581void ByteCodeGenerator::write16(uint16_t i) {
582 size_t n = fCode->size();
583 fCode->resize(n+2);
584 memcpy(fCode->data() + n, &i, 2);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500585}
Ben Wagner470e0ac2020-01-22 16:59:21 -0500586
Brian Osmanb08cc022020-04-02 11:38:40 -0400587void ByteCodeGenerator::write32(uint32_t i) {
588 size_t n = fCode->size();
589 fCode->resize(n+4);
590 memcpy(fCode->data() + n, &i, 4);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500591}
592
Brian Osmanb08cc022020-04-02 11:38:40 -0400593void ByteCodeGenerator::write(ByteCodeInstruction i, int count) {
594 switch (i) {
595 case ByteCodeInstruction::kLoopBegin: this->enterLoop(); break;
596 case ByteCodeInstruction::kLoopEnd: this->exitLoop(); break;
Ethan Nicholas2329da02020-01-24 15:49:33 -0500597
Brian Osmanb08cc022020-04-02 11:38:40 -0400598 case ByteCodeInstruction::kMaskPush: this->enterCondition(); break;
599 case ByteCodeInstruction::kMaskPop:
600 case ByteCodeInstruction::kMaskBlend: this->exitCondition(); break;
601 default: /* Do nothing */ break;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500602 }
Brian Osmanab8f3842020-04-07 09:30:44 -0400603 this->write16((uint16_t)i);
Brian Osmanb08cc022020-04-02 11:38:40 -0400604 fStackCount += StackUsage(i, count);
605 fMaxStackCount = std::max(fMaxStackCount, fStackCount);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500606}
607
Brian Osmanb08cc022020-04-02 11:38:40 -0400608static ByteCodeInstruction vector_instruction(ByteCodeInstruction base, int count) {
609 SkASSERT(count >= 1 && count <= 4);
610 return ((ByteCodeInstruction) ((int) base + 1 - count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500611}
612
Brian Osmanb08cc022020-04-02 11:38:40 -0400613void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
614 ByteCodeInstruction u, ByteCodeInstruction f,
Brian Osmanab8f3842020-04-07 09:30:44 -0400615 int count) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500616 switch (type_category(type)) {
617 case TypeCategory::kSigned:
Brian Osmanb08cc022020-04-02 11:38:40 -0400618 this->write(vector_instruction(s, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500619 break;
620 case TypeCategory::kUnsigned:
Brian Osmanb08cc022020-04-02 11:38:40 -0400621 this->write(vector_instruction(u, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500622 break;
623 case TypeCategory::kFloat: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400624 if (count > 4) {
625 this->write((ByteCodeInstruction)((int)f + 1), count);
Brian Osmanab8f3842020-04-07 09:30:44 -0400626 this->write8(count);
Brian Osmanb08cc022020-04-02 11:38:40 -0400627 } else {
628 this->write(vector_instruction(f, count));
629 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500630 break;
631 }
632 default:
633 SkASSERT(false);
634 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500635}
636
Brian Osmanb08cc022020-04-02 11:38:40 -0400637bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool discard) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400638 if (b.fOperator == Token::Kind::TK_EQ) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500639 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
Brian Osmanb08cc022020-04-02 11:38:40 -0400640 this->writeExpression(*b.fRight);
641 lvalue->store(discard);
642 discard = false;
643 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500644 }
645 const Type& lType = b.fLeft->fType;
646 const Type& rType = b.fRight->fType;
647 bool lVecOrMtx = (lType.kind() == Type::kVector_Kind || lType.kind() == Type::kMatrix_Kind);
648 bool rVecOrMtx = (rType.kind() == Type::kVector_Kind || rType.kind() == Type::kMatrix_Kind);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500649 Token::Kind op;
650 std::unique_ptr<LValue> lvalue;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500651 if (is_assignment(b.fOperator)) {
652 lvalue = this->getLValue(*b.fLeft);
Brian Osmanb08cc022020-04-02 11:38:40 -0400653 lvalue->load();
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500654 op = remove_assignment(b.fOperator);
655 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400656 this->writeExpression(*b.fLeft);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500657 op = b.fOperator;
658 if (!lVecOrMtx && rVecOrMtx) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400659 for (int i = SlotCount(rType); i > 1; --i) {
660 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400661 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500662 }
663 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500664 int count = std::max(SlotCount(lType), SlotCount(rType));
Brian Osmanb08cc022020-04-02 11:38:40 -0400665 SkDEBUGCODE(TypeCategory tc = type_category(lType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500666 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400667 case Token::Kind::TK_LOGICALAND: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400668 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
669 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400670 this->write(ByteCodeInstruction::kMaskPush);
671 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500672 DeferredLocation falseLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -0400673 this->writeExpression(*b.fRight);
674 this->write(ByteCodeInstruction::kAndB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500675 falseLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -0400676 this->write(ByteCodeInstruction::kMaskPop);
677 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500678 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400679 case Token::Kind::TK_LOGICALOR: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400680 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
681 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400682 this->write(ByteCodeInstruction::kNotB);
683 this->write(ByteCodeInstruction::kMaskPush);
684 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500685 DeferredLocation falseLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -0400686 this->writeExpression(*b.fRight);
687 this->write(ByteCodeInstruction::kOrB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500688 falseLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -0400689 this->write(ByteCodeInstruction::kMaskPop);
690 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500691 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400692 case Token::Kind::TK_SHL:
693 case Token::Kind::TK_SHR: {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500694 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
695 tc == SkSL::TypeCategory::kUnsigned));
696 if (!b.fRight->isConstant()) {
697 fErrors.error(b.fRight->fOffset, "Shift amounts must be constant");
Brian Osmanb08cc022020-04-02 11:38:40 -0400698 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500699 }
700 int64_t shift = b.fRight->getConstantInt();
701 if (shift < 0 || shift > 31) {
702 fErrors.error(b.fRight->fOffset, "Shift amount out of range");
Brian Osmanb08cc022020-04-02 11:38:40 -0400703 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500704 }
705
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400706 if (op == Token::Kind::TK_SHL) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400707 this->write(ByteCodeInstruction::kShiftLeft);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500708 } else {
709 this->write(type_category(lType) == TypeCategory::kSigned
Brian Osmanb08cc022020-04-02 11:38:40 -0400710 ? ByteCodeInstruction::kShiftRightS
711 : ByteCodeInstruction::kShiftRightU);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500712 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400713 this->write8(shift);
714 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500715 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500716
717 default:
718 break;
719 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400720 this->writeExpression(*b.fRight);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500721 if (lVecOrMtx && !rVecOrMtx) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400722 for (int i = SlotCount(lType); i > 1; --i) {
723 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400724 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500725 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400726 // Special case for M*V, V*M, M*M (but not V*V!)
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400727 if (op == Token::Kind::TK_STAR && lVecOrMtx && rVecOrMtx &&
Brian Osmanb08cc022020-04-02 11:38:40 -0400728 !(lType.kind() == Type::kVector_Kind && rType.kind() == Type::kVector_Kind)) {
729 this->write(ByteCodeInstruction::kMatrixMultiply,
730 SlotCount(b.fType) - (SlotCount(lType) + SlotCount(rType)));
731 int rCols = rType.columns(),
732 rRows = rType.rows(),
733 lCols = lType.columns(),
734 lRows = lType.rows();
735 // M*V treats the vector as a column
736 if (rType.kind() == Type::kVector_Kind) {
737 std::swap(rCols, rRows);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500738 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400739 SkASSERT(lCols == rRows);
740 SkASSERT(SlotCount(b.fType) == lRows * rCols);
741 this->write8(lCols);
742 this->write8(lRows);
743 this->write8(rCols);
744 } else {
745 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400746 case Token::Kind::TK_EQEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400747 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareIEQ,
748 ByteCodeInstruction::kCompareIEQ,
749 ByteCodeInstruction::kCompareFEQ,
750 count);
751 // Collapse to a single bool
752 for (int i = count; i > 1; --i) {
753 this->write(ByteCodeInstruction::kAndB);
754 }
755 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400756 case Token::Kind::TK_GT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400757 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGT,
758 ByteCodeInstruction::kCompareUGT,
759 ByteCodeInstruction::kCompareFGT,
760 count);
761 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400762 case Token::Kind::TK_GTEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400763 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGTEQ,
764 ByteCodeInstruction::kCompareUGTEQ,
765 ByteCodeInstruction::kCompareFGTEQ,
766 count);
767 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400768 case Token::Kind::TK_LT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400769 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLT,
770 ByteCodeInstruction::kCompareULT,
771 ByteCodeInstruction::kCompareFLT,
772 count);
773 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400774 case Token::Kind::TK_LTEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400775 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLTEQ,
776 ByteCodeInstruction::kCompareULTEQ,
777 ByteCodeInstruction::kCompareFLTEQ,
778 count);
779 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400780 case Token::Kind::TK_MINUS:
Brian Osmanb08cc022020-04-02 11:38:40 -0400781 this->writeTypedInstruction(lType, ByteCodeInstruction::kSubtractI,
782 ByteCodeInstruction::kSubtractI,
783 ByteCodeInstruction::kSubtractF,
784 count);
785 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400786 case Token::Kind::TK_NEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400787 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareINEQ,
788 ByteCodeInstruction::kCompareINEQ,
789 ByteCodeInstruction::kCompareFNEQ,
790 count);
791 // Collapse to a single bool
792 for (int i = count; i > 1; --i) {
793 this->write(ByteCodeInstruction::kOrB);
794 }
795 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400796 case Token::Kind::TK_PERCENT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400797 this->writeTypedInstruction(lType, ByteCodeInstruction::kRemainderS,
798 ByteCodeInstruction::kRemainderU,
799 ByteCodeInstruction::kRemainderF,
800 count);
801 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400802 case Token::Kind::TK_PLUS:
Brian Osmanb08cc022020-04-02 11:38:40 -0400803 this->writeTypedInstruction(lType, ByteCodeInstruction::kAddI,
804 ByteCodeInstruction::kAddI,
805 ByteCodeInstruction::kAddF,
806 count);
807 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400808 case Token::Kind::TK_SLASH:
Brian Osmanb08cc022020-04-02 11:38:40 -0400809 this->writeTypedInstruction(lType, ByteCodeInstruction::kDivideS,
810 ByteCodeInstruction::kDivideU,
811 ByteCodeInstruction::kDivideF,
812 count);
813 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400814 case Token::Kind::TK_STAR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400815 this->writeTypedInstruction(lType, ByteCodeInstruction::kMultiplyI,
816 ByteCodeInstruction::kMultiplyI,
817 ByteCodeInstruction::kMultiplyF,
818 count);
819 break;
820
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400821 case Token::Kind::TK_LOGICALXOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400822 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
823 this->write(ByteCodeInstruction::kXorB);
824 break;
825
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400826 case Token::Kind::TK_BITWISEAND:
Brian Osmanb08cc022020-04-02 11:38:40 -0400827 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
828 tc == SkSL::TypeCategory::kUnsigned));
829 this->write(ByteCodeInstruction::kAndB);
830 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400831 case Token::Kind::TK_BITWISEOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400832 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
833 tc == SkSL::TypeCategory::kUnsigned));
834 this->write(ByteCodeInstruction::kOrB);
835 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400836 case Token::Kind::TK_BITWISEXOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400837 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
838 tc == SkSL::TypeCategory::kUnsigned));
839 this->write(ByteCodeInstruction::kXorB);
840 break;
841
842 default:
843 fErrors.error(b.fOffset, SkSL::String::printf("Unsupported binary operator '%s'",
844 Compiler::OperatorName(op)));
845 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500846 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500847 }
848 if (lvalue) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400849 lvalue->store(discard);
850 discard = false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500851 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400852 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500853}
854
Brian Osmanb08cc022020-04-02 11:38:40 -0400855void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
856 this->write(ByteCodeInstruction::kPushImmediate);
857 this->write32(b.fValue ? ~0 : 0);
858}
859
860void ByteCodeGenerator::writeConstructor(const Constructor& c) {
861 for (const auto& arg : c.fArguments) {
862 this->writeExpression(*arg);
863 }
864 if (c.fArguments.size() == 1) {
865 const Type& inType = c.fArguments[0]->fType;
866 const Type& outType = c.fType;
867 TypeCategory inCategory = type_category(inType);
868 TypeCategory outCategory = type_category(outType);
869 int inCount = SlotCount(inType);
870 int outCount = SlotCount(outType);
871 if (inCategory != outCategory) {
872 SkASSERT(inCount == outCount);
873 if (inCategory == TypeCategory::kFloat) {
874 SkASSERT(outCategory == TypeCategory::kSigned ||
875 outCategory == TypeCategory::kUnsigned);
876 this->write(vector_instruction(ByteCodeInstruction::kConvertFtoI, outCount));
877 } else if (outCategory == TypeCategory::kFloat) {
878 if (inCategory == TypeCategory::kSigned) {
879 this->write(vector_instruction(ByteCodeInstruction::kConvertStoF, outCount));
880 } else {
881 SkASSERT(inCategory == TypeCategory::kUnsigned);
882 this->write(vector_instruction(ByteCodeInstruction::kConvertUtoF, outCount));
883 }
884 } else {
885 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500886 }
887 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400888 if (inType.kind() == Type::kMatrix_Kind && outType.kind() == Type::kMatrix_Kind) {
889 this->write(ByteCodeInstruction::kMatrixToMatrix,
890 SlotCount(outType) - SlotCount(inType));
891 this->write8(inType.columns());
892 this->write8(inType.rows());
893 this->write8(outType.columns());
894 this->write8(outType.rows());
895 } else if (inCount != outCount) {
896 SkASSERT(inCount == 1);
897 if (outType.kind() == Type::kMatrix_Kind) {
898 this->write(ByteCodeInstruction::kScalarToMatrix, SlotCount(outType) - 1);
899 this->write8(outType.columns());
900 this->write8(outType.rows());
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500901 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400902 SkASSERT(outType.kind() == Type::kVector_Kind);
903 for (; inCount != outCount; ++inCount) {
904 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400905 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500906 }
907 }
908 }
909}
910
Brian Osmanb08cc022020-04-02 11:38:40 -0400911void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500912 int argumentCount = 0;
913 for (const auto& arg : f.fArguments) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400914 this->writeExpression(*arg);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500915 argumentCount += SlotCount(arg->fType);
916 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400917 this->write(ByteCodeInstruction::kCallExternal, SlotCount(f.fType) - argumentCount);
918 SkASSERT(argumentCount <= 255);
919 this->write8(argumentCount);
920 this->write8(SlotCount(f.fType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500921 int index = fOutput->fExternalValues.size();
922 fOutput->fExternalValues.push_back(f.fFunction);
923 SkASSERT(index <= 255);
Brian Osmanb08cc022020-04-02 11:38:40 -0400924 this->write8(index);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500925}
926
Brian Osmanb08cc022020-04-02 11:38:40 -0400927void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
928 int count = SlotCount(e.fValue->type());
929 this->write(vector_instruction(ByteCodeInstruction::kReadExternal, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500930 int index = fOutput->fExternalValues.size();
931 fOutput->fExternalValues.push_back(e.fValue);
932 SkASSERT(index <= 255);
Brian Osmanb08cc022020-04-02 11:38:40 -0400933 this->write8(index);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500934}
935
Brian Osmanb08cc022020-04-02 11:38:40 -0400936void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
937 Location location = this->getLocation(expr);
938 int count = SlotCount(expr.fType);
Brian Osmanefb08402020-04-13 16:30:44 -0400939 if (count == 0) {
940 return;
941 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400942 if (location.isOnStack() || count > 4) {
943 if (!location.isOnStack()) {
944 this->write(ByteCodeInstruction::kPushImmediate);
945 this->write32(location.fSlot);
946 }
947 this->write(location.selectLoad(ByteCodeInstruction::kLoadExtended,
948 ByteCodeInstruction::kLoadExtendedGlobal,
949 ByteCodeInstruction::kLoadExtendedUniform),
950 count);
951 this->write8(count);
952 } else {
953 this->write(vector_instruction(location.selectLoad(ByteCodeInstruction::kLoad,
954 ByteCodeInstruction::kLoadGlobal,
955 ByteCodeInstruction::kLoadUniform),
956 count));
Brian Osmanb08cc022020-04-02 11:38:40 -0400957 this->write8(location.fSlot);
958 }
959}
960
961static inline uint32_t float_to_bits(float x) {
962 uint32_t u;
963 memcpy(&u, &x, sizeof(uint32_t));
964 return u;
965}
966
967void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
968 this->write(ByteCodeInstruction::kPushImmediate);
969 this->write32(float_to_bits(f.fValue));
970}
971
972void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
973 auto found = fIntrinsics.find(c.fFunction.fName);
974 if (found == fIntrinsics.end()) {
975 fErrors.error(c.fOffset, String::printf("Unsupported intrinsic: '%s'",
976 String(c.fFunction.fName).c_str()));
977 return;
978 }
979 int count = SlotCount(c.fArguments[0]->fType);
980 if (found->second.fIsSpecial) {
981 SpecialIntrinsic special = found->second.fValue.fSpecial;
982 switch (special) {
Brian Osman15c98cb2020-02-27 18:36:57 +0000983 case SpecialIntrinsic::kDot: {
984 SkASSERT(c.fArguments.size() == 2);
Brian Osmanb08cc022020-04-02 11:38:40 -0400985 SkASSERT(count == SlotCount(c.fArguments[1]->fType));
986 this->write(vector_instruction(ByteCodeInstruction::kMultiplyF, count));
Brian Osmanb08cc022020-04-02 11:38:40 -0400987 for (int i = count; i > 1; --i) {
988 this->write(ByteCodeInstruction::kAddF);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500989 }
990 break;
991 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400992 default:
993 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500994 }
995 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400996 switch (found->second.fValue.fInstruction) {
997 case ByteCodeInstruction::kCos:
998 case ByteCodeInstruction::kSin:
Brian Osmanb08cc022020-04-02 11:38:40 -0400999 case ByteCodeInstruction::kSqrt:
Brian Osmanab8f3842020-04-07 09:30:44 -04001000 case ByteCodeInstruction::kTan:
Brian Osmanb08cc022020-04-02 11:38:40 -04001001 SkASSERT(c.fArguments.size() > 0);
1002 this->write(vector_instruction(found->second.fValue.fInstruction, count));
1003 break;
1004 case ByteCodeInstruction::kInverse2x2: {
1005 SkASSERT(c.fArguments.size() > 0);
1006 auto op = ByteCodeInstruction::kInverse2x2;
1007 switch (count) {
1008 case 4: break; // float2x2
1009 case 9: op = ByteCodeInstruction::kInverse3x3; break;
1010 case 16: op = ByteCodeInstruction::kInverse4x4; break;
1011 default: SkASSERT(false);
1012 }
1013 this->write(op);
1014 break;
Brian Osman15c98cb2020-02-27 18:36:57 +00001015 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001016 default:
1017 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001018 }
1019 }
1020}
1021
Brian Osmanb08cc022020-04-02 11:38:40 -04001022void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001023 // Find the index of the function we're calling. We explicitly do not allow calls to functions
1024 // before they're defined. This is an easy-to-understand rule that prevents recursion.
Brian Osmanb08cc022020-04-02 11:38:40 -04001025 int idx = -1;
1026 for (size_t i = 0; i < fFunctions.size(); ++i) {
1027 if (f.fFunction.matches(fFunctions[i]->fDeclaration)) {
1028 idx = i;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001029 break;
1030 }
1031 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001032 if (idx == -1) {
1033 for (const auto& arg : f.fArguments) {
1034 this->writeExpression(*arg);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001035 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001036 this->writeIntrinsicCall(f);
1037 return;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001038 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001039
1040
1041 if (idx > 255) {
1042 fErrors.error(f.fOffset, "Function count limit exceeded");
1043 return;
1044 } else if (idx >= (int) fFunctions.size()) {
1045 fErrors.error(f.fOffset, "Call to undefined function");
1046 return;
1047 }
1048
1049 // We may need to deal with out parameters, so the sequence is tricky
1050 if (int returnCount = SlotCount(f.fType)) {
1051 this->write(ByteCodeInstruction::kReserve, returnCount);
1052 this->write8(returnCount);
1053 }
1054
1055 int argCount = f.fArguments.size();
1056 std::vector<std::unique_ptr<LValue>> lvalues;
1057 for (int i = 0; i < argCount; ++i) {
1058 const auto& param = f.fFunction.fParameters[i];
1059 const auto& arg = f.fArguments[i];
1060 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1061 lvalues.emplace_back(this->getLValue(*arg));
1062 lvalues.back()->load();
1063 } else {
1064 this->writeExpression(*arg);
1065 }
1066 }
1067
1068 // The space used by the call is based on the callee, but it also unwinds all of that before
1069 // we continue execution. We adjust our max stack depths below.
1070 this->write(ByteCodeInstruction::kCall);
1071 this->write8(idx);
1072
1073 const ByteCodeFunction* callee = fOutput->fFunctions[idx].get();
1074 fMaxLoopCount = std::max(fMaxLoopCount, fLoopCount + callee->fLoopCount);
1075 fMaxConditionCount = std::max(fMaxConditionCount, fConditionCount + callee->fConditionCount);
1076 fMaxStackCount = std::max(fMaxStackCount, fStackCount + callee->fLocalCount
1077 + callee->fStackCount);
1078
1079 // After the called function returns, the stack will still contain our arguments. We have to
1080 // pop them (storing any out parameters back to their lvalues as we go). We glob together slot
1081 // counts for all parameters that aren't out-params, so we can pop them in one big chunk.
1082 int popCount = 0;
1083 auto pop = [&]() {
1084 if (popCount > 4) {
1085 this->write(ByteCodeInstruction::kPopN, popCount);
1086 this->write8(popCount);
1087 } else if (popCount > 0) {
1088 this->write(vector_instruction(ByteCodeInstruction::kPop, popCount));
1089 }
1090 popCount = 0;
1091 };
1092
1093 for (int i = argCount - 1; i >= 0; --i) {
1094 const auto& param = f.fFunction.fParameters[i];
1095 const auto& arg = f.fArguments[i];
1096 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1097 pop();
1098 lvalues.back()->store(true);
1099 lvalues.pop_back();
1100 } else {
1101 popCount += SlotCount(arg->fType);
1102 }
1103 }
1104 pop();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001105}
1106
Brian Osmanb08cc022020-04-02 11:38:40 -04001107void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
1108 this->write(ByteCodeInstruction::kPushImmediate);
1109 this->write32(i.fValue);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001110}
1111
Brian Osmanb08cc022020-04-02 11:38:40 -04001112void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
1113 // not yet implemented
1114 abort();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001115}
1116
Brian Osmanb08cc022020-04-02 11:38:40 -04001117bool ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p, bool discard) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001118 switch (p.fOperator) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001119 case Token::Kind::TK_PLUSPLUS: // fall through
1120 case Token::Kind::TK_MINUSMINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001121 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1122 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
1123 lvalue->load();
1124 this->write(ByteCodeInstruction::kPushImmediate);
1125 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001126 if (p.fOperator == Token::Kind::TK_PLUSPLUS) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001127 this->writeTypedInstruction(p.fType,
1128 ByteCodeInstruction::kAddI,
1129 ByteCodeInstruction::kAddI,
1130 ByteCodeInstruction::kAddF,
1131 1);
1132 } else {
1133 this->writeTypedInstruction(p.fType,
1134 ByteCodeInstruction::kSubtractI,
1135 ByteCodeInstruction::kSubtractI,
1136 ByteCodeInstruction::kSubtractF,
1137 1);
1138 }
1139 lvalue->store(discard);
1140 discard = false;
1141 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001142 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001143 case Token::Kind::TK_MINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001144 this->writeExpression(*p.fOperand);
1145 this->writeTypedInstruction(p.fType,
1146 ByteCodeInstruction::kNegateI,
1147 ByteCodeInstruction::kNegateI,
1148 ByteCodeInstruction::kNegateF,
Brian Osmanab8f3842020-04-07 09:30:44 -04001149 SlotCount(p.fOperand->fType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001150 break;
1151 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001152 case Token::Kind::TK_LOGICALNOT:
1153 case Token::Kind::TK_BITWISENOT: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001154 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1155 SkDEBUGCODE(TypeCategory tc = type_category(p.fOperand->fType));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001156 SkASSERT((p.fOperator == Token::Kind::TK_LOGICALNOT && tc == TypeCategory::kBool) ||
1157 (p.fOperator == Token::Kind::TK_BITWISENOT && (tc == TypeCategory::kSigned ||
Brian Osmanb08cc022020-04-02 11:38:40 -04001158 tc == TypeCategory::kUnsigned)));
1159 this->writeExpression(*p.fOperand);
1160 this->write(ByteCodeInstruction::kNotB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001161 break;
1162 }
1163 default:
1164 SkASSERT(false);
1165 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001166 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001167}
1168
Brian Osmanb08cc022020-04-02 11:38:40 -04001169bool ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p, bool discard) {
1170 switch (p.fOperator) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001171 case Token::Kind::TK_PLUSPLUS: // fall through
1172 case Token::Kind::TK_MINUSMINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001173 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1174 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
1175 lvalue->load();
1176 // If we're not supposed to discard the result, then make a copy *before* the +/-
1177 if (!discard) {
1178 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -04001179 }
1180 this->write(ByteCodeInstruction::kPushImmediate);
1181 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001182 if (p.fOperator == Token::Kind::TK_PLUSPLUS) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001183 this->writeTypedInstruction(p.fType,
1184 ByteCodeInstruction::kAddI,
1185 ByteCodeInstruction::kAddI,
1186 ByteCodeInstruction::kAddF,
1187 1);
1188 } else {
1189 this->writeTypedInstruction(p.fType,
1190 ByteCodeInstruction::kSubtractI,
1191 ByteCodeInstruction::kSubtractI,
1192 ByteCodeInstruction::kSubtractF,
1193 1);
1194 }
1195 // Always consume the result as part of the store
1196 lvalue->store(true);
1197 discard = false;
1198 break;
1199 }
1200 default:
1201 SkASSERT(false);
1202 }
1203 return discard;
1204}
1205
1206void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001207 if (swizzle_is_simple(s)) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001208 this->writeVariableExpression(s);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001209 return;
1210 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001211
1212 switch (s.fBase->fKind) {
1213 case Expression::kVariableReference_Kind: {
1214 Location location = this->getLocation(*s.fBase);
1215 this->write(location.selectLoad(ByteCodeInstruction::kLoadSwizzle,
1216 ByteCodeInstruction::kLoadSwizzleGlobal,
1217 ByteCodeInstruction::kLoadSwizzleUniform),
1218 s.fComponents.size());
1219 this->write8(location.fSlot);
1220 this->write8(s.fComponents.size());
1221 for (int c : s.fComponents) {
1222 this->write8(c);
1223 }
1224 break;
1225 }
1226 default:
1227 this->writeExpression(*s.fBase);
1228 this->write(ByteCodeInstruction::kSwizzle,
1229 s.fComponents.size() - s.fBase->fType.columns());
1230 this->write8(s.fBase->fType.columns());
1231 this->write8(s.fComponents.size());
1232 for (int c : s.fComponents) {
1233 this->write8(c);
1234 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001235 }
1236}
1237
Brian Osmanb08cc022020-04-02 11:38:40 -04001238void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001239 int count = SlotCount(t.fType);
1240 SkASSERT(count == SlotCount(t.fIfTrue->fType));
1241 SkASSERT(count == SlotCount(t.fIfFalse->fType));
1242
Brian Osmanb08cc022020-04-02 11:38:40 -04001243 this->writeExpression(*t.fTest);
1244 this->write(ByteCodeInstruction::kMaskPush);
1245 this->writeExpression(*t.fIfTrue);
1246 this->write(ByteCodeInstruction::kMaskNegate);
1247 this->writeExpression(*t.fIfFalse);
1248 this->write(ByteCodeInstruction::kMaskBlend, count);
1249 this->write8(count);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001250}
1251
Brian Osmanb08cc022020-04-02 11:38:40 -04001252void ByteCodeGenerator::writeExpression(const Expression& e, bool discard) {
1253 switch (e.fKind) {
1254 case Expression::kBinary_Kind:
1255 discard = this->writeBinaryExpression((BinaryExpression&) e, discard);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001256 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001257 case Expression::kBoolLiteral_Kind:
1258 this->writeBoolLiteral((BoolLiteral&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001259 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001260 case Expression::kConstructor_Kind:
1261 this->writeConstructor((Constructor&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001262 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001263 case Expression::kExternalFunctionCall_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001264 this->writeExternalFunctionCall((ExternalFunctionCall&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001265 break;
1266 case Expression::kExternalValue_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001267 this->writeExternalValue((ExternalValueReference&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001268 break;
1269 case Expression::kFieldAccess_Kind:
1270 case Expression::kIndex_Kind:
1271 case Expression::kVariableReference_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001272 this->writeVariableExpression(e);
1273 break;
1274 case Expression::kFloatLiteral_Kind:
1275 this->writeFloatLiteral((FloatLiteral&) e);
1276 break;
1277 case Expression::kFunctionCall_Kind:
1278 this->writeFunctionCall((FunctionCall&) e);
1279 break;
1280 case Expression::kIntLiteral_Kind:
1281 this->writeIntLiteral((IntLiteral&) e);
1282 break;
1283 case Expression::kNullLiteral_Kind:
1284 this->writeNullLiteral((NullLiteral&) e);
1285 break;
1286 case Expression::kPrefix_Kind:
1287 discard = this->writePrefixExpression((PrefixExpression&) e, discard);
1288 break;
1289 case Expression::kPostfix_Kind:
1290 discard = this->writePostfixExpression((PostfixExpression&) e, discard);
1291 break;
1292 case Expression::kSwizzle_Kind:
1293 this->writeSwizzle((Swizzle&) e);
1294 break;
1295 case Expression::kTernary_Kind:
1296 this->writeTernaryExpression((TernaryExpression&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001297 break;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001298 default:
1299#ifdef SK_DEBUG
Brian Osmanb08cc022020-04-02 11:38:40 -04001300 printf("unsupported expression %s\n", e.description().c_str());
Ben Wagner470e0ac2020-01-22 16:59:21 -05001301#endif
Brian Osmanb08cc022020-04-02 11:38:40 -04001302 SkASSERT(false);
1303 }
1304 if (discard) {
1305 int count = SlotCount(e.fType);
1306 if (count > 4) {
1307 this->write(ByteCodeInstruction::kPopN, count);
1308 this->write8(count);
1309 } else if (count != 0) {
1310 this->write(vector_instruction(ByteCodeInstruction::kPop, count));
1311 }
1312 discard = false;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001313 }
Ethan Nicholas7deb1c22020-01-22 10:31:55 -05001314}
1315
Brian Osmanb08cc022020-04-02 11:38:40 -04001316class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
1317public:
1318 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
1319 : INHERITED(*generator)
1320 , fCount(ByteCodeGenerator::SlotCount(value.type()))
1321 , fIndex(index) {}
1322
1323 void load() override {
1324 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001325 fGenerator.write8(fIndex);
1326 }
1327
1328 void store(bool discard) override {
1329 if (!discard) {
1330 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001331 }
1332 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001333 fGenerator.write8(fIndex);
1334 }
1335
1336private:
1337 typedef LValue INHERITED;
1338
1339 int fCount;
1340
1341 int fIndex;
1342};
1343
1344class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
1345public:
1346 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
1347 : INHERITED(*generator)
1348 , fSwizzle(swizzle) {}
1349
1350 void load() override {
1351 fGenerator.writeSwizzle(fSwizzle);
1352 }
1353
1354 void store(bool discard) override {
1355 int count = fSwizzle.fComponents.size();
1356 if (!discard) {
1357 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001358 }
1359 ByteCodeGenerator::Location location = fGenerator.getLocation(*fSwizzle.fBase);
1360 if (location.isOnStack()) {
1361 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreSwizzleIndirect,
1362 ByteCodeInstruction::kStoreSwizzleIndirectGlobal),
1363 count);
1364 } else {
1365 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreSwizzle,
1366 ByteCodeInstruction::kStoreSwizzleGlobal),
1367 count);
1368 fGenerator.write8(location.fSlot);
1369 }
1370 fGenerator.write8(count);
1371 for (int c : fSwizzle.fComponents) {
1372 fGenerator.write8(c);
1373 }
1374 }
1375
1376private:
1377 const Swizzle& fSwizzle;
1378
1379 typedef LValue INHERITED;
1380};
1381
1382class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
1383public:
1384 ByteCodeExpressionLValue(ByteCodeGenerator* generator, const Expression& expr)
1385 : INHERITED(*generator)
1386 , fExpression(expr) {}
1387
1388 void load() override {
1389 fGenerator.writeVariableExpression(fExpression);
1390 }
1391
1392 void store(bool discard) override {
1393 int count = ByteCodeGenerator::SlotCount(fExpression.fType);
1394 if (!discard) {
1395 if (count > 4) {
1396 fGenerator.write(ByteCodeInstruction::kDupN, count);
1397 fGenerator.write8(count);
1398 } else {
1399 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001400 }
1401 }
1402 ByteCodeGenerator::Location location = fGenerator.getLocation(fExpression);
1403 if (location.isOnStack() || count > 4) {
1404 if (!location.isOnStack()) {
1405 fGenerator.write(ByteCodeInstruction::kPushImmediate);
1406 fGenerator.write32(location.fSlot);
1407 }
1408 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreExtended,
1409 ByteCodeInstruction::kStoreExtendedGlobal),
1410 count);
1411 fGenerator.write8(count);
1412 } else {
1413 fGenerator.write(
1414 vector_instruction(location.selectStore(ByteCodeInstruction::kStore,
1415 ByteCodeInstruction::kStoreGlobal),
1416 count));
1417 fGenerator.write8(location.fSlot);
1418 }
1419 }
1420
1421private:
1422 typedef LValue INHERITED;
1423
1424 const Expression& fExpression;
1425};
1426
1427std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
1428 switch (e.fKind) {
1429 case Expression::kExternalValue_Kind: {
1430 ExternalValue* value = ((ExternalValueReference&) e).fValue;
1431 int index = fOutput->fExternalValues.size();
1432 fOutput->fExternalValues.push_back(value);
1433 SkASSERT(index <= 255);
1434 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
1435 }
1436 case Expression::kFieldAccess_Kind:
1437 case Expression::kIndex_Kind:
1438 case Expression::kVariableReference_Kind:
1439 return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
1440 case Expression::kSwizzle_Kind: {
1441 const Swizzle& s = (const Swizzle&) e;
1442 return swizzle_is_simple(s)
1443 ? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e))
1444 : std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s));
1445 }
1446 case Expression::kTernary_Kind:
1447 default:
1448#ifdef SK_DEBUG
1449 ABORT("unsupported lvalue %s\n", e.description().c_str());
1450#endif
1451 return nullptr;
1452 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001453}
1454
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001455void ByteCodeGenerator::writeBlock(const Block& b) {
1456 for (const auto& s : b.fStatements) {
1457 this->writeStatement(*s);
1458 }
1459}
1460
Brian Osmanb08cc022020-04-02 11:38:40 -04001461void ByteCodeGenerator::setBreakTargets() {
1462 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
1463 for (DeferredLocation& b : breaks) {
1464 b.set();
1465 }
1466 fBreakTargets.pop();
1467}
1468
1469void ByteCodeGenerator::setContinueTargets() {
1470 std::vector<DeferredLocation>& continues = fContinueTargets.top();
1471 for (DeferredLocation& c : continues) {
1472 c.set();
1473 }
1474 fContinueTargets.pop();
1475}
1476
1477void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
1478 // TODO: Include BranchIfAllFalse to top-most LoopNext
1479 this->write(ByteCodeInstruction::kLoopBreak);
1480}
1481
1482void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
1483 // TODO: Include BranchIfAllFalse to top-most LoopNext
1484 this->write(ByteCodeInstruction::kLoopContinue);
1485}
1486
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001487void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001488 this->write(ByteCodeInstruction::kLoopBegin);
1489 size_t start = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001490 this->writeStatement(*d.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001491 this->write(ByteCodeInstruction::kLoopNext);
1492 this->writeExpression(*d.fTest);
1493 this->write(ByteCodeInstruction::kLoopMask);
1494 // TODO: Could shorten this with kBranchIfAnyTrue
1495 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001496 DeferredLocation endLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -04001497 this->write(ByteCodeInstruction::kBranch);
1498 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001499 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001500 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001501}
1502
1503void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001504 fContinueTargets.emplace();
1505 fBreakTargets.emplace();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001506 if (f.fInitializer) {
1507 this->writeStatement(*f.fInitializer);
1508 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001509 this->write(ByteCodeInstruction::kLoopBegin);
1510 size_t start = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001511 if (f.fTest) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001512 this->writeExpression(*f.fTest);
1513 this->write(ByteCodeInstruction::kLoopMask);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001514 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001515 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001516 DeferredLocation endLocation(this);
1517 this->writeStatement(*f.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001518 this->write(ByteCodeInstruction::kLoopNext);
Brian Osman569f12f2019-06-13 11:23:57 -04001519 if (f.fNext) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001520 this->writeExpression(*f.fNext, true);
Brian Osman569f12f2019-06-13 11:23:57 -04001521 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001522 this->write(ByteCodeInstruction::kBranch);
1523 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001524 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001525 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001526}
1527
1528void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001529 this->writeExpression(*i.fTest);
1530 this->write(ByteCodeInstruction::kMaskPush);
1531 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001532 DeferredLocation falseLocation(this);
1533 this->writeStatement(*i.fIfTrue);
1534 falseLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001535 if (i.fIfFalse) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001536 this->write(ByteCodeInstruction::kMaskNegate);
1537 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001538 DeferredLocation endLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001539 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -05001540 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001541 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001542 this->write(ByteCodeInstruction::kMaskPop);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001543}
1544
Brian Osmanb08cc022020-04-02 11:38:40 -04001545void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
1546 if (fLoopCount || fConditionCount) {
Brian Osman4a47da72019-07-12 11:30:32 -04001547 fErrors.error(r.fOffset, "return not allowed inside conditional or loop");
1548 return;
1549 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001550 int count = SlotCount(r.fExpression->fType);
1551 this->writeExpression(*r.fExpression);
1552
1553 // Technically, the kReturn also pops fOutput->fLocalCount values from the stack, too, but we
1554 // haven't counted pushing those (they're outside the scope of our stack tracking). Instead,
1555 // we account for those in writeFunction().
1556
1557 // This is all fine because we don't allow conditional returns, so we only return once anyway.
1558 this->write(ByteCodeInstruction::kReturn, -count);
1559 this->write8(count);
1560}
1561
1562void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
1563 // not yet implemented
1564 abort();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001565}
1566
1567void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1568 for (const auto& declStatement : v.fVars) {
1569 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
Brian Osmanb08cc022020-04-02 11:38:40 -04001570 // we need to grab the location even if we don't use it, to ensure it has been allocated
1571 Location location = this->getLocation(*decl.fVar);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001572 if (decl.fValue) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001573 this->writeExpression(*decl.fValue);
1574 int count = SlotCount(decl.fValue->fType);
1575 if (count > 4) {
1576 this->write(ByteCodeInstruction::kPushImmediate);
1577 this->write32(location.fSlot);
1578 this->write(ByteCodeInstruction::kStoreExtended, count);
1579 this->write8(count);
1580 } else {
1581 this->write(vector_instruction(ByteCodeInstruction::kStore, count));
1582 this->write8(location.fSlot);
1583 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001584 }
1585 }
1586}
1587
1588void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001589 this->write(ByteCodeInstruction::kLoopBegin);
1590 size_t cond = fCode->size();
1591 this->writeExpression(*w.fTest);
1592 this->write(ByteCodeInstruction::kLoopMask);
1593 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001594 DeferredLocation endLocation(this);
1595 this->writeStatement(*w.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001596 this->write(ByteCodeInstruction::kLoopNext);
1597 this->write(ByteCodeInstruction::kBranch);
1598 this->write16(cond);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001599 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001600 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001601}
1602
1603void ByteCodeGenerator::writeStatement(const Statement& s) {
1604 switch (s.fKind) {
1605 case Statement::kBlock_Kind:
1606 this->writeBlock((Block&) s);
1607 break;
1608 case Statement::kBreak_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001609 this->writeBreakStatement((BreakStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001610 break;
1611 case Statement::kContinue_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001612 this->writeContinueStatement((ContinueStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001613 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001614 case Statement::kDiscard_Kind:
1615 // not yet implemented
1616 abort();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001617 case Statement::kDo_Kind:
1618 this->writeDoStatement((DoStatement&) s);
1619 break;
Brian Osman3e29f1d2019-05-28 09:35:05 -04001620 case Statement::kExpression_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001621 this->writeExpression(*((ExpressionStatement&) s).fExpression, true);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001622 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001623 case Statement::kFor_Kind:
1624 this->writeForStatement((ForStatement&) s);
1625 break;
1626 case Statement::kIf_Kind:
1627 this->writeIfStatement((IfStatement&) s);
1628 break;
1629 case Statement::kNop_Kind:
1630 break;
1631 case Statement::kReturn_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001632 this->writeReturnStatement((ReturnStatement&) s);
1633 break;
1634 case Statement::kSwitch_Kind:
1635 this->writeSwitchStatement((SwitchStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001636 break;
1637 case Statement::kVarDeclarations_Kind:
1638 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1639 break;
1640 case Statement::kWhile_Kind:
1641 this->writeWhileStatement((WhileStatement&) s);
1642 break;
1643 default:
Brian Osmanb08cc022020-04-02 11:38:40 -04001644 SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001645 }
1646}
1647
Brian Osmanb08cc022020-04-02 11:38:40 -04001648ByteCodeFunction::ByteCodeFunction(const FunctionDeclaration* declaration)
1649 : fName(declaration->fName) {
Brian Osman80164412019-06-07 13:00:23 -04001650 fParameterCount = 0;
Brian Osmanb08cc022020-04-02 11:38:40 -04001651 for (const auto& p : declaration->fParameters) {
1652 int slots = ByteCodeGenerator::SlotCount(p->fType);
1653 fParameters.push_back({ slots, (bool)(p->fModifiers.fFlags & Modifiers::kOut_Flag) });
1654 fParameterCount += slots;
Brian Osman80164412019-06-07 13:00:23 -04001655 }
1656}
1657
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001658}