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