• 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 namespace SkSL {
11 
ByteCodeGenerator(const Program * program,ErrorReporter * errors,ByteCode * output)12 ByteCodeGenerator::ByteCodeGenerator(const Program* program, ErrorReporter* errors,
13                                      ByteCode* output)
14     : INHERITED(program, errors, nullptr)
15     , fOutput(output)
16     , fIntrinsics {
17         { "cos",     ByteCode::Instruction::kCos },
18         { "dot",     SpecialIntrinsic::kDot },
19         { "inverse", SpecialIntrinsic::kInverse },
20         { "print",   ByteCode::Instruction::kPrint },
21         { "sin",     ByteCode::Instruction::kSin },
22         { "sqrt",    ByteCode::Instruction::kSqrt },
23         { "tan",     ByteCode::Instruction::kTan },
24     } {}
25 
SlotCount(const Type & type)26 int ByteCodeGenerator::SlotCount(const Type& type) {
27     if (type.kind() == Type::kOther_Kind) {
28         return 0;
29     } else if (type.kind() == Type::kStruct_Kind) {
30         int slots = 0;
31         for (const auto& f : type.fields()) {
32             slots += SlotCount(*f.fType);
33         }
34         SkASSERT(slots <= 255);
35         return slots;
36     } else if (type.kind() == Type::kArray_Kind) {
37         int columns = type.columns();
38         SkASSERT(columns >= 0);
39         int slots = columns * SlotCount(type.componentType());
40         SkASSERT(slots <= 255);
41         return slots;
42     } else {
43         return type.columns() * type.rows();
44     }
45 }
46 
is_uniform(const SkSL::Variable & var)47 static inline bool is_uniform(const SkSL::Variable& var) {
48     return var.fModifiers.fFlags & Modifiers::kUniform_Flag;
49 }
50 
is_in(const SkSL::Variable & var)51 static inline bool is_in(const SkSL::Variable& var) {
52     return var.fModifiers.fFlags & Modifiers::kIn_Flag;
53 }
getLocation(const Variable & var)54 ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var) {
55     // given that we seldom have more than a couple of variables, linear search is probably the most
56     // efficient way to handle lookups
57     switch (var.fStorage) {
58         case Variable::kLocal_Storage: {
59             for (int i = fLocals.size() - 1; i >= 0; --i) {
60                 if (fLocals[i] == &var) {
61                     return ByteCode::Pointer{(uint16_t) (i + fParameterCount)};
62                 }
63             }
64             int result = fLocals.size() + fParameterCount;
65             fLocals.push_back(&var);
66             for (int i = 0; i < SlotCount(var.fType) - 1; ++i) {
67                 fLocals.push_back(nullptr);
68             }
69             SkASSERT(result <= ByteCode::kPointerMax);
70             return ByteCode::Pointer{(uint16_t) result};
71         }
72         case Variable::kParameter_Storage: {
73             int offset = 0;
74             for (const auto& p : fFunction->fDeclaration.fParameters) {
75                 if (p == &var) {
76                     SkASSERT(offset <= ByteCode::kPointerMax);
77                     return ByteCode::Pointer{(uint16_t) offset};
78                 }
79                 offset += SlotCount(p->fType);
80             }
81             SkASSERT(false);
82             return ByteCode::Pointer{0};
83         }
84         case Variable::kGlobal_Storage: {
85             if (is_in(var)) {
86                 // If you see this error, it means the program is using raw 'in' variables. You
87                 // should either specialize the program (Compiler::specialize) to bake in the final
88                 // values of the 'in' variables, or not use 'in' variables (maybe you meant to use
89                 // 'uniform' instead?).
90                 fErrors.error(var.fOffset,
91                               "'in' variable is not specialized or has unsupported type");
92                 return ByteCode::Pointer{0};
93             }
94             bool isUniform = is_uniform(var);
95             int offset = isUniform ? fOutput->getGlobalSlotCount() : 0;
96             for (const auto& e : fProgram) {
97                 if (e.fKind == ProgramElement::kVar_Kind) {
98                     VarDeclarations& decl = (VarDeclarations&) e;
99                     for (const auto& v : decl.fVars) {
100                         const Variable* declVar = ((VarDeclaration&) *v).fVar;
101                         if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
102                             continue;
103                         }
104                         if (isUniform != is_uniform(*declVar)) {
105                             continue;
106                         }
107                         if (declVar == &var) {
108                             SkASSERT(offset <= ByteCode::kPointerMax);
109                             return ByteCode::Pointer{(uint16_t) offset};
110                         }
111                         offset += SlotCount(declVar->fType);
112                     }
113                 }
114             }
115             SkASSERT(false);
116             return ByteCode::Pointer{0};
117         }
118         default:
119             SkASSERT(false);
120             return ByteCode::Pointer{0};
121     }
122 }
123 
124 // A "simple" Swizzle is based on a variable (or a compound variable like a struct or array), and
125 // that references consecutive values, such that it can be implemented using normal load/store ops
126 // with an offset. Note that all single-component swizzles (of suitable base types) are simple.
swizzle_is_simple(const Swizzle & s)127 static bool swizzle_is_simple(const Swizzle& s) {
128     switch (s.fBase->fKind) {
129         case Expression::kFieldAccess_Kind:
130         case Expression::kIndex_Kind:
131         case Expression::kVariableReference_Kind:
132             break;
133         default:
134             return false;
135     }
136 
137     for (size_t i = 1; i < s.fComponents.size(); ++i) {
138         if (s.fComponents[i] != s.fComponents[i - 1] + 1) {
139             return false;
140         }
141     }
142     return true;
143 }
144 
getLocation(const Expression & expr)145 ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Expression& expr) {
146     switch (expr.fKind) {
147         case Expression::kFieldAccess_Kind: {
148             const FieldAccess& f = (const FieldAccess&) expr;
149             Location result = this->getLocation(*f.fBase);
150             int offset = 0;
151             for (int i = 0; i < f.fFieldIndex; ++i) {
152                 offset += SlotCount(*f.fBase->fType.fields()[i].fType);
153             }
154             return result.offset(*this, offset);
155         }
156         case Expression::kIndex_Kind: {
157             const IndexExpression& idx = (const IndexExpression&) expr;
158             int stride = SlotCount(idx.fType);
159             int length = idx.fBase->fType.columns();
160             Location result = this->getLocation(*idx.fBase);
161             if (idx.fIndex->isConstant()) {
162                 int64_t index = idx.fIndex->getConstantInt();
163                 if (index < 0 || index >= length) {
164                     fErrors.error(idx.fIndex->fOffset, "Array index out of bounds");
165                     return result;
166                 }
167                 return result.offset(*this, index * stride);
168             } else {
169                 ByteCode::Register index = this->next(1);
170                 this->writeExpression(*idx.fIndex, index);
171                 this->write(ByteCode::Instruction::kBoundsCheck);
172                 this->write(index);
173                 this->write(length);
174                 ByteCode::Register imm = this->next(1);
175                 this->write(ByteCode::Instruction::kImmediate);
176                 this->write(imm);
177                 this->write(ByteCode::Immediate{stride});
178                 ByteCode::Register offset = this->next(1);
179                 this->write(ByteCode::Instruction::kMultiplyI);
180                 this->write(offset);
181                 this->write(index);
182                 this->write(imm);
183                 return result.offset(*this, offset);
184             }
185         }
186         case Expression::kSwizzle_Kind: {
187             const Swizzle& s = (const Swizzle&) expr;
188             SkASSERT(swizzle_is_simple(s));
189             return this->getLocation(*s.fBase).offset(*this, s.fComponents[0]);
190         }
191         case Expression::kVariableReference_Kind: {
192             const Variable& var = ((const VariableReference&) expr).fVariable;
193             return this->getLocation(var);
194         }
195         default:
196             SkASSERT(false);
197             return ByteCode::Pointer{0};
198     }
199 }
200 
getStorage(const Expression & expr)201 Variable::Storage ByteCodeGenerator::getStorage(const Expression& expr) {
202     switch (expr.fKind) {
203         case Expression::kFieldAccess_Kind: {
204             const FieldAccess& f = (const FieldAccess&) expr;
205             return this->getStorage(*f.fBase);
206         }
207         case Expression::kIndex_Kind: {
208             const IndexExpression& idx = (const IndexExpression&) expr;
209             return this->getStorage(*idx.fBase);
210         }
211         case Expression::kSwizzle_Kind: {
212             const Swizzle& s = (const Swizzle&) expr;
213             return this->getStorage(*s.fBase);
214         }
215         case Expression::kVariableReference_Kind: {
216             const Variable& var = ((const VariableReference&) expr).fVariable;
217             return var.fStorage;
218         }
219         default:
220             SkASSERT(false);
221             return Variable::kLocal_Storage;
222     }
223 }
224 
getLoadInstruction(ByteCodeGenerator::Location location,Variable::Storage storage)225 ByteCode::Instruction ByteCodeGenerator::getLoadInstruction(ByteCodeGenerator::Location location,
226                                                             Variable::Storage storage) {
227     switch (storage) {
228         case Variable::kGlobal_Storage:
229             switch (location.fKind) {
230                 case Location::kPointer_Kind: return ByteCode::Instruction::kLoadDirect;
231                 case Location::kRegister_Kind: return ByteCode::Instruction::kLoad;
232             }
233         case Variable::kParameter_Storage:
234             switch (location.fKind) {
235                 case Location::kPointer_Kind: return ByteCode::Instruction::kLoadParameterDirect;
236                 case Location::kRegister_Kind: return ByteCode::Instruction::kLoadParameter;
237             }
238         case Variable::kLocal_Storage:
239             switch (location.fKind) {
240                 case Location::kPointer_Kind: return ByteCode::Instruction::kLoadStackDirect;
241                 case Location::kRegister_Kind: return ByteCode::Instruction::kLoadStack;
242             }
243         default:
244             break;
245     }
246     SkASSERT(false);
247     return ByteCode::Instruction::kNop;
248 }
249 
getStoreInstruction(ByteCodeGenerator::Location location,Variable::Storage storage)250 ByteCode::Instruction ByteCodeGenerator::getStoreInstruction(ByteCodeGenerator::Location location,
251                                                              Variable::Storage storage) {
252     switch (storage) {
253         case Variable::kGlobal_Storage:
254             switch (location.fKind) {
255                 case Location::kPointer_Kind: return ByteCode::Instruction::kStoreDirect;
256                 case Location::kRegister_Kind: return ByteCode::Instruction::kStore;
257             }
258         case Variable::kParameter_Storage:
259             switch (location.fKind) {
260                 case Location::kPointer_Kind: return ByteCode::Instruction::kStoreParameterDirect;
261                 case Location::kRegister_Kind: return ByteCode::Instruction::kStoreParameter;
262             }
263         case Variable::kLocal_Storage:
264             switch (location.fKind) {
265                 case Location::kPointer_Kind: return ByteCode::Instruction::kStoreStackDirect;
266                 case Location::kRegister_Kind: return ByteCode::Instruction::kStoreStack;
267             }
268         default:
269             break;
270     }
271     SkASSERT(false);
272     return ByteCode::Instruction::kNop;
273 }
274 
275 #define VEC(inst) ((ByteCode::Instruction) ((uint16_t) inst + 1))
276 
277 class ByteCodeSimpleLValue : public ByteCodeGenerator::LValue {
278 public:
ByteCodeSimpleLValue(ByteCodeGenerator * generator,ByteCodeGenerator::Location location,int count,ByteCode::Instruction load,ByteCode::Instruction store)279     ByteCodeSimpleLValue(ByteCodeGenerator* generator, ByteCodeGenerator::Location location,
280                          int count, ByteCode::Instruction load, ByteCode::Instruction store)
281         : INHERITED(*generator)
282         , fLocation(location)
283         , fCount((uint8_t) count)
284         , fLoad(load)
285         , fStore(store) {}
286 
load(ByteCode::Register result)287     void load(ByteCode::Register result) override {
288         fGenerator.write(fLoad, fCount);
289         fGenerator.write(result);
290         fGenerator.write(fLocation);
291     }
292 
store(ByteCode::Register src)293     void store(ByteCode::Register src) override {
294         fGenerator.write(fStore, fCount);
295         fGenerator.write(fLocation);
296         fGenerator.write(src);
297     }
298 
299 private:
300     ByteCodeGenerator::Location fLocation;
301 
302     uint8_t fCount;
303 
304     ByteCode::Instruction fLoad;
305 
306     ByteCode::Instruction fStore;
307 
308     typedef ByteCodeGenerator::LValue INHERITED;
309 };
310 
311 class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
312 public:
ByteCodeSwizzleLValue(ByteCodeGenerator * generator,const Swizzle * swizzle)313     ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle* swizzle)
314         : INHERITED(*generator)
315         , fSwizzle(*swizzle) {}
316 
load(ByteCode::Register result)317     void load(ByteCode::Register result) override {
318         fGenerator.writeSwizzle(fSwizzle, result);
319     }
320 
store(ByteCode::Register src)321     void store(ByteCode::Register src) override {
322         ByteCodeGenerator::Location target = fGenerator.getLocation(*fSwizzle.fBase);
323         ByteCode::Instruction inst = fGenerator.getStoreInstruction(
324                                                             target,
325                                                             fGenerator.getStorage(*fSwizzle.fBase));
326         for (size_t i = 0; i < fSwizzle.fComponents.size(); ++i) {
327             ByteCodeGenerator::Location final = target.offset(fGenerator, fSwizzle.fComponents[i]);
328             fGenerator.write(inst);
329             fGenerator.write(final);
330             fGenerator.write(src + i);
331         }
332     }
333 
334 private:
335     const Swizzle& fSwizzle;
336 
337     typedef ByteCodeGenerator::LValue INHERITED;
338 };
339 
340 class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
341 public:
ByteCodeExternalValueLValue(ByteCodeGenerator * generator,ExternalValue & value,int index)342     ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
343         : INHERITED(*generator)
344         , fIndex(index)
345         , fSlotCount(ByteCodeGenerator::SlotCount(value.type())) {
346         SkASSERT(fSlotCount <= 4);
347     }
348 
load(ByteCode::Register result)349     void load(ByteCode::Register result) override {
350         fGenerator.write(ByteCode::Instruction::kReadExternal);
351         fGenerator.write(result);
352         fGenerator.write((uint8_t) fSlotCount);
353         fGenerator.write((uint8_t) fIndex);
354     }
355 
store(ByteCode::Register src)356     void store(ByteCode::Register src) override {
357         fGenerator.write(ByteCode::Instruction::kWriteExternal);
358         fGenerator.write((uint8_t) fIndex);
359         fGenerator.write((uint8_t) fSlotCount);
360         fGenerator.write(src);
361     }
362 
363 private:
364     typedef LValue INHERITED;
365 
366     int fIndex;
367 
368     int fSlotCount;
369 };
370 
getLValue(const Expression & expr)371 std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& expr) {
372     switch (expr.fKind) {
373         case Expression::kExternalValue_Kind: {
374             ExternalValue* value = ((ExternalValueReference&) expr).fValue;
375             int index = fOutput->fExternalValues.size();
376             fOutput->fExternalValues.push_back(value);
377             SkASSERT(index <= 255);
378             return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
379         }
380         case Expression::kFieldAccess_Kind:
381         case Expression::kIndex_Kind:
382         case Expression::kVariableReference_Kind: {
383             Location location = this->getLocation(expr);
384             Variable::Storage storage = this->getStorage(expr);
385             ByteCode::Instruction loadInst = this->getLoadInstruction(location, storage);
386             ByteCode::Instruction storeInst = this->getStoreInstruction(location, storage);
387             return std::unique_ptr<LValue>(new ByteCodeSimpleLValue(this, location,
388                                                                     SlotCount(expr.fType),
389                                                                     loadInst, storeInst));
390         }
391         case Expression::kSwizzle_Kind:
392             return std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, &(Swizzle&) expr));
393         default:
394             ABORT("unsupported lvalue\n");
395     }
396 }
397 
next(int count)398 ByteCode::Register ByteCodeGenerator::next(int count) {
399     SkASSERT(fNextRegister + count <= ByteCode::kRegisterMax);
400     fNextRegister += count;
401     return ByteCode::Register{(uint16_t) (fNextRegister - count)};
402 }
403 
type_category(const Type & type)404 static TypeCategory type_category(const Type& type) {
405     switch (type.kind()) {
406         case Type::Kind::kVector_Kind:
407         case Type::Kind::kMatrix_Kind:
408             return type_category(type.componentType());
409         default:
410             String name = type.displayName();
411             if (name == "bool") {
412                 return TypeCategory::kBool;
413             } else if (name == "int" || name == "short") {
414                 return TypeCategory::kSigned;
415             } else if (name == "uint" || name == "ushort") {
416                 return TypeCategory::kUnsigned;
417             } else {
418                 SkASSERT(name == "float" || name == "half");
419                 return TypeCategory::kFloat;
420             }
421             ABORT("unsupported type: %s\n", name.c_str());
422     }
423 }
424 
write(ByteCode::Instruction inst,int count)425 void ByteCodeGenerator::write(ByteCode::Instruction inst, int count) {
426     SkASSERT(count <= 255);
427     if (count > 1) {
428         this->write(VEC(inst));
429         this->write((uint8_t) count);
430     }
431     else {
432         this->write(inst);
433     }
434 }
435 
writeTypedInstruction(const Type & type,ByteCode::Instruction s,ByteCode::Instruction u,ByteCode::Instruction f)436 void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCode::Instruction s,
437                                               ByteCode::Instruction u, ByteCode::Instruction f) {
438     switch (type_category(type)) {
439         case TypeCategory::kSigned:
440             this->write(s);
441             break;
442         case TypeCategory::kUnsigned:
443             this->write(u);
444             break;
445         case TypeCategory::kFloat: {
446             this->write(f);
447             break;
448         }
449         default:
450             SkASSERT(false);
451     }
452 }
453 
writeVectorBinaryInstruction(const Type & operandType,ByteCode::Register left,ByteCode::Register right,ByteCode::Instruction s,ByteCode::Instruction u,ByteCode::Instruction f,ByteCode::Register result)454 void ByteCodeGenerator::writeVectorBinaryInstruction(const Type& operandType,
455                                                      ByteCode::Register left,
456                                                      ByteCode::Register right,
457                                                      ByteCode::Instruction s,
458                                                      ByteCode::Instruction u,
459                                                      ByteCode::Instruction f,
460                                                      ByteCode::Register result) {
461     uint8_t count = (uint8_t) SlotCount(operandType);
462     if (count == 1) {
463         this->writeTypedInstruction(operandType, s, u, f);
464     }
465     else {
466         this->writeTypedInstruction(operandType, VEC(s), VEC(u), VEC(f));
467         this->write(count);
468     }
469     this->write(result);
470     this->write(left);
471     this->write(right);
472 }
473 
writeBinaryInstruction(const Type & operandType,ByteCode::Register left,ByteCode::Register right,ByteCode::Instruction s,ByteCode::Instruction u,ByteCode::Instruction f,ByteCode::Register result)474 void ByteCodeGenerator::writeBinaryInstruction(const Type& operandType,
475                                                ByteCode::Register left,
476                                                ByteCode::Register right,
477                                                ByteCode::Instruction s,
478                                                ByteCode::Instruction u,
479                                                ByteCode::Instruction f,
480                                                ByteCode::Register result) {
481     for (int i = 0; i < SlotCount(operandType); ++i) {
482         this->writeTypedInstruction(operandType, s, u, f);
483         this->write(result + i);
484         this->write(left + i);
485         this->write(right + i);
486     }
487 }
488 
writeBinaryExpression(const BinaryExpression & b,ByteCode::Register result)489 void ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
490                                               ByteCode::Register result) {
491     if (b.fOperator == Token::Kind::EQ) {
492         std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
493         this->writeExpression(*b.fRight, result);
494         lvalue->store(result);
495         return;
496     }
497     const Type& lType = b.fLeft->fType;
498     const Type& rType = b.fRight->fType;
499     bool lVecOrMtx = (lType.kind() == Type::kVector_Kind || lType.kind() == Type::kMatrix_Kind);
500     bool rVecOrMtx = (rType.kind() == Type::kVector_Kind || rType.kind() == Type::kMatrix_Kind);
501     const Type* operandType;
502     if (!lVecOrMtx && rVecOrMtx) {
503         operandType = &rType;
504     } else {
505         operandType = &lType;
506     }
507     Token::Kind op;
508     std::unique_ptr<LValue> lvalue;
509     ByteCode::Register left;
510     switch (b.fOperator) {
511         case Token::Kind::LOGICALAND:
512         case Token::Kind::LOGICALANDEQ:
513         case Token::Kind::LOGICALOR:
514         case Token::Kind::LOGICALOREQ:
515             left = result;
516             break;
517         default:
518             left = this->next(SlotCount(*operandType));
519     }
520     if (is_assignment(b.fOperator)) {
521         lvalue = this->getLValue(*b.fLeft);
522         lvalue->load(left);
523         op = remove_assignment(b.fOperator);
524     } else {
525         this->writeExpression(*b.fLeft, left);
526         op = b.fOperator;
527         if (!lVecOrMtx && rVecOrMtx) {
528             this->write(ByteCode::Instruction::kSplat);
529             this->write((uint8_t) (SlotCount(rType) - 1));
530             this->write(left + 1);
531             this->write(left);
532         }
533     }
534     SkDEBUGCODE(TypeCategory tc = type_category(lType));
535     int count = std::max(SlotCount(lType), SlotCount(rType));
536     switch (op) {
537         case Token::Kind::LOGICALAND: {
538             SkASSERT(left.fIndex == result.fIndex);
539             this->write(ByteCode::Instruction::kMaskPush);
540             ++fConditionCount;
541             this->write(left);
542             this->write(ByteCode::Instruction::kBranchIfAllFalse);
543             DeferredLocation falseLocation(this);
544             SkASSERT(SlotCount(b.fRight->fType) == 1);
545             ByteCode::Register right = this->next(1);
546             this->writeExpression(*b.fRight, right);
547             this->write(ByteCode::Instruction::kAnd);
548             this->write(result);
549             this->write(left);
550             this->write(right);
551             falseLocation.set();
552             --fConditionCount;
553             this->write(ByteCode::Instruction::kMaskPop);
554             return;
555         }
556         case Token::Kind::LOGICALOR: {
557             SkASSERT(left.fIndex == result.fIndex);
558             ByteCode::Register mask = this->next(1);
559             this->write(ByteCode::Instruction::kNot);
560             this->write(mask);
561             this->write(left);
562             this->write(ByteCode::Instruction::kMaskPush);
563             ++fConditionCount;
564             this->write(mask);
565             this->write(ByteCode::Instruction::kBranchIfAllFalse);
566             DeferredLocation falseLocation(this);
567             SkASSERT(SlotCount(b.fRight->fType) == 1);
568             ByteCode::Register right = this->next(1);
569             this->writeExpression(*b.fRight, right);
570             this->write(ByteCode::Instruction::kOr);
571             this->write(result);
572             this->write(left);
573             this->write(right);
574             falseLocation.set();
575             --fConditionCount;
576             this->write(ByteCode::Instruction::kMaskPop);
577             return;
578         }
579         case Token::Kind::SHL:
580         case Token::Kind::SHR: {
581             SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
582                                     tc == SkSL::TypeCategory::kUnsigned));
583             if (!b.fRight->isConstant()) {
584                 fErrors.error(b.fRight->fOffset, "Shift amounts must be constant");
585                 return;
586             }
587             int64_t shift = b.fRight->getConstantInt();
588             if (shift < 0 || shift > 31) {
589                 fErrors.error(b.fRight->fOffset, "Shift amount out of range");
590                 return;
591             }
592 
593             if (op == Token::Kind::SHL) {
594                 this->write(ByteCode::Instruction::kShiftLeft);
595             } else {
596                 this->write(type_category(lType) == TypeCategory::kSigned
597                                 ? ByteCode::Instruction::kShiftRightS
598                                 : ByteCode::Instruction::kShiftRightU);
599             }
600             this->write(result);
601             this->write(left);
602             this->write((uint8_t) shift);
603             return;
604         }
605         case Token::Kind::STAR:
606             // Special case for M*V, V*M, M*M (but not V*V!)
607             if (lType.columns() > 1 && rType.columns() > 1 &&
608                 (lType.rows() > 1 || rType.rows() > 1)) {
609                 ByteCode::Register right = this->next(SlotCount(rType));
610                 this->writeExpression(*b.fRight, right);
611                 int rCols = rType.columns(),
612                     rRows = rType.rows(),
613                     lCols = lType.columns(),
614                     lRows = lType.rows();
615                 // M*V treats the vector as a column
616                 if (rType.kind() == Type::kVector_Kind) {
617                     std::swap(rCols, rRows);
618                 }
619                 SkASSERT(lCols == rRows);
620                 SkASSERT(SlotCount(b.fType) == lRows * rCols);
621                 this->write(ByteCode::Instruction::kMatrixMultiply);
622                 this->write(result);
623                 this->write(left);
624                 this->write(right);
625                 this->write((uint8_t) lCols);
626                 this->write((uint8_t) lRows);
627                 this->write((uint8_t) rCols);
628                 return;
629             }
630 
631         default:
632             break;
633     }
634     ByteCode::Register right = this->next(SlotCount(*operandType));
635     this->writeExpression(*b.fRight, right);
636     if (lVecOrMtx && !rVecOrMtx) {
637         this->write(ByteCode::Instruction::kSplat);
638         this->write((uint8_t) (SlotCount(*operandType) - 1));
639         this->write(right + 1);
640         this->write(right);
641     }
642     switch (op) {
643         case Token::Kind::EQEQ:
644             this->writeBinaryInstruction(*operandType, left, right,
645                                          ByteCode::Instruction::kCompareEQI,
646                                          ByteCode::Instruction::kCompareEQI,
647                                          ByteCode::Instruction::kCompareEQF,
648                                          result);
649             // Collapse to a single bool
650             for (int i = 1; i < count; ++i) {
651                 this->write(ByteCode::Instruction::kAnd);
652                 this->write(result);
653                 this->write(result);
654                 this->write(result + i);
655             }
656             break;
657         case Token::Kind::GT:
658             this->writeBinaryInstruction(*operandType, left, right,
659                                          ByteCode::Instruction::kCompareGTS,
660                                          ByteCode::Instruction::kCompareGTU,
661                                          ByteCode::Instruction::kCompareGTF,
662                                          result);
663             break;
664         case Token::Kind::GTEQ:
665             this->writeBinaryInstruction(*operandType, left, right,
666                                          ByteCode::Instruction::kCompareGTEQS,
667                                          ByteCode::Instruction::kCompareGTEQU,
668                                          ByteCode::Instruction::kCompareGTEQF,
669                                          result);
670             break;
671         case Token::Kind::LT:
672             this->writeBinaryInstruction(*operandType, left, right,
673                                          ByteCode::Instruction::kCompareLTS,
674                                          ByteCode::Instruction::kCompareLTU,
675                                          ByteCode::Instruction::kCompareLTF,
676                                          result);
677             break;
678         case Token::Kind::LTEQ:
679             this->writeBinaryInstruction(*operandType, left, right,
680                                          ByteCode::Instruction::kCompareLTEQS,
681                                          ByteCode::Instruction::kCompareLTEQU,
682                                          ByteCode::Instruction::kCompareLTEQF,
683                                          result);
684             break;
685         case Token::Kind::MINUS:
686             this->writeVectorBinaryInstruction(*operandType, left, right,
687                                                ByteCode::Instruction::kSubtractI,
688                                                ByteCode::Instruction::kSubtractI,
689                                                ByteCode::Instruction::kSubtractF,
690                                                result);
691             break;
692         case Token::Kind::NEQ:
693             this->writeBinaryInstruction(*operandType, left, right,
694                                          ByteCode::Instruction::kCompareNEQI,
695                                          ByteCode::Instruction::kCompareNEQI,
696                                          ByteCode::Instruction::kCompareNEQF,
697                                          result);
698             // Collapse to a single bool
699             for (int i = 1; i < count; ++i) {
700                 this->write(ByteCode::Instruction::kOr);
701                 this->write(result);
702                 this->write(result);
703                 this->write(result + i);
704             }
705             break;
706         case Token::Kind::PERCENT:
707             this->writeVectorBinaryInstruction(*operandType, left, right,
708                                                ByteCode::Instruction::kRemainderS,
709                                                ByteCode::Instruction::kRemainderU,
710                                                ByteCode::Instruction::kRemainderF,
711                                                result);
712             break;
713         case Token::Kind::PLUS:
714             this->writeVectorBinaryInstruction(*operandType, left, right,
715                                                ByteCode::Instruction::kAddI,
716                                                ByteCode::Instruction::kAddI,
717                                                ByteCode::Instruction::kAddF,
718                                                result);
719             break;
720         case Token::Kind::SLASH:
721             this->writeVectorBinaryInstruction(*operandType, left, right,
722                                                ByteCode::Instruction::kDivideS,
723                                                ByteCode::Instruction::kDivideU,
724                                                ByteCode::Instruction::kDivideF,
725                                                result);
726             break;
727         case Token::Kind::STAR:
728             this->writeVectorBinaryInstruction(*operandType, left, right,
729                                                ByteCode::Instruction::kMultiplyI,
730                                                ByteCode::Instruction::kMultiplyI,
731                                                ByteCode::Instruction::kMultiplyF,
732                                                result);
733             break;
734         case Token::Kind::LOGICALXOR: {
735             SkASSERT(tc == SkSL::TypeCategory::kBool);
736             this->write(ByteCode::Instruction::kXor);
737             this->write(result);
738             this->write(left);
739             this->write(right);
740             break;
741         }
742         case Token::Kind::BITWISEAND: {
743             SkASSERT(tc == SkSL::TypeCategory::kSigned || tc == SkSL::TypeCategory::kUnsigned);
744             this->write(ByteCode::Instruction::kAnd);
745             this->write(result);
746             this->write(left);
747             this->write(right);
748             break;
749         }
750         case Token::Kind::BITWISEOR: {
751             SkASSERT(tc == SkSL::TypeCategory::kSigned || tc == SkSL::TypeCategory::kUnsigned);
752             this->write(ByteCode::Instruction::kOr);
753             this->write(result);
754             this->write(left);
755             this->write(right);
756             break;
757         }
758         case Token::Kind::BITWISEXOR: {
759             SkASSERT(tc == SkSL::TypeCategory::kSigned || tc == SkSL::TypeCategory::kUnsigned);
760             this->write(ByteCode::Instruction::kXor);
761             this->write(result);
762             this->write(left);
763             this->write(right);
764             break;
765         }
766         default:
767             fErrors.error(b.fOffset, SkSL::String::printf("Unsupported binary operator '%s'",
768                                                           Compiler::OperatorName(op)));
769             break;
770     }
771     if (lvalue) {
772         lvalue->store(result);
773     }
774 }
775 
writeConstructor(const Constructor & c,ByteCode::Register result)776 void ByteCodeGenerator::writeConstructor(const Constructor& c, ByteCode::Register result) {
777     if (c.fType.rows() > 1) {
778         if (c.fArguments.size() == 1) {
779             if (SlotCount(c.fArguments[0]->fType) == 1) {
780                 ByteCode::Register v = this->next(1);
781                 this->writeExpression(*c.fArguments[0], v);
782                 this->write(ByteCode::Instruction::kScalarToMatrix);
783                 this->write(result);
784                 this->write(v);
785                 this->write((uint8_t) c.fType.columns());
786                 this->write((uint8_t) c.fType.rows());
787                 return;
788             } else if (c.fArguments[0]->fType.rows() > 1) {
789                 ByteCode::Register v = this->next(SlotCount(c.fArguments[0]->fType));
790                 this->writeExpression(*c.fArguments[0], v);
791                 this->write(ByteCode::Instruction::kMatrixToMatrix);
792                 this->write(result);
793                 this->write(v);
794                 this->write((uint8_t) c.fArguments[0]->fType.columns());
795                 this->write((uint8_t) c.fArguments[0]->fType.rows());
796                 this->write((uint8_t) c.fType.columns());
797                 this->write((uint8_t) c.fType.rows());
798                 return;
799             }
800         }
801         int offset = 0;
802         for (const auto& arg : c.fArguments) {
803             this->writeExpression(*arg, ByteCode::Register{(uint16_t) (result.fIndex + offset)});
804             offset += SlotCount(arg->fType);
805         }
806         return;
807     }
808     if (c.fArguments.size() == 1 && c.fArguments[0]->fType.columns() == 1 &&
809         c.fType.columns() > 1) {
810         SkASSERT(SlotCount(c.fArguments[0]->fType) == 1);
811         ByteCode::Register v = result;
812         this->writeExpression(*c.fArguments[0], v);
813         this->write(ByteCode::Instruction::kSplat);
814         this->write((uint8_t) (c.fType.columns() - 1));
815         this->write(v + 1);
816         this->write(v);
817         return;
818     }
819     ByteCode::Instruction inst;
820     switch (type_category(c.fArguments[0]->fType)) {
821         case TypeCategory::kSigned:
822             if (type_category(c.fType) == TypeCategory::kFloat) {
823                 inst = ByteCode::Instruction::kSignedToFloat;
824             } else {
825                 inst = ByteCode::Instruction::kNop;
826             }
827             break;
828         case TypeCategory::kUnsigned:
829             if (type_category(c.fType) == TypeCategory::kFloat) {
830                 inst = ByteCode::Instruction::kUnsignedToFloat;
831             } else {
832                 inst = ByteCode::Instruction::kNop;
833             }
834             break;
835         case TypeCategory::kFloat:
836             if (type_category(c.fType) == TypeCategory::kSigned) {
837                 inst = ByteCode::Instruction::kFloatToSigned;
838             } else if (type_category(c.fType) == TypeCategory::kUnsigned) {
839                 inst = ByteCode::Instruction::kFloatToUnsigned;
840             } else {
841                 inst = ByteCode::Instruction::kNop;
842             }
843             break;
844         default:
845             SkASSERT(false);
846             return;
847     }
848     ByteCode::Register values;
849     if (inst == ByteCode::Instruction::kNop) {
850         values = result;
851     } else {
852         values = this->next(SlotCount(c.fType));
853     }
854     ByteCode::Register v = values;
855     for (size_t i = 0; i < c.fArguments.size(); ++i) {
856         this->writeExpression(*c.fArguments[i], v);
857         v.fIndex += SlotCount(c.fArguments[i]->fType);
858     }
859     if (inst != ByteCode::Instruction::kNop) {
860         v = values;
861         ByteCode::Register target = result;
862         for (size_t i = 0; i < c.fArguments.size(); ++i) {
863             int count = SlotCount(c.fArguments[i]->fType);
864             for (int j = 0; j < count; ++j) {
865                 this->write(inst);
866                 this->write(target);
867                 ++target.fIndex;
868                 this->write(v + j);
869             }
870         }
871     }
872 }
873 
writeExternalFunctionCall(const ExternalFunctionCall & f,ByteCode::Register result)874 void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f,
875                                                   ByteCode::Register result) {
876     int argumentCount = 0;
877     for (const auto& arg : f.fArguments) {
878         argumentCount += SlotCount(arg->fType);
879     }
880     ByteCode::Register args = this->next(argumentCount);
881     argumentCount = 0;
882     for (const auto& arg : f.fArguments) {
883         this->writeExpression(*arg, args + argumentCount);
884         argumentCount += SlotCount(arg->fType);
885     }
886     this->write(ByteCode::Instruction::kCallExternal);
887     this->write(result);
888     int index = fOutput->fExternalValues.size();
889     fOutput->fExternalValues.push_back(f.fFunction);
890     SkASSERT(index <= 255);
891     this->write((uint8_t) index);
892     SkASSERT(SlotCount(f.fType) <= 255);
893     this->write((uint8_t) SlotCount(f.fType));
894     this->write(args);
895     SkASSERT(argumentCount <= 255);
896     this->write((uint8_t) argumentCount);
897 }
898 
writeExternalValue(const ExternalValueReference & e,ByteCode::Register result)899 void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e,
900                                            ByteCode::Register result) {
901     this->write(ByteCode::Instruction::kReadExternal);
902     this->write(result);
903     this->write((uint8_t) SlotCount(e.fValue->type()));
904     int index = fOutput->fExternalValues.size();
905     fOutput->fExternalValues.push_back(e.fValue);
906     SkASSERT(index <= 255);
907     this->write((uint8_t) index);
908 }
909 
writeIntrinsicCall(const FunctionCall & c,Intrinsic intrinsic,ByteCode::Register result)910 void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c, Intrinsic intrinsic,
911                                            ByteCode::Register result) {
912     if (intrinsic.fIsSpecial) {
913         switch (intrinsic.fValue.fSpecial) {
914             case SpecialIntrinsic::kDot: {
915                 SkASSERT(c.fArguments.size() == 2);
916                 int count = SlotCount(c.fArguments[0]->fType);
917                 ByteCode::Register left = this->next(count);
918                 this->writeExpression(*c.fArguments[0], left);
919                 ByteCode::Register right = this->next(count);
920                 this->writeExpression(*c.fArguments[1], right);
921                 ByteCode::Register product = this->next(count);
922                 this->writeTypedInstruction(c.fType,
923                                             ByteCode::Instruction::kMultiplyIN,
924                                             ByteCode::Instruction::kMultiplyIN,
925                                             ByteCode::Instruction::kMultiplyFN);
926                 this->write((uint8_t) count);
927                 this->write(product);
928                 this->write(left);
929                 this->write(right);
930                 ByteCode::Register total = product;
931                 for (int i = 1; i < count; ++i) {
932                     this->writeTypedInstruction(c.fType,
933                                                 ByteCode::Instruction::kAddI,
934                                                 ByteCode::Instruction::kAddI,
935                                                 ByteCode::Instruction::kAddF);
936                     ByteCode::Register sum = i == count - 1 ? result : this->next(1);
937                     this->write(sum);
938                     this->write(total);
939                     this->write(product + i);
940                     total = sum;
941                 }
942                 break;
943             }
944             case SpecialIntrinsic::kInverse: {
945                 SkASSERT(c.fArguments.size() == 1);
946                 int count = SlotCount(c.fArguments[0]->fType);
947                 ByteCode::Register arg = this->next(count);
948                 this->writeExpression(*c.fArguments[0], arg);
949                 switch (SlotCount(c.fArguments[0]->fType)) {
950                     case 4:  this->write(ByteCode::Instruction::kInverse2x2); break;
951                     case 9:  this->write(ByteCode::Instruction::kInverse3x3); break;
952                     case 16: this->write(ByteCode::Instruction::kInverse4x4); break;
953                     default: SkASSERT(false);
954                 }
955                 this->write(result);
956                 this->write(arg);
957                 break;
958             }
959         }
960     } else {
961         std::vector<ByteCode::Register> argRegs;
962         for (const auto& expr : c.fArguments) {
963             ByteCode::Register reg = this->next(SlotCount(expr->fType));
964             this->writeExpression(*expr, reg);
965             argRegs.push_back(reg);
966         }
967         this->write(intrinsic.fValue.fInstruction);
968         if (c.fType.fName != "void") {
969             this->write(result);
970         }
971         for (ByteCode::Register arg : argRegs) {
972             this->write(arg);
973         }
974     }
975 }
976 
writeFunctionCall(const FunctionCall & c,ByteCode::Register result)977 void ByteCodeGenerator::writeFunctionCall(const FunctionCall& c, ByteCode::Register result) {
978     auto found = fIntrinsics.find(c.fFunction.fName);
979     if (found != fIntrinsics.end()) {
980         return this->writeIntrinsicCall(c, found->second, result);
981     }
982     int argCount = c.fArguments.size();
983     std::vector<std::unique_ptr<LValue>> lvalues;
984     int parameterSlotCount = 0;
985     for (const auto& p : c.fFunction.fParameters) {
986         parameterSlotCount += SlotCount(p->fType);
987     }
988     ByteCode::Register argStart = this->next(parameterSlotCount);
989     ByteCode::Register nextArg = argStart;
990     for (int i = 0; i < argCount; ++i) {
991         const auto& param = c.fFunction.fParameters[i];
992         const auto& arg = c.fArguments[i];
993         if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
994             lvalues.emplace_back(this->getLValue(*arg));
995             lvalues.back()->load(nextArg);
996         } else {
997             this->writeExpression(*arg, nextArg);
998         }
999         nextArg.fIndex += SlotCount(arg->fType);
1000     }
1001     // Find the index of the function we're calling. We explicitly do not allow calls to functions
1002     // before they're defined. This is an easy-to-understand rule that prevents recursion.
1003     size_t idx;
1004     for (idx = 0; idx < fFunctions.size(); ++idx) {
1005         if (c.fFunction.matches(fFunctions[idx]->fDeclaration)) {
1006             break;
1007         }
1008     }
1009     if (idx > 255) {
1010         fErrors.error(c.fOffset, "Function count limit exceeded");
1011         return;
1012     } else if (idx >= fOutput->fFunctions.size()) {
1013         fErrors.error(c.fOffset, "Call to undefined function");
1014         return;
1015     }
1016 
1017     this->write(ByteCode::Instruction::kCall);
1018     this->write(result);
1019     this->write((uint8_t) idx);
1020     this->write(argStart);
1021     nextArg = argStart;
1022     auto lvalue = lvalues.begin();
1023     for (int i = 0; i < argCount; ++i) {
1024         const auto& param = c.fFunction.fParameters[i];
1025         if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1026             (*(lvalue++))->store(nextArg);
1027         }
1028         nextArg.fIndex += SlotCount(param->fType);
1029     }
1030 }
1031 
incOrDec(Token::Kind op,Expression & operand,bool prefix,ByteCode::Register result)1032 void ByteCodeGenerator::incOrDec(Token::Kind op, Expression& operand, bool prefix,
1033                                  ByteCode::Register result) {
1034     SkASSERT(op == Token::Kind::PLUSPLUS || op == Token::Kind::MINUSMINUS);
1035     std::unique_ptr<LValue> lvalue = this->getLValue(operand);
1036     SkASSERT(SlotCount(operand.fType) == 1);
1037     ByteCode::Register value;
1038     if (prefix) {
1039         value = this->next(1);
1040     } else {
1041         value = result;
1042     }
1043     lvalue->load(value);
1044     ByteCode::Register one = this->next(1);
1045     this->write(ByteCode::Instruction::kImmediate);
1046     this->write(one);
1047     if (type_category(operand.fType) == TypeCategory::kFloat) {
1048         this->write(ByteCode::Immediate(1.0f));
1049     } else {
1050         this->write(ByteCode::Immediate((int32_t) 1));
1051     }
1052     if (op == Token::Kind::PLUSPLUS) {
1053         this->writeTypedInstruction(operand.fType,
1054                                     ByteCode::Instruction::kAddI,
1055                                     ByteCode::Instruction::kAddI,
1056                                     ByteCode::Instruction::kAddF);
1057     } else {
1058         this->writeTypedInstruction(operand.fType,
1059                                     ByteCode::Instruction::kSubtractI,
1060                                     ByteCode::Instruction::kSubtractI,
1061                                     ByteCode::Instruction::kSubtractF);
1062     }
1063     if (prefix) {
1064         this->write(result);
1065         this->write(value);
1066         this->write(one);
1067         lvalue->store(result);
1068     } else {
1069         ByteCode::Register temp = this->next(1);
1070         this->write(temp);
1071         this->write(value);
1072         this->write(one);
1073         lvalue->store(temp);
1074     }
1075 }
1076 
writePostfixExpression(const PostfixExpression & p,ByteCode::Register result)1077 void ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p,
1078                                                ByteCode::Register result) {
1079     this->incOrDec(p.fOperator, *p.fOperand, false, result);
1080 }
1081 
writePrefixExpression(const PrefixExpression & p,ByteCode::Register result)1082 void ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p,
1083                                               ByteCode::Register result) {
1084     switch (p.fOperator) {
1085         case Token::Kind::PLUSPLUS:
1086         case Token::Kind::MINUSMINUS: {
1087             return this->incOrDec(p.fOperator, *p.fOperand, true, result);
1088         }
1089         case Token::Kind::MINUS: {
1090             ByteCode::Register src = this->next(SlotCount(p.fType));
1091             this->writeExpression(*p.fOperand, src);
1092             for (int i = 0; i < SlotCount(p.fType); ++i) {
1093                 this->writeTypedInstruction(p.fType,
1094                                             ByteCode::Instruction::kNegateS,
1095                                             ByteCode::Instruction::kNegateS,
1096                                             ByteCode::Instruction::kNegateF);
1097                 this->write(result + i);
1098                 this->write(src + i);
1099             }
1100             break;
1101         }
1102         case Token::Kind::LOGICALNOT:
1103         case Token::Kind::BITWISENOT: {
1104             ByteCode::Register src = this->next(SlotCount(p.fType));
1105             this->writeExpression(*p.fOperand, src);
1106             for (int i = 0; i < SlotCount(p.fType); ++i) {
1107                 this->write(ByteCode::Instruction::kNot);
1108                 this->write(result + i);
1109                 this->write(src + i);
1110             }
1111             break;
1112         }
1113         default:
1114             SkASSERT(false);
1115     }
1116 }
1117 
writeSwizzle(const Swizzle & s,ByteCode::Register result)1118 void ByteCodeGenerator::writeSwizzle(const Swizzle& s, ByteCode::Register result) {
1119     if (swizzle_is_simple(s)) {
1120         this->writeVariableExpression(s, result);
1121         return;
1122     }
1123     ByteCode::Register base = this->writeExpression(*s.fBase);
1124     for (int i = 0; i < (int) s.fComponents.size(); ++i) {
1125         this->write(ByteCode::Instruction::kCopy);
1126         this->write(result + i);
1127         this->write(base + s.fComponents[i]);
1128     }
1129 }
1130 
writeTernaryExpression(const TernaryExpression & t,ByteCode::Register result)1131 void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t,
1132                                                ByteCode::Register result) {
1133     int count = SlotCount(t.fType);
1134     SkASSERT(count == SlotCount(t.fIfTrue->fType));
1135     SkASSERT(count == SlotCount(t.fIfFalse->fType));
1136 
1137     ByteCode::Register test = this->writeExpression(*t.fTest);
1138     this->write(ByteCode::Instruction::kMaskPush);
1139     ++fConditionCount;
1140     this->write(test);
1141     ByteCode::Register ifTrue = this->writeExpression(*t.fIfTrue);
1142     this->write(ByteCode::Instruction::kMaskNegate);
1143     ByteCode::Register ifFalse = this->writeExpression(*t.fIfFalse);
1144     --fConditionCount;
1145     this->write(ByteCode::Instruction::kMaskPop);
1146     for (int i = 0; i < count; ++i) {
1147         this->write(ByteCode::Instruction::kSelect);
1148         this->write(result + i);
1149         this->write(test);
1150         this->write(ifTrue + i);
1151         this->write(ifFalse + i);
1152     }
1153 }
1154 
writeVariableExpression(const Expression & expr,ByteCode::Register result)1155 void ByteCodeGenerator::writeVariableExpression(const Expression& expr,
1156                                                 ByteCode::Register result) {
1157     ByteCodeGenerator::Location location = this->getLocation(expr);
1158     int count = SlotCount(expr.fType);
1159     ByteCode::Instruction load = this->getLoadInstruction(location, this->getStorage(expr));
1160     this->write(load, count);
1161     this->write(result);
1162     this->write(location);
1163 }
1164 
writeExpression(const Expression & expr,ByteCode::Register result)1165 void ByteCodeGenerator::writeExpression(const Expression& expr, ByteCode::Register result) {
1166     switch (expr.fKind) {
1167         case Expression::kBoolLiteral_Kind: {
1168             this->write(ByteCode::Instruction::kImmediate);
1169             this->write(result);
1170             this->write(ByteCode::Immediate((int32_t) (((BoolLiteral&) expr).fValue ? -1 : 0)));
1171             break;
1172         }
1173         case Expression::kBinary_Kind: {
1174             this->writeBinaryExpression((BinaryExpression&) expr, result);
1175             break;
1176         }
1177         case Expression::kConstructor_Kind: {
1178             this->writeConstructor((Constructor&) expr, result);
1179             break;
1180         }
1181         case Expression::kExternalFunctionCall_Kind:
1182             this->writeExternalFunctionCall((ExternalFunctionCall&) expr, result);
1183             break;
1184         case Expression::kExternalValue_Kind:
1185             this->writeExternalValue((ExternalValueReference&) expr, result);
1186             break;
1187         case Expression::kFloatLiteral_Kind: {
1188             this->write(ByteCode::Instruction::kImmediate);
1189             this->write(result);
1190             this->write(ByteCode::Immediate((float) ((FloatLiteral&) expr).fValue));
1191             break;
1192         }
1193         case Expression::kFunctionCall_Kind: {
1194             this->writeFunctionCall((FunctionCall&) expr, result);
1195             break;
1196         }
1197         case Expression::kIntLiteral_Kind: {
1198             this->write(ByteCode::Instruction::kImmediate);
1199             this->write(result);
1200             this->write(ByteCode::Immediate((int32_t) ((IntLiteral&) expr).fValue));
1201             break;
1202         }
1203         case Expression::kPostfix_Kind:
1204             this->writePostfixExpression((PostfixExpression&) expr, result);
1205             break;
1206         case Expression::kPrefix_Kind:
1207             this->writePrefixExpression((PrefixExpression&) expr, result);
1208             break;
1209         case Expression::kSwizzle_Kind:
1210             this->writeSwizzle((Swizzle&) expr, result);
1211             break;
1212         case Expression::kTernary_Kind:
1213             this->writeTernaryExpression((TernaryExpression&) expr, result);
1214             break;
1215         case Expression::kFieldAccess_Kind:
1216         case Expression::kIndex_Kind:
1217         case Expression::kVariableReference_Kind:
1218             this->writeVariableExpression(expr, result);
1219             break;
1220         default:
1221 #ifdef SK_DEBUG
1222             ABORT("unsupported lvalue %s\n", expr.description().c_str());
1223 #endif
1224             break;
1225     }
1226 }
1227 
writeExpression(const Expression & expr)1228 ByteCode::Register ByteCodeGenerator::writeExpression(const Expression& expr) {
1229     ByteCode::Register result = this->next(SlotCount(expr.fType));
1230     this->writeExpression(expr, result);
1231     return result;
1232 }
1233 
writeBlock(const Block & b)1234 void ByteCodeGenerator::writeBlock(const Block& b) {
1235     for (const auto& s : b.fStatements) {
1236         this->writeStatement(*s);
1237     }
1238 }
1239 
writeDoStatement(const DoStatement & d)1240 void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
1241     this->write(ByteCode::Instruction::kLoopBegin);
1242     ++fConditionCount;
1243     SkASSERT(fCode->size() < ByteCode::kPointerMax);
1244     ByteCode::Pointer start{(uint16_t) fCode->size()};
1245     this->writeStatement(*d.fStatement);
1246     ByteCode::Register test = this->writeExpression(*d.fTest);
1247     this->write(ByteCode::Instruction::kLoopNext);
1248     this->write(ByteCode::Instruction::kLoopMask);
1249     this->write(test);
1250     this->write(ByteCode::Instruction::kBranchIfAllFalse);
1251     DeferredLocation endLocation(this);
1252     this->write(ByteCode::Instruction::kBranch);
1253     this->write(start);
1254     endLocation.set();
1255     --fConditionCount;
1256     this->write(ByteCode::Instruction::kLoopEnd);
1257 }
1258 
writeForStatement(const ForStatement & f)1259 void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
1260     if (f.fInitializer) {
1261         this->writeStatement(*f.fInitializer);
1262     }
1263     this->write(ByteCode::Instruction::kLoopBegin);
1264     ++fConditionCount;
1265     ByteCode::Pointer start{(uint16_t) fCode->size()};
1266     if (f.fTest) {
1267         ByteCode::Register test = this->writeExpression(*f.fTest);
1268         this->write(ByteCode::Instruction::kLoopMask);
1269         this->write(test);
1270     }
1271     this->write(ByteCode::Instruction::kBranchIfAllFalse);
1272     DeferredLocation endLocation(this);
1273     this->writeStatement(*f.fStatement);
1274     this->write(ByteCode::Instruction::kLoopNext);
1275     if (f.fNext) {
1276         this->writeExpression(*f.fNext);
1277     }
1278     this->write(ByteCode::Instruction::kBranch);
1279     this->write(start);
1280     endLocation.set();
1281     --fConditionCount;
1282     this->write(ByteCode::Instruction::kLoopEnd);
1283 }
1284 
writeIfStatement(const IfStatement & i)1285 void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
1286     ByteCode::Register test = this->writeExpression(*i.fTest);
1287     this->write(ByteCode::Instruction::kMaskPush);
1288     ++fConditionCount;
1289     this->write(test);
1290     this->write(ByteCode::Instruction::kBranchIfAllFalse);
1291     DeferredLocation falseLocation(this);
1292     this->writeStatement(*i.fIfTrue);
1293     falseLocation.set();
1294     if (i.fIfFalse) {
1295         this->write(ByteCode::Instruction::kMaskNegate);
1296         this->write(ByteCode::Instruction::kBranchIfAllFalse);
1297         DeferredLocation endLocation(this);
1298         this->writeStatement(*i.fIfFalse);
1299         endLocation.set();
1300     }
1301     --fConditionCount;
1302     this->write(ByteCode::Instruction::kMaskPop);
1303 }
1304 
writeReturn(const ReturnStatement & r)1305 void ByteCodeGenerator::writeReturn(const ReturnStatement& r) {
1306     if (fConditionCount) {
1307         fErrors.error(r.fOffset, "return not allowed inside conditional or loop");
1308         return;
1309     }
1310     if (r.fExpression) {
1311         ByteCode::Register value = this->writeExpression(*r.fExpression);
1312         this->write(ByteCode::Instruction::kReturnValue);
1313         this->write(value);
1314     }
1315     else {
1316         this->write(ByteCode::Instruction::kReturn);
1317     }
1318 }
1319 
writeVarDeclarations(const VarDeclarations & v)1320 void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1321     for (const auto& declStatement : v.fVars) {
1322         const VarDeclaration& decl = (VarDeclaration&) *declStatement;
1323         // we need to grab the location even if we don't use it, to ensure it
1324         // has been allocated
1325         ByteCodeGenerator::Location location = this->getLocation(*decl.fVar);
1326         if (decl.fValue) {
1327             ByteCode::Register src = this->writeExpression(*decl.fValue);
1328             uint8_t count = (uint8_t) SlotCount(decl.fVar->fType);
1329             this->write(ByteCode::Instruction::kStoreStackDirect, count);
1330             this->write(location);
1331             this->write(src);
1332         }
1333     }
1334 }
1335 
writeWhileStatement(const WhileStatement & w)1336 void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
1337     this->write(ByteCode::Instruction::kLoopBegin);
1338     ++fConditionCount;
1339     SkASSERT(fCode->size() < ByteCode::kPointerMax);
1340     ByteCode::Pointer start{(uint16_t) fCode->size()};
1341     ByteCode::Register test = this->writeExpression(*w.fTest);
1342     this->write(ByteCode::Instruction::kLoopMask);
1343     this->write(test);
1344     this->write(ByteCode::Instruction::kBranchIfAllFalse);
1345     DeferredLocation endLocation(this);
1346     this->writeStatement(*w.fStatement);
1347     this->write(ByteCode::Instruction::kLoopNext);
1348     this->write(ByteCode::Instruction::kBranch);
1349     this->write(start);
1350     endLocation.set();
1351     --fConditionCount;
1352     this->write(ByteCode::Instruction::kLoopEnd);
1353 }
1354 
writeStatement(const Statement & s)1355 void ByteCodeGenerator::writeStatement(const Statement& s) {
1356     switch (s.fKind) {
1357         case Statement::kBlock_Kind:
1358             this->writeBlock((Block&) s);
1359             break;
1360         case Statement::kBreak_Kind:
1361             this->write(ByteCode::Instruction::kBreak);
1362             break;
1363         case Statement::kContinue_Kind:
1364             this->write(ByteCode::Instruction::kContinue);
1365             break;
1366         case Statement::kDo_Kind:
1367             this->writeDoStatement((DoStatement&) s);
1368             break;
1369         case Statement::kExpression_Kind:
1370             this->writeExpression(*((ExpressionStatement&) s).fExpression);
1371             break;
1372         case Statement::kFor_Kind:
1373             this->writeForStatement((ForStatement&) s);
1374             break;
1375         case Statement::kIf_Kind:
1376             this->writeIfStatement((IfStatement&) s);
1377             break;
1378         case Statement::kNop_Kind:
1379             break;
1380         case Statement::kReturn_Kind:
1381             this->writeReturn((ReturnStatement&) s);
1382             break;
1383         case Statement::kVarDeclarations_Kind:
1384             this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1385             break;
1386         case Statement::kWhile_Kind:
1387             this->writeWhileStatement((WhileStatement&) s);
1388             break;
1389         default:
1390             ABORT("unsupported statement\n");
1391     }
1392 }
1393 
writeFunction(const FunctionDefinition & f)1394 void ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
1395     fFunction = &f;
1396     std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
1397     result->fReturnSlotCount = SlotCount(f.fDeclaration.fReturnType);
1398     fParameterCount = 0;
1399     fConditionCount = 0;
1400     for (const auto& p : f.fDeclaration.fParameters) {
1401         int count = SlotCount(p->fType);
1402         bool isOut = ((p->fModifiers.fFlags & Modifiers::kOut_Flag) != 0);
1403         result->fParameters.push_back(ByteCodeFunction::Parameter{count, isOut});
1404         fParameterCount += count;
1405     }
1406     result->fParameterSlotCount = fParameterCount;
1407     fCode = &result->fCode;
1408     this->writeStatement(*f.fBody);
1409     result->fStackSlotCount = fLocals.size();
1410     if (f.fDeclaration.fReturnType.fName == "void") {
1411         this->write(ByteCode::Instruction::kReturn);
1412     } else {
1413         this->write(ByteCode::Instruction::kAbort);
1414     }
1415     fOutput->fFunctions.push_back(std::move(result));
1416     SkASSERT(fConditionCount == 0);
1417 }
1418 
gatherUniforms(const Type & type,const String & name)1419 void ByteCodeGenerator::gatherUniforms(const Type& type, const String& name) {
1420     if (type.kind() == Type::kOther_Kind) {
1421         return;
1422     } else if (type.kind() == Type::kStruct_Kind) {
1423         for (const auto& f : type.fields()) {
1424             this->gatherUniforms(*f.fType, name + "." + f.fName);
1425         }
1426     } else if (type.kind() == Type::kArray_Kind) {
1427         for (int i = 0; i < type.columns(); ++i) {
1428             this->gatherUniforms(type.componentType(), String::printf("%s[%d]", name.c_str(), i));
1429         }
1430     } else {
1431         fOutput->fUniforms.push_back({ name, type_category(type), type.rows(), type.columns(),
1432                                        fOutput->fUniformSlotCount });
1433         fOutput->fUniformSlotCount += type.columns() * type.rows();
1434     }
1435 }
1436 
generateCode()1437 bool ByteCodeGenerator::generateCode() {
1438     fOutput->fGlobalSlotCount = 0;
1439     fOutput->fUniformSlotCount = 0;
1440     for (const auto& pe : fProgram) {
1441         if (pe.fKind == ProgramElement::kVar_Kind) {
1442             VarDeclarations& decl = (VarDeclarations&) pe;
1443             for (const auto& v : decl.fVars) {
1444                 const Variable* declVar = ((VarDeclaration&) *v).fVar;
1445                 if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
1446                     continue;
1447                 }
1448                 if (is_uniform(*declVar)) {
1449                     this->gatherUniforms(declVar->fType, declVar->fName);
1450                 } else {
1451                     fOutput->fGlobalSlotCount += SlotCount(declVar->fType);
1452                 }
1453             }
1454         }
1455     }
1456     for (const auto& pe : fProgram) {
1457         if (pe.fKind == ProgramElement::kFunction_Kind) {
1458             FunctionDefinition& f = (FunctionDefinition&) pe;
1459             fFunctions.push_back(&f);
1460             this->writeFunction(f);
1461         }
1462     }
1463     return fErrors.errorCount() == 0;
1464 }
1465 
1466 } // namespace
1467