blob: 4415fd5f9b7012c299c1d3e6f76957d1117934f0 [file] [log] [blame]
Mike Reed8520e762020-04-30 12:06:23 -04001/*
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04002 * Copyright 2019 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/sksl/SkSLByteCodeGenerator.h"
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04009
Brian Osmanb08cc022020-04-02 11:38:40 -040010#include <algorithm>
11
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040012namespace SkSL {
13
Brian Osmanb08cc022020-04-02 11:38:40 -040014static TypeCategory type_category(const Type& type) {
15 switch (type.kind()) {
16 case Type::Kind::kVector_Kind:
17 case Type::Kind::kMatrix_Kind:
18 return type_category(type.componentType());
19 default:
20 if (type.fName == "bool") {
21 return TypeCategory::kBool;
22 } else if (type.fName == "int" ||
23 type.fName == "short" ||
24 type.fName == "$intLiteral") {
25 return TypeCategory::kSigned;
26 } else if (type.fName == "uint" ||
27 type.fName == "ushort") {
28 return TypeCategory::kUnsigned;
29 } else {
30 SkASSERT(type.fName == "float" ||
31 type.fName == "half" ||
32 type.fName == "$floatLiteral");
33 return TypeCategory::kFloat;
34 }
35 ABORT("unsupported type: %s\n", type.displayName().c_str());
36 }
37}
38
39
40ByteCodeGenerator::ByteCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
41 ByteCode* output)
Ethan Nicholas82162ee2019-05-21 16:05:08 -040042 : INHERITED(program, errors, nullptr)
Brian Osmanb08cc022020-04-02 11:38:40 -040043 , fContext(*context)
Ethan Nicholasae9633b2019-05-24 12:46:34 -040044 , fOutput(output)
45 , fIntrinsics {
Mike Reed8520e762020-04-30 12:06:23 -040046 { "atan", ByteCodeInstruction::kATan },
Brian Osmanb08cc022020-04-02 11:38:40 -040047 { "cos", ByteCodeInstruction::kCos },
Brian Osman15c98cb2020-02-27 18:36:57 +000048 { "dot", SpecialIntrinsic::kDot },
Mike Reed8520e762020-04-30 12:06:23 -040049 { "fract", ByteCodeInstruction::kFract },
Brian Osmanb08cc022020-04-02 11:38:40 -040050 { "inverse", ByteCodeInstruction::kInverse2x2 },
Mike Klein45be0772020-05-01 09:13:18 -050051 { "length", SpecialIntrinsic::kLength },
Brian Osmanb08cc022020-04-02 11:38:40 -040052 { "sin", ByteCodeInstruction::kSin },
53 { "sqrt", ByteCodeInstruction::kSqrt },
54 { "tan", ByteCodeInstruction::kTan },
55 } {}
56
Ethan Nicholas82162ee2019-05-21 16:05:08 -040057
Brian Osman07c117b2019-05-23 12:51:06 -070058int ByteCodeGenerator::SlotCount(const Type& type) {
Brian Osmanfba386b2019-06-20 14:54:15 -040059 if (type.kind() == Type::kOther_Kind) {
60 return 0;
61 } else if (type.kind() == Type::kStruct_Kind) {
Brian Osman07c117b2019-05-23 12:51:06 -070062 int slots = 0;
63 for (const auto& f : type.fields()) {
64 slots += SlotCount(*f.fType);
65 }
66 SkASSERT(slots <= 255);
67 return slots;
68 } else if (type.kind() == Type::kArray_Kind) {
69 int columns = type.columns();
70 SkASSERT(columns >= 0);
71 int slots = columns * SlotCount(type.componentType());
72 SkASSERT(slots <= 255);
73 return slots;
74 } else {
75 return type.columns() * type.rows();
76 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040077}
78
Brian Osman1c110a02019-10-01 14:53:32 -040079static inline bool is_uniform(const SkSL::Variable& var) {
80 return var.fModifiers.fFlags & Modifiers::kUniform_Flag;
81}
82
Brian Osmaneadfeb92020-01-09 12:43:03 -050083static inline bool is_in(const SkSL::Variable& var) {
84 return var.fModifiers.fFlags & Modifiers::kIn_Flag;
85}
Brian Osmanb08cc022020-04-02 11:38:40 -040086
87void ByteCodeGenerator::gatherUniforms(const Type& type, const String& name) {
88 if (type.kind() == Type::kOther_Kind) {
89 return;
90 } else if (type.kind() == Type::kStruct_Kind) {
91 for (const auto& f : type.fields()) {
92 this->gatherUniforms(*f.fType, name + "." + f.fName);
Ethan Nicholasb962eff2020-01-23 16:49:41 -050093 }
Brian Osmanb08cc022020-04-02 11:38:40 -040094 } else if (type.kind() == Type::kArray_Kind) {
95 for (int i = 0; i < type.columns(); ++i) {
96 this->gatherUniforms(type.componentType(), String::printf("%s[%d]", name.c_str(), i));
Ethan Nicholasb962eff2020-01-23 16:49:41 -050097 }
Brian Osmanb08cc022020-04-02 11:38:40 -040098 } else {
99 fOutput->fUniforms.push_back({ name, type_category(type), type.rows(), type.columns(),
100 fOutput->fUniformSlotCount });
101 fOutput->fUniformSlotCount += type.columns() * type.rows();
102 }
103}
104
105bool ByteCodeGenerator::generateCode() {
106 for (const auto& e : fProgram) {
107 switch (e.fKind) {
108 case ProgramElement::kFunction_Kind: {
109 std::unique_ptr<ByteCodeFunction> f = this->writeFunction((FunctionDefinition&) e);
110 if (!f) {
111 return false;
112 }
113 fOutput->fFunctions.push_back(std::move(f));
114 fFunctions.push_back(&(FunctionDefinition&)e);
115 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500116 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400117 case ProgramElement::kVar_Kind: {
118 VarDeclarations& decl = (VarDeclarations&) e;
119 for (const auto& v : decl.fVars) {
120 const Variable* declVar = ((VarDeclaration&) *v).fVar;
121 if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
122 continue;
123 }
124 if (is_uniform(*declVar)) {
125 this->gatherUniforms(declVar->fType, declVar->fName);
126 } else {
127 fOutput->fGlobalSlotCount += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400128 }
129 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400130 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400131 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400132 default:
133 ; // ignore
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400134 }
135 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400136 return 0 == fErrors.errorCount();
137}
138
139std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
140 fFunction = &f;
141 std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
142 fParameterCount = result->fParameterCount;
143 fLoopCount = fMaxLoopCount = 0;
144 fConditionCount = fMaxConditionCount = 0;
145 fStackCount = fMaxStackCount = 0;
146 fCode = &result->fCode;
147
148 this->writeStatement(*f.fBody);
149 if (0 == fErrors.errorCount()) {
150 SkASSERT(fLoopCount == 0);
151 SkASSERT(fConditionCount == 0);
152 SkASSERT(fStackCount == 0);
153 }
154 this->write(ByteCodeInstruction::kReturn, 0);
155 this->write8(0);
156
157 result->fLocalCount = fLocals.size();
158 result->fConditionCount = fMaxConditionCount;
159 result->fLoopCount = fMaxLoopCount;
160 result->fStackCount = fMaxStackCount;
161
162 const Type& returnType = f.fDeclaration.fReturnType;
163 if (returnType != *fContext.fVoid_Type) {
164 result->fReturnCount = SlotCount(returnType);
165 }
166 fLocals.clear();
167 fFunction = nullptr;
168 return result;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400169}
170
Brian Osman0785db02019-05-24 14:19:11 -0400171// A "simple" Swizzle is based on a variable (or a compound variable like a struct or array), and
172// that references consecutive values, such that it can be implemented using normal load/store ops
173// with an offset. Note that all single-component swizzles (of suitable base types) are simple.
174static bool swizzle_is_simple(const Swizzle& s) {
175 switch (s.fBase->fKind) {
176 case Expression::kFieldAccess_Kind:
177 case Expression::kIndex_Kind:
178 case Expression::kVariableReference_Kind:
179 break;
180 default:
181 return false;
182 }
183
184 for (size_t i = 1; i < s.fComponents.size(); ++i) {
185 if (s.fComponents[i] != s.fComponents[i - 1] + 1) {
186 return false;
187 }
188 }
189 return true;
190}
191
Brian Osmanb08cc022020-04-02 11:38:40 -0400192int ByteCodeGenerator::StackUsage(ByteCodeInstruction inst, int count_) {
193 // Ensures that we use count iff we're passed a non-default value. Most instructions have an
194 // implicit count, so the caller shouldn't need to worry about it (or count makes no sense).
195 // The asserts avoids callers thinking they're supplying useful information in that scenario,
196 // or failing to supply necessary information for the ops that need a count.
197 struct CountValue {
198 operator int() {
199 SkASSERT(val != ByteCodeGenerator::kUnusedStackCount);
200 SkDEBUGCODE(used = true);
201 return val;
202 }
203 ~CountValue() {
204 SkASSERT(used || val == ByteCodeGenerator::kUnusedStackCount);
205 }
206 int val;
207 SkDEBUGCODE(bool used = false;)
208 } count = { count_ };
209
210 switch (inst) {
211 // Unary functions/operators that don't change stack depth at all:
212#define VECTOR_UNARY_OP(base) \
213 case ByteCodeInstruction::base: \
214 case ByteCodeInstruction::base ## 2: \
215 case ByteCodeInstruction::base ## 3: \
216 case ByteCodeInstruction::base ## 4: \
217 return 0;
218
219 VECTOR_UNARY_OP(kConvertFtoI)
220 VECTOR_UNARY_OP(kConvertStoF)
221 VECTOR_UNARY_OP(kConvertUtoF)
222
Mike Reed8520e762020-04-30 12:06:23 -0400223 VECTOR_UNARY_OP(kATan)
Brian Osmanb08cc022020-04-02 11:38:40 -0400224 VECTOR_UNARY_OP(kCos)
Mike Reed8520e762020-04-30 12:06:23 -0400225 VECTOR_UNARY_OP(kFract)
Brian Osmanb08cc022020-04-02 11:38:40 -0400226 VECTOR_UNARY_OP(kSin)
227 VECTOR_UNARY_OP(kSqrt)
228 VECTOR_UNARY_OP(kTan)
229
230 VECTOR_UNARY_OP(kNegateF)
231 VECTOR_UNARY_OP(kNegateI)
232
233 case ByteCodeInstruction::kInverse2x2:
234 case ByteCodeInstruction::kInverse3x3:
235 case ByteCodeInstruction::kInverse4x4: return 0;
236
237 case ByteCodeInstruction::kClampIndex: return 0;
238 case ByteCodeInstruction::kNotB: return 0;
239 case ByteCodeInstruction::kNegateFN: return 0;
240 case ByteCodeInstruction::kShiftLeft: return 0;
241 case ByteCodeInstruction::kShiftRightS: return 0;
242 case ByteCodeInstruction::kShiftRightU: return 0;
243
244#undef VECTOR_UNARY_OP
245
246 // Binary functions/operators that do a 2 -> 1 reduction (possibly N times)
247#define VECTOR_BINARY_OP(base) \
248 case ByteCodeInstruction::base: return -1; \
249 case ByteCodeInstruction::base ## 2: return -2; \
250 case ByteCodeInstruction::base ## 3: return -3; \
251 case ByteCodeInstruction::base ## 4: return -4;
252
253#define VECTOR_MATRIX_BINARY_OP(base) \
254 VECTOR_BINARY_OP(base) \
255 case ByteCodeInstruction::base ## N: return -count;
256
257 case ByteCodeInstruction::kAndB: return -1;
258 case ByteCodeInstruction::kOrB: return -1;
259 case ByteCodeInstruction::kXorB: return -1;
260
261 VECTOR_BINARY_OP(kAddI)
262 VECTOR_MATRIX_BINARY_OP(kAddF)
263
264 VECTOR_BINARY_OP(kCompareIEQ)
265 VECTOR_MATRIX_BINARY_OP(kCompareFEQ)
266 VECTOR_BINARY_OP(kCompareINEQ)
267 VECTOR_MATRIX_BINARY_OP(kCompareFNEQ)
268 VECTOR_BINARY_OP(kCompareSGT)
269 VECTOR_BINARY_OP(kCompareUGT)
270 VECTOR_BINARY_OP(kCompareFGT)
271 VECTOR_BINARY_OP(kCompareSGTEQ)
272 VECTOR_BINARY_OP(kCompareUGTEQ)
273 VECTOR_BINARY_OP(kCompareFGTEQ)
274 VECTOR_BINARY_OP(kCompareSLT)
275 VECTOR_BINARY_OP(kCompareULT)
276 VECTOR_BINARY_OP(kCompareFLT)
277 VECTOR_BINARY_OP(kCompareSLTEQ)
278 VECTOR_BINARY_OP(kCompareULTEQ)
279 VECTOR_BINARY_OP(kCompareFLTEQ)
280
281 VECTOR_BINARY_OP(kDivideS)
282 VECTOR_BINARY_OP(kDivideU)
283 VECTOR_MATRIX_BINARY_OP(kDivideF)
284 VECTOR_BINARY_OP(kMultiplyI)
285 VECTOR_MATRIX_BINARY_OP(kMultiplyF)
286 VECTOR_BINARY_OP(kRemainderF)
287 VECTOR_BINARY_OP(kRemainderS)
288 VECTOR_BINARY_OP(kRemainderU)
289 VECTOR_BINARY_OP(kSubtractI)
290 VECTOR_MATRIX_BINARY_OP(kSubtractF)
291
292#undef VECTOR_BINARY_OP
293#undef VECTOR_MATRIX_BINARY_OP
294
295 // Ops that push or load data to grow the stack:
296 case ByteCodeInstruction::kDup:
297 case ByteCodeInstruction::kLoad:
298 case ByteCodeInstruction::kLoadGlobal:
299 case ByteCodeInstruction::kLoadUniform:
300 case ByteCodeInstruction::kReadExternal:
301 case ByteCodeInstruction::kPushImmediate:
302 return 1;
303
304 case ByteCodeInstruction::kDup2:
305 case ByteCodeInstruction::kLoad2:
306 case ByteCodeInstruction::kLoadGlobal2:
307 case ByteCodeInstruction::kLoadUniform2:
308 case ByteCodeInstruction::kReadExternal2:
309 return 2;
310
311 case ByteCodeInstruction::kDup3:
312 case ByteCodeInstruction::kLoad3:
313 case ByteCodeInstruction::kLoadGlobal3:
314 case ByteCodeInstruction::kLoadUniform3:
315 case ByteCodeInstruction::kReadExternal3:
316 return 3;
317
318 case ByteCodeInstruction::kDup4:
319 case ByteCodeInstruction::kLoad4:
320 case ByteCodeInstruction::kLoadGlobal4:
321 case ByteCodeInstruction::kLoadUniform4:
322 case ByteCodeInstruction::kReadExternal4:
323 return 4;
324
325 case ByteCodeInstruction::kDupN:
326 case ByteCodeInstruction::kLoadSwizzle:
327 case ByteCodeInstruction::kLoadSwizzleGlobal:
328 case ByteCodeInstruction::kLoadSwizzleUniform:
329 return count;
330
331 // Pushes 'count' values, minus one for the 'address' that's consumed first
332 case ByteCodeInstruction::kLoadExtended:
333 case ByteCodeInstruction::kLoadExtendedGlobal:
334 case ByteCodeInstruction::kLoadExtendedUniform:
335 return count - 1;
336
337 // Ops that pop or store data to shrink the stack:
338 case ByteCodeInstruction::kPop:
339 case ByteCodeInstruction::kStore:
340 case ByteCodeInstruction::kStoreGlobal:
341 case ByteCodeInstruction::kWriteExternal:
342 return -1;
343
344 case ByteCodeInstruction::kPop2:
345 case ByteCodeInstruction::kStore2:
346 case ByteCodeInstruction::kStoreGlobal2:
347 case ByteCodeInstruction::kWriteExternal2:
348 return -2;
349
350 case ByteCodeInstruction::kPop3:
351 case ByteCodeInstruction::kStore3:
352 case ByteCodeInstruction::kStoreGlobal3:
353 case ByteCodeInstruction::kWriteExternal3:
354 return -3;
355
356 case ByteCodeInstruction::kPop4:
357 case ByteCodeInstruction::kStore4:
358 case ByteCodeInstruction::kStoreGlobal4:
359 case ByteCodeInstruction::kWriteExternal4:
360 return -4;
361
362 case ByteCodeInstruction::kPopN:
363 case ByteCodeInstruction::kStoreSwizzle:
364 case ByteCodeInstruction::kStoreSwizzleGlobal:
365 return -count;
366
367 // Consumes 'count' values, plus one for the 'address'
368 case ByteCodeInstruction::kStoreExtended:
369 case ByteCodeInstruction::kStoreExtendedGlobal:
370 case ByteCodeInstruction::kStoreSwizzleIndirect:
371 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal:
372 return -count - 1;
373
374 // Strange ops where the caller computes the delta for us:
375 case ByteCodeInstruction::kCallExternal:
376 case ByteCodeInstruction::kMatrixToMatrix:
377 case ByteCodeInstruction::kMatrixMultiply:
378 case ByteCodeInstruction::kReserve:
379 case ByteCodeInstruction::kReturn:
380 case ByteCodeInstruction::kScalarToMatrix:
381 case ByteCodeInstruction::kSwizzle:
382 return count;
383
384 // Miscellaneous
385
386 // kCall is net-zero. Max stack depth is adjusted in writeFunctionCall.
387 case ByteCodeInstruction::kCall: return 0;
388 case ByteCodeInstruction::kBranch: return 0;
389 case ByteCodeInstruction::kBranchIfAllFalse: return 0;
390
391 case ByteCodeInstruction::kMaskPush: return -1;
392 case ByteCodeInstruction::kMaskPop: return 0;
393 case ByteCodeInstruction::kMaskNegate: return 0;
394 case ByteCodeInstruction::kMaskBlend: return -count;
395
396 case ByteCodeInstruction::kLoopBegin: return 0;
397 case ByteCodeInstruction::kLoopNext: return 0;
398 case ByteCodeInstruction::kLoopMask: return -1;
399 case ByteCodeInstruction::kLoopEnd: return 0;
400 case ByteCodeInstruction::kLoopBreak: return 0;
401 case ByteCodeInstruction::kLoopContinue: return 0;
402
403 default:
404 ABORT("unsupported instruction %d\n", (int)inst);
405 return 0;
406 }
407}
408
409ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var) {
410 // given that we seldom have more than a couple of variables, linear search is probably the most
411 // efficient way to handle lookups
412 switch (var.fStorage) {
413 case Variable::kLocal_Storage: {
414 for (int i = fLocals.size() - 1; i >= 0; --i) {
415 if (fLocals[i] == &var) {
416 SkASSERT(fParameterCount + i <= 255);
417 return { fParameterCount + i, Storage::kLocal };
418 }
419 }
420 int result = fParameterCount + fLocals.size();
421 fLocals.push_back(&var);
422 for (int i = 0; i < SlotCount(var.fType) - 1; ++i) {
423 fLocals.push_back(nullptr);
424 }
425 SkASSERT(result <= 255);
426 return { result, Storage::kLocal };
427 }
428 case Variable::kParameter_Storage: {
429 int offset = 0;
430 for (const auto& p : fFunction->fDeclaration.fParameters) {
431 if (p == &var) {
432 SkASSERT(offset <= 255);
433 return { offset, Storage::kLocal };
434 }
435 offset += SlotCount(p->fType);
436 }
437 SkASSERT(false);
438 return Location::MakeInvalid();
439 }
440 case Variable::kGlobal_Storage: {
441 if (is_in(var)) {
442 // If you see this error, it means the program is using raw 'in' variables. You
443 // should either specialize the program (Compiler::specialize) to bake in the final
444 // values of the 'in' variables, or not use 'in' variables (maybe you meant to use
445 // 'uniform' instead?).
446 fErrors.error(var.fOffset,
447 "'in' variable is not specialized or has unsupported type");
448 return Location::MakeInvalid();
449 }
450 int offset = 0;
451 bool isUniform = is_uniform(var);
452 for (const auto& e : fProgram) {
453 if (e.fKind == ProgramElement::kVar_Kind) {
454 VarDeclarations& decl = (VarDeclarations&) e;
455 for (const auto& v : decl.fVars) {
456 const Variable* declVar = ((VarDeclaration&) *v).fVar;
457 if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
458 continue;
459 }
460 if (isUniform != is_uniform(*declVar)) {
461 continue;
462 }
463 if (declVar == &var) {
464 SkASSERT(offset <= 255);
465 return { offset, isUniform ? Storage::kUniform : Storage::kGlobal };
466 }
467 offset += SlotCount(declVar->fType);
468 }
469 }
470 }
471 SkASSERT(false);
472 return Location::MakeInvalid();
473 }
474 default:
475 SkASSERT(false);
476 return Location::MakeInvalid();
477 }
478}
479
Brian Osman1c110a02019-10-01 14:53:32 -0400480ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Expression& expr) {
Brian Osman07c117b2019-05-23 12:51:06 -0700481 switch (expr.fKind) {
482 case Expression::kFieldAccess_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400483 const FieldAccess& f = (const FieldAccess&)expr;
484 Location baseLoc = this->getLocation(*f.fBase);
Brian Osman07c117b2019-05-23 12:51:06 -0700485 int offset = 0;
486 for (int i = 0; i < f.fFieldIndex; ++i) {
487 offset += SlotCount(*f.fBase->fType.fields()[i].fType);
488 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400489 if (baseLoc.isOnStack()) {
490 if (offset != 0) {
491 this->write(ByteCodeInstruction::kPushImmediate);
492 this->write32(offset);
493 this->write(ByteCodeInstruction::kAddI);
Ben Wagner470e0ac2020-01-22 16:59:21 -0500494 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400495 return baseLoc;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500496 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400497 return baseLoc + offset;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500498 }
Ben Wagner470e0ac2020-01-22 16:59:21 -0500499 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400500 case Expression::kIndex_Kind: {
501 const IndexExpression& i = (const IndexExpression&)expr;
502 int stride = SlotCount(i.fType);
503 int length = i.fBase->fType.columns();
504 SkASSERT(length <= 255);
505 int offset = -1;
506 if (i.fIndex->isConstant()) {
507 int64_t index = i.fIndex->getConstantInt();
508 if (index < 0 || index >= length) {
509 fErrors.error(i.fIndex->fOffset, "Array index out of bounds.");
510 return Location::MakeInvalid();
511 }
512 offset = index * stride;
513 } else {
514 if (i.fIndex->hasSideEffects()) {
515 // Having a side-effect in an indexer is technically safe for an rvalue,
516 // but with lvalues we have to evaluate the indexer twice, so make it an error.
517 fErrors.error(i.fIndex->fOffset,
518 "Index expressions with side-effects not supported in byte code.");
519 return Location::MakeInvalid();
520 }
521 this->writeExpression(*i.fIndex);
522 this->write(ByteCodeInstruction::kClampIndex);
523 this->write8(length);
524 if (stride != 1) {
525 this->write(ByteCodeInstruction::kPushImmediate);
526 this->write32(stride);
527 this->write(ByteCodeInstruction::kMultiplyI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400528 }
529 }
530 Location baseLoc = this->getLocation(*i.fBase);
531
532 // Are both components known statically?
533 if (!baseLoc.isOnStack() && offset >= 0) {
534 return baseLoc + offset;
535 }
536
537 // At least one component is dynamic (and on the stack).
538
539 // If the other component is zero, we're done
540 if (baseLoc.fSlot == 0 || offset == 0) {
541 return baseLoc.makeOnStack();
542 }
543
544 // Push the non-dynamic component (if any) to the stack, then add the two
545 if (!baseLoc.isOnStack()) {
546 this->write(ByteCodeInstruction::kPushImmediate);
547 this->write32(baseLoc.fSlot);
548 }
549 if (offset >= 0) {
550 this->write(ByteCodeInstruction::kPushImmediate);
551 this->write32(offset);
552 }
553 this->write(ByteCodeInstruction::kAddI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400554 return baseLoc.makeOnStack();
555 }
Brian Osman0785db02019-05-24 14:19:11 -0400556 case Expression::kSwizzle_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400557 const Swizzle& s = (const Swizzle&)expr;
Brian Osman0785db02019-05-24 14:19:11 -0400558 SkASSERT(swizzle_is_simple(s));
Brian Osmanb08cc022020-04-02 11:38:40 -0400559 Location baseLoc = this->getLocation(*s.fBase);
560 int offset = s.fComponents[0];
561 if (baseLoc.isOnStack()) {
562 if (offset != 0) {
563 this->write(ByteCodeInstruction::kPushImmediate);
564 this->write32(offset);
565 this->write(ByteCodeInstruction::kAddI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400566 }
567 return baseLoc;
568 } else {
569 return baseLoc + offset;
570 }
Brian Osman0785db02019-05-24 14:19:11 -0400571 }
Brian Osman07c117b2019-05-23 12:51:06 -0700572 case Expression::kVariableReference_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400573 const Variable& var = ((const VariableReference&)expr).fVariable;
Brian Osman07c117b2019-05-23 12:51:06 -0700574 return this->getLocation(var);
575 }
576 default:
577 SkASSERT(false);
Brian Osmanb08cc022020-04-02 11:38:40 -0400578 return Location::MakeInvalid();
Brian Osman07c117b2019-05-23 12:51:06 -0700579 }
580}
581
Brian Osmanb08cc022020-04-02 11:38:40 -0400582void ByteCodeGenerator::write8(uint8_t b) {
583 fCode->push_back(b);
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500584}
585
Brian Osmanb08cc022020-04-02 11:38:40 -0400586void ByteCodeGenerator::write16(uint16_t i) {
587 size_t n = fCode->size();
588 fCode->resize(n+2);
589 memcpy(fCode->data() + n, &i, 2);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500590}
Ben Wagner470e0ac2020-01-22 16:59:21 -0500591
Brian Osmanb08cc022020-04-02 11:38:40 -0400592void ByteCodeGenerator::write32(uint32_t i) {
593 size_t n = fCode->size();
594 fCode->resize(n+4);
595 memcpy(fCode->data() + n, &i, 4);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500596}
597
Brian Osmanb08cc022020-04-02 11:38:40 -0400598void ByteCodeGenerator::write(ByteCodeInstruction i, int count) {
599 switch (i) {
600 case ByteCodeInstruction::kLoopBegin: this->enterLoop(); break;
601 case ByteCodeInstruction::kLoopEnd: this->exitLoop(); break;
Ethan Nicholas2329da02020-01-24 15:49:33 -0500602
Brian Osmanb08cc022020-04-02 11:38:40 -0400603 case ByteCodeInstruction::kMaskPush: this->enterCondition(); break;
604 case ByteCodeInstruction::kMaskPop:
605 case ByteCodeInstruction::kMaskBlend: this->exitCondition(); break;
606 default: /* Do nothing */ break;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500607 }
Brian Osmanab8f3842020-04-07 09:30:44 -0400608 this->write16((uint16_t)i);
Brian Osmanb08cc022020-04-02 11:38:40 -0400609 fStackCount += StackUsage(i, count);
610 fMaxStackCount = std::max(fMaxStackCount, fStackCount);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500611}
612
Brian Osmanb08cc022020-04-02 11:38:40 -0400613static ByteCodeInstruction vector_instruction(ByteCodeInstruction base, int count) {
614 SkASSERT(count >= 1 && count <= 4);
615 return ((ByteCodeInstruction) ((int) base + 1 - count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500616}
617
Brian Osmanb08cc022020-04-02 11:38:40 -0400618void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
619 ByteCodeInstruction u, ByteCodeInstruction f,
Brian Osmanab8f3842020-04-07 09:30:44 -0400620 int count) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500621 switch (type_category(type)) {
622 case TypeCategory::kSigned:
Brian Osmanb08cc022020-04-02 11:38:40 -0400623 this->write(vector_instruction(s, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500624 break;
625 case TypeCategory::kUnsigned:
Brian Osmanb08cc022020-04-02 11:38:40 -0400626 this->write(vector_instruction(u, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500627 break;
628 case TypeCategory::kFloat: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400629 if (count > 4) {
630 this->write((ByteCodeInstruction)((int)f + 1), count);
Brian Osmanab8f3842020-04-07 09:30:44 -0400631 this->write8(count);
Brian Osmanb08cc022020-04-02 11:38:40 -0400632 } else {
633 this->write(vector_instruction(f, count));
634 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500635 break;
636 }
637 default:
638 SkASSERT(false);
639 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500640}
641
Brian Osmanb08cc022020-04-02 11:38:40 -0400642bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool discard) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400643 if (b.fOperator == Token::Kind::TK_EQ) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500644 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
Brian Osmanb08cc022020-04-02 11:38:40 -0400645 this->writeExpression(*b.fRight);
646 lvalue->store(discard);
647 discard = false;
648 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500649 }
650 const Type& lType = b.fLeft->fType;
651 const Type& rType = b.fRight->fType;
652 bool lVecOrMtx = (lType.kind() == Type::kVector_Kind || lType.kind() == Type::kMatrix_Kind);
653 bool rVecOrMtx = (rType.kind() == Type::kVector_Kind || rType.kind() == Type::kMatrix_Kind);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500654 Token::Kind op;
655 std::unique_ptr<LValue> lvalue;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500656 if (is_assignment(b.fOperator)) {
657 lvalue = this->getLValue(*b.fLeft);
Brian Osmanb08cc022020-04-02 11:38:40 -0400658 lvalue->load();
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500659 op = remove_assignment(b.fOperator);
660 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400661 this->writeExpression(*b.fLeft);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500662 op = b.fOperator;
663 if (!lVecOrMtx && rVecOrMtx) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400664 for (int i = SlotCount(rType); i > 1; --i) {
665 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400666 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500667 }
668 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500669 int count = std::max(SlotCount(lType), SlotCount(rType));
Brian Osmanb08cc022020-04-02 11:38:40 -0400670 SkDEBUGCODE(TypeCategory tc = type_category(lType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500671 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400672 case Token::Kind::TK_LOGICALAND: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400673 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
674 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400675 this->write(ByteCodeInstruction::kMaskPush);
676 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500677 DeferredLocation falseLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -0400678 this->writeExpression(*b.fRight);
679 this->write(ByteCodeInstruction::kAndB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500680 falseLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -0400681 this->write(ByteCodeInstruction::kMaskPop);
682 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500683 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400684 case Token::Kind::TK_LOGICALOR: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400685 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
686 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400687 this->write(ByteCodeInstruction::kNotB);
688 this->write(ByteCodeInstruction::kMaskPush);
689 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500690 DeferredLocation falseLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -0400691 this->writeExpression(*b.fRight);
692 this->write(ByteCodeInstruction::kOrB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500693 falseLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -0400694 this->write(ByteCodeInstruction::kMaskPop);
695 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500696 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400697 case Token::Kind::TK_SHL:
698 case Token::Kind::TK_SHR: {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500699 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
700 tc == SkSL::TypeCategory::kUnsigned));
701 if (!b.fRight->isConstant()) {
702 fErrors.error(b.fRight->fOffset, "Shift amounts must be constant");
Brian Osmanb08cc022020-04-02 11:38:40 -0400703 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500704 }
705 int64_t shift = b.fRight->getConstantInt();
706 if (shift < 0 || shift > 31) {
707 fErrors.error(b.fRight->fOffset, "Shift amount out of range");
Brian Osmanb08cc022020-04-02 11:38:40 -0400708 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500709 }
710
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400711 if (op == Token::Kind::TK_SHL) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400712 this->write(ByteCodeInstruction::kShiftLeft);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500713 } else {
714 this->write(type_category(lType) == TypeCategory::kSigned
Brian Osmanb08cc022020-04-02 11:38:40 -0400715 ? ByteCodeInstruction::kShiftRightS
716 : ByteCodeInstruction::kShiftRightU);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500717 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400718 this->write8(shift);
719 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500720 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500721
722 default:
723 break;
724 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400725 this->writeExpression(*b.fRight);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500726 if (lVecOrMtx && !rVecOrMtx) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400727 for (int i = SlotCount(lType); i > 1; --i) {
728 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400729 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500730 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400731 // Special case for M*V, V*M, M*M (but not V*V!)
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400732 if (op == Token::Kind::TK_STAR && lVecOrMtx && rVecOrMtx &&
Brian Osmanb08cc022020-04-02 11:38:40 -0400733 !(lType.kind() == Type::kVector_Kind && rType.kind() == Type::kVector_Kind)) {
734 this->write(ByteCodeInstruction::kMatrixMultiply,
735 SlotCount(b.fType) - (SlotCount(lType) + SlotCount(rType)));
736 int rCols = rType.columns(),
737 rRows = rType.rows(),
738 lCols = lType.columns(),
739 lRows = lType.rows();
740 // M*V treats the vector as a column
741 if (rType.kind() == Type::kVector_Kind) {
742 std::swap(rCols, rRows);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500743 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400744 SkASSERT(lCols == rRows);
745 SkASSERT(SlotCount(b.fType) == lRows * rCols);
746 this->write8(lCols);
747 this->write8(lRows);
748 this->write8(rCols);
749 } else {
750 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400751 case Token::Kind::TK_EQEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400752 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareIEQ,
753 ByteCodeInstruction::kCompareIEQ,
754 ByteCodeInstruction::kCompareFEQ,
755 count);
756 // Collapse to a single bool
757 for (int i = count; i > 1; --i) {
758 this->write(ByteCodeInstruction::kAndB);
759 }
760 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400761 case Token::Kind::TK_GT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400762 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGT,
763 ByteCodeInstruction::kCompareUGT,
764 ByteCodeInstruction::kCompareFGT,
765 count);
766 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400767 case Token::Kind::TK_GTEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400768 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGTEQ,
769 ByteCodeInstruction::kCompareUGTEQ,
770 ByteCodeInstruction::kCompareFGTEQ,
771 count);
772 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400773 case Token::Kind::TK_LT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400774 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLT,
775 ByteCodeInstruction::kCompareULT,
776 ByteCodeInstruction::kCompareFLT,
777 count);
778 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400779 case Token::Kind::TK_LTEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400780 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLTEQ,
781 ByteCodeInstruction::kCompareULTEQ,
782 ByteCodeInstruction::kCompareFLTEQ,
783 count);
784 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400785 case Token::Kind::TK_MINUS:
Brian Osmanb08cc022020-04-02 11:38:40 -0400786 this->writeTypedInstruction(lType, ByteCodeInstruction::kSubtractI,
787 ByteCodeInstruction::kSubtractI,
788 ByteCodeInstruction::kSubtractF,
789 count);
790 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400791 case Token::Kind::TK_NEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400792 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareINEQ,
793 ByteCodeInstruction::kCompareINEQ,
794 ByteCodeInstruction::kCompareFNEQ,
795 count);
796 // Collapse to a single bool
797 for (int i = count; i > 1; --i) {
798 this->write(ByteCodeInstruction::kOrB);
799 }
800 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400801 case Token::Kind::TK_PERCENT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400802 this->writeTypedInstruction(lType, ByteCodeInstruction::kRemainderS,
803 ByteCodeInstruction::kRemainderU,
804 ByteCodeInstruction::kRemainderF,
805 count);
806 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400807 case Token::Kind::TK_PLUS:
Brian Osmanb08cc022020-04-02 11:38:40 -0400808 this->writeTypedInstruction(lType, ByteCodeInstruction::kAddI,
809 ByteCodeInstruction::kAddI,
810 ByteCodeInstruction::kAddF,
811 count);
812 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400813 case Token::Kind::TK_SLASH:
Brian Osmanb08cc022020-04-02 11:38:40 -0400814 this->writeTypedInstruction(lType, ByteCodeInstruction::kDivideS,
815 ByteCodeInstruction::kDivideU,
816 ByteCodeInstruction::kDivideF,
817 count);
818 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400819 case Token::Kind::TK_STAR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400820 this->writeTypedInstruction(lType, ByteCodeInstruction::kMultiplyI,
821 ByteCodeInstruction::kMultiplyI,
822 ByteCodeInstruction::kMultiplyF,
823 count);
824 break;
825
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400826 case Token::Kind::TK_LOGICALXOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400827 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
828 this->write(ByteCodeInstruction::kXorB);
829 break;
830
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400831 case Token::Kind::TK_BITWISEAND:
Brian Osmanb08cc022020-04-02 11:38:40 -0400832 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
833 tc == SkSL::TypeCategory::kUnsigned));
834 this->write(ByteCodeInstruction::kAndB);
835 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400836 case Token::Kind::TK_BITWISEOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400837 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
838 tc == SkSL::TypeCategory::kUnsigned));
839 this->write(ByteCodeInstruction::kOrB);
840 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400841 case Token::Kind::TK_BITWISEXOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400842 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
843 tc == SkSL::TypeCategory::kUnsigned));
844 this->write(ByteCodeInstruction::kXorB);
845 break;
846
847 default:
848 fErrors.error(b.fOffset, SkSL::String::printf("Unsupported binary operator '%s'",
849 Compiler::OperatorName(op)));
850 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500851 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500852 }
853 if (lvalue) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400854 lvalue->store(discard);
855 discard = false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500856 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400857 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500858}
859
Brian Osmanb08cc022020-04-02 11:38:40 -0400860void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
861 this->write(ByteCodeInstruction::kPushImmediate);
862 this->write32(b.fValue ? ~0 : 0);
863}
864
865void ByteCodeGenerator::writeConstructor(const Constructor& c) {
866 for (const auto& arg : c.fArguments) {
867 this->writeExpression(*arg);
868 }
869 if (c.fArguments.size() == 1) {
870 const Type& inType = c.fArguments[0]->fType;
871 const Type& outType = c.fType;
872 TypeCategory inCategory = type_category(inType);
873 TypeCategory outCategory = type_category(outType);
874 int inCount = SlotCount(inType);
875 int outCount = SlotCount(outType);
876 if (inCategory != outCategory) {
877 SkASSERT(inCount == outCount);
878 if (inCategory == TypeCategory::kFloat) {
879 SkASSERT(outCategory == TypeCategory::kSigned ||
880 outCategory == TypeCategory::kUnsigned);
881 this->write(vector_instruction(ByteCodeInstruction::kConvertFtoI, outCount));
882 } else if (outCategory == TypeCategory::kFloat) {
883 if (inCategory == TypeCategory::kSigned) {
884 this->write(vector_instruction(ByteCodeInstruction::kConvertStoF, outCount));
885 } else {
886 SkASSERT(inCategory == TypeCategory::kUnsigned);
887 this->write(vector_instruction(ByteCodeInstruction::kConvertUtoF, outCount));
888 }
889 } else {
890 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500891 }
892 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400893 if (inType.kind() == Type::kMatrix_Kind && outType.kind() == Type::kMatrix_Kind) {
894 this->write(ByteCodeInstruction::kMatrixToMatrix,
895 SlotCount(outType) - SlotCount(inType));
896 this->write8(inType.columns());
897 this->write8(inType.rows());
898 this->write8(outType.columns());
899 this->write8(outType.rows());
900 } else if (inCount != outCount) {
901 SkASSERT(inCount == 1);
902 if (outType.kind() == Type::kMatrix_Kind) {
903 this->write(ByteCodeInstruction::kScalarToMatrix, SlotCount(outType) - 1);
904 this->write8(outType.columns());
905 this->write8(outType.rows());
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500906 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400907 SkASSERT(outType.kind() == Type::kVector_Kind);
908 for (; inCount != outCount; ++inCount) {
909 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400910 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500911 }
912 }
913 }
914}
915
Brian Osmanb08cc022020-04-02 11:38:40 -0400916void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500917 int argumentCount = 0;
918 for (const auto& arg : f.fArguments) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400919 this->writeExpression(*arg);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500920 argumentCount += SlotCount(arg->fType);
921 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400922 this->write(ByteCodeInstruction::kCallExternal, SlotCount(f.fType) - argumentCount);
923 SkASSERT(argumentCount <= 255);
924 this->write8(argumentCount);
925 this->write8(SlotCount(f.fType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500926 int index = fOutput->fExternalValues.size();
927 fOutput->fExternalValues.push_back(f.fFunction);
928 SkASSERT(index <= 255);
Brian Osmanb08cc022020-04-02 11:38:40 -0400929 this->write8(index);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500930}
931
Brian Osmanb08cc022020-04-02 11:38:40 -0400932void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
933 int count = SlotCount(e.fValue->type());
934 this->write(vector_instruction(ByteCodeInstruction::kReadExternal, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500935 int index = fOutput->fExternalValues.size();
936 fOutput->fExternalValues.push_back(e.fValue);
937 SkASSERT(index <= 255);
Brian Osmanb08cc022020-04-02 11:38:40 -0400938 this->write8(index);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500939}
940
Brian Osmanb08cc022020-04-02 11:38:40 -0400941void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
942 Location location = this->getLocation(expr);
943 int count = SlotCount(expr.fType);
Brian Osmanefb08402020-04-13 16:30:44 -0400944 if (count == 0) {
945 return;
946 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400947 if (location.isOnStack() || count > 4) {
948 if (!location.isOnStack()) {
949 this->write(ByteCodeInstruction::kPushImmediate);
950 this->write32(location.fSlot);
951 }
952 this->write(location.selectLoad(ByteCodeInstruction::kLoadExtended,
953 ByteCodeInstruction::kLoadExtendedGlobal,
954 ByteCodeInstruction::kLoadExtendedUniform),
955 count);
956 this->write8(count);
957 } else {
958 this->write(vector_instruction(location.selectLoad(ByteCodeInstruction::kLoad,
959 ByteCodeInstruction::kLoadGlobal,
960 ByteCodeInstruction::kLoadUniform),
961 count));
Brian Osmanb08cc022020-04-02 11:38:40 -0400962 this->write8(location.fSlot);
963 }
964}
965
966static inline uint32_t float_to_bits(float x) {
967 uint32_t u;
968 memcpy(&u, &x, sizeof(uint32_t));
969 return u;
970}
971
972void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
973 this->write(ByteCodeInstruction::kPushImmediate);
974 this->write32(float_to_bits(f.fValue));
975}
976
977void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
978 auto found = fIntrinsics.find(c.fFunction.fName);
979 if (found == fIntrinsics.end()) {
980 fErrors.error(c.fOffset, String::printf("Unsupported intrinsic: '%s'",
981 String(c.fFunction.fName).c_str()));
982 return;
983 }
Mike Klein45be0772020-05-01 09:13:18 -0500984 Intrinsic intrin = found->second;
985
Brian Osmanb08cc022020-04-02 11:38:40 -0400986 int count = SlotCount(c.fArguments[0]->fType);
Mike Klein45be0772020-05-01 09:13:18 -0500987 if (intrin.is_special) {
988 switch (intrin.special) {
Brian Osman15c98cb2020-02-27 18:36:57 +0000989 case SpecialIntrinsic::kDot: {
990 SkASSERT(c.fArguments.size() == 2);
Brian Osmanb08cc022020-04-02 11:38:40 -0400991 SkASSERT(count == SlotCount(c.fArguments[1]->fType));
992 this->write(vector_instruction(ByteCodeInstruction::kMultiplyF, count));
Mike Klein45be0772020-05-01 09:13:18 -0500993 for (int i = count-1; i --> 0;) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400994 this->write(ByteCodeInstruction::kAddF);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500995 }
Mike Klein45be0772020-05-01 09:13:18 -0500996 } break;
997
998 case SpecialIntrinsic::kLength: {
999 SkASSERT(c.fArguments.size() == 1);
1000 this->write(vector_instruction(ByteCodeInstruction::kDup , count));
1001 this->write(vector_instruction(ByteCodeInstruction::kMultiplyF, count));
1002 for (int i = count-1; i --> 0;) {
1003 this->write(ByteCodeInstruction::kAddF);
1004 }
1005 this->write(ByteCodeInstruction::kSqrt);
1006 } break;
1007
Brian Osmanb08cc022020-04-02 11:38:40 -04001008 default:
1009 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001010 }
1011 } else {
Mike Klein45be0772020-05-01 09:13:18 -05001012 switch (intrin.instruction) {
Mike Reed8520e762020-04-30 12:06:23 -04001013 case ByteCodeInstruction::kATan:
Brian Osmanb08cc022020-04-02 11:38:40 -04001014 case ByteCodeInstruction::kCos:
Mike Reed8520e762020-04-30 12:06:23 -04001015 case ByteCodeInstruction::kFract:
Brian Osmanb08cc022020-04-02 11:38:40 -04001016 case ByteCodeInstruction::kSin:
Brian Osmanb08cc022020-04-02 11:38:40 -04001017 case ByteCodeInstruction::kSqrt:
Brian Osmanab8f3842020-04-07 09:30:44 -04001018 case ByteCodeInstruction::kTan:
Brian Osmanb08cc022020-04-02 11:38:40 -04001019 SkASSERT(c.fArguments.size() > 0);
Mike Klein45be0772020-05-01 09:13:18 -05001020 this->write(vector_instruction(intrin.instruction, count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001021 break;
Mike Klein45be0772020-05-01 09:13:18 -05001022
Brian Osmanb08cc022020-04-02 11:38:40 -04001023 case ByteCodeInstruction::kInverse2x2: {
1024 SkASSERT(c.fArguments.size() > 0);
1025 auto op = ByteCodeInstruction::kInverse2x2;
1026 switch (count) {
1027 case 4: break; // float2x2
1028 case 9: op = ByteCodeInstruction::kInverse3x3; break;
1029 case 16: op = ByteCodeInstruction::kInverse4x4; break;
1030 default: SkASSERT(false);
1031 }
1032 this->write(op);
1033 break;
Brian Osman15c98cb2020-02-27 18:36:57 +00001034 }
Mike Klein45be0772020-05-01 09:13:18 -05001035
Brian Osmanb08cc022020-04-02 11:38:40 -04001036 default:
1037 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001038 }
1039 }
1040}
1041
Brian Osmanb08cc022020-04-02 11:38:40 -04001042void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001043 // Find the index of the function we're calling. We explicitly do not allow calls to functions
1044 // before they're defined. This is an easy-to-understand rule that prevents recursion.
Brian Osmanb08cc022020-04-02 11:38:40 -04001045 int idx = -1;
1046 for (size_t i = 0; i < fFunctions.size(); ++i) {
1047 if (f.fFunction.matches(fFunctions[i]->fDeclaration)) {
1048 idx = i;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001049 break;
1050 }
1051 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001052 if (idx == -1) {
1053 for (const auto& arg : f.fArguments) {
1054 this->writeExpression(*arg);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001055 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001056 this->writeIntrinsicCall(f);
1057 return;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001058 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001059
1060
1061 if (idx > 255) {
1062 fErrors.error(f.fOffset, "Function count limit exceeded");
1063 return;
1064 } else if (idx >= (int) fFunctions.size()) {
1065 fErrors.error(f.fOffset, "Call to undefined function");
1066 return;
1067 }
1068
1069 // We may need to deal with out parameters, so the sequence is tricky
1070 if (int returnCount = SlotCount(f.fType)) {
1071 this->write(ByteCodeInstruction::kReserve, returnCount);
1072 this->write8(returnCount);
1073 }
1074
1075 int argCount = f.fArguments.size();
1076 std::vector<std::unique_ptr<LValue>> lvalues;
1077 for (int i = 0; i < argCount; ++i) {
1078 const auto& param = f.fFunction.fParameters[i];
1079 const auto& arg = f.fArguments[i];
1080 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1081 lvalues.emplace_back(this->getLValue(*arg));
1082 lvalues.back()->load();
1083 } else {
1084 this->writeExpression(*arg);
1085 }
1086 }
1087
1088 // The space used by the call is based on the callee, but it also unwinds all of that before
1089 // we continue execution. We adjust our max stack depths below.
1090 this->write(ByteCodeInstruction::kCall);
1091 this->write8(idx);
1092
1093 const ByteCodeFunction* callee = fOutput->fFunctions[idx].get();
1094 fMaxLoopCount = std::max(fMaxLoopCount, fLoopCount + callee->fLoopCount);
1095 fMaxConditionCount = std::max(fMaxConditionCount, fConditionCount + callee->fConditionCount);
1096 fMaxStackCount = std::max(fMaxStackCount, fStackCount + callee->fLocalCount
1097 + callee->fStackCount);
1098
1099 // After the called function returns, the stack will still contain our arguments. We have to
1100 // pop them (storing any out parameters back to their lvalues as we go). We glob together slot
1101 // counts for all parameters that aren't out-params, so we can pop them in one big chunk.
1102 int popCount = 0;
1103 auto pop = [&]() {
1104 if (popCount > 4) {
1105 this->write(ByteCodeInstruction::kPopN, popCount);
1106 this->write8(popCount);
1107 } else if (popCount > 0) {
1108 this->write(vector_instruction(ByteCodeInstruction::kPop, popCount));
1109 }
1110 popCount = 0;
1111 };
1112
1113 for (int i = argCount - 1; i >= 0; --i) {
1114 const auto& param = f.fFunction.fParameters[i];
1115 const auto& arg = f.fArguments[i];
1116 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1117 pop();
1118 lvalues.back()->store(true);
1119 lvalues.pop_back();
1120 } else {
1121 popCount += SlotCount(arg->fType);
1122 }
1123 }
1124 pop();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001125}
1126
Brian Osmanb08cc022020-04-02 11:38:40 -04001127void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
1128 this->write(ByteCodeInstruction::kPushImmediate);
1129 this->write32(i.fValue);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001130}
1131
Brian Osmanb08cc022020-04-02 11:38:40 -04001132void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
1133 // not yet implemented
1134 abort();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001135}
1136
Brian Osmanb08cc022020-04-02 11:38:40 -04001137bool ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p, bool discard) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001138 switch (p.fOperator) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001139 case Token::Kind::TK_PLUSPLUS: // fall through
1140 case Token::Kind::TK_MINUSMINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001141 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1142 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
1143 lvalue->load();
1144 this->write(ByteCodeInstruction::kPushImmediate);
1145 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001146 if (p.fOperator == Token::Kind::TK_PLUSPLUS) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001147 this->writeTypedInstruction(p.fType,
1148 ByteCodeInstruction::kAddI,
1149 ByteCodeInstruction::kAddI,
1150 ByteCodeInstruction::kAddF,
1151 1);
1152 } else {
1153 this->writeTypedInstruction(p.fType,
1154 ByteCodeInstruction::kSubtractI,
1155 ByteCodeInstruction::kSubtractI,
1156 ByteCodeInstruction::kSubtractF,
1157 1);
1158 }
1159 lvalue->store(discard);
1160 discard = false;
1161 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001162 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001163 case Token::Kind::TK_MINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001164 this->writeExpression(*p.fOperand);
1165 this->writeTypedInstruction(p.fType,
1166 ByteCodeInstruction::kNegateI,
1167 ByteCodeInstruction::kNegateI,
1168 ByteCodeInstruction::kNegateF,
Brian Osmanab8f3842020-04-07 09:30:44 -04001169 SlotCount(p.fOperand->fType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001170 break;
1171 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001172 case Token::Kind::TK_LOGICALNOT:
1173 case Token::Kind::TK_BITWISENOT: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001174 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1175 SkDEBUGCODE(TypeCategory tc = type_category(p.fOperand->fType));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001176 SkASSERT((p.fOperator == Token::Kind::TK_LOGICALNOT && tc == TypeCategory::kBool) ||
1177 (p.fOperator == Token::Kind::TK_BITWISENOT && (tc == TypeCategory::kSigned ||
Brian Osmanb08cc022020-04-02 11:38:40 -04001178 tc == TypeCategory::kUnsigned)));
1179 this->writeExpression(*p.fOperand);
1180 this->write(ByteCodeInstruction::kNotB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001181 break;
1182 }
1183 default:
1184 SkASSERT(false);
1185 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001186 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001187}
1188
Brian Osmanb08cc022020-04-02 11:38:40 -04001189bool ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p, bool discard) {
1190 switch (p.fOperator) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001191 case Token::Kind::TK_PLUSPLUS: // fall through
1192 case Token::Kind::TK_MINUSMINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001193 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1194 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
1195 lvalue->load();
1196 // If we're not supposed to discard the result, then make a copy *before* the +/-
1197 if (!discard) {
1198 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -04001199 }
1200 this->write(ByteCodeInstruction::kPushImmediate);
1201 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001202 if (p.fOperator == Token::Kind::TK_PLUSPLUS) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001203 this->writeTypedInstruction(p.fType,
1204 ByteCodeInstruction::kAddI,
1205 ByteCodeInstruction::kAddI,
1206 ByteCodeInstruction::kAddF,
1207 1);
1208 } else {
1209 this->writeTypedInstruction(p.fType,
1210 ByteCodeInstruction::kSubtractI,
1211 ByteCodeInstruction::kSubtractI,
1212 ByteCodeInstruction::kSubtractF,
1213 1);
1214 }
1215 // Always consume the result as part of the store
1216 lvalue->store(true);
1217 discard = false;
1218 break;
1219 }
1220 default:
1221 SkASSERT(false);
1222 }
1223 return discard;
1224}
1225
1226void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001227 if (swizzle_is_simple(s)) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001228 this->writeVariableExpression(s);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001229 return;
1230 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001231
1232 switch (s.fBase->fKind) {
1233 case Expression::kVariableReference_Kind: {
1234 Location location = this->getLocation(*s.fBase);
1235 this->write(location.selectLoad(ByteCodeInstruction::kLoadSwizzle,
1236 ByteCodeInstruction::kLoadSwizzleGlobal,
1237 ByteCodeInstruction::kLoadSwizzleUniform),
1238 s.fComponents.size());
1239 this->write8(location.fSlot);
1240 this->write8(s.fComponents.size());
1241 for (int c : s.fComponents) {
1242 this->write8(c);
1243 }
1244 break;
1245 }
1246 default:
1247 this->writeExpression(*s.fBase);
1248 this->write(ByteCodeInstruction::kSwizzle,
1249 s.fComponents.size() - s.fBase->fType.columns());
1250 this->write8(s.fBase->fType.columns());
1251 this->write8(s.fComponents.size());
1252 for (int c : s.fComponents) {
1253 this->write8(c);
1254 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001255 }
1256}
1257
Brian Osmanb08cc022020-04-02 11:38:40 -04001258void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001259 int count = SlotCount(t.fType);
1260 SkASSERT(count == SlotCount(t.fIfTrue->fType));
1261 SkASSERT(count == SlotCount(t.fIfFalse->fType));
1262
Brian Osmanb08cc022020-04-02 11:38:40 -04001263 this->writeExpression(*t.fTest);
1264 this->write(ByteCodeInstruction::kMaskPush);
1265 this->writeExpression(*t.fIfTrue);
1266 this->write(ByteCodeInstruction::kMaskNegate);
1267 this->writeExpression(*t.fIfFalse);
1268 this->write(ByteCodeInstruction::kMaskBlend, count);
1269 this->write8(count);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001270}
1271
Brian Osmanb08cc022020-04-02 11:38:40 -04001272void ByteCodeGenerator::writeExpression(const Expression& e, bool discard) {
1273 switch (e.fKind) {
1274 case Expression::kBinary_Kind:
1275 discard = this->writeBinaryExpression((BinaryExpression&) e, discard);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001276 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001277 case Expression::kBoolLiteral_Kind:
1278 this->writeBoolLiteral((BoolLiteral&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001279 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001280 case Expression::kConstructor_Kind:
1281 this->writeConstructor((Constructor&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001282 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001283 case Expression::kExternalFunctionCall_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001284 this->writeExternalFunctionCall((ExternalFunctionCall&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001285 break;
1286 case Expression::kExternalValue_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001287 this->writeExternalValue((ExternalValueReference&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001288 break;
1289 case Expression::kFieldAccess_Kind:
1290 case Expression::kIndex_Kind:
1291 case Expression::kVariableReference_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001292 this->writeVariableExpression(e);
1293 break;
1294 case Expression::kFloatLiteral_Kind:
1295 this->writeFloatLiteral((FloatLiteral&) e);
1296 break;
1297 case Expression::kFunctionCall_Kind:
1298 this->writeFunctionCall((FunctionCall&) e);
1299 break;
1300 case Expression::kIntLiteral_Kind:
1301 this->writeIntLiteral((IntLiteral&) e);
1302 break;
1303 case Expression::kNullLiteral_Kind:
1304 this->writeNullLiteral((NullLiteral&) e);
1305 break;
1306 case Expression::kPrefix_Kind:
1307 discard = this->writePrefixExpression((PrefixExpression&) e, discard);
1308 break;
1309 case Expression::kPostfix_Kind:
1310 discard = this->writePostfixExpression((PostfixExpression&) e, discard);
1311 break;
1312 case Expression::kSwizzle_Kind:
1313 this->writeSwizzle((Swizzle&) e);
1314 break;
1315 case Expression::kTernary_Kind:
1316 this->writeTernaryExpression((TernaryExpression&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001317 break;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001318 default:
1319#ifdef SK_DEBUG
Brian Osmanb08cc022020-04-02 11:38:40 -04001320 printf("unsupported expression %s\n", e.description().c_str());
Ben Wagner470e0ac2020-01-22 16:59:21 -05001321#endif
Brian Osmanb08cc022020-04-02 11:38:40 -04001322 SkASSERT(false);
1323 }
1324 if (discard) {
1325 int count = SlotCount(e.fType);
1326 if (count > 4) {
1327 this->write(ByteCodeInstruction::kPopN, count);
1328 this->write8(count);
1329 } else if (count != 0) {
1330 this->write(vector_instruction(ByteCodeInstruction::kPop, count));
1331 }
1332 discard = false;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001333 }
Ethan Nicholas7deb1c22020-01-22 10:31:55 -05001334}
1335
Brian Osmanb08cc022020-04-02 11:38:40 -04001336class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
1337public:
1338 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
1339 : INHERITED(*generator)
1340 , fCount(ByteCodeGenerator::SlotCount(value.type()))
1341 , fIndex(index) {}
1342
1343 void load() override {
1344 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001345 fGenerator.write8(fIndex);
1346 }
1347
1348 void store(bool discard) override {
1349 if (!discard) {
1350 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001351 }
1352 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001353 fGenerator.write8(fIndex);
1354 }
1355
1356private:
1357 typedef LValue INHERITED;
1358
1359 int fCount;
1360
1361 int fIndex;
1362};
1363
1364class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
1365public:
1366 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
1367 : INHERITED(*generator)
1368 , fSwizzle(swizzle) {}
1369
1370 void load() override {
1371 fGenerator.writeSwizzle(fSwizzle);
1372 }
1373
1374 void store(bool discard) override {
1375 int count = fSwizzle.fComponents.size();
1376 if (!discard) {
1377 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001378 }
1379 ByteCodeGenerator::Location location = fGenerator.getLocation(*fSwizzle.fBase);
1380 if (location.isOnStack()) {
1381 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreSwizzleIndirect,
1382 ByteCodeInstruction::kStoreSwizzleIndirectGlobal),
1383 count);
1384 } else {
1385 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreSwizzle,
1386 ByteCodeInstruction::kStoreSwizzleGlobal),
1387 count);
1388 fGenerator.write8(location.fSlot);
1389 }
1390 fGenerator.write8(count);
1391 for (int c : fSwizzle.fComponents) {
1392 fGenerator.write8(c);
1393 }
1394 }
1395
1396private:
1397 const Swizzle& fSwizzle;
1398
1399 typedef LValue INHERITED;
1400};
1401
1402class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
1403public:
1404 ByteCodeExpressionLValue(ByteCodeGenerator* generator, const Expression& expr)
1405 : INHERITED(*generator)
1406 , fExpression(expr) {}
1407
1408 void load() override {
1409 fGenerator.writeVariableExpression(fExpression);
1410 }
1411
1412 void store(bool discard) override {
1413 int count = ByteCodeGenerator::SlotCount(fExpression.fType);
1414 if (!discard) {
1415 if (count > 4) {
1416 fGenerator.write(ByteCodeInstruction::kDupN, count);
1417 fGenerator.write8(count);
1418 } else {
1419 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001420 }
1421 }
1422 ByteCodeGenerator::Location location = fGenerator.getLocation(fExpression);
1423 if (location.isOnStack() || count > 4) {
1424 if (!location.isOnStack()) {
1425 fGenerator.write(ByteCodeInstruction::kPushImmediate);
1426 fGenerator.write32(location.fSlot);
1427 }
1428 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreExtended,
1429 ByteCodeInstruction::kStoreExtendedGlobal),
1430 count);
1431 fGenerator.write8(count);
1432 } else {
1433 fGenerator.write(
1434 vector_instruction(location.selectStore(ByteCodeInstruction::kStore,
1435 ByteCodeInstruction::kStoreGlobal),
1436 count));
1437 fGenerator.write8(location.fSlot);
1438 }
1439 }
1440
1441private:
1442 typedef LValue INHERITED;
1443
1444 const Expression& fExpression;
1445};
1446
1447std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
1448 switch (e.fKind) {
1449 case Expression::kExternalValue_Kind: {
1450 ExternalValue* value = ((ExternalValueReference&) e).fValue;
1451 int index = fOutput->fExternalValues.size();
1452 fOutput->fExternalValues.push_back(value);
1453 SkASSERT(index <= 255);
1454 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
1455 }
1456 case Expression::kFieldAccess_Kind:
1457 case Expression::kIndex_Kind:
1458 case Expression::kVariableReference_Kind:
1459 return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
1460 case Expression::kSwizzle_Kind: {
1461 const Swizzle& s = (const Swizzle&) e;
1462 return swizzle_is_simple(s)
1463 ? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e))
1464 : std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s));
1465 }
1466 case Expression::kTernary_Kind:
1467 default:
1468#ifdef SK_DEBUG
1469 ABORT("unsupported lvalue %s\n", e.description().c_str());
1470#endif
1471 return nullptr;
1472 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001473}
1474
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001475void ByteCodeGenerator::writeBlock(const Block& b) {
1476 for (const auto& s : b.fStatements) {
1477 this->writeStatement(*s);
1478 }
1479}
1480
Brian Osmanb08cc022020-04-02 11:38:40 -04001481void ByteCodeGenerator::setBreakTargets() {
1482 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
1483 for (DeferredLocation& b : breaks) {
1484 b.set();
1485 }
1486 fBreakTargets.pop();
1487}
1488
1489void ByteCodeGenerator::setContinueTargets() {
1490 std::vector<DeferredLocation>& continues = fContinueTargets.top();
1491 for (DeferredLocation& c : continues) {
1492 c.set();
1493 }
1494 fContinueTargets.pop();
1495}
1496
1497void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
1498 // TODO: Include BranchIfAllFalse to top-most LoopNext
1499 this->write(ByteCodeInstruction::kLoopBreak);
1500}
1501
1502void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
1503 // TODO: Include BranchIfAllFalse to top-most LoopNext
1504 this->write(ByteCodeInstruction::kLoopContinue);
1505}
1506
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001507void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001508 this->write(ByteCodeInstruction::kLoopBegin);
1509 size_t start = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001510 this->writeStatement(*d.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001511 this->write(ByteCodeInstruction::kLoopNext);
1512 this->writeExpression(*d.fTest);
1513 this->write(ByteCodeInstruction::kLoopMask);
1514 // TODO: Could shorten this with kBranchIfAnyTrue
1515 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001516 DeferredLocation endLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -04001517 this->write(ByteCodeInstruction::kBranch);
1518 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001519 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001520 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001521}
1522
1523void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001524 fContinueTargets.emplace();
1525 fBreakTargets.emplace();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001526 if (f.fInitializer) {
1527 this->writeStatement(*f.fInitializer);
1528 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001529 this->write(ByteCodeInstruction::kLoopBegin);
1530 size_t start = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001531 if (f.fTest) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001532 this->writeExpression(*f.fTest);
1533 this->write(ByteCodeInstruction::kLoopMask);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001534 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001535 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001536 DeferredLocation endLocation(this);
1537 this->writeStatement(*f.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001538 this->write(ByteCodeInstruction::kLoopNext);
Brian Osman569f12f2019-06-13 11:23:57 -04001539 if (f.fNext) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001540 this->writeExpression(*f.fNext, true);
Brian Osman569f12f2019-06-13 11:23:57 -04001541 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001542 this->write(ByteCodeInstruction::kBranch);
1543 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001544 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001545 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001546}
1547
1548void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001549 this->writeExpression(*i.fTest);
1550 this->write(ByteCodeInstruction::kMaskPush);
1551 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001552 DeferredLocation falseLocation(this);
1553 this->writeStatement(*i.fIfTrue);
1554 falseLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001555 if (i.fIfFalse) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001556 this->write(ByteCodeInstruction::kMaskNegate);
1557 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001558 DeferredLocation endLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001559 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -05001560 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001561 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001562 this->write(ByteCodeInstruction::kMaskPop);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001563}
1564
Brian Osmanb08cc022020-04-02 11:38:40 -04001565void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
1566 if (fLoopCount || fConditionCount) {
Brian Osman4a47da72019-07-12 11:30:32 -04001567 fErrors.error(r.fOffset, "return not allowed inside conditional or loop");
1568 return;
1569 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001570 int count = SlotCount(r.fExpression->fType);
1571 this->writeExpression(*r.fExpression);
1572
1573 // Technically, the kReturn also pops fOutput->fLocalCount values from the stack, too, but we
1574 // haven't counted pushing those (they're outside the scope of our stack tracking). Instead,
1575 // we account for those in writeFunction().
1576
1577 // This is all fine because we don't allow conditional returns, so we only return once anyway.
1578 this->write(ByteCodeInstruction::kReturn, -count);
1579 this->write8(count);
1580}
1581
1582void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
1583 // not yet implemented
1584 abort();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001585}
1586
1587void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1588 for (const auto& declStatement : v.fVars) {
1589 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
Brian Osmanb08cc022020-04-02 11:38:40 -04001590 // we need to grab the location even if we don't use it, to ensure it has been allocated
1591 Location location = this->getLocation(*decl.fVar);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001592 if (decl.fValue) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001593 this->writeExpression(*decl.fValue);
1594 int count = SlotCount(decl.fValue->fType);
1595 if (count > 4) {
1596 this->write(ByteCodeInstruction::kPushImmediate);
1597 this->write32(location.fSlot);
1598 this->write(ByteCodeInstruction::kStoreExtended, count);
1599 this->write8(count);
1600 } else {
1601 this->write(vector_instruction(ByteCodeInstruction::kStore, count));
1602 this->write8(location.fSlot);
1603 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001604 }
1605 }
1606}
1607
1608void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001609 this->write(ByteCodeInstruction::kLoopBegin);
1610 size_t cond = fCode->size();
1611 this->writeExpression(*w.fTest);
1612 this->write(ByteCodeInstruction::kLoopMask);
1613 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001614 DeferredLocation endLocation(this);
1615 this->writeStatement(*w.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001616 this->write(ByteCodeInstruction::kLoopNext);
1617 this->write(ByteCodeInstruction::kBranch);
1618 this->write16(cond);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001619 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001620 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001621}
1622
1623void ByteCodeGenerator::writeStatement(const Statement& s) {
1624 switch (s.fKind) {
1625 case Statement::kBlock_Kind:
1626 this->writeBlock((Block&) s);
1627 break;
1628 case Statement::kBreak_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001629 this->writeBreakStatement((BreakStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001630 break;
1631 case Statement::kContinue_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001632 this->writeContinueStatement((ContinueStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001633 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001634 case Statement::kDiscard_Kind:
1635 // not yet implemented
1636 abort();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001637 case Statement::kDo_Kind:
1638 this->writeDoStatement((DoStatement&) s);
1639 break;
Brian Osman3e29f1d2019-05-28 09:35:05 -04001640 case Statement::kExpression_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001641 this->writeExpression(*((ExpressionStatement&) s).fExpression, true);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001642 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001643 case Statement::kFor_Kind:
1644 this->writeForStatement((ForStatement&) s);
1645 break;
1646 case Statement::kIf_Kind:
1647 this->writeIfStatement((IfStatement&) s);
1648 break;
1649 case Statement::kNop_Kind:
1650 break;
1651 case Statement::kReturn_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001652 this->writeReturnStatement((ReturnStatement&) s);
1653 break;
1654 case Statement::kSwitch_Kind:
1655 this->writeSwitchStatement((SwitchStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001656 break;
1657 case Statement::kVarDeclarations_Kind:
1658 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1659 break;
1660 case Statement::kWhile_Kind:
1661 this->writeWhileStatement((WhileStatement&) s);
1662 break;
1663 default:
Brian Osmanb08cc022020-04-02 11:38:40 -04001664 SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001665 }
1666}
1667
Brian Osmanb08cc022020-04-02 11:38:40 -04001668ByteCodeFunction::ByteCodeFunction(const FunctionDeclaration* declaration)
1669 : fName(declaration->fName) {
Brian Osman80164412019-06-07 13:00:23 -04001670 fParameterCount = 0;
Brian Osmanb08cc022020-04-02 11:38:40 -04001671 for (const auto& p : declaration->fParameters) {
1672 int slots = ByteCodeGenerator::SlotCount(p->fType);
1673 fParameters.push_back({ slots, (bool)(p->fModifiers.fFlags & Modifiers::kOut_Flag) });
1674 fParameterCount += slots;
Brian Osman80164412019-06-07 13:00:23 -04001675 }
1676}
1677
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001678}