1/*
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
8#include "src/sksl/SkSLByteCodeGenerator.h"
9
10#include <algorithm>
11
12namespace SkSL {
13
14static 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)
42 : INHERITED(program, errors, nullptr)
43 , fContext(*context)
44 , fOutput(output)
45 , fIntrinsics {
46 { "cos", ByteCodeInstruction::kCos },
47 { "dot", SpecialIntrinsic::kDot },
48 { "inverse", ByteCodeInstruction::kInverse2x2 },
49 { "sin", ByteCodeInstruction::kSin },
50 { "sqrt", ByteCodeInstruction::kSqrt },
51 { "tan", ByteCodeInstruction::kTan },
52 } {}
53
54
55int ByteCodeGenerator::SlotCount(const Type& type) {
56 if (type.kind() == Type::kOther_Kind) {
57 return 0;
58 } else if (type.kind() == Type::kStruct_Kind) {
59 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 }
74}
75
76static inline bool is_uniform(const SkSL::Variable& var) {
77 return var.fModifiers.fFlags & Modifiers::kUniform_Flag;
78}
79
80static inline bool is_in(const SkSL::Variable& var) {
81 return var.fModifiers.fFlags & Modifiers::kIn_Flag;
82}
83
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);
90 }
91 } 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));
94 }
95 } 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;
113 }
114 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);
125 }
126 }
127 break;
128 }
129 default:
130 ; // ignore
131 }
132 }
133 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;
166}
167
168// 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
189int 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
475ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Expression& expr) {
476 switch (expr.fKind) {
477 case Expression::kFieldAccess_Kind: {
478 const FieldAccess& f = (const FieldAccess&)expr;
479 Location baseLoc = this->getLocation(*f.fBase);
480 int offset = 0;
481 for (int i = 0; i < f.fFieldIndex; ++i) {
482 offset += SlotCount(*f.fBase->fType.fields()[i].fType);
483 }
484 if (baseLoc.isOnStack()) {
485 if (offset != 0) {
486 this->write(ByteCodeInstruction::kPushImmediate);
487 this->write32(offset);
488 this->write(ByteCodeInstruction::kAddI);
489 this->write8(1);
490 }
491 return baseLoc;
492 } else {
493 return baseLoc + offset;
494 }
495 }
496 case Expression::kIndex_Kind: {
497 const IndexExpression& i = (const IndexExpression&)expr;
498 int stride = SlotCount(i.fType);
499 int length = i.fBase->fType.columns();
500 SkASSERT(length <= 255);
501 int offset = -1;
502 if (i.fIndex->isConstant()) {
503 int64_t index = i.fIndex->getConstantInt();
504 if (index < 0 || index >= length) {
505 fErrors.error(i.fIndex->fOffset, "Array index out of bounds.");
506 return Location::MakeInvalid();
507 }
508 offset = index * stride;
509 } else {
510 if (i.fIndex->hasSideEffects()) {
511 // Having a side-effect in an indexer is technically safe for an rvalue,
512 // but with lvalues we have to evaluate the indexer twice, so make it an error.
513 fErrors.error(i.fIndex->fOffset,
514 "Index expressions with side-effects not supported in byte code.");
515 return Location::MakeInvalid();
516 }
517 this->writeExpression(*i.fIndex);
518 this->write(ByteCodeInstruction::kClampIndex);
519 this->write8(length);
520 if (stride != 1) {
521 this->write(ByteCodeInstruction::kPushImmediate);
522 this->write32(stride);
523 this->write(ByteCodeInstruction::kMultiplyI);
524 this->write8(1);
525 }
526 }
527 Location baseLoc = this->getLocation(*i.fBase);
528
529 // Are both components known statically?
530 if (!baseLoc.isOnStack() && offset >= 0) {
531 return baseLoc + offset;
532 }
533
534 // At least one component is dynamic (and on the stack).
535
536 // If the other component is zero, we're done
537 if (baseLoc.fSlot == 0 || offset == 0) {
538 return baseLoc.makeOnStack();
539 }
540
541 // Push the non-dynamic component (if any) to the stack, then add the two
542 if (!baseLoc.isOnStack()) {
543 this->write(ByteCodeInstruction::kPushImmediate);
544 this->write32(baseLoc.fSlot);
545 }
546 if (offset >= 0) {
547 this->write(ByteCodeInstruction::kPushImmediate);
548 this->write32(offset);
549 }
550 this->write(ByteCodeInstruction::kAddI);
551 this->write8(1);
552 return baseLoc.makeOnStack();
553 }
554 case Expression::kSwizzle_Kind: {
555 const Swizzle& s = (const Swizzle&)expr;
556 SkASSERT(swizzle_is_simple(s));
557 Location baseLoc = this->getLocation(*s.fBase);
558 int offset = s.fComponents[0];
559 if (baseLoc.isOnStack()) {
560 if (offset != 0) {
561 this->write(ByteCodeInstruction::kPushImmediate);
562 this->write32(offset);
563 this->write(ByteCodeInstruction::kAddI);
564 this->write8(1);
565 }
566 return baseLoc;
567 } else {
568 return baseLoc + offset;
569 }
570 }
571 case Expression::kVariableReference_Kind: {
572 const Variable& var = ((const VariableReference&)expr).fVariable;
573 return this->getLocation(var);
574 }
575 default:
576 SkASSERT(false);
577 return Location::MakeInvalid();
578 }
579}
580
581void ByteCodeGenerator::write8(uint8_t b) {
582 fCode->push_back(b);
583}
584
585void ByteCodeGenerator::write16(uint16_t i) {
586 size_t n = fCode->size();
587 fCode->resize(n+2);
588 memcpy(fCode->data() + n, &i, 2);
589}
590
591void ByteCodeGenerator::write32(uint32_t i) {
592 size_t n = fCode->size();
593 fCode->resize(n+4);
594 memcpy(fCode->data() + n, &i, 4);
595}
596
597void ByteCodeGenerator::write(ByteCodeInstruction i, int count) {
598 switch (i) {
599 case ByteCodeInstruction::kLoopBegin: this->enterLoop(); break;
600 case ByteCodeInstruction::kLoopEnd: this->exitLoop(); break;
601
602 case ByteCodeInstruction::kMaskPush: this->enterCondition(); break;
603 case ByteCodeInstruction::kMaskPop:
604 case ByteCodeInstruction::kMaskBlend: this->exitCondition(); break;
605 default: /* Do nothing */ break;
606 }
607 instruction val = (instruction) i;
608 size_t n = fCode->size();
609 fCode->resize(n + sizeof(val));
610 memcpy(fCode->data() + n, &val, sizeof(val));
611 fStackCount += StackUsage(i, count);
612 fMaxStackCount = std::max(fMaxStackCount, fStackCount);
613}
614
615static ByteCodeInstruction vector_instruction(ByteCodeInstruction base, int count) {
616 SkASSERT(count >= 1 && count <= 4);
617 return ((ByteCodeInstruction) ((int) base + 1 - count));
618}
619
620void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
621 ByteCodeInstruction u, ByteCodeInstruction f,
622 int count, bool writeCount) {
623 switch (type_category(type)) {
624 case TypeCategory::kSigned:
625 this->write(vector_instruction(s, count));
626 break;
627 case TypeCategory::kUnsigned:
628 this->write(vector_instruction(u, count));
629 break;
630 case TypeCategory::kFloat: {
631 if (count > 4) {
632 this->write((ByteCodeInstruction)((int)f + 1), count);
633 } else {
634 this->write(vector_instruction(f, count));
635 }
636 break;
637 }
638 default:
639 SkASSERT(false);
640 }
641 if (writeCount) {
642 this->write8(count);
643 }
644}
645
646bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool discard) {
647 if (b.fOperator == Token::Kind::EQ) {
648 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
649 this->writeExpression(*b.fRight);
650 lvalue->store(discard);
651 discard = false;
652 return discard;
653 }
654 const Type& lType = b.fLeft->fType;
655 const Type& rType = b.fRight->fType;
656 bool lVecOrMtx = (lType.kind() == Type::kVector_Kind || lType.kind() == Type::kMatrix_Kind);
657 bool rVecOrMtx = (rType.kind() == Type::kVector_Kind || rType.kind() == Type::kMatrix_Kind);
658 Token::Kind op;
659 std::unique_ptr<LValue> lvalue;
660 if (is_assignment(b.fOperator)) {
661 lvalue = this->getLValue(*b.fLeft);
662 lvalue->load();
663 op = remove_assignment(b.fOperator);
664 } else {
665 this->writeExpression(*b.fLeft);
666 op = b.fOperator;
667 if (!lVecOrMtx && rVecOrMtx) {
668 for (int i = SlotCount(rType); i > 1; --i) {
669 this->write(ByteCodeInstruction::kDup);
670 this->write8(1);
671 }
672 }
673 }
674 int count = std::max(SlotCount(lType), SlotCount(rType));
675 SkDEBUGCODE(TypeCategory tc = type_category(lType));
676 switch (op) {
677 case Token::Kind::LOGICALAND: {
678 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
679 this->write(ByteCodeInstruction::kDup);
680 this->write8(1);
681 this->write(ByteCodeInstruction::kMaskPush);
682 this->write(ByteCodeInstruction::kBranchIfAllFalse);
683 DeferredLocation falseLocation(this);
684 this->writeExpression(*b.fRight);
685 this->write(ByteCodeInstruction::kAndB);
686 falseLocation.set();
687 this->write(ByteCodeInstruction::kMaskPop);
688 return false;
689 }
690 case Token::Kind::LOGICALOR: {
691 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
692 this->write(ByteCodeInstruction::kDup);
693 this->write8(1);
694 this->write(ByteCodeInstruction::kNotB);
695 this->write(ByteCodeInstruction::kMaskPush);
696 this->write(ByteCodeInstruction::kBranchIfAllFalse);
697 DeferredLocation falseLocation(this);
698 this->writeExpression(*b.fRight);
699 this->write(ByteCodeInstruction::kOrB);
700 falseLocation.set();
701 this->write(ByteCodeInstruction::kMaskPop);
702 return false;
703 }
704 case Token::Kind::SHL:
705 case Token::Kind::SHR: {
706 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
707 tc == SkSL::TypeCategory::kUnsigned));
708 if (!b.fRight->isConstant()) {
709 fErrors.error(b.fRight->fOffset, "Shift amounts must be constant");
710 return false;
711 }
712 int64_t shift = b.fRight->getConstantInt();
713 if (shift < 0 || shift > 31) {
714 fErrors.error(b.fRight->fOffset, "Shift amount out of range");
715 return false;
716 }
717
718 if (op == Token::Kind::SHL) {
719 this->write(ByteCodeInstruction::kShiftLeft);
720 } else {
721 this->write(type_category(lType) == TypeCategory::kSigned
722 ? ByteCodeInstruction::kShiftRightS
723 : ByteCodeInstruction::kShiftRightU);
724 }
725 this->write8(shift);
726 return false;
727 }
728
729 default:
730 break;
731 }
732 this->writeExpression(*b.fRight);
733 if (lVecOrMtx && !rVecOrMtx) {
734 for (int i = SlotCount(lType); i > 1; --i) {
735 this->write(ByteCodeInstruction::kDup);
736 this->write8(1);
737 }
738 }
739 // Special case for M*V, V*M, M*M (but not V*V!)
740 if (op == Token::Kind::STAR && lVecOrMtx && rVecOrMtx &&
741 !(lType.kind() == Type::kVector_Kind && rType.kind() == Type::kVector_Kind)) {
742 this->write(ByteCodeInstruction::kMatrixMultiply,
743 SlotCount(b.fType) - (SlotCount(lType) + SlotCount(rType)));
744 int rCols = rType.columns(),
745 rRows = rType.rows(),
746 lCols = lType.columns(),
747 lRows = lType.rows();
748 // M*V treats the vector as a column
749 if (rType.kind() == Type::kVector_Kind) {
750 std::swap(rCols, rRows);
751 }
752 SkASSERT(lCols == rRows);
753 SkASSERT(SlotCount(b.fType) == lRows * rCols);
754 this->write8(lCols);
755 this->write8(lRows);
756 this->write8(rCols);
757 } else {
758 switch (op) {
759 case Token::Kind::EQEQ:
760 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareIEQ,
761 ByteCodeInstruction::kCompareIEQ,
762 ByteCodeInstruction::kCompareFEQ,
763 count);
764 // Collapse to a single bool
765 for (int i = count; i > 1; --i) {
766 this->write(ByteCodeInstruction::kAndB);
767 }
768 break;
769 case Token::Kind::GT:
770 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGT,
771 ByteCodeInstruction::kCompareUGT,
772 ByteCodeInstruction::kCompareFGT,
773 count);
774 break;
775 case Token::Kind::GTEQ:
776 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGTEQ,
777 ByteCodeInstruction::kCompareUGTEQ,
778 ByteCodeInstruction::kCompareFGTEQ,
779 count);
780 break;
781 case Token::Kind::LT:
782 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLT,
783 ByteCodeInstruction::kCompareULT,
784 ByteCodeInstruction::kCompareFLT,
785 count);
786 break;
787 case Token::Kind::LTEQ:
788 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLTEQ,
789 ByteCodeInstruction::kCompareULTEQ,
790 ByteCodeInstruction::kCompareFLTEQ,
791 count);
792 break;
793 case Token::Kind::MINUS:
794 this->writeTypedInstruction(lType, ByteCodeInstruction::kSubtractI,
795 ByteCodeInstruction::kSubtractI,
796 ByteCodeInstruction::kSubtractF,
797 count);
798 break;
799 case Token::Kind::NEQ:
800 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareINEQ,
801 ByteCodeInstruction::kCompareINEQ,
802 ByteCodeInstruction::kCompareFNEQ,
803 count);
804 // Collapse to a single bool
805 for (int i = count; i > 1; --i) {
806 this->write(ByteCodeInstruction::kOrB);
807 }
808 break;
809 case Token::Kind::PERCENT:
810 this->writeTypedInstruction(lType, ByteCodeInstruction::kRemainderS,
811 ByteCodeInstruction::kRemainderU,
812 ByteCodeInstruction::kRemainderF,
813 count);
814 break;
815 case Token::Kind::PLUS:
816 this->writeTypedInstruction(lType, ByteCodeInstruction::kAddI,
817 ByteCodeInstruction::kAddI,
818 ByteCodeInstruction::kAddF,
819 count);
820 break;
821 case Token::Kind::SLASH:
822 this->writeTypedInstruction(lType, ByteCodeInstruction::kDivideS,
823 ByteCodeInstruction::kDivideU,
824 ByteCodeInstruction::kDivideF,
825 count);
826 break;
827 case Token::Kind::STAR:
828 this->writeTypedInstruction(lType, ByteCodeInstruction::kMultiplyI,
829 ByteCodeInstruction::kMultiplyI,
830 ByteCodeInstruction::kMultiplyF,
831 count);
832 break;
833
834 case Token::Kind::LOGICALXOR:
835 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
836 this->write(ByteCodeInstruction::kXorB);
837 break;
838
839 case Token::Kind::BITWISEAND:
840 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
841 tc == SkSL::TypeCategory::kUnsigned));
842 this->write(ByteCodeInstruction::kAndB);
843 break;
844 case Token::Kind::BITWISEOR:
845 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
846 tc == SkSL::TypeCategory::kUnsigned));
847 this->write(ByteCodeInstruction::kOrB);
848 break;
849 case Token::Kind::BITWISEXOR:
850 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
851 tc == SkSL::TypeCategory::kUnsigned));
852 this->write(ByteCodeInstruction::kXorB);
853 break;
854
855 default:
856 fErrors.error(b.fOffset, SkSL::String::printf("Unsupported binary operator '%s'",
857 Compiler::OperatorName(op)));
858 break;
859 }
860 }
861 if (lvalue) {
862 lvalue->store(discard);
863 discard = false;
864 }
865 return discard;
866}
867
868void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
869 this->write(ByteCodeInstruction::kPushImmediate);
870 this->write32(b.fValue ? ~0 : 0);
871}
872
873void ByteCodeGenerator::writeConstructor(const Constructor& c) {
874 for (const auto& arg : c.fArguments) {
875 this->writeExpression(*arg);
876 }
877 if (c.fArguments.size() == 1) {
878 const Type& inType = c.fArguments[0]->fType;
879 const Type& outType = c.fType;
880 TypeCategory inCategory = type_category(inType);
881 TypeCategory outCategory = type_category(outType);
882 int inCount = SlotCount(inType);
883 int outCount = SlotCount(outType);
884 if (inCategory != outCategory) {
885 SkASSERT(inCount == outCount);
886 if (inCategory == TypeCategory::kFloat) {
887 SkASSERT(outCategory == TypeCategory::kSigned ||
888 outCategory == TypeCategory::kUnsigned);
889 this->write(vector_instruction(ByteCodeInstruction::kConvertFtoI, outCount));
890 } else if (outCategory == TypeCategory::kFloat) {
891 if (inCategory == TypeCategory::kSigned) {
892 this->write(vector_instruction(ByteCodeInstruction::kConvertStoF, outCount));
893 } else {
894 SkASSERT(inCategory == TypeCategory::kUnsigned);
895 this->write(vector_instruction(ByteCodeInstruction::kConvertUtoF, outCount));
896 }
897 } else {
898 SkASSERT(false);
899 }
900 }
901 if (inType.kind() == Type::kMatrix_Kind && outType.kind() == Type::kMatrix_Kind) {
902 this->write(ByteCodeInstruction::kMatrixToMatrix,
903 SlotCount(outType) - SlotCount(inType));
904 this->write8(inType.columns());
905 this->write8(inType.rows());
906 this->write8(outType.columns());
907 this->write8(outType.rows());
908 } else if (inCount != outCount) {
909 SkASSERT(inCount == 1);
910 if (outType.kind() == Type::kMatrix_Kind) {
911 this->write(ByteCodeInstruction::kScalarToMatrix, SlotCount(outType) - 1);
912 this->write8(outType.columns());
913 this->write8(outType.rows());
914 } else {
915 SkASSERT(outType.kind() == Type::kVector_Kind);
916 for (; inCount != outCount; ++inCount) {
917 this->write(ByteCodeInstruction::kDup);
918 this->write8(1);
919 }
920 }
921 }
922 }
923}
924
925void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f) {
926 int argumentCount = 0;
927 for (const auto& arg : f.fArguments) {
928 this->writeExpression(*arg);
929 argumentCount += SlotCount(arg->fType);
930 }
931 this->write(ByteCodeInstruction::kCallExternal, SlotCount(f.fType) - argumentCount);
932 SkASSERT(argumentCount <= 255);
933 this->write8(argumentCount);
934 this->write8(SlotCount(f.fType));
935 int index = fOutput->fExternalValues.size();
936 fOutput->fExternalValues.push_back(f.fFunction);
937 SkASSERT(index <= 255);
938 this->write8(index);
939}
940
941void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
942 int count = SlotCount(e.fValue->type());
943 this->write(vector_instruction(ByteCodeInstruction::kReadExternal, count));
944 this->write8(count);
945 int index = fOutput->fExternalValues.size();
946 fOutput->fExternalValues.push_back(e.fValue);
947 SkASSERT(index <= 255);
948 this->write8(index);
949}
950
951void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
952 Location location = this->getLocation(expr);
953 int count = SlotCount(expr.fType);
954 if (location.isOnStack() || count > 4) {
955 if (!location.isOnStack()) {
956 this->write(ByteCodeInstruction::kPushImmediate);
957 this->write32(location.fSlot);
958 }
959 this->write(location.selectLoad(ByteCodeInstruction::kLoadExtended,
960 ByteCodeInstruction::kLoadExtendedGlobal,
961 ByteCodeInstruction::kLoadExtendedUniform),
962 count);
963 this->write8(count);
964 } else {
965 this->write(vector_instruction(location.selectLoad(ByteCodeInstruction::kLoad,
966 ByteCodeInstruction::kLoadGlobal,
967 ByteCodeInstruction::kLoadUniform),
968 count));
969 this->write8(count);
970 this->write8(location.fSlot);
971 }
972}
973
974static inline uint32_t float_to_bits(float x) {
975 uint32_t u;
976 memcpy(&u, &x, sizeof(uint32_t));
977 return u;
978}
979
980void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
981 this->write(ByteCodeInstruction::kPushImmediate);
982 this->write32(float_to_bits(f.fValue));
983}
984
985void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
986 auto found = fIntrinsics.find(c.fFunction.fName);
987 if (found == fIntrinsics.end()) {
988 fErrors.error(c.fOffset, String::printf("Unsupported intrinsic: '%s'",
989 String(c.fFunction.fName).c_str()));
990 return;
991 }
992 int count = SlotCount(c.fArguments[0]->fType);
993 if (found->second.fIsSpecial) {
994 SpecialIntrinsic special = found->second.fValue.fSpecial;
995 switch (special) {
996 case SpecialIntrinsic::kDot: {
997 SkASSERT(c.fArguments.size() == 2);
998 SkASSERT(count == SlotCount(c.fArguments[1]->fType));
999 this->write(vector_instruction(ByteCodeInstruction::kMultiplyF, count));
1000 this->write8(count);
1001 for (int i = count; i > 1; --i) {
1002 this->write(ByteCodeInstruction::kAddF);
1003 this->write8(1);
1004 }
1005 break;
1006 }
1007 default:
1008 SkASSERT(false);
1009 }
1010 } else {
1011 switch (found->second.fValue.fInstruction) {
1012 case ByteCodeInstruction::kCos:
1013 case ByteCodeInstruction::kSin:
1014 case ByteCodeInstruction::kTan:
1015 SkASSERT(c.fArguments.size() > 0);
1016 this->write(vector_instruction(found->second.fValue.fInstruction, count));
1017 this->write8(count);
1018 break;
1019 case ByteCodeInstruction::kSqrt:
1020 SkASSERT(c.fArguments.size() > 0);
1021 this->write(vector_instruction(found->second.fValue.fInstruction, count));
1022 break;
1023 case ByteCodeInstruction::kInverse2x2: {
1024 SkASSERT(c.fArguments.size() > 0);
1025 auto op = ByteCodeInstruction::kInverse2x2;
1026 switch (count) {
1027 case 4: break; // float2x2
1028 case 9: op = ByteCodeInstruction::kInverse3x3; break;
1029 case 16: op = ByteCodeInstruction::kInverse4x4; break;
1030 default: SkASSERT(false);
1031 }
1032 this->write(op);
1033 break;
1034 }
1035 default:
1036 SkASSERT(false);
1037 }
1038 }
1039}
1040
1041void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
1042 // Find the index of the function we're calling. We explicitly do not allow calls to functions
1043 // before they're defined. This is an easy-to-understand rule that prevents recursion.
1044 int idx = -1;
1045 for (size_t i = 0; i < fFunctions.size(); ++i) {
1046 if (f.fFunction.matches(fFunctions[i]->fDeclaration)) {
1047 idx = i;
1048 break;
1049 }
1050 }
1051 if (idx == -1) {
1052 for (const auto& arg : f.fArguments) {
1053 this->writeExpression(*arg);
1054 }
1055 this->writeIntrinsicCall(f);
1056 return;
1057 }
1058
1059
1060 if (idx > 255) {
1061 fErrors.error(f.fOffset, "Function count limit exceeded");
1062 return;
1063 } else if (idx >= (int) fFunctions.size()) {
1064 fErrors.error(f.fOffset, "Call to undefined function");
1065 return;
1066 }
1067
1068 // We may need to deal with out parameters, so the sequence is tricky
1069 if (int returnCount = SlotCount(f.fType)) {
1070 this->write(ByteCodeInstruction::kReserve, returnCount);
1071 this->write8(returnCount);
1072 }
1073
1074 int argCount = f.fArguments.size();
1075 std::vector<std::unique_ptr<LValue>> lvalues;
1076 for (int i = 0; i < argCount; ++i) {
1077 const auto& param = f.fFunction.fParameters[i];
1078 const auto& arg = f.fArguments[i];
1079 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1080 lvalues.emplace_back(this->getLValue(*arg));
1081 lvalues.back()->load();
1082 } else {
1083 this->writeExpression(*arg);
1084 }
1085 }
1086
1087 // The space used by the call is based on the callee, but it also unwinds all of that before
1088 // we continue execution. We adjust our max stack depths below.
1089 this->write(ByteCodeInstruction::kCall);
1090 this->write8(idx);
1091
1092 const ByteCodeFunction* callee = fOutput->fFunctions[idx].get();
1093 fMaxLoopCount = std::max(fMaxLoopCount, fLoopCount + callee->fLoopCount);
1094 fMaxConditionCount = std::max(fMaxConditionCount, fConditionCount + callee->fConditionCount);
1095 fMaxStackCount = std::max(fMaxStackCount, fStackCount + callee->fLocalCount
1096 + callee->fStackCount);
1097
1098 // After the called function returns, the stack will still contain our arguments. We have to
1099 // pop them (storing any out parameters back to their lvalues as we go). We glob together slot
1100 // counts for all parameters that aren't out-params, so we can pop them in one big chunk.
1101 int popCount = 0;
1102 auto pop = [&]() {
1103 if (popCount > 4) {
1104 this->write(ByteCodeInstruction::kPopN, popCount);
1105 this->write8(popCount);
1106 } else if (popCount > 0) {
1107 this->write(vector_instruction(ByteCodeInstruction::kPop, popCount));
1108 }
1109 popCount = 0;
1110 };
1111
1112 for (int i = argCount - 1; i >= 0; --i) {
1113 const auto& param = f.fFunction.fParameters[i];
1114 const auto& arg = f.fArguments[i];
1115 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1116 pop();
1117 lvalues.back()->store(true);
1118 lvalues.pop_back();
1119 } else {
1120 popCount += SlotCount(arg->fType);
1121 }
1122 }
1123 pop();
1124}
1125
1126void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
1127 this->write(ByteCodeInstruction::kPushImmediate);
1128 this->write32(i.fValue);
1129}
1130
1131void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
1132 // not yet implemented
1133 abort();
1134}
1135
1136bool ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p, bool discard) {
1137 switch (p.fOperator) {
1138 case Token::Kind::PLUSPLUS: // fall through
1139 case Token::Kind::MINUSMINUS: {
1140 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1141 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
1142 lvalue->load();
1143 this->write(ByteCodeInstruction::kPushImmediate);
1144 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
1145 if (p.fOperator == Token::Kind::PLUSPLUS) {
1146 this->writeTypedInstruction(p.fType,
1147 ByteCodeInstruction::kAddI,
1148 ByteCodeInstruction::kAddI,
1149 ByteCodeInstruction::kAddF,
1150 1);
1151 } else {
1152 this->writeTypedInstruction(p.fType,
1153 ByteCodeInstruction::kSubtractI,
1154 ByteCodeInstruction::kSubtractI,
1155 ByteCodeInstruction::kSubtractF,
1156 1);
1157 }
1158 lvalue->store(discard);
1159 discard = false;
1160 break;
1161 }
1162 case Token::Kind::MINUS: {
1163 this->writeExpression(*p.fOperand);
1164 this->writeTypedInstruction(p.fType,
1165 ByteCodeInstruction::kNegateI,
1166 ByteCodeInstruction::kNegateI,
1167 ByteCodeInstruction::kNegateF,
1168 SlotCount(p.fOperand->fType),
1169 false);
1170 break;
1171 }
1172 case Token::Kind::LOGICALNOT:
1173 case Token::Kind::BITWISENOT: {
1174 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1175 SkDEBUGCODE(TypeCategory tc = type_category(p.fOperand->fType));
1176 SkASSERT((p.fOperator == Token::Kind::LOGICALNOT && tc == TypeCategory::kBool) ||
1177 (p.fOperator == Token::Kind::BITWISENOT && (tc == TypeCategory::kSigned ||
1178 tc == TypeCategory::kUnsigned)));
1179 this->writeExpression(*p.fOperand);
1180 this->write(ByteCodeInstruction::kNotB);
1181 break;
1182 }
1183 default:
1184 SkASSERT(false);
1185 }
1186 return discard;
1187}
1188
1189bool ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p, bool discard) {
1190 switch (p.fOperator) {
1191 case Token::Kind::PLUSPLUS: // fall through
1192 case Token::Kind::MINUSMINUS: {
1193 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1194 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
1195 lvalue->load();
1196 // If we're not supposed to discard the result, then make a copy *before* the +/-
1197 if (!discard) {
1198 this->write(ByteCodeInstruction::kDup);
1199 this->write8(1);
1200 }
1201 this->write(ByteCodeInstruction::kPushImmediate);
1202 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
1203 if (p.fOperator == Token::Kind::PLUSPLUS) {
1204 this->writeTypedInstruction(p.fType,
1205 ByteCodeInstruction::kAddI,
1206 ByteCodeInstruction::kAddI,
1207 ByteCodeInstruction::kAddF,
1208 1);
1209 } else {
1210 this->writeTypedInstruction(p.fType,
1211 ByteCodeInstruction::kSubtractI,
1212 ByteCodeInstruction::kSubtractI,
1213 ByteCodeInstruction::kSubtractF,
1214 1);
1215 }
1216 // Always consume the result as part of the store
1217 lvalue->store(true);
1218 discard = false;
1219 break;
1220 }
1221 default:
1222 SkASSERT(false);
1223 }
1224 return discard;
1225}
1226
1227void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
1228 if (swizzle_is_simple(s)) {
1229 this->writeVariableExpression(s);
1230 return;
1231 }
1232
1233 switch (s.fBase->fKind) {
1234 case Expression::kVariableReference_Kind: {
1235 Location location = this->getLocation(*s.fBase);
1236 this->write(location.selectLoad(ByteCodeInstruction::kLoadSwizzle,
1237 ByteCodeInstruction::kLoadSwizzleGlobal,
1238 ByteCodeInstruction::kLoadSwizzleUniform),
1239 s.fComponents.size());
1240 this->write8(location.fSlot);
1241 this->write8(s.fComponents.size());
1242 for (int c : s.fComponents) {
1243 this->write8(c);
1244 }
1245 break;
1246 }
1247 default:
1248 this->writeExpression(*s.fBase);
1249 this->write(ByteCodeInstruction::kSwizzle,
1250 s.fComponents.size() - s.fBase->fType.columns());
1251 this->write8(s.fBase->fType.columns());
1252 this->write8(s.fComponents.size());
1253 for (int c : s.fComponents) {
1254 this->write8(c);
1255 }
1256 }
1257}
1258
1259void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
1260 int count = SlotCount(t.fType);
1261 SkASSERT(count == SlotCount(t.fIfTrue->fType));
1262 SkASSERT(count == SlotCount(t.fIfFalse->fType));
1263
1264 this->writeExpression(*t.fTest);
1265 this->write(ByteCodeInstruction::kMaskPush);
1266 this->writeExpression(*t.fIfTrue);
1267 this->write(ByteCodeInstruction::kMaskNegate);
1268 this->writeExpression(*t.fIfFalse);
1269 this->write(ByteCodeInstruction::kMaskBlend, count);
1270 this->write8(count);
1271}
1272
1273void ByteCodeGenerator::writeExpression(const Expression& e, bool discard) {
1274 switch (e.fKind) {
1275 case Expression::kBinary_Kind:
1276 discard = this->writeBinaryExpression((BinaryExpression&) e, discard);
1277 break;
1278 case Expression::kBoolLiteral_Kind:
1279 this->writeBoolLiteral((BoolLiteral&) e);
1280 break;
1281 case Expression::kConstructor_Kind:
1282 this->writeConstructor((Constructor&) e);
1283 break;
1284 case Expression::kExternalFunctionCall_Kind:
1285 this->writeExternalFunctionCall((ExternalFunctionCall&) e);
1286 break;
1287 case Expression::kExternalValue_Kind:
1288 this->writeExternalValue((ExternalValueReference&) e);
1289 break;
1290 case Expression::kFieldAccess_Kind:
1291 case Expression::kIndex_Kind:
1292 case Expression::kVariableReference_Kind:
1293 this->writeVariableExpression(e);
1294 break;
1295 case Expression::kFloatLiteral_Kind:
1296 this->writeFloatLiteral((FloatLiteral&) e);
1297 break;
1298 case Expression::kFunctionCall_Kind:
1299 this->writeFunctionCall((FunctionCall&) e);
1300 break;
1301 case Expression::kIntLiteral_Kind:
1302 this->writeIntLiteral((IntLiteral&) e);
1303 break;
1304 case Expression::kNullLiteral_Kind:
1305 this->writeNullLiteral((NullLiteral&) e);
1306 break;
1307 case Expression::kPrefix_Kind:
1308 discard = this->writePrefixExpression((PrefixExpression&) e, discard);
1309 break;
1310 case Expression::kPostfix_Kind:
1311 discard = this->writePostfixExpression((PostfixExpression&) e, discard);
1312 break;
1313 case Expression::kSwizzle_Kind:
1314 this->writeSwizzle((Swizzle&) e);
1315 break;
1316 case Expression::kTernary_Kind:
1317 this->writeTernaryExpression((TernaryExpression&) e);
1318 break;
1319 default:
1320#ifdef SK_DEBUG
1321 printf("unsupported expression %s\n", e.description().c_str());
1322#endif
1323 SkASSERT(false);
1324 }
1325 if (discard) {
1326 int count = SlotCount(e.fType);
1327 if (count > 4) {
1328 this->write(ByteCodeInstruction::kPopN, count);
1329 this->write8(count);
1330 } else if (count != 0) {
1331 this->write(vector_instruction(ByteCodeInstruction::kPop, count));
1332 }
1333 discard = false;
1334 }
1335}
1336
1337class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
1338public:
1339 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
1340 : INHERITED(*generator)
1341 , fCount(ByteCodeGenerator::SlotCount(value.type()))
1342 , fIndex(index) {}
1343
1344 void load() override {
1345 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
1346 fGenerator.write8(fCount);
1347 fGenerator.write8(fIndex);
1348 }
1349
1350 void store(bool discard) override {
1351 if (!discard) {
1352 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
1353 fGenerator.write8(fCount);
1354 }
1355 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
1356 fGenerator.write8(fCount);
1357 fGenerator.write8(fIndex);
1358 }
1359
1360private:
1361 typedef LValue INHERITED;
1362
1363 int fCount;
1364
1365 int fIndex;
1366};
1367
1368class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
1369public:
1370 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
1371 : INHERITED(*generator)
1372 , fSwizzle(swizzle) {}
1373
1374 void load() override {
1375 fGenerator.writeSwizzle(fSwizzle);
1376 }
1377
1378 void store(bool discard) override {
1379 int count = fSwizzle.fComponents.size();
1380 if (!discard) {
1381 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
1382 fGenerator.write8(count);
1383 }
1384 ByteCodeGenerator::Location location = fGenerator.getLocation(*fSwizzle.fBase);
1385 if (location.isOnStack()) {
1386 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreSwizzleIndirect,
1387 ByteCodeInstruction::kStoreSwizzleIndirectGlobal),
1388 count);
1389 } else {
1390 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreSwizzle,
1391 ByteCodeInstruction::kStoreSwizzleGlobal),
1392 count);
1393 fGenerator.write8(location.fSlot);
1394 }
1395 fGenerator.write8(count);
1396 for (int c : fSwizzle.fComponents) {
1397 fGenerator.write8(c);
1398 }
1399 }
1400
1401private:
1402 const Swizzle& fSwizzle;
1403
1404 typedef LValue INHERITED;
1405};
1406
1407class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
1408public:
1409 ByteCodeExpressionLValue(ByteCodeGenerator* generator, const Expression& expr)
1410 : INHERITED(*generator)
1411 , fExpression(expr) {}
1412
1413 void load() override {
1414 fGenerator.writeVariableExpression(fExpression);
1415 }
1416
1417 void store(bool discard) override {
1418 int count = ByteCodeGenerator::SlotCount(fExpression.fType);
1419 if (!discard) {
1420 if (count > 4) {
1421 fGenerator.write(ByteCodeInstruction::kDupN, count);
1422 fGenerator.write8(count);
1423 } else {
1424 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
1425 fGenerator.write8(count);
1426 }
1427 }
1428 ByteCodeGenerator::Location location = fGenerator.getLocation(fExpression);
1429 if (location.isOnStack() || count > 4) {
1430 if (!location.isOnStack()) {
1431 fGenerator.write(ByteCodeInstruction::kPushImmediate);
1432 fGenerator.write32(location.fSlot);
1433 }
1434 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreExtended,
1435 ByteCodeInstruction::kStoreExtendedGlobal),
1436 count);
1437 fGenerator.write8(count);
1438 } else {
1439 fGenerator.write(
1440 vector_instruction(location.selectStore(ByteCodeInstruction::kStore,
1441 ByteCodeInstruction::kStoreGlobal),
1442 count));
1443 fGenerator.write8(location.fSlot);
1444 }
1445 }
1446
1447private:
1448 typedef LValue INHERITED;
1449
1450 const Expression& fExpression;
1451};
1452
1453std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
1454 switch (e.fKind) {
1455 case Expression::kExternalValue_Kind: {
1456 ExternalValue* value = ((ExternalValueReference&) e).fValue;
1457 int index = fOutput->fExternalValues.size();
1458 fOutput->fExternalValues.push_back(value);
1459 SkASSERT(index <= 255);
1460 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
1461 }
1462 case Expression::kFieldAccess_Kind:
1463 case Expression::kIndex_Kind:
1464 case Expression::kVariableReference_Kind:
1465 return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
1466 case Expression::kSwizzle_Kind: {
1467 const Swizzle& s = (const Swizzle&) e;
1468 return swizzle_is_simple(s)
1469 ? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e))
1470 : std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s));
1471 }
1472 case Expression::kTernary_Kind:
1473 default:
1474#ifdef SK_DEBUG
1475 ABORT("unsupported lvalue %s\n", e.description().c_str());
1476#endif
1477 return nullptr;
1478 }
1479}
1480
1481void ByteCodeGenerator::writeBlock(const Block& b) {
1482 for (const auto& s : b.fStatements) {
1483 this->writeStatement(*s);
1484 }
1485}
1486
1487void ByteCodeGenerator::setBreakTargets() {
1488 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
1489 for (DeferredLocation& b : breaks) {
1490 b.set();
1491 }
1492 fBreakTargets.pop();
1493}
1494
1495void ByteCodeGenerator::setContinueTargets() {
1496 std::vector<DeferredLocation>& continues = fContinueTargets.top();
1497 for (DeferredLocation& c : continues) {
1498 c.set();
1499 }
1500 fContinueTargets.pop();
1501}
1502
1503void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
1504 // TODO: Include BranchIfAllFalse to top-most LoopNext
1505 this->write(ByteCodeInstruction::kLoopBreak);
1506}
1507
1508void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
1509 // TODO: Include BranchIfAllFalse to top-most LoopNext
1510 this->write(ByteCodeInstruction::kLoopContinue);
1511}
1512
1513void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
1514 this->write(ByteCodeInstruction::kLoopBegin);
1515 size_t start = fCode->size();
1516 this->writeStatement(*d.fStatement);
1517 this->write(ByteCodeInstruction::kLoopNext);
1518 this->writeExpression(*d.fTest);
1519 this->write(ByteCodeInstruction::kLoopMask);
1520 // TODO: Could shorten this with kBranchIfAnyTrue
1521 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1522 DeferredLocation endLocation(this);
1523 this->write(ByteCodeInstruction::kBranch);
1524 this->write16(start);
1525 endLocation.set();
1526 this->write(ByteCodeInstruction::kLoopEnd);
1527}
1528
1529void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
1530 fContinueTargets.emplace();
1531 fBreakTargets.emplace();
1532 if (f.fInitializer) {
1533 this->writeStatement(*f.fInitializer);
1534 }
1535 this->write(ByteCodeInstruction::kLoopBegin);
1536 size_t start = fCode->size();
1537 if (f.fTest) {
1538 this->writeExpression(*f.fTest);
1539 this->write(ByteCodeInstruction::kLoopMask);
1540 }
1541 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1542 DeferredLocation endLocation(this);
1543 this->writeStatement(*f.fStatement);
1544 this->write(ByteCodeInstruction::kLoopNext);
1545 if (f.fNext) {
1546 this->writeExpression(*f.fNext, true);
1547 }
1548 this->write(ByteCodeInstruction::kBranch);
1549 this->write16(start);
1550 endLocation.set();
1551 this->write(ByteCodeInstruction::kLoopEnd);
1552}
1553
1554void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
1555 this->writeExpression(*i.fTest);
1556 this->write(ByteCodeInstruction::kMaskPush);
1557 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1558 DeferredLocation falseLocation(this);
1559 this->writeStatement(*i.fIfTrue);
1560 falseLocation.set();
1561 if (i.fIfFalse) {
1562 this->write(ByteCodeInstruction::kMaskNegate);
1563 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1564 DeferredLocation endLocation(this);
1565 this->writeStatement(*i.fIfFalse);
1566 endLocation.set();
1567 }
1568 this->write(ByteCodeInstruction::kMaskPop);
1569}
1570
1571void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
1572 if (fLoopCount || fConditionCount) {
1573 fErrors.error(r.fOffset, "return not allowed inside conditional or loop");
1574 return;
1575 }
1576 int count = SlotCount(r.fExpression->fType);
1577 this->writeExpression(*r.fExpression);
1578
1579 // Technically, the kReturn also pops fOutput->fLocalCount values from the stack, too, but we
1580 // haven't counted pushing those (they're outside the scope of our stack tracking). Instead,
1581 // we account for those in writeFunction().
1582
1583 // This is all fine because we don't allow conditional returns, so we only return once anyway.
1584 this->write(ByteCodeInstruction::kReturn, -count);
1585 this->write8(count);
1586}
1587
1588void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
1589 // not yet implemented
1590 abort();
1591}
1592
1593void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1594 for (const auto& declStatement : v.fVars) {
1595 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
1596 // we need to grab the location even if we don't use it, to ensure it has been allocated
1597 Location location = this->getLocation(*decl.fVar);
1598 if (decl.fValue) {
1599 this->writeExpression(*decl.fValue);
1600 int count = SlotCount(decl.fValue->fType);
1601 if (count > 4) {
1602 this->write(ByteCodeInstruction::kPushImmediate);
1603 this->write32(location.fSlot);
1604 this->write(ByteCodeInstruction::kStoreExtended, count);
1605 this->write8(count);
1606 } else {
1607 this->write(vector_instruction(ByteCodeInstruction::kStore, count));
1608 this->write8(location.fSlot);
1609 }
1610 }
1611 }
1612}
1613
1614void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
1615 this->write(ByteCodeInstruction::kLoopBegin);
1616 size_t cond = fCode->size();
1617 this->writeExpression(*w.fTest);
1618 this->write(ByteCodeInstruction::kLoopMask);
1619 this->write(ByteCodeInstruction::kBranchIfAllFalse);
1620 DeferredLocation endLocation(this);
1621 this->writeStatement(*w.fStatement);
1622 this->write(ByteCodeInstruction::kLoopNext);
1623 this->write(ByteCodeInstruction::kBranch);
1624 this->write16(cond);
1625 endLocation.set();
1626 this->write(ByteCodeInstruction::kLoopEnd);
1627}
1628
1629void ByteCodeGenerator::writeStatement(const Statement& s) {
1630 switch (s.fKind) {
1631 case Statement::kBlock_Kind:
1632 this->writeBlock((Block&) s);
1633 break;
1634 case Statement::kBreak_Kind:
1635 this->writeBreakStatement((BreakStatement&) s);
1636 break;
1637 case Statement::kContinue_Kind:
1638 this->writeContinueStatement((ContinueStatement&) s);
1639 break;
1640 case Statement::kDiscard_Kind:
1641 // not yet implemented
1642 abort();
1643 case Statement::kDo_Kind:
1644 this->writeDoStatement((DoStatement&) s);
1645 break;
1646 case Statement::kExpression_Kind:
1647 this->writeExpression(*((ExpressionStatement&) s).fExpression, true);
1648 break;
1649 case Statement::kFor_Kind:
1650 this->writeForStatement((ForStatement&) s);
1651 break;
1652 case Statement::kIf_Kind:
1653 this->writeIfStatement((IfStatement&) s);
1654 break;
1655 case Statement::kNop_Kind:
1656 break;
1657 case Statement::kReturn_Kind:
1658 this->writeReturnStatement((ReturnStatement&) s);
1659 break;
1660 case Statement::kSwitch_Kind:
1661 this->writeSwitchStatement((SwitchStatement&) s);
1662 break;
1663 case Statement::kVarDeclarations_Kind:
1664 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1665 break;
1666 case Statement::kWhile_Kind:
1667 this->writeWhileStatement((WhileStatement&) s);
1668 break;
1669 default:
1670 SkASSERT(false);
1671 }
1672}
1673
1674ByteCodeFunction::ByteCodeFunction(const FunctionDeclaration* declaration)
1675 : fName(declaration->fName) {
1676 fParameterCount = 0;
1677 for (const auto& p : declaration->fParameters) {
1678 int slots = ByteCodeGenerator::SlotCount(p->fType);
1679 fParameters.push_back({ slots, (bool)(p->fModifiers.fFlags & Modifiers::kOut_Flag) });
1680 fParameterCount += slots;
1681 }
1682}
1683
1684}
1685