• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
12 namespace SkSL {
13 
ByteCodeGenerator(const Context * context,const Program * program,ErrorReporter * errors,ByteCode * output)14 ByteCodeGenerator::ByteCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
15                   ByteCode* output)
16     : INHERITED(program, errors, nullptr)
17     , fContext(*context)
18     , fOutput(output)
19     , fIntrinsics {
20         { "cos",     ByteCodeInstruction::kCos },
21         { "dot",     SpecialIntrinsic::kDot },
22         { "inverse", ByteCodeInstruction::kInverse2x2 },
23         { "sin",     ByteCodeInstruction::kSin },
24         { "sqrt",    ByteCodeInstruction::kSqrt },
25         { "tan",     ByteCodeInstruction::kTan },
26       } {}
27 
28 
SlotCount(const Type & type)29 int ByteCodeGenerator::SlotCount(const Type& type) {
30     if (type.kind() == Type::kOther_Kind) {
31         return 0;
32     } else if (type.kind() == Type::kStruct_Kind) {
33         int slots = 0;
34         for (const auto& f : type.fields()) {
35             slots += SlotCount(*f.fType);
36         }
37         SkASSERT(slots <= 255);
38         return slots;
39     } else if (type.kind() == Type::kArray_Kind) {
40         int columns = type.columns();
41         SkASSERT(columns >= 0);
42         int slots = columns * SlotCount(type.componentType());
43         SkASSERT(slots <= 255);
44         return slots;
45     } else {
46         return type.columns() * type.rows();
47     }
48 }
49 
generateCode()50 bool ByteCodeGenerator::generateCode() {
51     for (const auto& e : fProgram) {
52         switch (e.fKind) {
53             case ProgramElement::kFunction_Kind: {
54                 std::unique_ptr<ByteCodeFunction> f = this->writeFunction((FunctionDefinition&) e);
55                 if (!f) {
56                     return false;
57                 }
58                 fOutput->fFunctions.push_back(std::move(f));
59                 fFunctions.push_back(&(FunctionDefinition&)e);
60                 break;
61             }
62             case ProgramElement::kVar_Kind: {
63                 VarDeclarations& decl = (VarDeclarations&) e;
64                 for (const auto& v : decl.fVars) {
65                     const Variable* declVar = ((VarDeclaration&) *v).fVar;
66                     if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
67                         continue;
68                     }
69                     if (declVar->fModifiers.fFlags & Modifiers::kIn_Flag) {
70                         for (int i = SlotCount(declVar->fType); i > 0; --i) {
71                             fOutput->fInputSlots.push_back(fOutput->fGlobalCount++);
72                         }
73                     } else {
74                         fOutput->fGlobalCount += SlotCount(declVar->fType);
75                     }
76                 }
77                 break;
78             }
79             default:
80                 ; // ignore
81         }
82     }
83     return 0 == fErrors.errorCount();
84 }
85 
writeFunction(const FunctionDefinition & f)86 std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
87     fFunction = &f;
88     std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
89     fParameterCount = result->fParameterCount;
90     fLoopCount = fMaxLoopCount = 0;
91     fConditionCount = fMaxConditionCount = 0;
92     fStackCount = fMaxStackCount = 0;
93     fCode = &result->fCode;
94 
95     this->writeStatement(*f.fBody);
96     if (0 == fErrors.errorCount()) {
97         SkASSERT(fLoopCount == 0);
98         SkASSERT(fConditionCount == 0);
99         SkASSERT(fStackCount == 0);
100     }
101     this->write(ByteCodeInstruction::kReturn, 0);
102     this->write8(0);
103 
104     result->fLocalCount     = fLocals.size();
105     result->fConditionCount = fMaxConditionCount;
106     result->fLoopCount      = fMaxLoopCount;
107     result->fStackCount     = fMaxStackCount;
108 
109     const Type& returnType = f.fDeclaration.fReturnType;
110     if (returnType != *fContext.fVoid_Type) {
111         result->fReturnCount = SlotCount(returnType);
112     }
113     fLocals.clear();
114     fFunction = nullptr;
115     return result;
116 }
117 
118 enum class TypeCategory {
119     kBool,
120     kSigned,
121     kUnsigned,
122     kFloat,
123 };
124 
type_category(const Type & type)125 static TypeCategory type_category(const Type& type) {
126     switch (type.kind()) {
127         case Type::Kind::kVector_Kind:
128         case Type::Kind::kMatrix_Kind:
129             return type_category(type.componentType());
130         default:
131             if (type.fName == "bool") {
132                 return TypeCategory::kBool;
133             } else if (type.fName == "int" || type.fName == "short") {
134                 return TypeCategory::kSigned;
135             } else if (type.fName == "uint" || type.fName == "ushort") {
136                 return TypeCategory::kUnsigned;
137             } else {
138                 SkASSERT(type.fName == "float" || type.fName == "half");
139                 return TypeCategory::kFloat;
140             }
141             ABORT("unsupported type: %s\n", type.description().c_str());
142     }
143 }
144 
145 // A "simple" Swizzle is based on a variable (or a compound variable like a struct or array), and
146 // that references consecutive values, such that it can be implemented using normal load/store ops
147 // with an offset. Note that all single-component swizzles (of suitable base types) are simple.
swizzle_is_simple(const Swizzle & s)148 static bool swizzle_is_simple(const Swizzle& s) {
149     switch (s.fBase->fKind) {
150         case Expression::kFieldAccess_Kind:
151         case Expression::kIndex_Kind:
152         case Expression::kVariableReference_Kind:
153             break;
154         default:
155             return false;
156     }
157 
158     for (size_t i = 1; i < s.fComponents.size(); ++i) {
159         if (s.fComponents[i] != s.fComponents[i - 1] + 1) {
160             return false;
161         }
162     }
163     return true;
164 }
165 
StackUsage(ByteCodeInstruction inst,int count_)166 int ByteCodeGenerator::StackUsage(ByteCodeInstruction inst, int count_) {
167     // Ensures that we use count iff we're passed a non-default value. Most instructions have an
168     // implicit count, so the caller shouldn't need to worry about it (or count makes no sense).
169     // The asserts avoids callers thinking they're supplying useful information in that scenario,
170     // or failing to supply necessary information for the ops that need a count.
171     struct CountValue {
172         operator int() {
173             SkASSERT(val != ByteCodeGenerator::kUnusedStackCount);
174             SkDEBUGCODE(used = true);
175             return val;
176         }
177         ~CountValue() {
178             SkASSERT(used || val == ByteCodeGenerator::kUnusedStackCount);
179         }
180         int val;
181         SkDEBUGCODE(bool used = false;)
182     } count = { count_ };
183 
184     switch (inst) {
185         // Unary functions/operators that don't change stack depth at all:
186 #define VECTOR_UNARY_OP(base)                \
187         case ByteCodeInstruction::base:      \
188         case ByteCodeInstruction::base ## 2: \
189         case ByteCodeInstruction::base ## 3: \
190         case ByteCodeInstruction::base ## 4: \
191             return 0;
192 
193         VECTOR_UNARY_OP(kConvertFtoI)
194         VECTOR_UNARY_OP(kConvertStoF)
195         VECTOR_UNARY_OP(kConvertUtoF)
196 
197         VECTOR_UNARY_OP(kCos)
198         VECTOR_UNARY_OP(kSin)
199         VECTOR_UNARY_OP(kSqrt)
200         VECTOR_UNARY_OP(kTan)
201 
202         VECTOR_UNARY_OP(kNegateF)
203         VECTOR_UNARY_OP(kNegateI)
204 
205         case ByteCodeInstruction::kInverse2x2:
206         case ByteCodeInstruction::kInverse3x3:
207         case ByteCodeInstruction::kInverse4x4: return 0;
208 
209         case ByteCodeInstruction::kClampIndex: return 0;
210         case ByteCodeInstruction::kNotB: return 0;
211         case ByteCodeInstruction::kNegateFN: return 0;
212 
213 #undef VECTOR_UNARY_OP
214 
215         // Binary functions/operators that do a 2 -> 1 reduction (possibly N times)
216 #define VECTOR_BINARY_OP(base)                          \
217         case ByteCodeInstruction::base:      return -1; \
218         case ByteCodeInstruction::base ## 2: return -2; \
219         case ByteCodeInstruction::base ## 3: return -3; \
220         case ByteCodeInstruction::base ## 4: return -4;
221 
222 #define VECTOR_MATRIX_BINARY_OP(base)                   \
223         VECTOR_BINARY_OP(base)                          \
224         case ByteCodeInstruction::base ## N: return -count;
225 
226         case ByteCodeInstruction::kAndB: return -1;
227         case ByteCodeInstruction::kOrB:  return -1;
228         case ByteCodeInstruction::kXorB: return -1;
229 
230         VECTOR_BINARY_OP(kAddI)
231         VECTOR_MATRIX_BINARY_OP(kAddF)
232 
233         VECTOR_BINARY_OP(kCompareIEQ)
234         VECTOR_MATRIX_BINARY_OP(kCompareFEQ)
235         VECTOR_BINARY_OP(kCompareINEQ)
236         VECTOR_MATRIX_BINARY_OP(kCompareFNEQ)
237         VECTOR_BINARY_OP(kCompareSGT)
238         VECTOR_BINARY_OP(kCompareUGT)
239         VECTOR_BINARY_OP(kCompareFGT)
240         VECTOR_BINARY_OP(kCompareSGTEQ)
241         VECTOR_BINARY_OP(kCompareUGTEQ)
242         VECTOR_BINARY_OP(kCompareFGTEQ)
243         VECTOR_BINARY_OP(kCompareSLT)
244         VECTOR_BINARY_OP(kCompareULT)
245         VECTOR_BINARY_OP(kCompareFLT)
246         VECTOR_BINARY_OP(kCompareSLTEQ)
247         VECTOR_BINARY_OP(kCompareULTEQ)
248         VECTOR_BINARY_OP(kCompareFLTEQ)
249 
250         VECTOR_BINARY_OP(kDivideS)
251         VECTOR_BINARY_OP(kDivideU)
252         VECTOR_MATRIX_BINARY_OP(kDivideF)
253         VECTOR_BINARY_OP(kMultiplyI)
254         VECTOR_MATRIX_BINARY_OP(kMultiplyF)
255         VECTOR_BINARY_OP(kRemainderF)
256         VECTOR_BINARY_OP(kRemainderS)
257         VECTOR_BINARY_OP(kRemainderU)
258         VECTOR_BINARY_OP(kSubtractI)
259         VECTOR_MATRIX_BINARY_OP(kSubtractF)
260 
261 #undef VECTOR_BINARY_OP
262 #undef VECTOR_MATRIX_BINARY_OP
263 
264         // Ops that push or load data to grow the stack:
265         case ByteCodeInstruction::kDup:
266         case ByteCodeInstruction::kLoad:
267         case ByteCodeInstruction::kLoadGlobal:
268         case ByteCodeInstruction::kReadExternal:
269         case ByteCodeInstruction::kPushImmediate:
270             return 1;
271 
272         case ByteCodeInstruction::kDup2:
273         case ByteCodeInstruction::kLoad2:
274         case ByteCodeInstruction::kLoadGlobal2:
275         case ByteCodeInstruction::kReadExternal2:
276             return 2;
277 
278         case ByteCodeInstruction::kDup3:
279         case ByteCodeInstruction::kLoad3:
280         case ByteCodeInstruction::kLoadGlobal3:
281         case ByteCodeInstruction::kReadExternal3:
282             return 3;
283 
284         case ByteCodeInstruction::kDup4:
285         case ByteCodeInstruction::kLoad4:
286         case ByteCodeInstruction::kLoadGlobal4:
287         case ByteCodeInstruction::kReadExternal4:
288             return 4;
289 
290         case ByteCodeInstruction::kDupN:
291         case ByteCodeInstruction::kLoadSwizzle:
292         case ByteCodeInstruction::kLoadSwizzleGlobal:
293             return count;
294 
295         // Pushes 'count' values, minus one for the 'address' that's consumed first
296         case ByteCodeInstruction::kLoadExtended:
297         case ByteCodeInstruction::kLoadExtendedGlobal:
298             return count - 1;
299 
300         // Ops that pop or store data to shrink the stack:
301         case ByteCodeInstruction::kPop:
302         case ByteCodeInstruction::kStore:
303         case ByteCodeInstruction::kStoreGlobal:
304         case ByteCodeInstruction::kWriteExternal:
305             return -1;
306 
307         case ByteCodeInstruction::kPop2:
308         case ByteCodeInstruction::kStore2:
309         case ByteCodeInstruction::kStoreGlobal2:
310         case ByteCodeInstruction::kWriteExternal2:
311             return -2;
312 
313         case ByteCodeInstruction::kPop3:
314         case ByteCodeInstruction::kStore3:
315         case ByteCodeInstruction::kStoreGlobal3:
316         case ByteCodeInstruction::kWriteExternal3:
317             return -3;
318 
319         case ByteCodeInstruction::kPop4:
320         case ByteCodeInstruction::kStore4:
321         case ByteCodeInstruction::kStoreGlobal4:
322         case ByteCodeInstruction::kWriteExternal4:
323             return -4;
324 
325         case ByteCodeInstruction::kPopN:
326         case ByteCodeInstruction::kStoreSwizzle:
327         case ByteCodeInstruction::kStoreSwizzleGlobal:
328             return -count;
329 
330         // Consumes 'count' values, plus one for the 'address'
331         case ByteCodeInstruction::kStoreExtended:
332         case ByteCodeInstruction::kStoreExtendedGlobal:
333         case ByteCodeInstruction::kStoreSwizzleIndirect:
334         case ByteCodeInstruction::kStoreSwizzleIndirectGlobal:
335             return -count - 1;
336 
337         // Strange ops where the caller computes the delta for us:
338         case ByteCodeInstruction::kCallExternal:
339         case ByteCodeInstruction::kMatrixToMatrix:
340         case ByteCodeInstruction::kMatrixMultiply:
341         case ByteCodeInstruction::kReserve:
342         case ByteCodeInstruction::kReturn:
343         case ByteCodeInstruction::kScalarToMatrix:
344         case ByteCodeInstruction::kSwizzle:
345             return count;
346 
347         // Miscellaneous
348 
349         // kCall is net-zero. Max stack depth is adjusted in writeFunctionCall.
350         case ByteCodeInstruction::kCall:             return 0;
351         case ByteCodeInstruction::kBranch:           return 0;
352         case ByteCodeInstruction::kBranchIfAllFalse: return 0;
353 
354         case ByteCodeInstruction::kMaskPush:         return -1;
355         case ByteCodeInstruction::kMaskPop:          return 0;
356         case ByteCodeInstruction::kMaskNegate:       return 0;
357         case ByteCodeInstruction::kMaskBlend:        return -count;
358 
359         case ByteCodeInstruction::kLoopBegin:        return 0;
360         case ByteCodeInstruction::kLoopNext:         return 0;
361         case ByteCodeInstruction::kLoopMask:         return -1;
362         case ByteCodeInstruction::kLoopEnd:          return 0;
363         case ByteCodeInstruction::kLoopBreak:        return 0;
364         case ByteCodeInstruction::kLoopContinue:     return 0;
365 
366         default:
367             ABORT("unsupported instruction %d\n", (int)inst);
368             return 0;
369     }
370 }
371 
getLocation(const Variable & var)372 int ByteCodeGenerator::getLocation(const Variable& var) {
373     // given that we seldom have more than a couple of variables, linear search is probably the most
374     // efficient way to handle lookups
375     switch (var.fStorage) {
376         case Variable::kLocal_Storage: {
377             for (int i = fLocals.size() - 1; i >= 0; --i) {
378                 if (fLocals[i] == &var) {
379                     SkASSERT(fParameterCount + i <= 255);
380                     return fParameterCount + i;
381                 }
382             }
383             int result = fParameterCount + fLocals.size();
384             fLocals.push_back(&var);
385             for (int i = 0; i < SlotCount(var.fType) - 1; ++i) {
386                 fLocals.push_back(nullptr);
387             }
388             SkASSERT(result <= 255);
389             return result;
390         }
391         case Variable::kParameter_Storage: {
392             int offset = 0;
393             for (const auto& p : fFunction->fDeclaration.fParameters) {
394                 if (p == &var) {
395                     SkASSERT(offset <= 255);
396                     return offset;
397                 }
398                 offset += SlotCount(p->fType);
399             }
400             SkASSERT(false);
401             return 0;
402         }
403         case Variable::kGlobal_Storage: {
404             int offset = 0;
405             for (const auto& e : fProgram) {
406                 if (e.fKind == ProgramElement::kVar_Kind) {
407                     VarDeclarations& decl = (VarDeclarations&) e;
408                     for (const auto& v : decl.fVars) {
409                         const Variable* declVar = ((VarDeclaration&) *v).fVar;
410                         if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
411                             continue;
412                         }
413                         if (declVar == &var) {
414                             SkASSERT(offset <= 255);
415                             return offset;
416                         }
417                         offset += SlotCount(declVar->fType);
418                     }
419                 }
420             }
421             SkASSERT(false);
422             return 0;
423         }
424         default:
425             SkASSERT(false);
426             return 0;
427     }
428 }
429 
getLocation(const Expression & expr,Variable::Storage * storage)430 int ByteCodeGenerator::getLocation(const Expression& expr, Variable::Storage* storage) {
431     switch (expr.fKind) {
432         case Expression::kFieldAccess_Kind: {
433             const FieldAccess& f = (const FieldAccess&)expr;
434             int baseAddr = this->getLocation(*f.fBase, storage);
435             int offset = 0;
436             for (int i = 0; i < f.fFieldIndex; ++i) {
437                 offset += SlotCount(*f.fBase->fType.fields()[i].fType);
438             }
439             if (baseAddr < 0) {
440                 if (offset != 0) {
441                     this->write(ByteCodeInstruction::kPushImmediate);
442                     this->write32(offset);
443                     this->write(ByteCodeInstruction::kAddI);
444                 }
445                 return -1;
446             } else {
447                 return baseAddr + offset;
448             }
449         }
450         case Expression::kIndex_Kind: {
451             const IndexExpression& i = (const IndexExpression&)expr;
452             int stride = SlotCount(i.fType);
453             int length = i.fBase->fType.columns();
454             SkASSERT(length <= 255);
455             int offset = -1;
456             if (i.fIndex->isConstant()) {
457                 int64_t index = i.fIndex->getConstantInt();
458                 if (index < 0 || index >= length) {
459                     fErrors.error(i.fIndex->fOffset, "Array index out of bounds.");
460                     return 0;
461                 }
462                 offset = index * stride;
463             } else {
464                 if (i.fIndex->hasSideEffects()) {
465                     // Having a side-effect in an indexer is technically safe for an rvalue,
466                     // but with lvalues we have to evaluate the indexer twice, so make it an error.
467                     fErrors.error(i.fIndex->fOffset,
468                             "Index expressions with side-effects not supported in byte code.");
469                     return 0;
470                 }
471                 this->writeExpression(*i.fIndex);
472                 this->write(ByteCodeInstruction::kClampIndex);
473                 this->write8(length);
474                 if (stride != 1) {
475                     this->write(ByteCodeInstruction::kPushImmediate);
476                     this->write32(stride);
477                     this->write(ByteCodeInstruction::kMultiplyI);
478                 }
479             }
480             int baseAddr = this->getLocation(*i.fBase, storage);
481 
482             // Are both components known statically?
483             if (baseAddr >= 0 && offset >= 0) {
484                 return baseAddr + offset;
485             }
486 
487             // At least one component is dynamic (and on the stack).
488 
489             // If the other component is zero, we're done
490             if (baseAddr == 0 || offset == 0) {
491                 return -1;
492             }
493 
494             // Push the non-dynamic component (if any) to the stack, then add the two
495             if (baseAddr >= 0) {
496                 this->write(ByteCodeInstruction::kPushImmediate);
497                 this->write32(baseAddr);
498             }
499             if (offset >= 0) {
500                 this->write(ByteCodeInstruction::kPushImmediate);
501                 this->write32(offset);
502             }
503             this->write(ByteCodeInstruction::kAddI);
504             return -1;
505         }
506         case Expression::kSwizzle_Kind: {
507             const Swizzle& s = (const Swizzle&)expr;
508             SkASSERT(swizzle_is_simple(s));
509             int baseAddr = this->getLocation(*s.fBase, storage);
510             int offset = s.fComponents[0];
511             if (baseAddr < 0) {
512                 if (offset != 0) {
513                     this->write(ByteCodeInstruction::kPushImmediate);
514                     this->write32(offset);
515                     this->write(ByteCodeInstruction::kAddI);
516                 }
517                 return -1;
518             } else {
519                 return baseAddr + offset;
520             }
521         }
522         case Expression::kVariableReference_Kind: {
523             const Variable& var = ((const VariableReference&)expr).fVariable;
524             *storage = var.fStorage;
525             return this->getLocation(var);
526         }
527         default:
528             SkASSERT(false);
529             return 0;
530     }
531 }
532 
write8(uint8_t b)533 void ByteCodeGenerator::write8(uint8_t b) {
534     fCode->push_back(b);
535 }
536 
write16(uint16_t i)537 void ByteCodeGenerator::write16(uint16_t i) {
538     size_t n = fCode->size();
539     fCode->resize(n+2);
540     memcpy(fCode->data() + n, &i, 2);
541 }
542 
write32(uint32_t i)543 void ByteCodeGenerator::write32(uint32_t i) {
544     size_t n = fCode->size();
545     fCode->resize(n+4);
546     memcpy(fCode->data() + n, &i, 4);
547 }
548 
write(ByteCodeInstruction i,int count)549 void ByteCodeGenerator::write(ByteCodeInstruction i, int count) {
550     switch (i) {
551         case ByteCodeInstruction::kLoopBegin: this->enterLoop();      break;
552         case ByteCodeInstruction::kLoopEnd:   this->exitLoop();       break;
553 
554         case ByteCodeInstruction::kMaskPush:  this->enterCondition(); break;
555         case ByteCodeInstruction::kMaskPop:
556         case ByteCodeInstruction::kMaskBlend: this->exitCondition();  break;
557         default: /* Do nothing */ break;
558     }
559     this->write16((uint16_t)i);
560     fStackCount += StackUsage(i, count);
561     fMaxStackCount = std::max(fMaxStackCount, fStackCount);
562 }
563 
vector_instruction(ByteCodeInstruction base,int count)564 static ByteCodeInstruction vector_instruction(ByteCodeInstruction base, int count) {
565     SkASSERT(count >= 1 && count <= 4);
566     return ((ByteCodeInstruction) ((int) base + count - 1));
567 }
568 
writeTypedInstruction(const Type & type,ByteCodeInstruction s,ByteCodeInstruction u,ByteCodeInstruction f,int count)569 void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
570                                               ByteCodeInstruction u, ByteCodeInstruction f,
571                                               int count) {
572     switch (type_category(type)) {
573         case TypeCategory::kSigned:
574             this->write(vector_instruction(s, count));
575             break;
576         case TypeCategory::kUnsigned:
577             this->write(vector_instruction(u, count));
578             break;
579         case TypeCategory::kFloat: {
580             if (count > 4) {
581                 this->write((ByteCodeInstruction)((int)f + 4), count);
582                 this->write8(count);
583             } else {
584                 this->write(vector_instruction(f, count));
585             }
586             break;
587         }
588         default:
589             SkASSERT(false);
590     }
591 }
592 
writeBinaryExpression(const BinaryExpression & b,bool discard)593 bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool discard) {
594     if (b.fOperator == Token::Kind::EQ) {
595         std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
596         this->writeExpression(*b.fRight);
597         lvalue->store(discard);
598         discard = false;
599         return discard;
600     }
601     const Type& lType = b.fLeft->fType;
602     const Type& rType = b.fRight->fType;
603     bool lVecOrMtx = (lType.kind() == Type::kVector_Kind || lType.kind() == Type::kMatrix_Kind);
604     bool rVecOrMtx = (rType.kind() == Type::kVector_Kind || rType.kind() == Type::kMatrix_Kind);
605     Token::Kind op;
606     std::unique_ptr<LValue> lvalue;
607     if (is_assignment(b.fOperator)) {
608         lvalue = this->getLValue(*b.fLeft);
609         lvalue->load();
610         op = remove_assignment(b.fOperator);
611     } else {
612         this->writeExpression(*b.fLeft);
613         op = b.fOperator;
614         if (!lVecOrMtx && rVecOrMtx) {
615             for (int i = SlotCount(rType); i > 1; --i) {
616                 this->write(ByteCodeInstruction::kDup);
617             }
618         }
619     }
620     this->writeExpression(*b.fRight);
621     if (lVecOrMtx && !rVecOrMtx) {
622         for (int i = SlotCount(lType); i > 1; --i) {
623             this->write(ByteCodeInstruction::kDup);
624         }
625     }
626     // Special case for M*V, V*M, M*M (but not V*V!)
627     if (op == Token::Kind::STAR && lVecOrMtx && rVecOrMtx &&
628         !(lType.kind() == Type::kVector_Kind && rType.kind() == Type::kVector_Kind)) {
629         this->write(ByteCodeInstruction::kMatrixMultiply,
630                     SlotCount(b.fType) - (SlotCount(lType) + SlotCount(rType)));
631         int rCols = rType.columns(),
632             rRows = rType.rows(),
633             lCols = lType.columns(),
634             lRows = lType.rows();
635         // M*V treats the vector as a column
636         if (rType.kind() == Type::kVector_Kind) {
637             std::swap(rCols, rRows);
638         }
639         SkASSERT(lCols == rRows);
640         SkASSERT(SlotCount(b.fType) == lRows * rCols);
641         this->write8(lCols);
642         this->write8(lRows);
643         this->write8(rCols);
644     } else {
645         int count = std::max(SlotCount(lType), SlotCount(rType));
646         switch (op) {
647             case Token::Kind::EQEQ:
648                 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareIEQ,
649                                             ByteCodeInstruction::kCompareIEQ,
650                                             ByteCodeInstruction::kCompareFEQ,
651                                             count);
652                 // Collapse to a single bool
653                 for (int i = count; i > 1; --i) {
654                     this->write(ByteCodeInstruction::kAndB);
655                 }
656                 break;
657             case Token::Kind::GT:
658                 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGT,
659                                             ByteCodeInstruction::kCompareUGT,
660                                             ByteCodeInstruction::kCompareFGT,
661                                             count);
662                 break;
663             case Token::Kind::GTEQ:
664                 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGTEQ,
665                                             ByteCodeInstruction::kCompareUGTEQ,
666                                             ByteCodeInstruction::kCompareFGTEQ,
667                                             count);
668                 break;
669             case Token::Kind::LT:
670                 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLT,
671                                             ByteCodeInstruction::kCompareULT,
672                                             ByteCodeInstruction::kCompareFLT,
673                                             count);
674                 break;
675             case Token::Kind::LTEQ:
676                 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLTEQ,
677                                             ByteCodeInstruction::kCompareULTEQ,
678                                             ByteCodeInstruction::kCompareFLTEQ,
679                                             count);
680                 break;
681             case Token::Kind::MINUS:
682                 this->writeTypedInstruction(lType, ByteCodeInstruction::kSubtractI,
683                                             ByteCodeInstruction::kSubtractI,
684                                             ByteCodeInstruction::kSubtractF,
685                                             count);
686                 break;
687             case Token::Kind::NEQ:
688                 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareINEQ,
689                                             ByteCodeInstruction::kCompareINEQ,
690                                             ByteCodeInstruction::kCompareFNEQ,
691                                             count);
692                 // Collapse to a single bool
693                 for (int i = count; i > 1; --i) {
694                     this->write(ByteCodeInstruction::kOrB);
695                 }
696                 break;
697             case Token::Kind::PERCENT:
698                 this->writeTypedInstruction(lType, ByteCodeInstruction::kRemainderS,
699                                             ByteCodeInstruction::kRemainderU,
700                                             ByteCodeInstruction::kRemainderF,
701                                             count);
702                 break;
703             case Token::Kind::PLUS:
704                 this->writeTypedInstruction(lType, ByteCodeInstruction::kAddI,
705                                             ByteCodeInstruction::kAddI,
706                                             ByteCodeInstruction::kAddF,
707                                             count);
708                 break;
709             case Token::Kind::SLASH:
710                 this->writeTypedInstruction(lType, ByteCodeInstruction::kDivideS,
711                                             ByteCodeInstruction::kDivideU,
712                                             ByteCodeInstruction::kDivideF,
713                                             count);
714                 break;
715             case Token::Kind::STAR:
716                 this->writeTypedInstruction(lType, ByteCodeInstruction::kMultiplyI,
717                                             ByteCodeInstruction::kMultiplyI,
718                                             ByteCodeInstruction::kMultiplyF,
719                                             count);
720                 break;
721 
722             case Token::Kind::LOGICALAND:
723                 SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
724                 this->write(ByteCodeInstruction::kAndB);
725                 break;
726             case Token::Kind::LOGICALNOT:
727                 SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
728                 this->write(ByteCodeInstruction::kNotB);
729                 break;
730             case Token::Kind::LOGICALOR:
731                 SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
732                 this->write(ByteCodeInstruction::kOrB);
733                 break;
734             case Token::Kind::LOGICALXOR:
735                 SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
736                 this->write(ByteCodeInstruction::kXorB);
737                 break;
738 
739             default:
740                 fErrors.error(b.fOffset, SkSL::String::printf("Unsupported binary operator '%s'",
741                                                               Compiler::OperatorName(op)));
742                 break;
743         }
744     }
745     if (lvalue) {
746         lvalue->store(discard);
747         discard = false;
748     }
749     return discard;
750 }
751 
writeBoolLiteral(const BoolLiteral & b)752 void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
753     this->write(ByteCodeInstruction::kPushImmediate);
754     this->write32(b.fValue ? ~0 : 0);
755 }
756 
writeConstructor(const Constructor & c)757 void ByteCodeGenerator::writeConstructor(const Constructor& c) {
758     for (const auto& arg : c.fArguments) {
759         this->writeExpression(*arg);
760     }
761     if (c.fArguments.size() == 1) {
762         const Type& inType = c.fArguments[0]->fType;
763         const Type& outType = c.fType;
764         TypeCategory inCategory = type_category(inType);
765         TypeCategory outCategory = type_category(outType);
766         int inCount = SlotCount(inType);
767         int outCount = SlotCount(outType);
768         if (inCategory != outCategory) {
769             SkASSERT(inCount == outCount);
770             if (inCategory == TypeCategory::kFloat) {
771                 SkASSERT(outCategory == TypeCategory::kSigned ||
772                          outCategory == TypeCategory::kUnsigned);
773                 this->write(vector_instruction(ByteCodeInstruction::kConvertFtoI, outCount));
774             } else if (outCategory == TypeCategory::kFloat) {
775                 if (inCategory == TypeCategory::kSigned) {
776                     this->write(vector_instruction(ByteCodeInstruction::kConvertStoF, outCount));
777                 } else {
778                     SkASSERT(inCategory == TypeCategory::kUnsigned);
779                     this->write(vector_instruction(ByteCodeInstruction::kConvertUtoF, outCount));
780                 }
781             } else {
782                 SkASSERT(false);
783             }
784         }
785         if (inType.kind() == Type::kMatrix_Kind && outType.kind() == Type::kMatrix_Kind) {
786             this->write(ByteCodeInstruction::kMatrixToMatrix,
787                         SlotCount(outType) - SlotCount(inType));
788             this->write8(inType.columns());
789             this->write8(inType.rows());
790             this->write8(outType.columns());
791             this->write8(outType.rows());
792         } else if (inCount != outCount) {
793             SkASSERT(inCount == 1);
794             if (outType.kind() == Type::kMatrix_Kind) {
795                 this->write(ByteCodeInstruction::kScalarToMatrix, SlotCount(outType) - 1);
796                 this->write8(outType.columns());
797                 this->write8(outType.rows());
798             } else {
799                 SkASSERT(outType.kind() == Type::kVector_Kind);
800                 for (; inCount != outCount; ++inCount) {
801                     this->write(ByteCodeInstruction::kDup);
802                 }
803             }
804         }
805     }
806 }
807 
writeExternalFunctionCall(const ExternalFunctionCall & f)808 void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f) {
809     int argumentCount = 0;
810     for (const auto& arg : f.fArguments) {
811         this->writeExpression(*arg);
812         argumentCount += SlotCount(arg->fType);
813     }
814     this->write(ByteCodeInstruction::kCallExternal, SlotCount(f.fType) - argumentCount);
815     SkASSERT(argumentCount <= 255);
816     this->write8(argumentCount);
817     this->write8(SlotCount(f.fType));
818     int index = fOutput->fExternalValues.size();
819     fOutput->fExternalValues.push_back(f.fFunction);
820     SkASSERT(index <= 255);
821     this->write8(index);
822 }
823 
writeExternalValue(const ExternalValueReference & e)824 void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
825     this->write(vector_instruction(ByteCodeInstruction::kReadExternal,
826                                    SlotCount(e.fValue->type())));
827     int index = fOutput->fExternalValues.size();
828     fOutput->fExternalValues.push_back(e.fValue);
829     SkASSERT(index <= 255);
830     this->write8(index);
831 }
832 
writeVariableExpression(const Expression & expr)833 void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
834     Variable::Storage storage = Variable::kLocal_Storage;
835     int location = this->getLocation(expr, &storage);
836     bool isGlobal = storage == Variable::kGlobal_Storage;
837     int count = SlotCount(expr.fType);
838     if (location < 0 || count > 4) {
839         if (location >= 0) {
840             this->write(ByteCodeInstruction::kPushImmediate);
841             this->write32(location);
842         }
843         this->write(isGlobal ? ByteCodeInstruction::kLoadExtendedGlobal
844                              : ByteCodeInstruction::kLoadExtended,
845                     count);
846         this->write8(count);
847     } else {
848         this->write(vector_instruction(isGlobal ? ByteCodeInstruction::kLoadGlobal
849                                                 : ByteCodeInstruction::kLoad,
850                                        count));
851         this->write8(location);
852     }
853 }
854 
float_to_bits(float x)855 static inline uint32_t float_to_bits(float x) {
856     uint32_t u;
857     memcpy(&u, &x, sizeof(uint32_t));
858     return u;
859 }
860 
writeFloatLiteral(const FloatLiteral & f)861 void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
862     this->write(ByteCodeInstruction::kPushImmediate);
863     this->write32(float_to_bits(f.fValue));
864 }
865 
writeIntrinsicCall(const FunctionCall & c)866 void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
867     auto found = fIntrinsics.find(c.fFunction.fName);
868     if (found == fIntrinsics.end()) {
869         fErrors.error(c.fOffset, "unsupported intrinsic function");
870         return;
871     }
872     int count = SlotCount(c.fArguments[0]->fType);
873     if (found->second.fIsSpecial) {
874         SpecialIntrinsic special = found->second.fValue.fSpecial;
875         switch (special) {
876             case SpecialIntrinsic::kDot: {
877                 SkASSERT(c.fArguments.size() == 2);
878                 SkASSERT(count == SlotCount(c.fArguments[1]->fType));
879                 this->write((ByteCodeInstruction)((int)ByteCodeInstruction::kMultiplyF + count-1));
880                 for (int i = count; i > 1; --i) {
881                     this->write(ByteCodeInstruction::kAddF);
882                 }
883                 break;
884             }
885             default:
886                 SkASSERT(false);
887         }
888     } else {
889         switch (found->second.fValue.fInstruction) {
890             case ByteCodeInstruction::kCos:
891             case ByteCodeInstruction::kSin:
892             case ByteCodeInstruction::kSqrt:
893             case ByteCodeInstruction::kTan:
894                 SkASSERT(c.fArguments.size() > 0);
895                 this->write((ByteCodeInstruction) ((int) found->second.fValue.fInstruction +
896                             count - 1));
897                 break;
898             case ByteCodeInstruction::kInverse2x2: {
899                 SkASSERT(c.fArguments.size() > 0);
900                 auto op = ByteCodeInstruction::kInverse2x2;
901                 switch (count) {
902                     case 4: break;  // float2x2
903                     case 9:  op = ByteCodeInstruction::kInverse3x3; break;
904                     case 16: op = ByteCodeInstruction::kInverse4x4; break;
905                     default: SkASSERT(false);
906                 }
907                 this->write(op);
908                 break;
909             }
910             default:
911                 SkASSERT(false);
912         }
913     }
914 }
915 
writeFunctionCall(const FunctionCall & f)916 void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
917     // Builtins have simple signatures...
918     if (f.fFunction.fBuiltin) {
919         for (const auto& arg : f.fArguments) {
920             this->writeExpression(*arg);
921         }
922         this->writeIntrinsicCall(f);
923         return;
924     }
925 
926     // Find the index of the function we're calling. We explicitly do not allow calls to functions
927     // before they're defined. This is an easy-to-understand rule that prevents recursion.
928     size_t idx;
929     for (idx = 0; idx < fFunctions.size(); ++idx) {
930         if (f.fFunction.matches(fFunctions[idx]->fDeclaration)) {
931             break;
932         }
933     }
934     if (idx > 255) {
935         fErrors.error(f.fOffset, "Function count limit exceeded");
936         return;
937     } else if (idx >= fFunctions.size()) {
938         fErrors.error(f.fOffset, "Call to undefined function");
939         return;
940     }
941 
942     // We may need to deal with out parameters, so the sequence is tricky
943     if (int returnCount = SlotCount(f.fType)) {
944         this->write(ByteCodeInstruction::kReserve, returnCount);
945         this->write8(returnCount);
946     }
947 
948     int argCount = f.fArguments.size();
949     std::vector<std::unique_ptr<LValue>> lvalues;
950     for (int i = 0; i < argCount; ++i) {
951         const auto& param = f.fFunction.fParameters[i];
952         const auto& arg = f.fArguments[i];
953         if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
954             lvalues.emplace_back(this->getLValue(*arg));
955             lvalues.back()->load();
956         } else {
957             this->writeExpression(*arg);
958         }
959     }
960 
961     // The space used by the call is based on the callee, but it also unwinds all of that before
962     // we continue execution. We adjust our max stack depths below.
963     this->write(ByteCodeInstruction::kCall);
964     this->write8(idx);
965 
966     const ByteCodeFunction* callee = fOutput->fFunctions[idx].get();
967     fMaxLoopCount      = std::max(fMaxLoopCount,      fLoopCount      + callee->fLoopCount);
968     fMaxConditionCount = std::max(fMaxConditionCount, fConditionCount + callee->fConditionCount);
969     fMaxStackCount     = std::max(fMaxStackCount,     fStackCount     + callee->fLocalCount
970                                                                       + callee->fStackCount);
971 
972     // After the called function returns, the stack will still contain our arguments. We have to
973     // pop them (storing any out parameters back to their lvalues as we go). We glob together slot
974     // counts for all parameters that aren't out-params, so we can pop them in one big chunk.
975     int popCount = 0;
976     auto pop = [&]() {
977         if (popCount > 4) {
978             this->write(ByteCodeInstruction::kPopN, popCount);
979             this->write8(popCount);
980         } else if (popCount > 0) {
981             this->write(vector_instruction(ByteCodeInstruction::kPop, popCount));
982         }
983         popCount = 0;
984     };
985 
986     for (int i = argCount - 1; i >= 0; --i) {
987         const auto& param = f.fFunction.fParameters[i];
988         const auto& arg = f.fArguments[i];
989         if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
990             pop();
991             lvalues.back()->store(true);
992             lvalues.pop_back();
993         } else {
994             popCount += SlotCount(arg->fType);
995         }
996     }
997     pop();
998 }
999 
writeIntLiteral(const IntLiteral & i)1000 void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
1001     this->write(ByteCodeInstruction::kPushImmediate);
1002     this->write32(i.fValue);
1003 }
1004 
writeNullLiteral(const NullLiteral & n)1005 void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
1006     // not yet implemented
1007     abort();
1008 }
1009 
writePrefixExpression(const PrefixExpression & p,bool discard)1010 bool ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p, bool discard) {
1011     switch (p.fOperator) {
1012         case Token::Kind::PLUSPLUS: // fall through
1013         case Token::Kind::MINUSMINUS: {
1014             SkASSERT(SlotCount(p.fOperand->fType) == 1);
1015             std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
1016             lvalue->load();
1017             this->write(ByteCodeInstruction::kPushImmediate);
1018             this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
1019             if (p.fOperator == Token::Kind::PLUSPLUS) {
1020                 this->writeTypedInstruction(p.fType,
1021                                             ByteCodeInstruction::kAddI,
1022                                             ByteCodeInstruction::kAddI,
1023                                             ByteCodeInstruction::kAddF,
1024                                             1);
1025             } else {
1026                 this->writeTypedInstruction(p.fType,
1027                                             ByteCodeInstruction::kSubtractI,
1028                                             ByteCodeInstruction::kSubtractI,
1029                                             ByteCodeInstruction::kSubtractF,
1030                                             1);
1031             }
1032             lvalue->store(discard);
1033             discard = false;
1034             break;
1035         }
1036         case Token::Kind::MINUS: {
1037             this->writeExpression(*p.fOperand);
1038             this->writeTypedInstruction(p.fType,
1039                                         ByteCodeInstruction::kNegateI,
1040                                         ByteCodeInstruction::kNegateI,
1041                                         ByteCodeInstruction::kNegateF,
1042                                         SlotCount(p.fOperand->fType));
1043             break;
1044         }
1045         default:
1046             SkASSERT(false);
1047     }
1048     return discard;
1049 }
1050 
writePostfixExpression(const PostfixExpression & p,bool discard)1051 bool ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p, bool discard) {
1052     switch (p.fOperator) {
1053         case Token::Kind::PLUSPLUS: // fall through
1054         case Token::Kind::MINUSMINUS: {
1055             SkASSERT(SlotCount(p.fOperand->fType) == 1);
1056             std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
1057             lvalue->load();
1058             // If we're not supposed to discard the result, then make a copy *before* the +/-
1059             if (!discard) {
1060                 this->write(ByteCodeInstruction::kDup);
1061             }
1062             this->write(ByteCodeInstruction::kPushImmediate);
1063             this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
1064             if (p.fOperator == Token::Kind::PLUSPLUS) {
1065                 this->writeTypedInstruction(p.fType,
1066                                             ByteCodeInstruction::kAddI,
1067                                             ByteCodeInstruction::kAddI,
1068                                             ByteCodeInstruction::kAddF,
1069                                             1);
1070             } else {
1071                 this->writeTypedInstruction(p.fType,
1072                                             ByteCodeInstruction::kSubtractI,
1073                                             ByteCodeInstruction::kSubtractI,
1074                                             ByteCodeInstruction::kSubtractF,
1075                                             1);
1076             }
1077             // Always consume the result as part of the store
1078             lvalue->store(true);
1079             discard = false;
1080             break;
1081         }
1082         default:
1083             SkASSERT(false);
1084     }
1085     return discard;
1086 }
1087 
writeSwizzle(const Swizzle & s)1088 void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
1089     if (swizzle_is_simple(s)) {
1090         this->writeVariableExpression(s);
1091         return;
1092     }
1093 
1094     switch (s.fBase->fKind) {
1095         case Expression::kVariableReference_Kind: {
1096             const Variable& var = ((VariableReference&) *s.fBase).fVariable;
1097             this->write(var.fStorage == Variable::kGlobal_Storage
1098                             ? ByteCodeInstruction::kLoadSwizzleGlobal
1099                             : ByteCodeInstruction::kLoadSwizzle,
1100                         s.fComponents.size());
1101             this->write8(this->getLocation(var));
1102             this->write8(s.fComponents.size());
1103             for (int c : s.fComponents) {
1104                 this->write8(c);
1105             }
1106             break;
1107         }
1108         default:
1109             this->writeExpression(*s.fBase);
1110             this->write(ByteCodeInstruction::kSwizzle,
1111                         s.fComponents.size() - s.fBase->fType.columns());
1112             this->write8(s.fBase->fType.columns());
1113             this->write8(s.fComponents.size());
1114             for (int c : s.fComponents) {
1115                 this->write8(c);
1116             }
1117     }
1118 }
1119 
writeTernaryExpression(const TernaryExpression & t)1120 void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
1121     int count = SlotCount(t.fType);
1122     SkASSERT(count == SlotCount(t.fIfTrue->fType));
1123     SkASSERT(count == SlotCount(t.fIfFalse->fType));
1124 
1125     this->writeExpression(*t.fTest);
1126     this->write(ByteCodeInstruction::kMaskPush);
1127     this->writeExpression(*t.fIfTrue);
1128     this->write(ByteCodeInstruction::kMaskNegate);
1129     this->writeExpression(*t.fIfFalse);
1130     this->write(ByteCodeInstruction::kMaskBlend, count);
1131     this->write8(count);
1132 }
1133 
writeExpression(const Expression & e,bool discard)1134 void ByteCodeGenerator::writeExpression(const Expression& e, bool discard) {
1135     switch (e.fKind) {
1136         case Expression::kBinary_Kind:
1137             discard = this->writeBinaryExpression((BinaryExpression&) e, discard);
1138             break;
1139         case Expression::kBoolLiteral_Kind:
1140             this->writeBoolLiteral((BoolLiteral&) e);
1141             break;
1142         case Expression::kConstructor_Kind:
1143             this->writeConstructor((Constructor&) e);
1144             break;
1145         case Expression::kExternalFunctionCall_Kind:
1146             this->writeExternalFunctionCall((ExternalFunctionCall&) e);
1147             break;
1148         case Expression::kExternalValue_Kind:
1149             this->writeExternalValue((ExternalValueReference&) e);
1150             break;
1151         case Expression::kFieldAccess_Kind:
1152         case Expression::kIndex_Kind:
1153         case Expression::kVariableReference_Kind:
1154             this->writeVariableExpression(e);
1155             break;
1156         case Expression::kFloatLiteral_Kind:
1157             this->writeFloatLiteral((FloatLiteral&) e);
1158             break;
1159         case Expression::kFunctionCall_Kind:
1160             this->writeFunctionCall((FunctionCall&) e);
1161             break;
1162         case Expression::kIntLiteral_Kind:
1163             this->writeIntLiteral((IntLiteral&) e);
1164             break;
1165         case Expression::kNullLiteral_Kind:
1166             this->writeNullLiteral((NullLiteral&) e);
1167             break;
1168         case Expression::kPrefix_Kind:
1169             discard = this->writePrefixExpression((PrefixExpression&) e, discard);
1170             break;
1171         case Expression::kPostfix_Kind:
1172             discard = this->writePostfixExpression((PostfixExpression&) e, discard);
1173             break;
1174         case Expression::kSwizzle_Kind:
1175             this->writeSwizzle((Swizzle&) e);
1176             break;
1177         case Expression::kTernary_Kind:
1178             this->writeTernaryExpression((TernaryExpression&) e);
1179             break;
1180         default:
1181             printf("unsupported expression %s\n", e.description().c_str());
1182             SkASSERT(false);
1183     }
1184     if (discard) {
1185         int count = SlotCount(e.fType);
1186         if (count > 4) {
1187             this->write(ByteCodeInstruction::kPopN, count);
1188             this->write8(count);
1189         } else if (count != 0) {
1190             this->write(vector_instruction(ByteCodeInstruction::kPop, count));
1191         }
1192         discard = false;
1193     }
1194 }
1195 
1196 class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
1197 public:
ByteCodeExternalValueLValue(ByteCodeGenerator * generator,ExternalValue & value,int index)1198     ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
1199         : INHERITED(*generator)
1200         , fCount(ByteCodeGenerator::SlotCount(value.type()))
1201         , fIndex(index) {}
1202 
load()1203     void load() override {
1204         fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
1205         fGenerator.write8(fIndex);
1206     }
1207 
store(bool discard)1208     void store(bool discard) override {
1209         if (!discard) {
1210             fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
1211         }
1212         fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
1213         fGenerator.write8(fIndex);
1214     }
1215 
1216 private:
1217     typedef LValue INHERITED;
1218 
1219     int fCount;
1220 
1221     int fIndex;
1222 };
1223 
1224 class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
1225 public:
ByteCodeSwizzleLValue(ByteCodeGenerator * generator,const Swizzle & swizzle)1226     ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
1227         : INHERITED(*generator)
1228         , fSwizzle(swizzle) {}
1229 
load()1230     void load() override {
1231         fGenerator.writeSwizzle(fSwizzle);
1232     }
1233 
store(bool discard)1234     void store(bool discard) override {
1235         int count = fSwizzle.fComponents.size();
1236         if (!discard) {
1237             fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
1238         }
1239         Variable::Storage storage = Variable::kLocal_Storage;
1240         int location = fGenerator.getLocation(*fSwizzle.fBase, &storage);
1241         bool isGlobal = storage == Variable::kGlobal_Storage;
1242         if (location < 0) {
1243             fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleIndirectGlobal
1244                                       : ByteCodeInstruction::kStoreSwizzleIndirect,
1245                              count);
1246         } else {
1247             fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreSwizzleGlobal
1248                                       : ByteCodeInstruction::kStoreSwizzle,
1249                              count);
1250             fGenerator.write8(location);
1251         }
1252         fGenerator.write8(count);
1253         for (int c : fSwizzle.fComponents) {
1254             fGenerator.write8(c);
1255         }
1256     }
1257 
1258 private:
1259     const Swizzle& fSwizzle;
1260 
1261     typedef LValue INHERITED;
1262 };
1263 
1264 class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
1265 public:
ByteCodeExpressionLValue(ByteCodeGenerator * generator,const Expression & expr)1266     ByteCodeExpressionLValue(ByteCodeGenerator* generator, const Expression& expr)
1267         : INHERITED(*generator)
1268         , fExpression(expr) {}
1269 
load()1270     void load() override {
1271         fGenerator.writeVariableExpression(fExpression);
1272     }
1273 
store(bool discard)1274     void store(bool discard) override {
1275         int count = ByteCodeGenerator::SlotCount(fExpression.fType);
1276         if (!discard) {
1277             if (count > 4) {
1278                 fGenerator.write(ByteCodeInstruction::kDupN, count);
1279                 fGenerator.write8(count);
1280             } else {
1281                 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
1282             }
1283         }
1284         Variable::Storage storage = Variable::kLocal_Storage;
1285         int location = fGenerator.getLocation(fExpression, &storage);
1286         bool isGlobal = storage == Variable::kGlobal_Storage;
1287         if (location < 0 || count > 4) {
1288             if (location >= 0) {
1289                 fGenerator.write(ByteCodeInstruction::kPushImmediate);
1290                 fGenerator.write32(location);
1291             }
1292             fGenerator.write(isGlobal ? ByteCodeInstruction::kStoreExtendedGlobal
1293                                       : ByteCodeInstruction::kStoreExtended,
1294                              count);
1295             fGenerator.write8(count);
1296         } else {
1297             fGenerator.write(vector_instruction(isGlobal ? ByteCodeInstruction::kStoreGlobal
1298                                                          : ByteCodeInstruction::kStore,
1299                                                 count));
1300             fGenerator.write8(location);
1301         }
1302     }
1303 
1304 private:
1305     typedef LValue INHERITED;
1306 
1307     const Expression& fExpression;
1308 };
1309 
getLValue(const Expression & e)1310 std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
1311     switch (e.fKind) {
1312         case Expression::kExternalValue_Kind: {
1313             ExternalValue* value = ((ExternalValueReference&) e).fValue;
1314             int index = fOutput->fExternalValues.size();
1315             fOutput->fExternalValues.push_back(value);
1316             SkASSERT(index <= 255);
1317             return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
1318         }
1319         case Expression::kFieldAccess_Kind:
1320         case Expression::kIndex_Kind:
1321         case Expression::kVariableReference_Kind:
1322             return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
1323         case Expression::kSwizzle_Kind: {
1324             const Swizzle& s = (const Swizzle&) e;
1325             return swizzle_is_simple(s)
1326                     ? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e))
1327                     : std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s));
1328         }
1329         case Expression::kTernary_Kind:
1330         default:
1331             printf("unsupported lvalue %s\n", e.description().c_str());
1332             return nullptr;
1333     }
1334 }
1335 
writeBlock(const Block & b)1336 void ByteCodeGenerator::writeBlock(const Block& b) {
1337     for (const auto& s : b.fStatements) {
1338         this->writeStatement(*s);
1339     }
1340 }
1341 
setBreakTargets()1342 void ByteCodeGenerator::setBreakTargets() {
1343     std::vector<DeferredLocation>& breaks = fBreakTargets.top();
1344     for (DeferredLocation& b : breaks) {
1345         b.set();
1346     }
1347     fBreakTargets.pop();
1348 }
1349 
setContinueTargets()1350 void ByteCodeGenerator::setContinueTargets() {
1351     std::vector<DeferredLocation>& continues = fContinueTargets.top();
1352     for (DeferredLocation& c : continues) {
1353         c.set();
1354     }
1355     fContinueTargets.pop();
1356 }
1357 
writeBreakStatement(const BreakStatement & b)1358 void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
1359     // TODO: Include BranchIfAllFalse to top-most LoopNext
1360     this->write(ByteCodeInstruction::kLoopBreak);
1361 }
1362 
writeContinueStatement(const ContinueStatement & c)1363 void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
1364     // TODO: Include BranchIfAllFalse to top-most LoopNext
1365     this->write(ByteCodeInstruction::kLoopContinue);
1366 }
1367 
writeDoStatement(const DoStatement & d)1368 void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
1369     this->write(ByteCodeInstruction::kLoopBegin);
1370     size_t start = fCode->size();
1371     this->writeStatement(*d.fStatement);
1372     this->write(ByteCodeInstruction::kLoopNext);
1373     this->writeExpression(*d.fTest);
1374     this->write(ByteCodeInstruction::kLoopMask);
1375     // TODO: Could shorten this with kBranchIfAnyTrue
1376     this->write(ByteCodeInstruction::kBranchIfAllFalse);
1377     DeferredLocation endLocation(this);
1378     this->write(ByteCodeInstruction::kBranch);
1379     this->write16(start);
1380     endLocation.set();
1381     this->write(ByteCodeInstruction::kLoopEnd);
1382 }
1383 
writeForStatement(const ForStatement & f)1384 void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
1385     fContinueTargets.emplace();
1386     fBreakTargets.emplace();
1387     if (f.fInitializer) {
1388         this->writeStatement(*f.fInitializer);
1389     }
1390     this->write(ByteCodeInstruction::kLoopBegin);
1391     size_t start = fCode->size();
1392     if (f.fTest) {
1393         this->writeExpression(*f.fTest);
1394         this->write(ByteCodeInstruction::kLoopMask);
1395     }
1396     this->write(ByteCodeInstruction::kBranchIfAllFalse);
1397     DeferredLocation endLocation(this);
1398     this->writeStatement(*f.fStatement);
1399     this->write(ByteCodeInstruction::kLoopNext);
1400     if (f.fNext) {
1401         this->writeExpression(*f.fNext, true);
1402     }
1403     this->write(ByteCodeInstruction::kBranch);
1404     this->write16(start);
1405     endLocation.set();
1406     this->write(ByteCodeInstruction::kLoopEnd);
1407 }
1408 
writeIfStatement(const IfStatement & i)1409 void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
1410     this->writeExpression(*i.fTest);
1411     this->write(ByteCodeInstruction::kMaskPush);
1412     this->write(ByteCodeInstruction::kBranchIfAllFalse);
1413     DeferredLocation falseLocation(this);
1414     this->writeStatement(*i.fIfTrue);
1415     falseLocation.set();
1416     if (i.fIfFalse) {
1417         this->write(ByteCodeInstruction::kMaskNegate);
1418         this->write(ByteCodeInstruction::kBranchIfAllFalse);
1419         DeferredLocation endLocation(this);
1420         this->writeStatement(*i.fIfFalse);
1421         endLocation.set();
1422     }
1423     this->write(ByteCodeInstruction::kMaskPop);
1424 }
1425 
writeReturnStatement(const ReturnStatement & r)1426 void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
1427     if (fLoopCount || fConditionCount) {
1428         fErrors.error(r.fOffset, "return not allowed inside conditional or loop");
1429         return;
1430     }
1431     int count = SlotCount(r.fExpression->fType);
1432     this->writeExpression(*r.fExpression);
1433 
1434     // Technically, the kReturn also pops fOutput->fLocalCount values from the stack, too, but we
1435     // haven't counted pushing those (they're outside the scope of our stack tracking). Instead,
1436     // we account for those in writeFunction().
1437 
1438     // This is all fine because we don't allow conditional returns, so we only return once anyway.
1439     this->write(ByteCodeInstruction::kReturn, -count);
1440     this->write8(count);
1441 }
1442 
writeSwitchStatement(const SwitchStatement & r)1443 void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
1444     // not yet implemented
1445     abort();
1446 }
1447 
writeVarDeclarations(const VarDeclarations & v)1448 void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1449     for (const auto& declStatement : v.fVars) {
1450         const VarDeclaration& decl = (VarDeclaration&) *declStatement;
1451         // we need to grab the location even if we don't use it, to ensure it
1452         // has been allocated
1453         int location = getLocation(*decl.fVar);
1454         if (decl.fValue) {
1455             this->writeExpression(*decl.fValue);
1456             int count = SlotCount(decl.fValue->fType);
1457             if (count > 4) {
1458                 this->write(ByteCodeInstruction::kPushImmediate);
1459                 this->write32(location);
1460                 this->write(ByteCodeInstruction::kStoreExtended, count);
1461                 this->write8(count);
1462             } else {
1463                 this->write(vector_instruction(ByteCodeInstruction::kStore, count));
1464                 this->write8(location);
1465             }
1466         }
1467     }
1468 }
1469 
writeWhileStatement(const WhileStatement & w)1470 void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
1471     this->write(ByteCodeInstruction::kLoopBegin);
1472     size_t cond = fCode->size();
1473     this->writeExpression(*w.fTest);
1474     this->write(ByteCodeInstruction::kLoopMask);
1475     this->write(ByteCodeInstruction::kBranchIfAllFalse);
1476     DeferredLocation endLocation(this);
1477     this->writeStatement(*w.fStatement);
1478     this->write(ByteCodeInstruction::kLoopNext);
1479     this->write(ByteCodeInstruction::kBranch);
1480     this->write16(cond);
1481     endLocation.set();
1482     this->write(ByteCodeInstruction::kLoopEnd);
1483 }
1484 
writeStatement(const Statement & s)1485 void ByteCodeGenerator::writeStatement(const Statement& s) {
1486     switch (s.fKind) {
1487         case Statement::kBlock_Kind:
1488             this->writeBlock((Block&) s);
1489             break;
1490         case Statement::kBreak_Kind:
1491             this->writeBreakStatement((BreakStatement&) s);
1492             break;
1493         case Statement::kContinue_Kind:
1494             this->writeContinueStatement((ContinueStatement&) s);
1495             break;
1496         case Statement::kDiscard_Kind:
1497             // not yet implemented
1498             abort();
1499         case Statement::kDo_Kind:
1500             this->writeDoStatement((DoStatement&) s);
1501             break;
1502         case Statement::kExpression_Kind:
1503             this->writeExpression(*((ExpressionStatement&) s).fExpression, true);
1504             break;
1505         case Statement::kFor_Kind:
1506             this->writeForStatement((ForStatement&) s);
1507             break;
1508         case Statement::kIf_Kind:
1509             this->writeIfStatement((IfStatement&) s);
1510             break;
1511         case Statement::kNop_Kind:
1512             break;
1513         case Statement::kReturn_Kind:
1514             this->writeReturnStatement((ReturnStatement&) s);
1515             break;
1516         case Statement::kSwitch_Kind:
1517             this->writeSwitchStatement((SwitchStatement&) s);
1518             break;
1519         case Statement::kVarDeclarations_Kind:
1520             this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1521             break;
1522         case Statement::kWhile_Kind:
1523             this->writeWhileStatement((WhileStatement&) s);
1524             break;
1525         default:
1526             SkASSERT(false);
1527     }
1528 }
1529 
ByteCodeFunction(const FunctionDeclaration * declaration)1530 ByteCodeFunction::ByteCodeFunction(const FunctionDeclaration* declaration)
1531         : fName(declaration->fName) {
1532     fParameterCount = 0;
1533     for (const auto& p : declaration->fParameters) {
1534         int slots = ByteCodeGenerator::SlotCount(p->fType);
1535         fParameters.push_back({ slots, (bool)(p->fModifiers.fFlags & Modifiers::kOut_Flag) });
1536         fParameterCount += slots;
1537     }
1538 }
1539 
1540 }
1541