blob: 60bff342ab51a4f22b41b3c9b6ce35a8b8e473c2 [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 },
51 { "sin", ByteCodeInstruction::kSin },
52 { "sqrt", ByteCodeInstruction::kSqrt },
53 { "tan", ByteCodeInstruction::kTan },
54 } {}
55
Ethan Nicholas82162ee2019-05-21 16:05:08 -040056
Brian Osman07c117b2019-05-23 12:51:06 -070057int ByteCodeGenerator::SlotCount(const Type& type) {
Brian Osmanfba386b2019-06-20 14:54:15 -040058 if (type.kind() == Type::kOther_Kind) {
59 return 0;
60 } else if (type.kind() == Type::kStruct_Kind) {
Brian Osman07c117b2019-05-23 12:51:06 -070061 int slots = 0;
62 for (const auto& f : type.fields()) {
63 slots += SlotCount(*f.fType);
64 }
65 SkASSERT(slots <= 255);
66 return slots;
67 } else if (type.kind() == Type::kArray_Kind) {
68 int columns = type.columns();
69 SkASSERT(columns >= 0);
70 int slots = columns * SlotCount(type.componentType());
71 SkASSERT(slots <= 255);
72 return slots;
73 } else {
74 return type.columns() * type.rows();
75 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040076}
77
Brian Osman1c110a02019-10-01 14:53:32 -040078static inline bool is_uniform(const SkSL::Variable& var) {
79 return var.fModifiers.fFlags & Modifiers::kUniform_Flag;
80}
81
Brian Osmaneadfeb92020-01-09 12:43:03 -050082static inline bool is_in(const SkSL::Variable& var) {
83 return var.fModifiers.fFlags & Modifiers::kIn_Flag;
84}
Brian Osmanb08cc022020-04-02 11:38:40 -040085
86void ByteCodeGenerator::gatherUniforms(const Type& type, const String& name) {
87 if (type.kind() == Type::kOther_Kind) {
88 return;
89 } else if (type.kind() == Type::kStruct_Kind) {
90 for (const auto& f : type.fields()) {
91 this->gatherUniforms(*f.fType, name + "." + f.fName);
Ethan Nicholasb962eff2020-01-23 16:49:41 -050092 }
Brian Osmanb08cc022020-04-02 11:38:40 -040093 } else if (type.kind() == Type::kArray_Kind) {
94 for (int i = 0; i < type.columns(); ++i) {
95 this->gatherUniforms(type.componentType(), String::printf("%s[%d]", name.c_str(), i));
Ethan Nicholasb962eff2020-01-23 16:49:41 -050096 }
Brian Osmanb08cc022020-04-02 11:38:40 -040097 } else {
98 fOutput->fUniforms.push_back({ name, type_category(type), type.rows(), type.columns(),
99 fOutput->fUniformSlotCount });
100 fOutput->fUniformSlotCount += type.columns() * type.rows();
101 }
102}
103
104bool ByteCodeGenerator::generateCode() {
105 for (const auto& e : fProgram) {
106 switch (e.fKind) {
107 case ProgramElement::kFunction_Kind: {
108 std::unique_ptr<ByteCodeFunction> f = this->writeFunction((FunctionDefinition&) e);
109 if (!f) {
110 return false;
111 }
112 fOutput->fFunctions.push_back(std::move(f));
113 fFunctions.push_back(&(FunctionDefinition&)e);
114 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500115 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400116 case ProgramElement::kVar_Kind: {
117 VarDeclarations& decl = (VarDeclarations&) e;
118 for (const auto& v : decl.fVars) {
119 const Variable* declVar = ((VarDeclaration&) *v).fVar;
120 if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
121 continue;
122 }
123 if (is_uniform(*declVar)) {
124 this->gatherUniforms(declVar->fType, declVar->fName);
125 } else {
126 fOutput->fGlobalSlotCount += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400127 }
128 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400129 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400130 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400131 default:
132 ; // ignore
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400133 }
134 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400135 return 0 == fErrors.errorCount();
136}
137
138std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
139 fFunction = &f;
140 std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
141 fParameterCount = result->fParameterCount;
142 fLoopCount = fMaxLoopCount = 0;
143 fConditionCount = fMaxConditionCount = 0;
144 fStackCount = fMaxStackCount = 0;
145 fCode = &result->fCode;
146
147 this->writeStatement(*f.fBody);
148 if (0 == fErrors.errorCount()) {
149 SkASSERT(fLoopCount == 0);
150 SkASSERT(fConditionCount == 0);
151 SkASSERT(fStackCount == 0);
152 }
153 this->write(ByteCodeInstruction::kReturn, 0);
154 this->write8(0);
155
156 result->fLocalCount = fLocals.size();
157 result->fConditionCount = fMaxConditionCount;
158 result->fLoopCount = fMaxLoopCount;
159 result->fStackCount = fMaxStackCount;
160
161 const Type& returnType = f.fDeclaration.fReturnType;
162 if (returnType != *fContext.fVoid_Type) {
163 result->fReturnCount = SlotCount(returnType);
164 }
165 fLocals.clear();
166 fFunction = nullptr;
167 return result;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400168}
169
Brian Osman0785db02019-05-24 14:19:11 -0400170// A "simple" Swizzle is based on a variable (or a compound variable like a struct or array), and
171// that references consecutive values, such that it can be implemented using normal load/store ops
172// with an offset. Note that all single-component swizzles (of suitable base types) are simple.
173static bool swizzle_is_simple(const Swizzle& s) {
174 switch (s.fBase->fKind) {
175 case Expression::kFieldAccess_Kind:
176 case Expression::kIndex_Kind:
177 case Expression::kVariableReference_Kind:
178 break;
179 default:
180 return false;
181 }
182
183 for (size_t i = 1; i < s.fComponents.size(); ++i) {
184 if (s.fComponents[i] != s.fComponents[i - 1] + 1) {
185 return false;
186 }
187 }
188 return true;
189}
190
Brian Osmanb08cc022020-04-02 11:38:40 -0400191int ByteCodeGenerator::StackUsage(ByteCodeInstruction inst, int count_) {
192 // Ensures that we use count iff we're passed a non-default value. Most instructions have an
193 // implicit count, so the caller shouldn't need to worry about it (or count makes no sense).
194 // The asserts avoids callers thinking they're supplying useful information in that scenario,
195 // or failing to supply necessary information for the ops that need a count.
196 struct CountValue {
197 operator int() {
198 SkASSERT(val != ByteCodeGenerator::kUnusedStackCount);
199 SkDEBUGCODE(used = true);
200 return val;
201 }
202 ~CountValue() {
203 SkASSERT(used || val == ByteCodeGenerator::kUnusedStackCount);
204 }
205 int val;
206 SkDEBUGCODE(bool used = false;)
207 } count = { count_ };
208
209 switch (inst) {
210 // Unary functions/operators that don't change stack depth at all:
211#define VECTOR_UNARY_OP(base) \
212 case ByteCodeInstruction::base: \
213 case ByteCodeInstruction::base ## 2: \
214 case ByteCodeInstruction::base ## 3: \
215 case ByteCodeInstruction::base ## 4: \
216 return 0;
217
218 VECTOR_UNARY_OP(kConvertFtoI)
219 VECTOR_UNARY_OP(kConvertStoF)
220 VECTOR_UNARY_OP(kConvertUtoF)
221
Mike Reed8520e762020-04-30 12:06:23 -0400222 VECTOR_UNARY_OP(kATan)
Brian Osmanb08cc022020-04-02 11:38:40 -0400223 VECTOR_UNARY_OP(kCos)
Mike Reed8520e762020-04-30 12:06:23 -0400224 VECTOR_UNARY_OP(kFract)
Brian Osmanb08cc022020-04-02 11:38:40 -0400225 VECTOR_UNARY_OP(kSin)
226 VECTOR_UNARY_OP(kSqrt)
227 VECTOR_UNARY_OP(kTan)
228
229 VECTOR_UNARY_OP(kNegateF)
230 VECTOR_UNARY_OP(kNegateI)
231
232 case ByteCodeInstruction::kInverse2x2:
233 case ByteCodeInstruction::kInverse3x3:
234 case ByteCodeInstruction::kInverse4x4: return 0;
235
236 case ByteCodeInstruction::kClampIndex: return 0;
237 case ByteCodeInstruction::kNotB: return 0;
238 case ByteCodeInstruction::kNegateFN: return 0;
239 case ByteCodeInstruction::kShiftLeft: return 0;
240 case ByteCodeInstruction::kShiftRightS: return 0;
241 case ByteCodeInstruction::kShiftRightU: return 0;
242
243#undef VECTOR_UNARY_OP
244
245 // Binary functions/operators that do a 2 -> 1 reduction (possibly N times)
246#define VECTOR_BINARY_OP(base) \
247 case ByteCodeInstruction::base: return -1; \
248 case ByteCodeInstruction::base ## 2: return -2; \
249 case ByteCodeInstruction::base ## 3: return -3; \
250 case ByteCodeInstruction::base ## 4: return -4;
251
252#define VECTOR_MATRIX_BINARY_OP(base) \
253 VECTOR_BINARY_OP(base) \
254 case ByteCodeInstruction::base ## N: return -count;
255
256 case ByteCodeInstruction::kAndB: return -1;
257 case ByteCodeInstruction::kOrB: return -1;
258 case ByteCodeInstruction::kXorB: return -1;
259
260 VECTOR_BINARY_OP(kAddI)
261 VECTOR_MATRIX_BINARY_OP(kAddF)
262
263 VECTOR_BINARY_OP(kCompareIEQ)
264 VECTOR_MATRIX_BINARY_OP(kCompareFEQ)
265 VECTOR_BINARY_OP(kCompareINEQ)
266 VECTOR_MATRIX_BINARY_OP(kCompareFNEQ)
267 VECTOR_BINARY_OP(kCompareSGT)
268 VECTOR_BINARY_OP(kCompareUGT)
269 VECTOR_BINARY_OP(kCompareFGT)
270 VECTOR_BINARY_OP(kCompareSGTEQ)
271 VECTOR_BINARY_OP(kCompareUGTEQ)
272 VECTOR_BINARY_OP(kCompareFGTEQ)
273 VECTOR_BINARY_OP(kCompareSLT)
274 VECTOR_BINARY_OP(kCompareULT)
275 VECTOR_BINARY_OP(kCompareFLT)
276 VECTOR_BINARY_OP(kCompareSLTEQ)
277 VECTOR_BINARY_OP(kCompareULTEQ)
278 VECTOR_BINARY_OP(kCompareFLTEQ)
279
280 VECTOR_BINARY_OP(kDivideS)
281 VECTOR_BINARY_OP(kDivideU)
282 VECTOR_MATRIX_BINARY_OP(kDivideF)
283 VECTOR_BINARY_OP(kMultiplyI)
284 VECTOR_MATRIX_BINARY_OP(kMultiplyF)
285 VECTOR_BINARY_OP(kRemainderF)
286 VECTOR_BINARY_OP(kRemainderS)
287 VECTOR_BINARY_OP(kRemainderU)
288 VECTOR_BINARY_OP(kSubtractI)
289 VECTOR_MATRIX_BINARY_OP(kSubtractF)
290
291#undef VECTOR_BINARY_OP
292#undef VECTOR_MATRIX_BINARY_OP
293
294 // Ops that push or load data to grow the stack:
295 case ByteCodeInstruction::kDup:
296 case ByteCodeInstruction::kLoad:
297 case ByteCodeInstruction::kLoadGlobal:
298 case ByteCodeInstruction::kLoadUniform:
299 case ByteCodeInstruction::kReadExternal:
300 case ByteCodeInstruction::kPushImmediate:
301 return 1;
302
303 case ByteCodeInstruction::kDup2:
304 case ByteCodeInstruction::kLoad2:
305 case ByteCodeInstruction::kLoadGlobal2:
306 case ByteCodeInstruction::kLoadUniform2:
307 case ByteCodeInstruction::kReadExternal2:
308 return 2;
309
310 case ByteCodeInstruction::kDup3:
311 case ByteCodeInstruction::kLoad3:
312 case ByteCodeInstruction::kLoadGlobal3:
313 case ByteCodeInstruction::kLoadUniform3:
314 case ByteCodeInstruction::kReadExternal3:
315 return 3;
316
317 case ByteCodeInstruction::kDup4:
318 case ByteCodeInstruction::kLoad4:
319 case ByteCodeInstruction::kLoadGlobal4:
320 case ByteCodeInstruction::kLoadUniform4:
321 case ByteCodeInstruction::kReadExternal4:
322 return 4;
323
324 case ByteCodeInstruction::kDupN:
325 case ByteCodeInstruction::kLoadSwizzle:
326 case ByteCodeInstruction::kLoadSwizzleGlobal:
327 case ByteCodeInstruction::kLoadSwizzleUniform:
328 return count;
329
330 // Pushes 'count' values, minus one for the 'address' that's consumed first
331 case ByteCodeInstruction::kLoadExtended:
332 case ByteCodeInstruction::kLoadExtendedGlobal:
333 case ByteCodeInstruction::kLoadExtendedUniform:
334 return count - 1;
335
336 // Ops that pop or store data to shrink the stack:
337 case ByteCodeInstruction::kPop:
338 case ByteCodeInstruction::kStore:
339 case ByteCodeInstruction::kStoreGlobal:
340 case ByteCodeInstruction::kWriteExternal:
341 return -1;
342
343 case ByteCodeInstruction::kPop2:
344 case ByteCodeInstruction::kStore2:
345 case ByteCodeInstruction::kStoreGlobal2:
346 case ByteCodeInstruction::kWriteExternal2:
347 return -2;
348
349 case ByteCodeInstruction::kPop3:
350 case ByteCodeInstruction::kStore3:
351 case ByteCodeInstruction::kStoreGlobal3:
352 case ByteCodeInstruction::kWriteExternal3:
353 return -3;
354
355 case ByteCodeInstruction::kPop4:
356 case ByteCodeInstruction::kStore4:
357 case ByteCodeInstruction::kStoreGlobal4:
358 case ByteCodeInstruction::kWriteExternal4:
359 return -4;
360
361 case ByteCodeInstruction::kPopN:
362 case ByteCodeInstruction::kStoreSwizzle:
363 case ByteCodeInstruction::kStoreSwizzleGlobal:
364 return -count;
365
366 // Consumes 'count' values, plus one for the 'address'
367 case ByteCodeInstruction::kStoreExtended:
368 case ByteCodeInstruction::kStoreExtendedGlobal:
369 case ByteCodeInstruction::kStoreSwizzleIndirect:
370 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal:
371 return -count - 1;
372
373 // Strange ops where the caller computes the delta for us:
374 case ByteCodeInstruction::kCallExternal:
375 case ByteCodeInstruction::kMatrixToMatrix:
376 case ByteCodeInstruction::kMatrixMultiply:
377 case ByteCodeInstruction::kReserve:
378 case ByteCodeInstruction::kReturn:
379 case ByteCodeInstruction::kScalarToMatrix:
380 case ByteCodeInstruction::kSwizzle:
381 return count;
382
383 // Miscellaneous
384
385 // kCall is net-zero. Max stack depth is adjusted in writeFunctionCall.
386 case ByteCodeInstruction::kCall: return 0;
387 case ByteCodeInstruction::kBranch: return 0;
388 case ByteCodeInstruction::kBranchIfAllFalse: return 0;
389
390 case ByteCodeInstruction::kMaskPush: return -1;
391 case ByteCodeInstruction::kMaskPop: return 0;
392 case ByteCodeInstruction::kMaskNegate: return 0;
393 case ByteCodeInstruction::kMaskBlend: return -count;
394
395 case ByteCodeInstruction::kLoopBegin: return 0;
396 case ByteCodeInstruction::kLoopNext: return 0;
397 case ByteCodeInstruction::kLoopMask: return -1;
398 case ByteCodeInstruction::kLoopEnd: return 0;
399 case ByteCodeInstruction::kLoopBreak: return 0;
400 case ByteCodeInstruction::kLoopContinue: return 0;
401
402 default:
403 ABORT("unsupported instruction %d\n", (int)inst);
404 return 0;
405 }
406}
407
408ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var) {
409 // given that we seldom have more than a couple of variables, linear search is probably the most
410 // efficient way to handle lookups
411 switch (var.fStorage) {
412 case Variable::kLocal_Storage: {
413 for (int i = fLocals.size() - 1; i >= 0; --i) {
414 if (fLocals[i] == &var) {
415 SkASSERT(fParameterCount + i <= 255);
416 return { fParameterCount + i, Storage::kLocal };
417 }
418 }
419 int result = fParameterCount + fLocals.size();
420 fLocals.push_back(&var);
421 for (int i = 0; i < SlotCount(var.fType) - 1; ++i) {
422 fLocals.push_back(nullptr);
423 }
424 SkASSERT(result <= 255);
425 return { result, Storage::kLocal };
426 }
427 case Variable::kParameter_Storage: {
428 int offset = 0;
429 for (const auto& p : fFunction->fDeclaration.fParameters) {
430 if (p == &var) {
431 SkASSERT(offset <= 255);
432 return { offset, Storage::kLocal };
433 }
434 offset += SlotCount(p->fType);
435 }
436 SkASSERT(false);
437 return Location::MakeInvalid();
438 }
439 case Variable::kGlobal_Storage: {
440 if (is_in(var)) {
441 // If you see this error, it means the program is using raw 'in' variables. You
442 // should either specialize the program (Compiler::specialize) to bake in the final
443 // values of the 'in' variables, or not use 'in' variables (maybe you meant to use
444 // 'uniform' instead?).
445 fErrors.error(var.fOffset,
446 "'in' variable is not specialized or has unsupported type");
447 return Location::MakeInvalid();
448 }
449 int offset = 0;
450 bool isUniform = is_uniform(var);
451 for (const auto& e : fProgram) {
452 if (e.fKind == ProgramElement::kVar_Kind) {
453 VarDeclarations& decl = (VarDeclarations&) e;
454 for (const auto& v : decl.fVars) {
455 const Variable* declVar = ((VarDeclaration&) *v).fVar;
456 if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
457 continue;
458 }
459 if (isUniform != is_uniform(*declVar)) {
460 continue;
461 }
462 if (declVar == &var) {
463 SkASSERT(offset <= 255);
464 return { offset, isUniform ? Storage::kUniform : Storage::kGlobal };
465 }
466 offset += SlotCount(declVar->fType);
467 }
468 }
469 }
470 SkASSERT(false);
471 return Location::MakeInvalid();
472 }
473 default:
474 SkASSERT(false);
475 return Location::MakeInvalid();
476 }
477}
478
Brian Osman1c110a02019-10-01 14:53:32 -0400479ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Expression& expr) {
Brian Osman07c117b2019-05-23 12:51:06 -0700480 switch (expr.fKind) {
481 case Expression::kFieldAccess_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400482 const FieldAccess& f = (const FieldAccess&)expr;
483 Location baseLoc = this->getLocation(*f.fBase);
Brian Osman07c117b2019-05-23 12:51:06 -0700484 int offset = 0;
485 for (int i = 0; i < f.fFieldIndex; ++i) {
486 offset += SlotCount(*f.fBase->fType.fields()[i].fType);
487 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400488 if (baseLoc.isOnStack()) {
489 if (offset != 0) {
490 this->write(ByteCodeInstruction::kPushImmediate);
491 this->write32(offset);
492 this->write(ByteCodeInstruction::kAddI);
Ben Wagner470e0ac2020-01-22 16:59:21 -0500493 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400494 return baseLoc;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500495 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400496 return baseLoc + offset;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500497 }
Ben Wagner470e0ac2020-01-22 16:59:21 -0500498 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400499 case Expression::kIndex_Kind: {
500 const IndexExpression& i = (const IndexExpression&)expr;
501 int stride = SlotCount(i.fType);
502 int length = i.fBase->fType.columns();
503 SkASSERT(length <= 255);
504 int offset = -1;
505 if (i.fIndex->isConstant()) {
506 int64_t index = i.fIndex->getConstantInt();
507 if (index < 0 || index >= length) {
508 fErrors.error(i.fIndex->fOffset, "Array index out of bounds.");
509 return Location::MakeInvalid();
510 }
511 offset = index * stride;
512 } else {
513 if (i.fIndex->hasSideEffects()) {
514 // Having a side-effect in an indexer is technically safe for an rvalue,
515 // but with lvalues we have to evaluate the indexer twice, so make it an error.
516 fErrors.error(i.fIndex->fOffset,
517 "Index expressions with side-effects not supported in byte code.");
518 return Location::MakeInvalid();
519 }
520 this->writeExpression(*i.fIndex);
521 this->write(ByteCodeInstruction::kClampIndex);
522 this->write8(length);
523 if (stride != 1) {
524 this->write(ByteCodeInstruction::kPushImmediate);
525 this->write32(stride);
526 this->write(ByteCodeInstruction::kMultiplyI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400527 }
528 }
529 Location baseLoc = this->getLocation(*i.fBase);
530
531 // Are both components known statically?
532 if (!baseLoc.isOnStack() && offset >= 0) {
533 return baseLoc + offset;
534 }
535
536 // At least one component is dynamic (and on the stack).
537
538 // If the other component is zero, we're done
539 if (baseLoc.fSlot == 0 || offset == 0) {
540 return baseLoc.makeOnStack();
541 }
542
543 // Push the non-dynamic component (if any) to the stack, then add the two
544 if (!baseLoc.isOnStack()) {
545 this->write(ByteCodeInstruction::kPushImmediate);
546 this->write32(baseLoc.fSlot);
547 }
548 if (offset >= 0) {
549 this->write(ByteCodeInstruction::kPushImmediate);
550 this->write32(offset);
551 }
552 this->write(ByteCodeInstruction::kAddI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400553 return baseLoc.makeOnStack();
554 }
Brian Osman0785db02019-05-24 14:19:11 -0400555 case Expression::kSwizzle_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400556 const Swizzle& s = (const Swizzle&)expr;
Brian Osman0785db02019-05-24 14:19:11 -0400557 SkASSERT(swizzle_is_simple(s));
Brian Osmanb08cc022020-04-02 11:38:40 -0400558 Location baseLoc = this->getLocation(*s.fBase);
559 int offset = s.fComponents[0];
560 if (baseLoc.isOnStack()) {
561 if (offset != 0) {
562 this->write(ByteCodeInstruction::kPushImmediate);
563 this->write32(offset);
564 this->write(ByteCodeInstruction::kAddI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400565 }
566 return baseLoc;
567 } else {
568 return baseLoc + offset;
569 }
Brian Osman0785db02019-05-24 14:19:11 -0400570 }
Brian Osman07c117b2019-05-23 12:51:06 -0700571 case Expression::kVariableReference_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400572 const Variable& var = ((const VariableReference&)expr).fVariable;
Brian Osman07c117b2019-05-23 12:51:06 -0700573 return this->getLocation(var);
574 }
575 default:
576 SkASSERT(false);
Brian Osmanb08cc022020-04-02 11:38:40 -0400577 return Location::MakeInvalid();
Brian Osman07c117b2019-05-23 12:51:06 -0700578 }
579}
580
Brian Osmanb08cc022020-04-02 11:38:40 -0400581void ByteCodeGenerator::write8(uint8_t b) {
582 fCode->push_back(b);
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500583}
584
Brian Osmanb08cc022020-04-02 11:38:40 -0400585void ByteCodeGenerator::write16(uint16_t i) {
586 size_t n = fCode->size();
587 fCode->resize(n+2);
588 memcpy(fCode->data() + n, &i, 2);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500589}
Ben Wagner470e0ac2020-01-22 16:59:21 -0500590
Brian Osmanb08cc022020-04-02 11:38:40 -0400591void ByteCodeGenerator::write32(uint32_t i) {
592 size_t n = fCode->size();
593 fCode->resize(n+4);
594 memcpy(fCode->data() + n, &i, 4);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500595}
596
Brian Osmanb08cc022020-04-02 11:38:40 -0400597void ByteCodeGenerator::write(ByteCodeInstruction i, int count) {
598 switch (i) {
599 case ByteCodeInstruction::kLoopBegin: this->enterLoop(); break;
600 case ByteCodeInstruction::kLoopEnd: this->exitLoop(); break;
Ethan Nicholas2329da02020-01-24 15:49:33 -0500601
Brian Osmanb08cc022020-04-02 11:38:40 -0400602 case ByteCodeInstruction::kMaskPush: this->enterCondition(); break;
603 case ByteCodeInstruction::kMaskPop:
604 case ByteCodeInstruction::kMaskBlend: this->exitCondition(); break;
605 default: /* Do nothing */ break;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500606 }
Brian Osmanab8f3842020-04-07 09:30:44 -0400607 this->write16((uint16_t)i);
Brian Osmanb08cc022020-04-02 11:38:40 -0400608 fStackCount += StackUsage(i, count);
609 fMaxStackCount = std::max(fMaxStackCount, fStackCount);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500610}
611
Brian Osmanb08cc022020-04-02 11:38:40 -0400612static ByteCodeInstruction vector_instruction(ByteCodeInstruction base, int count) {
613 SkASSERT(count >= 1 && count <= 4);
614 return ((ByteCodeInstruction) ((int) base + 1 - count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500615}
616
Brian Osmanb08cc022020-04-02 11:38:40 -0400617void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
618 ByteCodeInstruction u, ByteCodeInstruction f,
Brian Osmanab8f3842020-04-07 09:30:44 -0400619 int count) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500620 switch (type_category(type)) {
621 case TypeCategory::kSigned:
Brian Osmanb08cc022020-04-02 11:38:40 -0400622 this->write(vector_instruction(s, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500623 break;
624 case TypeCategory::kUnsigned:
Brian Osmanb08cc022020-04-02 11:38:40 -0400625 this->write(vector_instruction(u, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500626 break;
627 case TypeCategory::kFloat: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400628 if (count > 4) {
629 this->write((ByteCodeInstruction)((int)f + 1), count);
Brian Osmanab8f3842020-04-07 09:30:44 -0400630 this->write8(count);
Brian Osmanb08cc022020-04-02 11:38:40 -0400631 } else {
632 this->write(vector_instruction(f, count));
633 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500634 break;
635 }
636 default:
637 SkASSERT(false);
638 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500639}
640
Brian Osmanb08cc022020-04-02 11:38:40 -0400641bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool discard) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400642 if (b.fOperator == Token::Kind::TK_EQ) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500643 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
Brian Osmanb08cc022020-04-02 11:38:40 -0400644 this->writeExpression(*b.fRight);
645 lvalue->store(discard);
646 discard = false;
647 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500648 }
649 const Type& lType = b.fLeft->fType;
650 const Type& rType = b.fRight->fType;
651 bool lVecOrMtx = (lType.kind() == Type::kVector_Kind || lType.kind() == Type::kMatrix_Kind);
652 bool rVecOrMtx = (rType.kind() == Type::kVector_Kind || rType.kind() == Type::kMatrix_Kind);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500653 Token::Kind op;
654 std::unique_ptr<LValue> lvalue;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500655 if (is_assignment(b.fOperator)) {
656 lvalue = this->getLValue(*b.fLeft);
Brian Osmanb08cc022020-04-02 11:38:40 -0400657 lvalue->load();
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500658 op = remove_assignment(b.fOperator);
659 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400660 this->writeExpression(*b.fLeft);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500661 op = b.fOperator;
662 if (!lVecOrMtx && rVecOrMtx) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400663 for (int i = SlotCount(rType); i > 1; --i) {
664 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400665 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500666 }
667 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500668 int count = std::max(SlotCount(lType), SlotCount(rType));
Brian Osmanb08cc022020-04-02 11:38:40 -0400669 SkDEBUGCODE(TypeCategory tc = type_category(lType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500670 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400671 case Token::Kind::TK_LOGICALAND: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400672 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
673 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400674 this->write(ByteCodeInstruction::kMaskPush);
675 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500676 DeferredLocation falseLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -0400677 this->writeExpression(*b.fRight);
678 this->write(ByteCodeInstruction::kAndB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500679 falseLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -0400680 this->write(ByteCodeInstruction::kMaskPop);
681 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500682 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400683 case Token::Kind::TK_LOGICALOR: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400684 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
685 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400686 this->write(ByteCodeInstruction::kNotB);
687 this->write(ByteCodeInstruction::kMaskPush);
688 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500689 DeferredLocation falseLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -0400690 this->writeExpression(*b.fRight);
691 this->write(ByteCodeInstruction::kOrB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500692 falseLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -0400693 this->write(ByteCodeInstruction::kMaskPop);
694 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500695 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400696 case Token::Kind::TK_SHL:
697 case Token::Kind::TK_SHR: {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500698 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
699 tc == SkSL::TypeCategory::kUnsigned));
700 if (!b.fRight->isConstant()) {
701 fErrors.error(b.fRight->fOffset, "Shift amounts must be constant");
Brian Osmanb08cc022020-04-02 11:38:40 -0400702 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500703 }
704 int64_t shift = b.fRight->getConstantInt();
705 if (shift < 0 || shift > 31) {
706 fErrors.error(b.fRight->fOffset, "Shift amount out of range");
Brian Osmanb08cc022020-04-02 11:38:40 -0400707 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500708 }
709
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400710 if (op == Token::Kind::TK_SHL) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400711 this->write(ByteCodeInstruction::kShiftLeft);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500712 } else {
713 this->write(type_category(lType) == TypeCategory::kSigned
Brian Osmanb08cc022020-04-02 11:38:40 -0400714 ? ByteCodeInstruction::kShiftRightS
715 : ByteCodeInstruction::kShiftRightU);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500716 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400717 this->write8(shift);
718 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500719 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500720
721 default:
722 break;
723 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400724 this->writeExpression(*b.fRight);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500725 if (lVecOrMtx && !rVecOrMtx) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400726 for (int i = SlotCount(lType); i > 1; --i) {
727 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400728 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500729 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400730 // Special case for M*V, V*M, M*M (but not V*V!)
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400731 if (op == Token::Kind::TK_STAR && lVecOrMtx && rVecOrMtx &&
Brian Osmanb08cc022020-04-02 11:38:40 -0400732 !(lType.kind() == Type::kVector_Kind && rType.kind() == Type::kVector_Kind)) {
733 this->write(ByteCodeInstruction::kMatrixMultiply,
734 SlotCount(b.fType) - (SlotCount(lType) + SlotCount(rType)));
735 int rCols = rType.columns(),
736 rRows = rType.rows(),
737 lCols = lType.columns(),
738 lRows = lType.rows();
739 // M*V treats the vector as a column
740 if (rType.kind() == Type::kVector_Kind) {
741 std::swap(rCols, rRows);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500742 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400743 SkASSERT(lCols == rRows);
744 SkASSERT(SlotCount(b.fType) == lRows * rCols);
745 this->write8(lCols);
746 this->write8(lRows);
747 this->write8(rCols);
748 } else {
749 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400750 case Token::Kind::TK_EQEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400751 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareIEQ,
752 ByteCodeInstruction::kCompareIEQ,
753 ByteCodeInstruction::kCompareFEQ,
754 count);
755 // Collapse to a single bool
756 for (int i = count; i > 1; --i) {
757 this->write(ByteCodeInstruction::kAndB);
758 }
759 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400760 case Token::Kind::TK_GT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400761 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGT,
762 ByteCodeInstruction::kCompareUGT,
763 ByteCodeInstruction::kCompareFGT,
764 count);
765 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400766 case Token::Kind::TK_GTEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400767 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGTEQ,
768 ByteCodeInstruction::kCompareUGTEQ,
769 ByteCodeInstruction::kCompareFGTEQ,
770 count);
771 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400772 case Token::Kind::TK_LT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400773 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLT,
774 ByteCodeInstruction::kCompareULT,
775 ByteCodeInstruction::kCompareFLT,
776 count);
777 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400778 case Token::Kind::TK_LTEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400779 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLTEQ,
780 ByteCodeInstruction::kCompareULTEQ,
781 ByteCodeInstruction::kCompareFLTEQ,
782 count);
783 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400784 case Token::Kind::TK_MINUS:
Brian Osmanb08cc022020-04-02 11:38:40 -0400785 this->writeTypedInstruction(lType, ByteCodeInstruction::kSubtractI,
786 ByteCodeInstruction::kSubtractI,
787 ByteCodeInstruction::kSubtractF,
788 count);
789 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400790 case Token::Kind::TK_NEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400791 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareINEQ,
792 ByteCodeInstruction::kCompareINEQ,
793 ByteCodeInstruction::kCompareFNEQ,
794 count);
795 // Collapse to a single bool
796 for (int i = count; i > 1; --i) {
797 this->write(ByteCodeInstruction::kOrB);
798 }
799 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400800 case Token::Kind::TK_PERCENT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400801 this->writeTypedInstruction(lType, ByteCodeInstruction::kRemainderS,
802 ByteCodeInstruction::kRemainderU,
803 ByteCodeInstruction::kRemainderF,
804 count);
805 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400806 case Token::Kind::TK_PLUS:
Brian Osmanb08cc022020-04-02 11:38:40 -0400807 this->writeTypedInstruction(lType, ByteCodeInstruction::kAddI,
808 ByteCodeInstruction::kAddI,
809 ByteCodeInstruction::kAddF,
810 count);
811 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400812 case Token::Kind::TK_SLASH:
Brian Osmanb08cc022020-04-02 11:38:40 -0400813 this->writeTypedInstruction(lType, ByteCodeInstruction::kDivideS,
814 ByteCodeInstruction::kDivideU,
815 ByteCodeInstruction::kDivideF,
816 count);
817 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400818 case Token::Kind::TK_STAR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400819 this->writeTypedInstruction(lType, ByteCodeInstruction::kMultiplyI,
820 ByteCodeInstruction::kMultiplyI,
821 ByteCodeInstruction::kMultiplyF,
822 count);
823 break;
824
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400825 case Token::Kind::TK_LOGICALXOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400826 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
827 this->write(ByteCodeInstruction::kXorB);
828 break;
829
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400830 case Token::Kind::TK_BITWISEAND:
Brian Osmanb08cc022020-04-02 11:38:40 -0400831 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
832 tc == SkSL::TypeCategory::kUnsigned));
833 this->write(ByteCodeInstruction::kAndB);
834 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400835 case Token::Kind::TK_BITWISEOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400836 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
837 tc == SkSL::TypeCategory::kUnsigned));
838 this->write(ByteCodeInstruction::kOrB);
839 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400840 case Token::Kind::TK_BITWISEXOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400841 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
842 tc == SkSL::TypeCategory::kUnsigned));
843 this->write(ByteCodeInstruction::kXorB);
844 break;
845
846 default:
847 fErrors.error(b.fOffset, SkSL::String::printf("Unsupported binary operator '%s'",
848 Compiler::OperatorName(op)));
849 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500850 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500851 }
852 if (lvalue) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400853 lvalue->store(discard);
854 discard = false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500855 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400856 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500857}
858
Brian Osmanb08cc022020-04-02 11:38:40 -0400859void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
860 this->write(ByteCodeInstruction::kPushImmediate);
861 this->write32(b.fValue ? ~0 : 0);
862}
863
864void ByteCodeGenerator::writeConstructor(const Constructor& c) {
865 for (const auto& arg : c.fArguments) {
866 this->writeExpression(*arg);
867 }
868 if (c.fArguments.size() == 1) {
869 const Type& inType = c.fArguments[0]->fType;
870 const Type& outType = c.fType;
871 TypeCategory inCategory = type_category(inType);
872 TypeCategory outCategory = type_category(outType);
873 int inCount = SlotCount(inType);
874 int outCount = SlotCount(outType);
875 if (inCategory != outCategory) {
876 SkASSERT(inCount == outCount);
877 if (inCategory == TypeCategory::kFloat) {
878 SkASSERT(outCategory == TypeCategory::kSigned ||
879 outCategory == TypeCategory::kUnsigned);
880 this->write(vector_instruction(ByteCodeInstruction::kConvertFtoI, outCount));
881 } else if (outCategory == TypeCategory::kFloat) {
882 if (inCategory == TypeCategory::kSigned) {
883 this->write(vector_instruction(ByteCodeInstruction::kConvertStoF, outCount));
884 } else {
885 SkASSERT(inCategory == TypeCategory::kUnsigned);
886 this->write(vector_instruction(ByteCodeInstruction::kConvertUtoF, outCount));
887 }
888 } else {
889 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500890 }
891 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400892 if (inType.kind() == Type::kMatrix_Kind && outType.kind() == Type::kMatrix_Kind) {
893 this->write(ByteCodeInstruction::kMatrixToMatrix,
894 SlotCount(outType) - SlotCount(inType));
895 this->write8(inType.columns());
896 this->write8(inType.rows());
897 this->write8(outType.columns());
898 this->write8(outType.rows());
899 } else if (inCount != outCount) {
900 SkASSERT(inCount == 1);
901 if (outType.kind() == Type::kMatrix_Kind) {
902 this->write(ByteCodeInstruction::kScalarToMatrix, SlotCount(outType) - 1);
903 this->write8(outType.columns());
904 this->write8(outType.rows());
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500905 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400906 SkASSERT(outType.kind() == Type::kVector_Kind);
907 for (; inCount != outCount; ++inCount) {
908 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400909 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500910 }
911 }
912 }
913}
914
Brian Osmanb08cc022020-04-02 11:38:40 -0400915void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500916 int argumentCount = 0;
917 for (const auto& arg : f.fArguments) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400918 this->writeExpression(*arg);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500919 argumentCount += SlotCount(arg->fType);
920 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400921 this->write(ByteCodeInstruction::kCallExternal, SlotCount(f.fType) - argumentCount);
922 SkASSERT(argumentCount <= 255);
923 this->write8(argumentCount);
924 this->write8(SlotCount(f.fType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500925 int index = fOutput->fExternalValues.size();
926 fOutput->fExternalValues.push_back(f.fFunction);
927 SkASSERT(index <= 255);
Brian Osmanb08cc022020-04-02 11:38:40 -0400928 this->write8(index);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500929}
930
Brian Osmanb08cc022020-04-02 11:38:40 -0400931void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
932 int count = SlotCount(e.fValue->type());
933 this->write(vector_instruction(ByteCodeInstruction::kReadExternal, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500934 int index = fOutput->fExternalValues.size();
935 fOutput->fExternalValues.push_back(e.fValue);
936 SkASSERT(index <= 255);
Brian Osmanb08cc022020-04-02 11:38:40 -0400937 this->write8(index);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500938}
939
Brian Osmanb08cc022020-04-02 11:38:40 -0400940void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
941 Location location = this->getLocation(expr);
942 int count = SlotCount(expr.fType);
Brian Osmanefb08402020-04-13 16:30:44 -0400943 if (count == 0) {
944 return;
945 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400946 if (location.isOnStack() || count > 4) {
947 if (!location.isOnStack()) {
948 this->write(ByteCodeInstruction::kPushImmediate);
949 this->write32(location.fSlot);
950 }
951 this->write(location.selectLoad(ByteCodeInstruction::kLoadExtended,
952 ByteCodeInstruction::kLoadExtendedGlobal,
953 ByteCodeInstruction::kLoadExtendedUniform),
954 count);
955 this->write8(count);
956 } else {
957 this->write(vector_instruction(location.selectLoad(ByteCodeInstruction::kLoad,
958 ByteCodeInstruction::kLoadGlobal,
959 ByteCodeInstruction::kLoadUniform),
960 count));
Brian Osmanb08cc022020-04-02 11:38:40 -0400961 this->write8(location.fSlot);
962 }
963}
964
965static inline uint32_t float_to_bits(float x) {
966 uint32_t u;
967 memcpy(&u, &x, sizeof(uint32_t));
968 return u;
969}
970
971void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
972 this->write(ByteCodeInstruction::kPushImmediate);
973 this->write32(float_to_bits(f.fValue));
974}
975
976void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
977 auto found = fIntrinsics.find(c.fFunction.fName);
978 if (found == fIntrinsics.end()) {
979 fErrors.error(c.fOffset, String::printf("Unsupported intrinsic: '%s'",
980 String(c.fFunction.fName).c_str()));
981 return;
982 }
983 int count = SlotCount(c.fArguments[0]->fType);
984 if (found->second.fIsSpecial) {
985 SpecialIntrinsic special = found->second.fValue.fSpecial;
986 switch (special) {
Brian Osman15c98cb2020-02-27 18:36:57 +0000987 case SpecialIntrinsic::kDot: {
988 SkASSERT(c.fArguments.size() == 2);
Brian Osmanb08cc022020-04-02 11:38:40 -0400989 SkASSERT(count == SlotCount(c.fArguments[1]->fType));
990 this->write(vector_instruction(ByteCodeInstruction::kMultiplyF, count));
Brian Osmanb08cc022020-04-02 11:38:40 -0400991 for (int i = count; i > 1; --i) {
992 this->write(ByteCodeInstruction::kAddF);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500993 }
994 break;
995 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400996 default:
997 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500998 }
999 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -04001000 switch (found->second.fValue.fInstruction) {
Mike Reed8520e762020-04-30 12:06:23 -04001001 case ByteCodeInstruction::kATan:
Brian Osmanb08cc022020-04-02 11:38:40 -04001002 case ByteCodeInstruction::kCos:
Mike Reed8520e762020-04-30 12:06:23 -04001003 case ByteCodeInstruction::kFract:
Brian Osmanb08cc022020-04-02 11:38:40 -04001004 case ByteCodeInstruction::kSin:
Brian Osmanb08cc022020-04-02 11:38:40 -04001005 case ByteCodeInstruction::kSqrt:
Brian Osmanab8f3842020-04-07 09:30:44 -04001006 case ByteCodeInstruction::kTan:
Brian Osmanb08cc022020-04-02 11:38:40 -04001007 SkASSERT(c.fArguments.size() > 0);
1008 this->write(vector_instruction(found->second.fValue.fInstruction, count));
1009 break;
1010 case ByteCodeInstruction::kInverse2x2: {
1011 SkASSERT(c.fArguments.size() > 0);
1012 auto op = ByteCodeInstruction::kInverse2x2;
1013 switch (count) {
1014 case 4: break; // float2x2
1015 case 9: op = ByteCodeInstruction::kInverse3x3; break;
1016 case 16: op = ByteCodeInstruction::kInverse4x4; break;
1017 default: SkASSERT(false);
1018 }
1019 this->write(op);
1020 break;
Brian Osman15c98cb2020-02-27 18:36:57 +00001021 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001022 default:
1023 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001024 }
1025 }
1026}
1027
Brian Osmanb08cc022020-04-02 11:38:40 -04001028void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001029 // Find the index of the function we're calling. We explicitly do not allow calls to functions
1030 // before they're defined. This is an easy-to-understand rule that prevents recursion.
Brian Osmanb08cc022020-04-02 11:38:40 -04001031 int idx = -1;
1032 for (size_t i = 0; i < fFunctions.size(); ++i) {
1033 if (f.fFunction.matches(fFunctions[i]->fDeclaration)) {
1034 idx = i;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001035 break;
1036 }
1037 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001038 if (idx == -1) {
1039 for (const auto& arg : f.fArguments) {
1040 this->writeExpression(*arg);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001041 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001042 this->writeIntrinsicCall(f);
1043 return;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001044 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001045
1046
1047 if (idx > 255) {
1048 fErrors.error(f.fOffset, "Function count limit exceeded");
1049 return;
1050 } else if (idx >= (int) fFunctions.size()) {
1051 fErrors.error(f.fOffset, "Call to undefined function");
1052 return;
1053 }
1054
1055 // We may need to deal with out parameters, so the sequence is tricky
1056 if (int returnCount = SlotCount(f.fType)) {
1057 this->write(ByteCodeInstruction::kReserve, returnCount);
1058 this->write8(returnCount);
1059 }
1060
1061 int argCount = f.fArguments.size();
1062 std::vector<std::unique_ptr<LValue>> lvalues;
1063 for (int i = 0; i < argCount; ++i) {
1064 const auto& param = f.fFunction.fParameters[i];
1065 const auto& arg = f.fArguments[i];
1066 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1067 lvalues.emplace_back(this->getLValue(*arg));
1068 lvalues.back()->load();
1069 } else {
1070 this->writeExpression(*arg);
1071 }
1072 }
1073
1074 // The space used by the call is based on the callee, but it also unwinds all of that before
1075 // we continue execution. We adjust our max stack depths below.
1076 this->write(ByteCodeInstruction::kCall);
1077 this->write8(idx);
1078
1079 const ByteCodeFunction* callee = fOutput->fFunctions[idx].get();
1080 fMaxLoopCount = std::max(fMaxLoopCount, fLoopCount + callee->fLoopCount);
1081 fMaxConditionCount = std::max(fMaxConditionCount, fConditionCount + callee->fConditionCount);
1082 fMaxStackCount = std::max(fMaxStackCount, fStackCount + callee->fLocalCount
1083 + callee->fStackCount);
1084
1085 // After the called function returns, the stack will still contain our arguments. We have to
1086 // pop them (storing any out parameters back to their lvalues as we go). We glob together slot
1087 // counts for all parameters that aren't out-params, so we can pop them in one big chunk.
1088 int popCount = 0;
1089 auto pop = [&]() {
1090 if (popCount > 4) {
1091 this->write(ByteCodeInstruction::kPopN, popCount);
1092 this->write8(popCount);
1093 } else if (popCount > 0) {
1094 this->write(vector_instruction(ByteCodeInstruction::kPop, popCount));
1095 }
1096 popCount = 0;
1097 };
1098
1099 for (int i = argCount - 1; i >= 0; --i) {
1100 const auto& param = f.fFunction.fParameters[i];
1101 const auto& arg = f.fArguments[i];
1102 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1103 pop();
1104 lvalues.back()->store(true);
1105 lvalues.pop_back();
1106 } else {
1107 popCount += SlotCount(arg->fType);
1108 }
1109 }
1110 pop();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001111}
1112
Brian Osmanb08cc022020-04-02 11:38:40 -04001113void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
1114 this->write(ByteCodeInstruction::kPushImmediate);
1115 this->write32(i.fValue);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001116}
1117
Brian Osmanb08cc022020-04-02 11:38:40 -04001118void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
1119 // not yet implemented
1120 abort();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001121}
1122
Brian Osmanb08cc022020-04-02 11:38:40 -04001123bool ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p, bool discard) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001124 switch (p.fOperator) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001125 case Token::Kind::TK_PLUSPLUS: // fall through
1126 case Token::Kind::TK_MINUSMINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001127 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1128 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
1129 lvalue->load();
1130 this->write(ByteCodeInstruction::kPushImmediate);
1131 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001132 if (p.fOperator == Token::Kind::TK_PLUSPLUS) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001133 this->writeTypedInstruction(p.fType,
1134 ByteCodeInstruction::kAddI,
1135 ByteCodeInstruction::kAddI,
1136 ByteCodeInstruction::kAddF,
1137 1);
1138 } else {
1139 this->writeTypedInstruction(p.fType,
1140 ByteCodeInstruction::kSubtractI,
1141 ByteCodeInstruction::kSubtractI,
1142 ByteCodeInstruction::kSubtractF,
1143 1);
1144 }
1145 lvalue->store(discard);
1146 discard = false;
1147 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001148 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001149 case Token::Kind::TK_MINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001150 this->writeExpression(*p.fOperand);
1151 this->writeTypedInstruction(p.fType,
1152 ByteCodeInstruction::kNegateI,
1153 ByteCodeInstruction::kNegateI,
1154 ByteCodeInstruction::kNegateF,
Brian Osmanab8f3842020-04-07 09:30:44 -04001155 SlotCount(p.fOperand->fType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001156 break;
1157 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001158 case Token::Kind::TK_LOGICALNOT:
1159 case Token::Kind::TK_BITWISENOT: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001160 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1161 SkDEBUGCODE(TypeCategory tc = type_category(p.fOperand->fType));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001162 SkASSERT((p.fOperator == Token::Kind::TK_LOGICALNOT && tc == TypeCategory::kBool) ||
1163 (p.fOperator == Token::Kind::TK_BITWISENOT && (tc == TypeCategory::kSigned ||
Brian Osmanb08cc022020-04-02 11:38:40 -04001164 tc == TypeCategory::kUnsigned)));
1165 this->writeExpression(*p.fOperand);
1166 this->write(ByteCodeInstruction::kNotB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001167 break;
1168 }
1169 default:
1170 SkASSERT(false);
1171 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001172 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001173}
1174
Brian Osmanb08cc022020-04-02 11:38:40 -04001175bool ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p, bool discard) {
1176 switch (p.fOperator) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001177 case Token::Kind::TK_PLUSPLUS: // fall through
1178 case Token::Kind::TK_MINUSMINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001179 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1180 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
1181 lvalue->load();
1182 // If we're not supposed to discard the result, then make a copy *before* the +/-
1183 if (!discard) {
1184 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -04001185 }
1186 this->write(ByteCodeInstruction::kPushImmediate);
1187 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001188 if (p.fOperator == Token::Kind::TK_PLUSPLUS) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001189 this->writeTypedInstruction(p.fType,
1190 ByteCodeInstruction::kAddI,
1191 ByteCodeInstruction::kAddI,
1192 ByteCodeInstruction::kAddF,
1193 1);
1194 } else {
1195 this->writeTypedInstruction(p.fType,
1196 ByteCodeInstruction::kSubtractI,
1197 ByteCodeInstruction::kSubtractI,
1198 ByteCodeInstruction::kSubtractF,
1199 1);
1200 }
1201 // Always consume the result as part of the store
1202 lvalue->store(true);
1203 discard = false;
1204 break;
1205 }
1206 default:
1207 SkASSERT(false);
1208 }
1209 return discard;
1210}
1211
1212void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001213 if (swizzle_is_simple(s)) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001214 this->writeVariableExpression(s);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001215 return;
1216 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001217
1218 switch (s.fBase->fKind) {
1219 case Expression::kVariableReference_Kind: {
1220 Location location = this->getLocation(*s.fBase);
1221 this->write(location.selectLoad(ByteCodeInstruction::kLoadSwizzle,
1222 ByteCodeInstruction::kLoadSwizzleGlobal,
1223 ByteCodeInstruction::kLoadSwizzleUniform),
1224 s.fComponents.size());
1225 this->write8(location.fSlot);
1226 this->write8(s.fComponents.size());
1227 for (int c : s.fComponents) {
1228 this->write8(c);
1229 }
1230 break;
1231 }
1232 default:
1233 this->writeExpression(*s.fBase);
1234 this->write(ByteCodeInstruction::kSwizzle,
1235 s.fComponents.size() - s.fBase->fType.columns());
1236 this->write8(s.fBase->fType.columns());
1237 this->write8(s.fComponents.size());
1238 for (int c : s.fComponents) {
1239 this->write8(c);
1240 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001241 }
1242}
1243
Brian Osmanb08cc022020-04-02 11:38:40 -04001244void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001245 int count = SlotCount(t.fType);
1246 SkASSERT(count == SlotCount(t.fIfTrue->fType));
1247 SkASSERT(count == SlotCount(t.fIfFalse->fType));
1248
Brian Osmanb08cc022020-04-02 11:38:40 -04001249 this->writeExpression(*t.fTest);
1250 this->write(ByteCodeInstruction::kMaskPush);
1251 this->writeExpression(*t.fIfTrue);
1252 this->write(ByteCodeInstruction::kMaskNegate);
1253 this->writeExpression(*t.fIfFalse);
1254 this->write(ByteCodeInstruction::kMaskBlend, count);
1255 this->write8(count);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001256}
1257
Brian Osmanb08cc022020-04-02 11:38:40 -04001258void ByteCodeGenerator::writeExpression(const Expression& e, bool discard) {
1259 switch (e.fKind) {
1260 case Expression::kBinary_Kind:
1261 discard = this->writeBinaryExpression((BinaryExpression&) e, discard);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001262 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001263 case Expression::kBoolLiteral_Kind:
1264 this->writeBoolLiteral((BoolLiteral&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001265 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001266 case Expression::kConstructor_Kind:
1267 this->writeConstructor((Constructor&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001268 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001269 case Expression::kExternalFunctionCall_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001270 this->writeExternalFunctionCall((ExternalFunctionCall&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001271 break;
1272 case Expression::kExternalValue_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001273 this->writeExternalValue((ExternalValueReference&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001274 break;
1275 case Expression::kFieldAccess_Kind:
1276 case Expression::kIndex_Kind:
1277 case Expression::kVariableReference_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001278 this->writeVariableExpression(e);
1279 break;
1280 case Expression::kFloatLiteral_Kind:
1281 this->writeFloatLiteral((FloatLiteral&) e);
1282 break;
1283 case Expression::kFunctionCall_Kind:
1284 this->writeFunctionCall((FunctionCall&) e);
1285 break;
1286 case Expression::kIntLiteral_Kind:
1287 this->writeIntLiteral((IntLiteral&) e);
1288 break;
1289 case Expression::kNullLiteral_Kind:
1290 this->writeNullLiteral((NullLiteral&) e);
1291 break;
1292 case Expression::kPrefix_Kind:
1293 discard = this->writePrefixExpression((PrefixExpression&) e, discard);
1294 break;
1295 case Expression::kPostfix_Kind:
1296 discard = this->writePostfixExpression((PostfixExpression&) e, discard);
1297 break;
1298 case Expression::kSwizzle_Kind:
1299 this->writeSwizzle((Swizzle&) e);
1300 break;
1301 case Expression::kTernary_Kind:
1302 this->writeTernaryExpression((TernaryExpression&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001303 break;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001304 default:
1305#ifdef SK_DEBUG
Brian Osmanb08cc022020-04-02 11:38:40 -04001306 printf("unsupported expression %s\n", e.description().c_str());
Ben Wagner470e0ac2020-01-22 16:59:21 -05001307#endif
Brian Osmanb08cc022020-04-02 11:38:40 -04001308 SkASSERT(false);
1309 }
1310 if (discard) {
1311 int count = SlotCount(e.fType);
1312 if (count > 4) {
1313 this->write(ByteCodeInstruction::kPopN, count);
1314 this->write8(count);
1315 } else if (count != 0) {
1316 this->write(vector_instruction(ByteCodeInstruction::kPop, count));
1317 }
1318 discard = false;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001319 }
Ethan Nicholas7deb1c22020-01-22 10:31:55 -05001320}
1321
Brian Osmanb08cc022020-04-02 11:38:40 -04001322class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
1323public:
1324 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
1325 : INHERITED(*generator)
1326 , fCount(ByteCodeGenerator::SlotCount(value.type()))
1327 , fIndex(index) {}
1328
1329 void load() override {
1330 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001331 fGenerator.write8(fIndex);
1332 }
1333
1334 void store(bool discard) override {
1335 if (!discard) {
1336 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001337 }
1338 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001339 fGenerator.write8(fIndex);
1340 }
1341
1342private:
1343 typedef LValue INHERITED;
1344
1345 int fCount;
1346
1347 int fIndex;
1348};
1349
1350class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
1351public:
1352 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
1353 : INHERITED(*generator)
1354 , fSwizzle(swizzle) {}
1355
1356 void load() override {
1357 fGenerator.writeSwizzle(fSwizzle);
1358 }
1359
1360 void store(bool discard) override {
1361 int count = fSwizzle.fComponents.size();
1362 if (!discard) {
1363 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001364 }
1365 ByteCodeGenerator::Location location = fGenerator.getLocation(*fSwizzle.fBase);
1366 if (location.isOnStack()) {
1367 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreSwizzleIndirect,
1368 ByteCodeInstruction::kStoreSwizzleIndirectGlobal),
1369 count);
1370 } else {
1371 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreSwizzle,
1372 ByteCodeInstruction::kStoreSwizzleGlobal),
1373 count);
1374 fGenerator.write8(location.fSlot);
1375 }
1376 fGenerator.write8(count);
1377 for (int c : fSwizzle.fComponents) {
1378 fGenerator.write8(c);
1379 }
1380 }
1381
1382private:
1383 const Swizzle& fSwizzle;
1384
1385 typedef LValue INHERITED;
1386};
1387
1388class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
1389public:
1390 ByteCodeExpressionLValue(ByteCodeGenerator* generator, const Expression& expr)
1391 : INHERITED(*generator)
1392 , fExpression(expr) {}
1393
1394 void load() override {
1395 fGenerator.writeVariableExpression(fExpression);
1396 }
1397
1398 void store(bool discard) override {
1399 int count = ByteCodeGenerator::SlotCount(fExpression.fType);
1400 if (!discard) {
1401 if (count > 4) {
1402 fGenerator.write(ByteCodeInstruction::kDupN, count);
1403 fGenerator.write8(count);
1404 } else {
1405 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001406 }
1407 }
1408 ByteCodeGenerator::Location location = fGenerator.getLocation(fExpression);
1409 if (location.isOnStack() || count > 4) {
1410 if (!location.isOnStack()) {
1411 fGenerator.write(ByteCodeInstruction::kPushImmediate);
1412 fGenerator.write32(location.fSlot);
1413 }
1414 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreExtended,
1415 ByteCodeInstruction::kStoreExtendedGlobal),
1416 count);
1417 fGenerator.write8(count);
1418 } else {
1419 fGenerator.write(
1420 vector_instruction(location.selectStore(ByteCodeInstruction::kStore,
1421 ByteCodeInstruction::kStoreGlobal),
1422 count));
1423 fGenerator.write8(location.fSlot);
1424 }
1425 }
1426
1427private:
1428 typedef LValue INHERITED;
1429
1430 const Expression& fExpression;
1431};
1432
1433std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
1434 switch (e.fKind) {
1435 case Expression::kExternalValue_Kind: {
1436 ExternalValue* value = ((ExternalValueReference&) e).fValue;
1437 int index = fOutput->fExternalValues.size();
1438 fOutput->fExternalValues.push_back(value);
1439 SkASSERT(index <= 255);
1440 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
1441 }
1442 case Expression::kFieldAccess_Kind:
1443 case Expression::kIndex_Kind:
1444 case Expression::kVariableReference_Kind:
1445 return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
1446 case Expression::kSwizzle_Kind: {
1447 const Swizzle& s = (const Swizzle&) e;
1448 return swizzle_is_simple(s)
1449 ? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e))
1450 : std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s));
1451 }
1452 case Expression::kTernary_Kind:
1453 default:
1454#ifdef SK_DEBUG
1455 ABORT("unsupported lvalue %s\n", e.description().c_str());
1456#endif
1457 return nullptr;
1458 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001459}
1460
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001461void ByteCodeGenerator::writeBlock(const Block& b) {
1462 for (const auto& s : b.fStatements) {
1463 this->writeStatement(*s);
1464 }
1465}
1466
Brian Osmanb08cc022020-04-02 11:38:40 -04001467void ByteCodeGenerator::setBreakTargets() {
1468 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
1469 for (DeferredLocation& b : breaks) {
1470 b.set();
1471 }
1472 fBreakTargets.pop();
1473}
1474
1475void ByteCodeGenerator::setContinueTargets() {
1476 std::vector<DeferredLocation>& continues = fContinueTargets.top();
1477 for (DeferredLocation& c : continues) {
1478 c.set();
1479 }
1480 fContinueTargets.pop();
1481}
1482
1483void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
1484 // TODO: Include BranchIfAllFalse to top-most LoopNext
1485 this->write(ByteCodeInstruction::kLoopBreak);
1486}
1487
1488void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
1489 // TODO: Include BranchIfAllFalse to top-most LoopNext
1490 this->write(ByteCodeInstruction::kLoopContinue);
1491}
1492
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001493void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001494 this->write(ByteCodeInstruction::kLoopBegin);
1495 size_t start = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001496 this->writeStatement(*d.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001497 this->write(ByteCodeInstruction::kLoopNext);
1498 this->writeExpression(*d.fTest);
1499 this->write(ByteCodeInstruction::kLoopMask);
1500 // TODO: Could shorten this with kBranchIfAnyTrue
1501 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001502 DeferredLocation endLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -04001503 this->write(ByteCodeInstruction::kBranch);
1504 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001505 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001506 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001507}
1508
1509void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001510 fContinueTargets.emplace();
1511 fBreakTargets.emplace();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001512 if (f.fInitializer) {
1513 this->writeStatement(*f.fInitializer);
1514 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001515 this->write(ByteCodeInstruction::kLoopBegin);
1516 size_t start = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001517 if (f.fTest) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001518 this->writeExpression(*f.fTest);
1519 this->write(ByteCodeInstruction::kLoopMask);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001520 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001521 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001522 DeferredLocation endLocation(this);
1523 this->writeStatement(*f.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001524 this->write(ByteCodeInstruction::kLoopNext);
Brian Osman569f12f2019-06-13 11:23:57 -04001525 if (f.fNext) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001526 this->writeExpression(*f.fNext, true);
Brian Osman569f12f2019-06-13 11:23:57 -04001527 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001528 this->write(ByteCodeInstruction::kBranch);
1529 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001530 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001531 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001532}
1533
1534void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001535 this->writeExpression(*i.fTest);
1536 this->write(ByteCodeInstruction::kMaskPush);
1537 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001538 DeferredLocation falseLocation(this);
1539 this->writeStatement(*i.fIfTrue);
1540 falseLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001541 if (i.fIfFalse) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001542 this->write(ByteCodeInstruction::kMaskNegate);
1543 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001544 DeferredLocation endLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001545 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -05001546 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001547 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001548 this->write(ByteCodeInstruction::kMaskPop);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001549}
1550
Brian Osmanb08cc022020-04-02 11:38:40 -04001551void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
1552 if (fLoopCount || fConditionCount) {
Brian Osman4a47da72019-07-12 11:30:32 -04001553 fErrors.error(r.fOffset, "return not allowed inside conditional or loop");
1554 return;
1555 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001556 int count = SlotCount(r.fExpression->fType);
1557 this->writeExpression(*r.fExpression);
1558
1559 // Technically, the kReturn also pops fOutput->fLocalCount values from the stack, too, but we
1560 // haven't counted pushing those (they're outside the scope of our stack tracking). Instead,
1561 // we account for those in writeFunction().
1562
1563 // This is all fine because we don't allow conditional returns, so we only return once anyway.
1564 this->write(ByteCodeInstruction::kReturn, -count);
1565 this->write8(count);
1566}
1567
1568void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
1569 // not yet implemented
1570 abort();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001571}
1572
1573void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1574 for (const auto& declStatement : v.fVars) {
1575 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
Brian Osmanb08cc022020-04-02 11:38:40 -04001576 // we need to grab the location even if we don't use it, to ensure it has been allocated
1577 Location location = this->getLocation(*decl.fVar);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001578 if (decl.fValue) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001579 this->writeExpression(*decl.fValue);
1580 int count = SlotCount(decl.fValue->fType);
1581 if (count > 4) {
1582 this->write(ByteCodeInstruction::kPushImmediate);
1583 this->write32(location.fSlot);
1584 this->write(ByteCodeInstruction::kStoreExtended, count);
1585 this->write8(count);
1586 } else {
1587 this->write(vector_instruction(ByteCodeInstruction::kStore, count));
1588 this->write8(location.fSlot);
1589 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001590 }
1591 }
1592}
1593
1594void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001595 this->write(ByteCodeInstruction::kLoopBegin);
1596 size_t cond = fCode->size();
1597 this->writeExpression(*w.fTest);
1598 this->write(ByteCodeInstruction::kLoopMask);
1599 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001600 DeferredLocation endLocation(this);
1601 this->writeStatement(*w.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001602 this->write(ByteCodeInstruction::kLoopNext);
1603 this->write(ByteCodeInstruction::kBranch);
1604 this->write16(cond);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001605 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001606 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001607}
1608
1609void ByteCodeGenerator::writeStatement(const Statement& s) {
1610 switch (s.fKind) {
1611 case Statement::kBlock_Kind:
1612 this->writeBlock((Block&) s);
1613 break;
1614 case Statement::kBreak_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001615 this->writeBreakStatement((BreakStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001616 break;
1617 case Statement::kContinue_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001618 this->writeContinueStatement((ContinueStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001619 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001620 case Statement::kDiscard_Kind:
1621 // not yet implemented
1622 abort();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001623 case Statement::kDo_Kind:
1624 this->writeDoStatement((DoStatement&) s);
1625 break;
Brian Osman3e29f1d2019-05-28 09:35:05 -04001626 case Statement::kExpression_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001627 this->writeExpression(*((ExpressionStatement&) s).fExpression, true);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001628 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001629 case Statement::kFor_Kind:
1630 this->writeForStatement((ForStatement&) s);
1631 break;
1632 case Statement::kIf_Kind:
1633 this->writeIfStatement((IfStatement&) s);
1634 break;
1635 case Statement::kNop_Kind:
1636 break;
1637 case Statement::kReturn_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001638 this->writeReturnStatement((ReturnStatement&) s);
1639 break;
1640 case Statement::kSwitch_Kind:
1641 this->writeSwitchStatement((SwitchStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001642 break;
1643 case Statement::kVarDeclarations_Kind:
1644 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1645 break;
1646 case Statement::kWhile_Kind:
1647 this->writeWhileStatement((WhileStatement&) s);
1648 break;
1649 default:
Brian Osmanb08cc022020-04-02 11:38:40 -04001650 SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001651 }
1652}
1653
Brian Osmanb08cc022020-04-02 11:38:40 -04001654ByteCodeFunction::ByteCodeFunction(const FunctionDeclaration* declaration)
1655 : fName(declaration->fName) {
Brian Osman80164412019-06-07 13:00:23 -04001656 fParameterCount = 0;
Brian Osmanb08cc022020-04-02 11:38:40 -04001657 for (const auto& p : declaration->fParameters) {
1658 int slots = ByteCodeGenerator::SlotCount(p->fType);
1659 fParameters.push_back({ slots, (bool)(p->fModifiers.fFlags & Modifiers::kOut_Flag) });
1660 fParameterCount += slots;
Brian Osman80164412019-06-07 13:00:23 -04001661 }
1662}
1663
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001664}