blob: c625051ff0d839254b11bafc2ecdd2e95f0a0ee0 [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)
Brian Osman3479a952020-05-04 10:22:53 -040045 // If you're adding new intrinsics here, ensure that they're declared in sksl_interp.inc, so
46 // they're available to "generic" interpreter programs (eg particles).
47 // You can probably copy the declarations from sksl_gpu.inc.
Ethan Nicholasae9633b2019-05-24 12:46:34 -040048 , fIntrinsics {
Brian Osmand5f937b2020-05-04 12:07:29 -040049 { "atan", ByteCodeInstruction::kATan },
50 { "clamp", SpecialIntrinsic::kClamp },
51 { "cos", ByteCodeInstruction::kCos },
52 { "dot", SpecialIntrinsic::kDot },
53 { "fract", ByteCodeInstruction::kFract },
54 { "inverse", ByteCodeInstruction::kInverse2x2 },
55 { "length", SpecialIntrinsic::kLength },
56 { "max", SpecialIntrinsic::kMax },
57 { "min", SpecialIntrinsic::kMin },
58 { "mix", SpecialIntrinsic::kMix },
59 { "pow", ByteCodeInstruction::kPow },
60 { "saturate", SpecialIntrinsic::kSaturate },
61 { "sin", ByteCodeInstruction::kSin },
62 { "sqrt", ByteCodeInstruction::kSqrt },
63 { "tan", ByteCodeInstruction::kTan },
Brian Osman8842b372020-05-01 15:07:49 -040064
65 { "lessThan", { ByteCodeInstruction::kCompareFLT,
66 ByteCodeInstruction::kCompareSLT,
67 ByteCodeInstruction::kCompareULT } },
68 { "lessThanEqual", { ByteCodeInstruction::kCompareFLTEQ,
69 ByteCodeInstruction::kCompareSLTEQ,
70 ByteCodeInstruction::kCompareULTEQ } },
71 { "greaterThan", { ByteCodeInstruction::kCompareFGT,
72 ByteCodeInstruction::kCompareSGT,
73 ByteCodeInstruction::kCompareUGT } },
74 { "greaterThanEqual", { ByteCodeInstruction::kCompareFGTEQ,
75 ByteCodeInstruction::kCompareSGTEQ,
76 ByteCodeInstruction::kCompareUGTEQ } },
77 { "equal", { ByteCodeInstruction::kCompareFEQ,
78 ByteCodeInstruction::kCompareIEQ,
79 ByteCodeInstruction::kCompareIEQ } },
80 { "notEqual", { ByteCodeInstruction::kCompareFNEQ,
81 ByteCodeInstruction::kCompareINEQ,
82 ByteCodeInstruction::kCompareINEQ } },
83
84 { "any", SpecialIntrinsic::kAny },
85 { "all", SpecialIntrinsic::kAll },
86 { "not", ByteCodeInstruction::kNotB },
87 } {}
Brian Osmanb08cc022020-04-02 11:38:40 -040088
Ethan Nicholas82162ee2019-05-21 16:05:08 -040089
Brian Osman07c117b2019-05-23 12:51:06 -070090int ByteCodeGenerator::SlotCount(const Type& type) {
Brian Osmanfba386b2019-06-20 14:54:15 -040091 if (type.kind() == Type::kOther_Kind) {
92 return 0;
93 } else if (type.kind() == Type::kStruct_Kind) {
Brian Osman07c117b2019-05-23 12:51:06 -070094 int slots = 0;
95 for (const auto& f : type.fields()) {
96 slots += SlotCount(*f.fType);
97 }
98 SkASSERT(slots <= 255);
99 return slots;
100 } else if (type.kind() == Type::kArray_Kind) {
101 int columns = type.columns();
102 SkASSERT(columns >= 0);
103 int slots = columns * SlotCount(type.componentType());
104 SkASSERT(slots <= 255);
105 return slots;
106 } else {
107 return type.columns() * type.rows();
108 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400109}
110
Brian Osman1c110a02019-10-01 14:53:32 -0400111static inline bool is_uniform(const SkSL::Variable& var) {
112 return var.fModifiers.fFlags & Modifiers::kUniform_Flag;
113}
114
Brian Osmaneadfeb92020-01-09 12:43:03 -0500115static inline bool is_in(const SkSL::Variable& var) {
116 return var.fModifiers.fFlags & Modifiers::kIn_Flag;
117}
Brian Osmanb08cc022020-04-02 11:38:40 -0400118
119void ByteCodeGenerator::gatherUniforms(const Type& type, const String& name) {
120 if (type.kind() == Type::kOther_Kind) {
121 return;
122 } else if (type.kind() == Type::kStruct_Kind) {
123 for (const auto& f : type.fields()) {
124 this->gatherUniforms(*f.fType, name + "." + f.fName);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500125 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400126 } else if (type.kind() == Type::kArray_Kind) {
127 for (int i = 0; i < type.columns(); ++i) {
128 this->gatherUniforms(type.componentType(), String::printf("%s[%d]", name.c_str(), i));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500129 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400130 } else {
131 fOutput->fUniforms.push_back({ name, type_category(type), type.rows(), type.columns(),
132 fOutput->fUniformSlotCount });
133 fOutput->fUniformSlotCount += type.columns() * type.rows();
134 }
135}
136
137bool ByteCodeGenerator::generateCode() {
138 for (const auto& e : fProgram) {
139 switch (e.fKind) {
140 case ProgramElement::kFunction_Kind: {
141 std::unique_ptr<ByteCodeFunction> f = this->writeFunction((FunctionDefinition&) e);
142 if (!f) {
143 return false;
144 }
145 fOutput->fFunctions.push_back(std::move(f));
146 fFunctions.push_back(&(FunctionDefinition&)e);
147 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500148 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400149 case ProgramElement::kVar_Kind: {
150 VarDeclarations& decl = (VarDeclarations&) e;
151 for (const auto& v : decl.fVars) {
152 const Variable* declVar = ((VarDeclaration&) *v).fVar;
153 if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
154 continue;
155 }
156 if (is_uniform(*declVar)) {
157 this->gatherUniforms(declVar->fType, declVar->fName);
158 } else {
159 fOutput->fGlobalSlotCount += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400160 }
161 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400162 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400163 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400164 default:
165 ; // ignore
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400166 }
167 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400168 return 0 == fErrors.errorCount();
169}
170
171std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
172 fFunction = &f;
173 std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
174 fParameterCount = result->fParameterCount;
175 fLoopCount = fMaxLoopCount = 0;
176 fConditionCount = fMaxConditionCount = 0;
177 fStackCount = fMaxStackCount = 0;
178 fCode = &result->fCode;
179
180 this->writeStatement(*f.fBody);
181 if (0 == fErrors.errorCount()) {
182 SkASSERT(fLoopCount == 0);
183 SkASSERT(fConditionCount == 0);
184 SkASSERT(fStackCount == 0);
185 }
186 this->write(ByteCodeInstruction::kReturn, 0);
187 this->write8(0);
188
189 result->fLocalCount = fLocals.size();
190 result->fConditionCount = fMaxConditionCount;
191 result->fLoopCount = fMaxLoopCount;
192 result->fStackCount = fMaxStackCount;
193
194 const Type& returnType = f.fDeclaration.fReturnType;
195 if (returnType != *fContext.fVoid_Type) {
196 result->fReturnCount = SlotCount(returnType);
197 }
198 fLocals.clear();
199 fFunction = nullptr;
200 return result;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400201}
202
Brian Osman0785db02019-05-24 14:19:11 -0400203// A "simple" Swizzle is based on a variable (or a compound variable like a struct or array), and
204// that references consecutive values, such that it can be implemented using normal load/store ops
205// with an offset. Note that all single-component swizzles (of suitable base types) are simple.
206static bool swizzle_is_simple(const Swizzle& s) {
207 switch (s.fBase->fKind) {
208 case Expression::kFieldAccess_Kind:
209 case Expression::kIndex_Kind:
210 case Expression::kVariableReference_Kind:
211 break;
212 default:
213 return false;
214 }
215
216 for (size_t i = 1; i < s.fComponents.size(); ++i) {
217 if (s.fComponents[i] != s.fComponents[i - 1] + 1) {
218 return false;
219 }
220 }
221 return true;
222}
223
Brian Osmanb08cc022020-04-02 11:38:40 -0400224int ByteCodeGenerator::StackUsage(ByteCodeInstruction inst, int count_) {
225 // Ensures that we use count iff we're passed a non-default value. Most instructions have an
226 // implicit count, so the caller shouldn't need to worry about it (or count makes no sense).
227 // The asserts avoids callers thinking they're supplying useful information in that scenario,
228 // or failing to supply necessary information for the ops that need a count.
229 struct CountValue {
230 operator int() {
231 SkASSERT(val != ByteCodeGenerator::kUnusedStackCount);
232 SkDEBUGCODE(used = true);
233 return val;
234 }
235 ~CountValue() {
236 SkASSERT(used || val == ByteCodeGenerator::kUnusedStackCount);
237 }
238 int val;
239 SkDEBUGCODE(bool used = false;)
240 } count = { count_ };
241
242 switch (inst) {
243 // Unary functions/operators that don't change stack depth at all:
244#define VECTOR_UNARY_OP(base) \
245 case ByteCodeInstruction::base: \
246 case ByteCodeInstruction::base ## 2: \
247 case ByteCodeInstruction::base ## 3: \
248 case ByteCodeInstruction::base ## 4: \
249 return 0;
250
251 VECTOR_UNARY_OP(kConvertFtoI)
252 VECTOR_UNARY_OP(kConvertStoF)
253 VECTOR_UNARY_OP(kConvertUtoF)
254
Mike Reed8520e762020-04-30 12:06:23 -0400255 VECTOR_UNARY_OP(kATan)
Brian Osmanb08cc022020-04-02 11:38:40 -0400256 VECTOR_UNARY_OP(kCos)
Mike Reed8520e762020-04-30 12:06:23 -0400257 VECTOR_UNARY_OP(kFract)
Brian Osmanb08cc022020-04-02 11:38:40 -0400258 VECTOR_UNARY_OP(kSin)
259 VECTOR_UNARY_OP(kSqrt)
260 VECTOR_UNARY_OP(kTan)
261
262 VECTOR_UNARY_OP(kNegateF)
263 VECTOR_UNARY_OP(kNegateI)
Brian Osman8842b372020-05-01 15:07:49 -0400264 VECTOR_UNARY_OP(kNotB)
Brian Osmanb08cc022020-04-02 11:38:40 -0400265
266 case ByteCodeInstruction::kInverse2x2:
267 case ByteCodeInstruction::kInverse3x3:
268 case ByteCodeInstruction::kInverse4x4: return 0;
269
270 case ByteCodeInstruction::kClampIndex: return 0;
Brian Osmanb08cc022020-04-02 11:38:40 -0400271 case ByteCodeInstruction::kNegateFN: return 0;
272 case ByteCodeInstruction::kShiftLeft: return 0;
273 case ByteCodeInstruction::kShiftRightS: return 0;
274 case ByteCodeInstruction::kShiftRightU: return 0;
275
276#undef VECTOR_UNARY_OP
277
278 // Binary functions/operators that do a 2 -> 1 reduction (possibly N times)
279#define VECTOR_BINARY_OP(base) \
280 case ByteCodeInstruction::base: return -1; \
281 case ByteCodeInstruction::base ## 2: return -2; \
282 case ByteCodeInstruction::base ## 3: return -3; \
283 case ByteCodeInstruction::base ## 4: return -4;
284
285#define VECTOR_MATRIX_BINARY_OP(base) \
286 VECTOR_BINARY_OP(base) \
287 case ByteCodeInstruction::base ## N: return -count;
288
289 case ByteCodeInstruction::kAndB: return -1;
290 case ByteCodeInstruction::kOrB: return -1;
291 case ByteCodeInstruction::kXorB: return -1;
292
293 VECTOR_BINARY_OP(kAddI)
294 VECTOR_MATRIX_BINARY_OP(kAddF)
295
296 VECTOR_BINARY_OP(kCompareIEQ)
297 VECTOR_MATRIX_BINARY_OP(kCompareFEQ)
298 VECTOR_BINARY_OP(kCompareINEQ)
299 VECTOR_MATRIX_BINARY_OP(kCompareFNEQ)
300 VECTOR_BINARY_OP(kCompareSGT)
301 VECTOR_BINARY_OP(kCompareUGT)
302 VECTOR_BINARY_OP(kCompareFGT)
303 VECTOR_BINARY_OP(kCompareSGTEQ)
304 VECTOR_BINARY_OP(kCompareUGTEQ)
305 VECTOR_BINARY_OP(kCompareFGTEQ)
306 VECTOR_BINARY_OP(kCompareSLT)
307 VECTOR_BINARY_OP(kCompareULT)
308 VECTOR_BINARY_OP(kCompareFLT)
309 VECTOR_BINARY_OP(kCompareSLTEQ)
310 VECTOR_BINARY_OP(kCompareULTEQ)
311 VECTOR_BINARY_OP(kCompareFLTEQ)
312
313 VECTOR_BINARY_OP(kDivideS)
314 VECTOR_BINARY_OP(kDivideU)
315 VECTOR_MATRIX_BINARY_OP(kDivideF)
Brian Osmand5f937b2020-05-04 12:07:29 -0400316 VECTOR_BINARY_OP(kMaxF)
317 VECTOR_BINARY_OP(kMaxS)
318 VECTOR_BINARY_OP(kMinF)
319 VECTOR_BINARY_OP(kMinS)
Brian Osmanb08cc022020-04-02 11:38:40 -0400320 VECTOR_BINARY_OP(kMultiplyI)
321 VECTOR_MATRIX_BINARY_OP(kMultiplyF)
Florin Malita3facc9c2020-05-04 09:26:15 -0400322 VECTOR_BINARY_OP(kPow)
Brian Osmanb08cc022020-04-02 11:38:40 -0400323 VECTOR_BINARY_OP(kRemainderF)
324 VECTOR_BINARY_OP(kRemainderS)
325 VECTOR_BINARY_OP(kRemainderU)
326 VECTOR_BINARY_OP(kSubtractI)
327 VECTOR_MATRIX_BINARY_OP(kSubtractF)
328
329#undef VECTOR_BINARY_OP
330#undef VECTOR_MATRIX_BINARY_OP
331
332 // Ops that push or load data to grow the stack:
333 case ByteCodeInstruction::kDup:
334 case ByteCodeInstruction::kLoad:
335 case ByteCodeInstruction::kLoadGlobal:
336 case ByteCodeInstruction::kLoadUniform:
337 case ByteCodeInstruction::kReadExternal:
338 case ByteCodeInstruction::kPushImmediate:
339 return 1;
340
341 case ByteCodeInstruction::kDup2:
342 case ByteCodeInstruction::kLoad2:
343 case ByteCodeInstruction::kLoadGlobal2:
344 case ByteCodeInstruction::kLoadUniform2:
345 case ByteCodeInstruction::kReadExternal2:
346 return 2;
347
348 case ByteCodeInstruction::kDup3:
349 case ByteCodeInstruction::kLoad3:
350 case ByteCodeInstruction::kLoadGlobal3:
351 case ByteCodeInstruction::kLoadUniform3:
352 case ByteCodeInstruction::kReadExternal3:
353 return 3;
354
355 case ByteCodeInstruction::kDup4:
356 case ByteCodeInstruction::kLoad4:
357 case ByteCodeInstruction::kLoadGlobal4:
358 case ByteCodeInstruction::kLoadUniform4:
359 case ByteCodeInstruction::kReadExternal4:
360 return 4;
361
362 case ByteCodeInstruction::kDupN:
363 case ByteCodeInstruction::kLoadSwizzle:
364 case ByteCodeInstruction::kLoadSwizzleGlobal:
365 case ByteCodeInstruction::kLoadSwizzleUniform:
366 return count;
367
368 // Pushes 'count' values, minus one for the 'address' that's consumed first
369 case ByteCodeInstruction::kLoadExtended:
370 case ByteCodeInstruction::kLoadExtendedGlobal:
371 case ByteCodeInstruction::kLoadExtendedUniform:
372 return count - 1;
373
374 // Ops that pop or store data to shrink the stack:
375 case ByteCodeInstruction::kPop:
376 case ByteCodeInstruction::kStore:
377 case ByteCodeInstruction::kStoreGlobal:
378 case ByteCodeInstruction::kWriteExternal:
379 return -1;
380
381 case ByteCodeInstruction::kPop2:
382 case ByteCodeInstruction::kStore2:
383 case ByteCodeInstruction::kStoreGlobal2:
384 case ByteCodeInstruction::kWriteExternal2:
385 return -2;
386
387 case ByteCodeInstruction::kPop3:
388 case ByteCodeInstruction::kStore3:
389 case ByteCodeInstruction::kStoreGlobal3:
390 case ByteCodeInstruction::kWriteExternal3:
391 return -3;
392
393 case ByteCodeInstruction::kPop4:
394 case ByteCodeInstruction::kStore4:
395 case ByteCodeInstruction::kStoreGlobal4:
396 case ByteCodeInstruction::kWriteExternal4:
397 return -4;
398
399 case ByteCodeInstruction::kPopN:
400 case ByteCodeInstruction::kStoreSwizzle:
401 case ByteCodeInstruction::kStoreSwizzleGlobal:
402 return -count;
403
404 // Consumes 'count' values, plus one for the 'address'
405 case ByteCodeInstruction::kStoreExtended:
406 case ByteCodeInstruction::kStoreExtendedGlobal:
407 case ByteCodeInstruction::kStoreSwizzleIndirect:
408 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal:
409 return -count - 1;
410
411 // Strange ops where the caller computes the delta for us:
412 case ByteCodeInstruction::kCallExternal:
413 case ByteCodeInstruction::kMatrixToMatrix:
414 case ByteCodeInstruction::kMatrixMultiply:
415 case ByteCodeInstruction::kReserve:
416 case ByteCodeInstruction::kReturn:
417 case ByteCodeInstruction::kScalarToMatrix:
418 case ByteCodeInstruction::kSwizzle:
419 return count;
420
421 // Miscellaneous
422
Brian Osman8842b372020-05-01 15:07:49 -0400423 // kMix does a 3 -> 1 reduction (A, B, M -> A -or- B) for each component
424 case ByteCodeInstruction::kMix: return -2;
425 case ByteCodeInstruction::kMix2: return -4;
426 case ByteCodeInstruction::kMix3: return -6;
427 case ByteCodeInstruction::kMix4: return -8;
428
429 // kLerp works the same way (producing lerp(A, B, T) for each component)
430 case ByteCodeInstruction::kLerp: return -2;
431 case ByteCodeInstruction::kLerp2: return -4;
432 case ByteCodeInstruction::kLerp3: return -6;
433 case ByteCodeInstruction::kLerp4: return -8;
434
Brian Osmanb08cc022020-04-02 11:38:40 -0400435 // kCall is net-zero. Max stack depth is adjusted in writeFunctionCall.
436 case ByteCodeInstruction::kCall: return 0;
437 case ByteCodeInstruction::kBranch: return 0;
438 case ByteCodeInstruction::kBranchIfAllFalse: return 0;
439
440 case ByteCodeInstruction::kMaskPush: return -1;
441 case ByteCodeInstruction::kMaskPop: return 0;
442 case ByteCodeInstruction::kMaskNegate: return 0;
443 case ByteCodeInstruction::kMaskBlend: return -count;
444
445 case ByteCodeInstruction::kLoopBegin: return 0;
446 case ByteCodeInstruction::kLoopNext: return 0;
447 case ByteCodeInstruction::kLoopMask: return -1;
448 case ByteCodeInstruction::kLoopEnd: return 0;
449 case ByteCodeInstruction::kLoopBreak: return 0;
450 case ByteCodeInstruction::kLoopContinue: return 0;
Brian Osmanb08cc022020-04-02 11:38:40 -0400451 }
Brian Osmand5f937b2020-05-04 12:07:29 -0400452
453 SkUNREACHABLE;
Brian Osmanb08cc022020-04-02 11:38:40 -0400454}
455
456ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var) {
457 // given that we seldom have more than a couple of variables, linear search is probably the most
458 // efficient way to handle lookups
459 switch (var.fStorage) {
460 case Variable::kLocal_Storage: {
461 for (int i = fLocals.size() - 1; i >= 0; --i) {
462 if (fLocals[i] == &var) {
463 SkASSERT(fParameterCount + i <= 255);
464 return { fParameterCount + i, Storage::kLocal };
465 }
466 }
467 int result = fParameterCount + fLocals.size();
468 fLocals.push_back(&var);
469 for (int i = 0; i < SlotCount(var.fType) - 1; ++i) {
470 fLocals.push_back(nullptr);
471 }
472 SkASSERT(result <= 255);
473 return { result, Storage::kLocal };
474 }
475 case Variable::kParameter_Storage: {
476 int offset = 0;
477 for (const auto& p : fFunction->fDeclaration.fParameters) {
478 if (p == &var) {
479 SkASSERT(offset <= 255);
480 return { offset, Storage::kLocal };
481 }
482 offset += SlotCount(p->fType);
483 }
484 SkASSERT(false);
485 return Location::MakeInvalid();
486 }
487 case Variable::kGlobal_Storage: {
488 if (is_in(var)) {
489 // If you see this error, it means the program is using raw 'in' variables. You
490 // should either specialize the program (Compiler::specialize) to bake in the final
491 // values of the 'in' variables, or not use 'in' variables (maybe you meant to use
492 // 'uniform' instead?).
493 fErrors.error(var.fOffset,
494 "'in' variable is not specialized or has unsupported type");
495 return Location::MakeInvalid();
496 }
497 int offset = 0;
498 bool isUniform = is_uniform(var);
499 for (const auto& e : fProgram) {
500 if (e.fKind == ProgramElement::kVar_Kind) {
501 VarDeclarations& decl = (VarDeclarations&) e;
502 for (const auto& v : decl.fVars) {
503 const Variable* declVar = ((VarDeclaration&) *v).fVar;
504 if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
505 continue;
506 }
507 if (isUniform != is_uniform(*declVar)) {
508 continue;
509 }
510 if (declVar == &var) {
511 SkASSERT(offset <= 255);
512 return { offset, isUniform ? Storage::kUniform : Storage::kGlobal };
513 }
514 offset += SlotCount(declVar->fType);
515 }
516 }
517 }
518 SkASSERT(false);
519 return Location::MakeInvalid();
520 }
521 default:
522 SkASSERT(false);
523 return Location::MakeInvalid();
524 }
525}
526
Brian Osman1c110a02019-10-01 14:53:32 -0400527ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Expression& expr) {
Brian Osman07c117b2019-05-23 12:51:06 -0700528 switch (expr.fKind) {
529 case Expression::kFieldAccess_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400530 const FieldAccess& f = (const FieldAccess&)expr;
531 Location baseLoc = this->getLocation(*f.fBase);
Brian Osman07c117b2019-05-23 12:51:06 -0700532 int offset = 0;
533 for (int i = 0; i < f.fFieldIndex; ++i) {
534 offset += SlotCount(*f.fBase->fType.fields()[i].fType);
535 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400536 if (baseLoc.isOnStack()) {
537 if (offset != 0) {
538 this->write(ByteCodeInstruction::kPushImmediate);
539 this->write32(offset);
540 this->write(ByteCodeInstruction::kAddI);
Ben Wagner470e0ac2020-01-22 16:59:21 -0500541 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400542 return baseLoc;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500543 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400544 return baseLoc + offset;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500545 }
Ben Wagner470e0ac2020-01-22 16:59:21 -0500546 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400547 case Expression::kIndex_Kind: {
548 const IndexExpression& i = (const IndexExpression&)expr;
549 int stride = SlotCount(i.fType);
550 int length = i.fBase->fType.columns();
551 SkASSERT(length <= 255);
552 int offset = -1;
553 if (i.fIndex->isConstant()) {
554 int64_t index = i.fIndex->getConstantInt();
555 if (index < 0 || index >= length) {
556 fErrors.error(i.fIndex->fOffset, "Array index out of bounds.");
557 return Location::MakeInvalid();
558 }
559 offset = index * stride;
560 } else {
561 if (i.fIndex->hasSideEffects()) {
562 // Having a side-effect in an indexer is technically safe for an rvalue,
563 // but with lvalues we have to evaluate the indexer twice, so make it an error.
564 fErrors.error(i.fIndex->fOffset,
565 "Index expressions with side-effects not supported in byte code.");
566 return Location::MakeInvalid();
567 }
568 this->writeExpression(*i.fIndex);
569 this->write(ByteCodeInstruction::kClampIndex);
570 this->write8(length);
571 if (stride != 1) {
572 this->write(ByteCodeInstruction::kPushImmediate);
573 this->write32(stride);
574 this->write(ByteCodeInstruction::kMultiplyI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400575 }
576 }
577 Location baseLoc = this->getLocation(*i.fBase);
578
579 // Are both components known statically?
580 if (!baseLoc.isOnStack() && offset >= 0) {
581 return baseLoc + offset;
582 }
583
584 // At least one component is dynamic (and on the stack).
585
586 // If the other component is zero, we're done
587 if (baseLoc.fSlot == 0 || offset == 0) {
588 return baseLoc.makeOnStack();
589 }
590
591 // Push the non-dynamic component (if any) to the stack, then add the two
592 if (!baseLoc.isOnStack()) {
593 this->write(ByteCodeInstruction::kPushImmediate);
594 this->write32(baseLoc.fSlot);
595 }
596 if (offset >= 0) {
597 this->write(ByteCodeInstruction::kPushImmediate);
598 this->write32(offset);
599 }
600 this->write(ByteCodeInstruction::kAddI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400601 return baseLoc.makeOnStack();
602 }
Brian Osman0785db02019-05-24 14:19:11 -0400603 case Expression::kSwizzle_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400604 const Swizzle& s = (const Swizzle&)expr;
Brian Osman0785db02019-05-24 14:19:11 -0400605 SkASSERT(swizzle_is_simple(s));
Brian Osmanb08cc022020-04-02 11:38:40 -0400606 Location baseLoc = this->getLocation(*s.fBase);
607 int offset = s.fComponents[0];
608 if (baseLoc.isOnStack()) {
609 if (offset != 0) {
610 this->write(ByteCodeInstruction::kPushImmediate);
611 this->write32(offset);
612 this->write(ByteCodeInstruction::kAddI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400613 }
614 return baseLoc;
615 } else {
616 return baseLoc + offset;
617 }
Brian Osman0785db02019-05-24 14:19:11 -0400618 }
Brian Osman07c117b2019-05-23 12:51:06 -0700619 case Expression::kVariableReference_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400620 const Variable& var = ((const VariableReference&)expr).fVariable;
Brian Osman07c117b2019-05-23 12:51:06 -0700621 return this->getLocation(var);
622 }
623 default:
624 SkASSERT(false);
Brian Osmanb08cc022020-04-02 11:38:40 -0400625 return Location::MakeInvalid();
Brian Osman07c117b2019-05-23 12:51:06 -0700626 }
627}
628
Brian Osmanb08cc022020-04-02 11:38:40 -0400629void ByteCodeGenerator::write8(uint8_t b) {
630 fCode->push_back(b);
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500631}
632
Brian Osmanb08cc022020-04-02 11:38:40 -0400633void ByteCodeGenerator::write16(uint16_t i) {
634 size_t n = fCode->size();
635 fCode->resize(n+2);
636 memcpy(fCode->data() + n, &i, 2);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500637}
Ben Wagner470e0ac2020-01-22 16:59:21 -0500638
Brian Osmanb08cc022020-04-02 11:38:40 -0400639void ByteCodeGenerator::write32(uint32_t i) {
640 size_t n = fCode->size();
641 fCode->resize(n+4);
642 memcpy(fCode->data() + n, &i, 4);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500643}
644
Brian Osmanb08cc022020-04-02 11:38:40 -0400645void ByteCodeGenerator::write(ByteCodeInstruction i, int count) {
646 switch (i) {
647 case ByteCodeInstruction::kLoopBegin: this->enterLoop(); break;
648 case ByteCodeInstruction::kLoopEnd: this->exitLoop(); break;
Ethan Nicholas2329da02020-01-24 15:49:33 -0500649
Brian Osmanb08cc022020-04-02 11:38:40 -0400650 case ByteCodeInstruction::kMaskPush: this->enterCondition(); break;
651 case ByteCodeInstruction::kMaskPop:
652 case ByteCodeInstruction::kMaskBlend: this->exitCondition(); break;
653 default: /* Do nothing */ break;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500654 }
Brian Osmanab8f3842020-04-07 09:30:44 -0400655 this->write16((uint16_t)i);
Brian Osmanb08cc022020-04-02 11:38:40 -0400656 fStackCount += StackUsage(i, count);
657 fMaxStackCount = std::max(fMaxStackCount, fStackCount);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500658}
659
Brian Osmanb08cc022020-04-02 11:38:40 -0400660static ByteCodeInstruction vector_instruction(ByteCodeInstruction base, int count) {
661 SkASSERT(count >= 1 && count <= 4);
662 return ((ByteCodeInstruction) ((int) base + 1 - count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500663}
664
Brian Osmanb08cc022020-04-02 11:38:40 -0400665void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
666 ByteCodeInstruction u, ByteCodeInstruction f,
Brian Osmanab8f3842020-04-07 09:30:44 -0400667 int count) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500668 switch (type_category(type)) {
Brian Osman8842b372020-05-01 15:07:49 -0400669 case TypeCategory::kBool:
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500670 case TypeCategory::kSigned:
Brian Osmanb08cc022020-04-02 11:38:40 -0400671 this->write(vector_instruction(s, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500672 break;
673 case TypeCategory::kUnsigned:
Brian Osmanb08cc022020-04-02 11:38:40 -0400674 this->write(vector_instruction(u, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500675 break;
676 case TypeCategory::kFloat: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400677 if (count > 4) {
678 this->write((ByteCodeInstruction)((int)f + 1), count);
Brian Osmanab8f3842020-04-07 09:30:44 -0400679 this->write8(count);
Brian Osmanb08cc022020-04-02 11:38:40 -0400680 } else {
681 this->write(vector_instruction(f, count));
682 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500683 break;
684 }
685 default:
686 SkASSERT(false);
687 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500688}
689
Brian Osmanb08cc022020-04-02 11:38:40 -0400690bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool discard) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400691 if (b.fOperator == Token::Kind::TK_EQ) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500692 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
Brian Osmanb08cc022020-04-02 11:38:40 -0400693 this->writeExpression(*b.fRight);
694 lvalue->store(discard);
695 discard = false;
696 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500697 }
698 const Type& lType = b.fLeft->fType;
699 const Type& rType = b.fRight->fType;
700 bool lVecOrMtx = (lType.kind() == Type::kVector_Kind || lType.kind() == Type::kMatrix_Kind);
701 bool rVecOrMtx = (rType.kind() == Type::kVector_Kind || rType.kind() == Type::kMatrix_Kind);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500702 Token::Kind op;
703 std::unique_ptr<LValue> lvalue;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500704 if (is_assignment(b.fOperator)) {
705 lvalue = this->getLValue(*b.fLeft);
Brian Osmanb08cc022020-04-02 11:38:40 -0400706 lvalue->load();
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500707 op = remove_assignment(b.fOperator);
708 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400709 this->writeExpression(*b.fLeft);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500710 op = b.fOperator;
711 if (!lVecOrMtx && rVecOrMtx) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400712 for (int i = SlotCount(rType); i > 1; --i) {
713 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400714 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500715 }
716 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500717 int count = std::max(SlotCount(lType), SlotCount(rType));
Brian Osmanb08cc022020-04-02 11:38:40 -0400718 SkDEBUGCODE(TypeCategory tc = type_category(lType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500719 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400720 case Token::Kind::TK_LOGICALAND: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400721 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
722 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400723 this->write(ByteCodeInstruction::kMaskPush);
724 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500725 DeferredLocation falseLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -0400726 this->writeExpression(*b.fRight);
727 this->write(ByteCodeInstruction::kAndB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500728 falseLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -0400729 this->write(ByteCodeInstruction::kMaskPop);
730 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500731 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400732 case Token::Kind::TK_LOGICALOR: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400733 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
734 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400735 this->write(ByteCodeInstruction::kNotB);
736 this->write(ByteCodeInstruction::kMaskPush);
737 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500738 DeferredLocation falseLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -0400739 this->writeExpression(*b.fRight);
740 this->write(ByteCodeInstruction::kOrB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500741 falseLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -0400742 this->write(ByteCodeInstruction::kMaskPop);
743 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500744 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400745 case Token::Kind::TK_SHL:
746 case Token::Kind::TK_SHR: {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500747 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
748 tc == SkSL::TypeCategory::kUnsigned));
749 if (!b.fRight->isConstant()) {
750 fErrors.error(b.fRight->fOffset, "Shift amounts must be constant");
Brian Osmanb08cc022020-04-02 11:38:40 -0400751 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500752 }
753 int64_t shift = b.fRight->getConstantInt();
754 if (shift < 0 || shift > 31) {
755 fErrors.error(b.fRight->fOffset, "Shift amount out of range");
Brian Osmanb08cc022020-04-02 11:38:40 -0400756 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500757 }
758
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400759 if (op == Token::Kind::TK_SHL) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400760 this->write(ByteCodeInstruction::kShiftLeft);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500761 } else {
762 this->write(type_category(lType) == TypeCategory::kSigned
Brian Osmanb08cc022020-04-02 11:38:40 -0400763 ? ByteCodeInstruction::kShiftRightS
764 : ByteCodeInstruction::kShiftRightU);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500765 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400766 this->write8(shift);
767 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500768 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500769
770 default:
771 break;
772 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400773 this->writeExpression(*b.fRight);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500774 if (lVecOrMtx && !rVecOrMtx) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400775 for (int i = SlotCount(lType); i > 1; --i) {
776 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400777 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500778 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400779 // Special case for M*V, V*M, M*M (but not V*V!)
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400780 if (op == Token::Kind::TK_STAR && lVecOrMtx && rVecOrMtx &&
Brian Osmanb08cc022020-04-02 11:38:40 -0400781 !(lType.kind() == Type::kVector_Kind && rType.kind() == Type::kVector_Kind)) {
782 this->write(ByteCodeInstruction::kMatrixMultiply,
783 SlotCount(b.fType) - (SlotCount(lType) + SlotCount(rType)));
784 int rCols = rType.columns(),
785 rRows = rType.rows(),
786 lCols = lType.columns(),
787 lRows = lType.rows();
788 // M*V treats the vector as a column
789 if (rType.kind() == Type::kVector_Kind) {
790 std::swap(rCols, rRows);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500791 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400792 SkASSERT(lCols == rRows);
793 SkASSERT(SlotCount(b.fType) == lRows * rCols);
794 this->write8(lCols);
795 this->write8(lRows);
796 this->write8(rCols);
797 } else {
798 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400799 case Token::Kind::TK_EQEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400800 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareIEQ,
801 ByteCodeInstruction::kCompareIEQ,
802 ByteCodeInstruction::kCompareFEQ,
803 count);
804 // Collapse to a single bool
805 for (int i = count; i > 1; --i) {
806 this->write(ByteCodeInstruction::kAndB);
807 }
808 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400809 case Token::Kind::TK_GT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400810 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGT,
811 ByteCodeInstruction::kCompareUGT,
812 ByteCodeInstruction::kCompareFGT,
813 count);
814 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400815 case Token::Kind::TK_GTEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400816 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGTEQ,
817 ByteCodeInstruction::kCompareUGTEQ,
818 ByteCodeInstruction::kCompareFGTEQ,
819 count);
820 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400821 case Token::Kind::TK_LT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400822 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLT,
823 ByteCodeInstruction::kCompareULT,
824 ByteCodeInstruction::kCompareFLT,
825 count);
826 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400827 case Token::Kind::TK_LTEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400828 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLTEQ,
829 ByteCodeInstruction::kCompareULTEQ,
830 ByteCodeInstruction::kCompareFLTEQ,
831 count);
832 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400833 case Token::Kind::TK_MINUS:
Brian Osmanb08cc022020-04-02 11:38:40 -0400834 this->writeTypedInstruction(lType, ByteCodeInstruction::kSubtractI,
835 ByteCodeInstruction::kSubtractI,
836 ByteCodeInstruction::kSubtractF,
837 count);
838 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400839 case Token::Kind::TK_NEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400840 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareINEQ,
841 ByteCodeInstruction::kCompareINEQ,
842 ByteCodeInstruction::kCompareFNEQ,
843 count);
844 // Collapse to a single bool
845 for (int i = count; i > 1; --i) {
846 this->write(ByteCodeInstruction::kOrB);
847 }
848 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400849 case Token::Kind::TK_PERCENT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400850 this->writeTypedInstruction(lType, ByteCodeInstruction::kRemainderS,
851 ByteCodeInstruction::kRemainderU,
852 ByteCodeInstruction::kRemainderF,
853 count);
854 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400855 case Token::Kind::TK_PLUS:
Brian Osmanb08cc022020-04-02 11:38:40 -0400856 this->writeTypedInstruction(lType, ByteCodeInstruction::kAddI,
857 ByteCodeInstruction::kAddI,
858 ByteCodeInstruction::kAddF,
859 count);
860 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400861 case Token::Kind::TK_SLASH:
Brian Osmanb08cc022020-04-02 11:38:40 -0400862 this->writeTypedInstruction(lType, ByteCodeInstruction::kDivideS,
863 ByteCodeInstruction::kDivideU,
864 ByteCodeInstruction::kDivideF,
865 count);
866 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400867 case Token::Kind::TK_STAR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400868 this->writeTypedInstruction(lType, ByteCodeInstruction::kMultiplyI,
869 ByteCodeInstruction::kMultiplyI,
870 ByteCodeInstruction::kMultiplyF,
871 count);
872 break;
873
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400874 case Token::Kind::TK_LOGICALXOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400875 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
876 this->write(ByteCodeInstruction::kXorB);
877 break;
878
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400879 case Token::Kind::TK_BITWISEAND:
Brian Osmanb08cc022020-04-02 11:38:40 -0400880 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
881 tc == SkSL::TypeCategory::kUnsigned));
882 this->write(ByteCodeInstruction::kAndB);
883 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400884 case Token::Kind::TK_BITWISEOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400885 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
886 tc == SkSL::TypeCategory::kUnsigned));
887 this->write(ByteCodeInstruction::kOrB);
888 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400889 case Token::Kind::TK_BITWISEXOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400890 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
891 tc == SkSL::TypeCategory::kUnsigned));
892 this->write(ByteCodeInstruction::kXorB);
893 break;
894
895 default:
896 fErrors.error(b.fOffset, SkSL::String::printf("Unsupported binary operator '%s'",
897 Compiler::OperatorName(op)));
898 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500899 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500900 }
901 if (lvalue) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400902 lvalue->store(discard);
903 discard = false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500904 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400905 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500906}
907
Brian Osmanb08cc022020-04-02 11:38:40 -0400908void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
909 this->write(ByteCodeInstruction::kPushImmediate);
910 this->write32(b.fValue ? ~0 : 0);
911}
912
913void ByteCodeGenerator::writeConstructor(const Constructor& c) {
914 for (const auto& arg : c.fArguments) {
915 this->writeExpression(*arg);
916 }
917 if (c.fArguments.size() == 1) {
918 const Type& inType = c.fArguments[0]->fType;
919 const Type& outType = c.fType;
920 TypeCategory inCategory = type_category(inType);
921 TypeCategory outCategory = type_category(outType);
922 int inCount = SlotCount(inType);
923 int outCount = SlotCount(outType);
924 if (inCategory != outCategory) {
925 SkASSERT(inCount == outCount);
926 if (inCategory == TypeCategory::kFloat) {
927 SkASSERT(outCategory == TypeCategory::kSigned ||
928 outCategory == TypeCategory::kUnsigned);
929 this->write(vector_instruction(ByteCodeInstruction::kConvertFtoI, outCount));
930 } else if (outCategory == TypeCategory::kFloat) {
931 if (inCategory == TypeCategory::kSigned) {
932 this->write(vector_instruction(ByteCodeInstruction::kConvertStoF, outCount));
933 } else {
934 SkASSERT(inCategory == TypeCategory::kUnsigned);
935 this->write(vector_instruction(ByteCodeInstruction::kConvertUtoF, outCount));
936 }
937 } else {
938 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500939 }
940 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400941 if (inType.kind() == Type::kMatrix_Kind && outType.kind() == Type::kMatrix_Kind) {
942 this->write(ByteCodeInstruction::kMatrixToMatrix,
943 SlotCount(outType) - SlotCount(inType));
944 this->write8(inType.columns());
945 this->write8(inType.rows());
946 this->write8(outType.columns());
947 this->write8(outType.rows());
948 } else if (inCount != outCount) {
949 SkASSERT(inCount == 1);
950 if (outType.kind() == Type::kMatrix_Kind) {
951 this->write(ByteCodeInstruction::kScalarToMatrix, SlotCount(outType) - 1);
952 this->write8(outType.columns());
953 this->write8(outType.rows());
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500954 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400955 SkASSERT(outType.kind() == Type::kVector_Kind);
956 for (; inCount != outCount; ++inCount) {
957 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400958 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500959 }
960 }
961 }
962}
963
Brian Osmanb08cc022020-04-02 11:38:40 -0400964void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500965 int argumentCount = 0;
966 for (const auto& arg : f.fArguments) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400967 this->writeExpression(*arg);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500968 argumentCount += SlotCount(arg->fType);
969 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400970 this->write(ByteCodeInstruction::kCallExternal, SlotCount(f.fType) - argumentCount);
971 SkASSERT(argumentCount <= 255);
972 this->write8(argumentCount);
973 this->write8(SlotCount(f.fType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500974 int index = fOutput->fExternalValues.size();
975 fOutput->fExternalValues.push_back(f.fFunction);
976 SkASSERT(index <= 255);
Brian Osmanb08cc022020-04-02 11:38:40 -0400977 this->write8(index);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500978}
979
Brian Osmanb08cc022020-04-02 11:38:40 -0400980void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
981 int count = SlotCount(e.fValue->type());
982 this->write(vector_instruction(ByteCodeInstruction::kReadExternal, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500983 int index = fOutput->fExternalValues.size();
984 fOutput->fExternalValues.push_back(e.fValue);
985 SkASSERT(index <= 255);
Brian Osmanb08cc022020-04-02 11:38:40 -0400986 this->write8(index);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500987}
988
Brian Osmanb08cc022020-04-02 11:38:40 -0400989void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
990 Location location = this->getLocation(expr);
991 int count = SlotCount(expr.fType);
Brian Osmanefb08402020-04-13 16:30:44 -0400992 if (count == 0) {
993 return;
994 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400995 if (location.isOnStack() || count > 4) {
996 if (!location.isOnStack()) {
997 this->write(ByteCodeInstruction::kPushImmediate);
998 this->write32(location.fSlot);
999 }
1000 this->write(location.selectLoad(ByteCodeInstruction::kLoadExtended,
1001 ByteCodeInstruction::kLoadExtendedGlobal,
1002 ByteCodeInstruction::kLoadExtendedUniform),
1003 count);
1004 this->write8(count);
1005 } else {
1006 this->write(vector_instruction(location.selectLoad(ByteCodeInstruction::kLoad,
1007 ByteCodeInstruction::kLoadGlobal,
1008 ByteCodeInstruction::kLoadUniform),
1009 count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001010 this->write8(location.fSlot);
1011 }
1012}
1013
1014static inline uint32_t float_to_bits(float x) {
1015 uint32_t u;
1016 memcpy(&u, &x, sizeof(uint32_t));
1017 return u;
1018}
1019
1020void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
1021 this->write(ByteCodeInstruction::kPushImmediate);
1022 this->write32(float_to_bits(f.fValue));
1023}
1024
Brian Osman8842b372020-05-01 15:07:49 -04001025static bool is_generic_type(const Type* type, const Type* generic) {
1026 const std::vector<const Type*>& concrete(generic->coercibleTypes());
1027 return std::find(concrete.begin(), concrete.end(), type) != concrete.end();
1028}
1029
Brian Osmanb08cc022020-04-02 11:38:40 -04001030void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
1031 auto found = fIntrinsics.find(c.fFunction.fName);
1032 if (found == fIntrinsics.end()) {
1033 fErrors.error(c.fOffset, String::printf("Unsupported intrinsic: '%s'",
1034 String(c.fFunction.fName).c_str()));
1035 return;
1036 }
Mike Klein45be0772020-05-01 09:13:18 -05001037 Intrinsic intrin = found->second;
Brian Osmanb08cc022020-04-02 11:38:40 -04001038 int count = SlotCount(c.fArguments[0]->fType);
Brian Osmand5f937b2020-05-04 12:07:29 -04001039
1040 // Several intrinsics have variants where one argument is either scalar, or the same size as
1041 // the first argument. Call dupSmallerType(SlotCount(argType)) to ensure equal component count.
1042 auto dupSmallerType = [count, this](int smallCount) {
1043 SkASSERT(smallCount == 1 || smallCount == count);
1044 for (int i = smallCount; i < count; ++i) {
1045 this->write(ByteCodeInstruction::kDup);
1046 }
1047 };
1048
1049 if (intrin.is_special && (intrin.special == SpecialIntrinsic::kClamp ||
1050 intrin.special == SpecialIntrinsic::kSaturate)) {
1051 // These intrinsics are extra-special, we need instructions interleaved with arguments
1052 bool saturate = (intrin.special == SpecialIntrinsic::kSaturate);
1053 SkASSERT(c.fArguments.size() == (saturate ? 1 : 3));
1054 int limitCount = saturate ? 1 : SlotCount(c.fArguments[1]->fType);
1055
1056 // 'x'
1057 this->writeExpression(*c.fArguments[0]);
1058
1059 // 'minVal'
1060 if (saturate) {
1061 this->write(ByteCodeInstruction::kPushImmediate);
1062 this->write32(float_to_bits(0.0f));
1063 } else {
1064 this->writeExpression(*c.fArguments[1]);
1065 }
1066 dupSmallerType(limitCount);
1067 this->writeTypedInstruction(c.fArguments[0]->fType,
1068 ByteCodeInstruction::kMaxS,
1069 ByteCodeInstruction::kMaxS,
1070 ByteCodeInstruction::kMaxF,
1071 count);
1072
1073 // 'maxVal'
1074 if (saturate) {
1075 this->write(ByteCodeInstruction::kPushImmediate);
1076 this->write32(float_to_bits(1.0f));
1077 } else {
1078 SkASSERT(limitCount == SlotCount(c.fArguments[2]->fType));
1079 this->writeExpression(*c.fArguments[2]);
1080 }
1081 dupSmallerType(limitCount);
1082 this->writeTypedInstruction(c.fArguments[0]->fType,
1083 ByteCodeInstruction::kMinS,
1084 ByteCodeInstruction::kMinS,
1085 ByteCodeInstruction::kMinF,
1086 count);
1087 return;
1088 }
1089
1090 // All other intrinsics can handle their arguments being on the stack in order
1091 for (const auto& arg : c.fArguments) {
1092 this->writeExpression(*arg);
1093 }
1094
Mike Klein45be0772020-05-01 09:13:18 -05001095 if (intrin.is_special) {
1096 switch (intrin.special) {
Brian Osman8842b372020-05-01 15:07:49 -04001097 case SpecialIntrinsic::kAll: {
1098 for (int i = count-1; i --> 0;) {
1099 this->write(ByteCodeInstruction::kAndB);
1100 }
1101 } break;
1102
1103 case SpecialIntrinsic::kAny: {
1104 for (int i = count-1; i --> 0;) {
1105 this->write(ByteCodeInstruction::kOrB);
1106 }
1107 } break;
1108
Brian Osman15c98cb2020-02-27 18:36:57 +00001109 case SpecialIntrinsic::kDot: {
1110 SkASSERT(c.fArguments.size() == 2);
Brian Osmanb08cc022020-04-02 11:38:40 -04001111 SkASSERT(count == SlotCount(c.fArguments[1]->fType));
1112 this->write(vector_instruction(ByteCodeInstruction::kMultiplyF, count));
Mike Klein45be0772020-05-01 09:13:18 -05001113 for (int i = count-1; i --> 0;) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001114 this->write(ByteCodeInstruction::kAddF);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001115 }
Mike Klein45be0772020-05-01 09:13:18 -05001116 } break;
1117
1118 case SpecialIntrinsic::kLength: {
1119 SkASSERT(c.fArguments.size() == 1);
1120 this->write(vector_instruction(ByteCodeInstruction::kDup , count));
1121 this->write(vector_instruction(ByteCodeInstruction::kMultiplyF, count));
1122 for (int i = count-1; i --> 0;) {
1123 this->write(ByteCodeInstruction::kAddF);
1124 }
1125 this->write(ByteCodeInstruction::kSqrt);
1126 } break;
1127
Brian Osmand5f937b2020-05-04 12:07:29 -04001128 case SpecialIntrinsic::kMax:
1129 case SpecialIntrinsic::kMin: {
1130 SkASSERT(c.fArguments.size() == 2);
1131 // There are variants where the second argument is scalar
1132 dupSmallerType(SlotCount(c.fArguments[1]->fType));
1133 if (intrin.special == SpecialIntrinsic::kMax) {
1134 this->writeTypedInstruction(c.fArguments[0]->fType,
1135 ByteCodeInstruction::kMaxS,
1136 ByteCodeInstruction::kMaxS,
1137 ByteCodeInstruction::kMaxF,
1138 count);
1139 } else {
1140 this->writeTypedInstruction(c.fArguments[0]->fType,
1141 ByteCodeInstruction::kMinS,
1142 ByteCodeInstruction::kMinS,
1143 ByteCodeInstruction::kMinF,
1144 count);
1145 }
1146 } break;
1147
Brian Osman8842b372020-05-01 15:07:49 -04001148 case SpecialIntrinsic::kMix: {
1149 // Two main variants of mix to handle
1150 SkASSERT(c.fArguments.size() == 3);
1151 SkASSERT(count == SlotCount(c.fArguments[1]->fType));
1152 int selectorCount = SlotCount(c.fArguments[2]->fType);
1153
1154 if (is_generic_type(&c.fArguments[2]->fType, fContext.fGenBType_Type.get())) {
1155 // mix(genType, genType, genBoolType)
1156 SkASSERT(selectorCount == count);
1157 this->write(vector_instruction(ByteCodeInstruction::kMix, count));
1158 } else {
1159 // mix(genType, genType, genType) or mix(genType, genType, float)
Brian Osmand5f937b2020-05-04 12:07:29 -04001160 dupSmallerType(selectorCount);
Brian Osman8842b372020-05-01 15:07:49 -04001161 this->write(vector_instruction(ByteCodeInstruction::kLerp, count));
1162 }
1163 } break;
1164
Brian Osmanb08cc022020-04-02 11:38:40 -04001165 default:
1166 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001167 }
1168 } else {
Brian Osman8842b372020-05-01 15:07:49 -04001169 switch (intrin.inst_f) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001170 case ByteCodeInstruction::kInverse2x2: {
1171 SkASSERT(c.fArguments.size() > 0);
1172 auto op = ByteCodeInstruction::kInverse2x2;
1173 switch (count) {
1174 case 4: break; // float2x2
1175 case 9: op = ByteCodeInstruction::kInverse3x3; break;
1176 case 16: op = ByteCodeInstruction::kInverse4x4; break;
1177 default: SkASSERT(false);
1178 }
1179 this->write(op);
1180 break;
Brian Osman15c98cb2020-02-27 18:36:57 +00001181 }
Mike Klein45be0772020-05-01 09:13:18 -05001182
Brian Osmanb08cc022020-04-02 11:38:40 -04001183 default:
Brian Osman8842b372020-05-01 15:07:49 -04001184 this->writeTypedInstruction(c.fArguments[0]->fType, intrin.inst_s, intrin.inst_u,
1185 intrin.inst_f, count);
1186 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001187 }
1188 }
1189}
1190
Brian Osmanb08cc022020-04-02 11:38:40 -04001191void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001192 // Find the index of the function we're calling. We explicitly do not allow calls to functions
1193 // before they're defined. This is an easy-to-understand rule that prevents recursion.
Brian Osmanb08cc022020-04-02 11:38:40 -04001194 int idx = -1;
1195 for (size_t i = 0; i < fFunctions.size(); ++i) {
1196 if (f.fFunction.matches(fFunctions[i]->fDeclaration)) {
1197 idx = i;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001198 break;
1199 }
1200 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001201 if (idx == -1) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001202 this->writeIntrinsicCall(f);
1203 return;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001204 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001205
1206
1207 if (idx > 255) {
1208 fErrors.error(f.fOffset, "Function count limit exceeded");
1209 return;
1210 } else if (idx >= (int) fFunctions.size()) {
1211 fErrors.error(f.fOffset, "Call to undefined function");
1212 return;
1213 }
1214
1215 // We may need to deal with out parameters, so the sequence is tricky
1216 if (int returnCount = SlotCount(f.fType)) {
1217 this->write(ByteCodeInstruction::kReserve, returnCount);
1218 this->write8(returnCount);
1219 }
1220
1221 int argCount = f.fArguments.size();
1222 std::vector<std::unique_ptr<LValue>> lvalues;
1223 for (int i = 0; i < argCount; ++i) {
1224 const auto& param = f.fFunction.fParameters[i];
1225 const auto& arg = f.fArguments[i];
1226 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1227 lvalues.emplace_back(this->getLValue(*arg));
1228 lvalues.back()->load();
1229 } else {
1230 this->writeExpression(*arg);
1231 }
1232 }
1233
1234 // The space used by the call is based on the callee, but it also unwinds all of that before
1235 // we continue execution. We adjust our max stack depths below.
1236 this->write(ByteCodeInstruction::kCall);
1237 this->write8(idx);
1238
1239 const ByteCodeFunction* callee = fOutput->fFunctions[idx].get();
1240 fMaxLoopCount = std::max(fMaxLoopCount, fLoopCount + callee->fLoopCount);
1241 fMaxConditionCount = std::max(fMaxConditionCount, fConditionCount + callee->fConditionCount);
1242 fMaxStackCount = std::max(fMaxStackCount, fStackCount + callee->fLocalCount
1243 + callee->fStackCount);
1244
1245 // After the called function returns, the stack will still contain our arguments. We have to
1246 // pop them (storing any out parameters back to their lvalues as we go). We glob together slot
1247 // counts for all parameters that aren't out-params, so we can pop them in one big chunk.
1248 int popCount = 0;
1249 auto pop = [&]() {
1250 if (popCount > 4) {
1251 this->write(ByteCodeInstruction::kPopN, popCount);
1252 this->write8(popCount);
1253 } else if (popCount > 0) {
1254 this->write(vector_instruction(ByteCodeInstruction::kPop, popCount));
1255 }
1256 popCount = 0;
1257 };
1258
1259 for (int i = argCount - 1; i >= 0; --i) {
1260 const auto& param = f.fFunction.fParameters[i];
1261 const auto& arg = f.fArguments[i];
1262 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1263 pop();
1264 lvalues.back()->store(true);
1265 lvalues.pop_back();
1266 } else {
1267 popCount += SlotCount(arg->fType);
1268 }
1269 }
1270 pop();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001271}
1272
Brian Osmanb08cc022020-04-02 11:38:40 -04001273void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
1274 this->write(ByteCodeInstruction::kPushImmediate);
1275 this->write32(i.fValue);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001276}
1277
Brian Osmanb08cc022020-04-02 11:38:40 -04001278void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
1279 // not yet implemented
1280 abort();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001281}
1282
Brian Osmanb08cc022020-04-02 11:38:40 -04001283bool ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p, bool discard) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001284 switch (p.fOperator) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001285 case Token::Kind::TK_PLUSPLUS: // fall through
1286 case Token::Kind::TK_MINUSMINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001287 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1288 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
1289 lvalue->load();
1290 this->write(ByteCodeInstruction::kPushImmediate);
1291 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001292 if (p.fOperator == Token::Kind::TK_PLUSPLUS) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001293 this->writeTypedInstruction(p.fType,
1294 ByteCodeInstruction::kAddI,
1295 ByteCodeInstruction::kAddI,
1296 ByteCodeInstruction::kAddF,
1297 1);
1298 } else {
1299 this->writeTypedInstruction(p.fType,
1300 ByteCodeInstruction::kSubtractI,
1301 ByteCodeInstruction::kSubtractI,
1302 ByteCodeInstruction::kSubtractF,
1303 1);
1304 }
1305 lvalue->store(discard);
1306 discard = false;
1307 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001308 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001309 case Token::Kind::TK_MINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001310 this->writeExpression(*p.fOperand);
1311 this->writeTypedInstruction(p.fType,
1312 ByteCodeInstruction::kNegateI,
1313 ByteCodeInstruction::kNegateI,
1314 ByteCodeInstruction::kNegateF,
Brian Osmanab8f3842020-04-07 09:30:44 -04001315 SlotCount(p.fOperand->fType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001316 break;
1317 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001318 case Token::Kind::TK_LOGICALNOT:
1319 case Token::Kind::TK_BITWISENOT: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001320 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1321 SkDEBUGCODE(TypeCategory tc = type_category(p.fOperand->fType));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001322 SkASSERT((p.fOperator == Token::Kind::TK_LOGICALNOT && tc == TypeCategory::kBool) ||
1323 (p.fOperator == Token::Kind::TK_BITWISENOT && (tc == TypeCategory::kSigned ||
Brian Osmanb08cc022020-04-02 11:38:40 -04001324 tc == TypeCategory::kUnsigned)));
1325 this->writeExpression(*p.fOperand);
1326 this->write(ByteCodeInstruction::kNotB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001327 break;
1328 }
1329 default:
1330 SkASSERT(false);
1331 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001332 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001333}
1334
Brian Osmanb08cc022020-04-02 11:38:40 -04001335bool ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p, bool discard) {
1336 switch (p.fOperator) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001337 case Token::Kind::TK_PLUSPLUS: // fall through
1338 case Token::Kind::TK_MINUSMINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001339 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1340 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
1341 lvalue->load();
1342 // If we're not supposed to discard the result, then make a copy *before* the +/-
1343 if (!discard) {
1344 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -04001345 }
1346 this->write(ByteCodeInstruction::kPushImmediate);
1347 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001348 if (p.fOperator == Token::Kind::TK_PLUSPLUS) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001349 this->writeTypedInstruction(p.fType,
1350 ByteCodeInstruction::kAddI,
1351 ByteCodeInstruction::kAddI,
1352 ByteCodeInstruction::kAddF,
1353 1);
1354 } else {
1355 this->writeTypedInstruction(p.fType,
1356 ByteCodeInstruction::kSubtractI,
1357 ByteCodeInstruction::kSubtractI,
1358 ByteCodeInstruction::kSubtractF,
1359 1);
1360 }
1361 // Always consume the result as part of the store
1362 lvalue->store(true);
1363 discard = false;
1364 break;
1365 }
1366 default:
1367 SkASSERT(false);
1368 }
1369 return discard;
1370}
1371
1372void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001373 if (swizzle_is_simple(s)) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001374 this->writeVariableExpression(s);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001375 return;
1376 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001377
1378 switch (s.fBase->fKind) {
1379 case Expression::kVariableReference_Kind: {
1380 Location location = this->getLocation(*s.fBase);
1381 this->write(location.selectLoad(ByteCodeInstruction::kLoadSwizzle,
1382 ByteCodeInstruction::kLoadSwizzleGlobal,
1383 ByteCodeInstruction::kLoadSwizzleUniform),
1384 s.fComponents.size());
1385 this->write8(location.fSlot);
1386 this->write8(s.fComponents.size());
1387 for (int c : s.fComponents) {
1388 this->write8(c);
1389 }
1390 break;
1391 }
1392 default:
1393 this->writeExpression(*s.fBase);
1394 this->write(ByteCodeInstruction::kSwizzle,
1395 s.fComponents.size() - s.fBase->fType.columns());
1396 this->write8(s.fBase->fType.columns());
1397 this->write8(s.fComponents.size());
1398 for (int c : s.fComponents) {
1399 this->write8(c);
1400 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001401 }
1402}
1403
Brian Osmanb08cc022020-04-02 11:38:40 -04001404void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001405 int count = SlotCount(t.fType);
1406 SkASSERT(count == SlotCount(t.fIfTrue->fType));
1407 SkASSERT(count == SlotCount(t.fIfFalse->fType));
1408
Brian Osmanb08cc022020-04-02 11:38:40 -04001409 this->writeExpression(*t.fTest);
1410 this->write(ByteCodeInstruction::kMaskPush);
1411 this->writeExpression(*t.fIfTrue);
1412 this->write(ByteCodeInstruction::kMaskNegate);
1413 this->writeExpression(*t.fIfFalse);
1414 this->write(ByteCodeInstruction::kMaskBlend, count);
1415 this->write8(count);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001416}
1417
Brian Osmanb08cc022020-04-02 11:38:40 -04001418void ByteCodeGenerator::writeExpression(const Expression& e, bool discard) {
1419 switch (e.fKind) {
1420 case Expression::kBinary_Kind:
1421 discard = this->writeBinaryExpression((BinaryExpression&) e, discard);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001422 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001423 case Expression::kBoolLiteral_Kind:
1424 this->writeBoolLiteral((BoolLiteral&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001425 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001426 case Expression::kConstructor_Kind:
1427 this->writeConstructor((Constructor&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001428 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001429 case Expression::kExternalFunctionCall_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001430 this->writeExternalFunctionCall((ExternalFunctionCall&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001431 break;
1432 case Expression::kExternalValue_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001433 this->writeExternalValue((ExternalValueReference&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001434 break;
1435 case Expression::kFieldAccess_Kind:
1436 case Expression::kIndex_Kind:
1437 case Expression::kVariableReference_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001438 this->writeVariableExpression(e);
1439 break;
1440 case Expression::kFloatLiteral_Kind:
1441 this->writeFloatLiteral((FloatLiteral&) e);
1442 break;
1443 case Expression::kFunctionCall_Kind:
1444 this->writeFunctionCall((FunctionCall&) e);
1445 break;
1446 case Expression::kIntLiteral_Kind:
1447 this->writeIntLiteral((IntLiteral&) e);
1448 break;
1449 case Expression::kNullLiteral_Kind:
1450 this->writeNullLiteral((NullLiteral&) e);
1451 break;
1452 case Expression::kPrefix_Kind:
1453 discard = this->writePrefixExpression((PrefixExpression&) e, discard);
1454 break;
1455 case Expression::kPostfix_Kind:
1456 discard = this->writePostfixExpression((PostfixExpression&) e, discard);
1457 break;
1458 case Expression::kSwizzle_Kind:
1459 this->writeSwizzle((Swizzle&) e);
1460 break;
1461 case Expression::kTernary_Kind:
1462 this->writeTernaryExpression((TernaryExpression&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001463 break;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001464 default:
1465#ifdef SK_DEBUG
Brian Osmanb08cc022020-04-02 11:38:40 -04001466 printf("unsupported expression %s\n", e.description().c_str());
Ben Wagner470e0ac2020-01-22 16:59:21 -05001467#endif
Brian Osmanb08cc022020-04-02 11:38:40 -04001468 SkASSERT(false);
1469 }
1470 if (discard) {
1471 int count = SlotCount(e.fType);
1472 if (count > 4) {
1473 this->write(ByteCodeInstruction::kPopN, count);
1474 this->write8(count);
1475 } else if (count != 0) {
1476 this->write(vector_instruction(ByteCodeInstruction::kPop, count));
1477 }
1478 discard = false;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001479 }
Ethan Nicholas7deb1c22020-01-22 10:31:55 -05001480}
1481
Brian Osmanb08cc022020-04-02 11:38:40 -04001482class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
1483public:
1484 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
1485 : INHERITED(*generator)
1486 , fCount(ByteCodeGenerator::SlotCount(value.type()))
1487 , fIndex(index) {}
1488
1489 void load() override {
1490 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001491 fGenerator.write8(fIndex);
1492 }
1493
1494 void store(bool discard) override {
1495 if (!discard) {
1496 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001497 }
1498 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001499 fGenerator.write8(fIndex);
1500 }
1501
1502private:
1503 typedef LValue INHERITED;
1504
1505 int fCount;
1506
1507 int fIndex;
1508};
1509
1510class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
1511public:
1512 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
1513 : INHERITED(*generator)
1514 , fSwizzle(swizzle) {}
1515
1516 void load() override {
1517 fGenerator.writeSwizzle(fSwizzle);
1518 }
1519
1520 void store(bool discard) override {
1521 int count = fSwizzle.fComponents.size();
1522 if (!discard) {
1523 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001524 }
1525 ByteCodeGenerator::Location location = fGenerator.getLocation(*fSwizzle.fBase);
1526 if (location.isOnStack()) {
1527 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreSwizzleIndirect,
1528 ByteCodeInstruction::kStoreSwizzleIndirectGlobal),
1529 count);
1530 } else {
1531 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreSwizzle,
1532 ByteCodeInstruction::kStoreSwizzleGlobal),
1533 count);
1534 fGenerator.write8(location.fSlot);
1535 }
1536 fGenerator.write8(count);
1537 for (int c : fSwizzle.fComponents) {
1538 fGenerator.write8(c);
1539 }
1540 }
1541
1542private:
1543 const Swizzle& fSwizzle;
1544
1545 typedef LValue INHERITED;
1546};
1547
1548class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
1549public:
1550 ByteCodeExpressionLValue(ByteCodeGenerator* generator, const Expression& expr)
1551 : INHERITED(*generator)
1552 , fExpression(expr) {}
1553
1554 void load() override {
1555 fGenerator.writeVariableExpression(fExpression);
1556 }
1557
1558 void store(bool discard) override {
1559 int count = ByteCodeGenerator::SlotCount(fExpression.fType);
1560 if (!discard) {
1561 if (count > 4) {
1562 fGenerator.write(ByteCodeInstruction::kDupN, count);
1563 fGenerator.write8(count);
1564 } else {
1565 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001566 }
1567 }
1568 ByteCodeGenerator::Location location = fGenerator.getLocation(fExpression);
1569 if (location.isOnStack() || count > 4) {
1570 if (!location.isOnStack()) {
1571 fGenerator.write(ByteCodeInstruction::kPushImmediate);
1572 fGenerator.write32(location.fSlot);
1573 }
1574 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreExtended,
1575 ByteCodeInstruction::kStoreExtendedGlobal),
1576 count);
1577 fGenerator.write8(count);
1578 } else {
1579 fGenerator.write(
1580 vector_instruction(location.selectStore(ByteCodeInstruction::kStore,
1581 ByteCodeInstruction::kStoreGlobal),
1582 count));
1583 fGenerator.write8(location.fSlot);
1584 }
1585 }
1586
1587private:
1588 typedef LValue INHERITED;
1589
1590 const Expression& fExpression;
1591};
1592
1593std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
1594 switch (e.fKind) {
1595 case Expression::kExternalValue_Kind: {
1596 ExternalValue* value = ((ExternalValueReference&) e).fValue;
1597 int index = fOutput->fExternalValues.size();
1598 fOutput->fExternalValues.push_back(value);
1599 SkASSERT(index <= 255);
1600 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
1601 }
1602 case Expression::kFieldAccess_Kind:
1603 case Expression::kIndex_Kind:
1604 case Expression::kVariableReference_Kind:
1605 return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
1606 case Expression::kSwizzle_Kind: {
1607 const Swizzle& s = (const Swizzle&) e;
1608 return swizzle_is_simple(s)
1609 ? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e))
1610 : std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s));
1611 }
1612 case Expression::kTernary_Kind:
1613 default:
1614#ifdef SK_DEBUG
1615 ABORT("unsupported lvalue %s\n", e.description().c_str());
1616#endif
1617 return nullptr;
1618 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001619}
1620
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001621void ByteCodeGenerator::writeBlock(const Block& b) {
1622 for (const auto& s : b.fStatements) {
1623 this->writeStatement(*s);
1624 }
1625}
1626
Brian Osmanb08cc022020-04-02 11:38:40 -04001627void ByteCodeGenerator::setBreakTargets() {
1628 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
1629 for (DeferredLocation& b : breaks) {
1630 b.set();
1631 }
1632 fBreakTargets.pop();
1633}
1634
1635void ByteCodeGenerator::setContinueTargets() {
1636 std::vector<DeferredLocation>& continues = fContinueTargets.top();
1637 for (DeferredLocation& c : continues) {
1638 c.set();
1639 }
1640 fContinueTargets.pop();
1641}
1642
1643void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
1644 // TODO: Include BranchIfAllFalse to top-most LoopNext
1645 this->write(ByteCodeInstruction::kLoopBreak);
1646}
1647
1648void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
1649 // TODO: Include BranchIfAllFalse to top-most LoopNext
1650 this->write(ByteCodeInstruction::kLoopContinue);
1651}
1652
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001653void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001654 this->write(ByteCodeInstruction::kLoopBegin);
1655 size_t start = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001656 this->writeStatement(*d.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001657 this->write(ByteCodeInstruction::kLoopNext);
1658 this->writeExpression(*d.fTest);
1659 this->write(ByteCodeInstruction::kLoopMask);
1660 // TODO: Could shorten this with kBranchIfAnyTrue
1661 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001662 DeferredLocation endLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -04001663 this->write(ByteCodeInstruction::kBranch);
1664 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001665 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001666 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001667}
1668
1669void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001670 fContinueTargets.emplace();
1671 fBreakTargets.emplace();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001672 if (f.fInitializer) {
1673 this->writeStatement(*f.fInitializer);
1674 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001675 this->write(ByteCodeInstruction::kLoopBegin);
1676 size_t start = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001677 if (f.fTest) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001678 this->writeExpression(*f.fTest);
1679 this->write(ByteCodeInstruction::kLoopMask);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001680 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001681 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001682 DeferredLocation endLocation(this);
1683 this->writeStatement(*f.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001684 this->write(ByteCodeInstruction::kLoopNext);
Brian Osman569f12f2019-06-13 11:23:57 -04001685 if (f.fNext) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001686 this->writeExpression(*f.fNext, true);
Brian Osman569f12f2019-06-13 11:23:57 -04001687 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001688 this->write(ByteCodeInstruction::kBranch);
1689 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001690 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001691 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001692}
1693
1694void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001695 this->writeExpression(*i.fTest);
1696 this->write(ByteCodeInstruction::kMaskPush);
1697 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001698 DeferredLocation falseLocation(this);
1699 this->writeStatement(*i.fIfTrue);
1700 falseLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001701 if (i.fIfFalse) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001702 this->write(ByteCodeInstruction::kMaskNegate);
1703 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001704 DeferredLocation endLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001705 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -05001706 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001707 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001708 this->write(ByteCodeInstruction::kMaskPop);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001709}
1710
Brian Osmanb08cc022020-04-02 11:38:40 -04001711void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
1712 if (fLoopCount || fConditionCount) {
Brian Osman4a47da72019-07-12 11:30:32 -04001713 fErrors.error(r.fOffset, "return not allowed inside conditional or loop");
1714 return;
1715 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001716 int count = SlotCount(r.fExpression->fType);
1717 this->writeExpression(*r.fExpression);
1718
1719 // Technically, the kReturn also pops fOutput->fLocalCount values from the stack, too, but we
1720 // haven't counted pushing those (they're outside the scope of our stack tracking). Instead,
1721 // we account for those in writeFunction().
1722
1723 // This is all fine because we don't allow conditional returns, so we only return once anyway.
1724 this->write(ByteCodeInstruction::kReturn, -count);
1725 this->write8(count);
1726}
1727
1728void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
1729 // not yet implemented
1730 abort();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001731}
1732
1733void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1734 for (const auto& declStatement : v.fVars) {
1735 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
Brian Osmanb08cc022020-04-02 11:38:40 -04001736 // we need to grab the location even if we don't use it, to ensure it has been allocated
1737 Location location = this->getLocation(*decl.fVar);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001738 if (decl.fValue) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001739 this->writeExpression(*decl.fValue);
1740 int count = SlotCount(decl.fValue->fType);
1741 if (count > 4) {
1742 this->write(ByteCodeInstruction::kPushImmediate);
1743 this->write32(location.fSlot);
1744 this->write(ByteCodeInstruction::kStoreExtended, count);
1745 this->write8(count);
1746 } else {
1747 this->write(vector_instruction(ByteCodeInstruction::kStore, count));
1748 this->write8(location.fSlot);
1749 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001750 }
1751 }
1752}
1753
1754void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001755 this->write(ByteCodeInstruction::kLoopBegin);
1756 size_t cond = fCode->size();
1757 this->writeExpression(*w.fTest);
1758 this->write(ByteCodeInstruction::kLoopMask);
1759 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001760 DeferredLocation endLocation(this);
1761 this->writeStatement(*w.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001762 this->write(ByteCodeInstruction::kLoopNext);
1763 this->write(ByteCodeInstruction::kBranch);
1764 this->write16(cond);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001765 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001766 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001767}
1768
1769void ByteCodeGenerator::writeStatement(const Statement& s) {
1770 switch (s.fKind) {
1771 case Statement::kBlock_Kind:
1772 this->writeBlock((Block&) s);
1773 break;
1774 case Statement::kBreak_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001775 this->writeBreakStatement((BreakStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001776 break;
1777 case Statement::kContinue_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001778 this->writeContinueStatement((ContinueStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001779 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001780 case Statement::kDiscard_Kind:
1781 // not yet implemented
1782 abort();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001783 case Statement::kDo_Kind:
1784 this->writeDoStatement((DoStatement&) s);
1785 break;
Brian Osman3e29f1d2019-05-28 09:35:05 -04001786 case Statement::kExpression_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001787 this->writeExpression(*((ExpressionStatement&) s).fExpression, true);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001788 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001789 case Statement::kFor_Kind:
1790 this->writeForStatement((ForStatement&) s);
1791 break;
1792 case Statement::kIf_Kind:
1793 this->writeIfStatement((IfStatement&) s);
1794 break;
1795 case Statement::kNop_Kind:
1796 break;
1797 case Statement::kReturn_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001798 this->writeReturnStatement((ReturnStatement&) s);
1799 break;
1800 case Statement::kSwitch_Kind:
1801 this->writeSwitchStatement((SwitchStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001802 break;
1803 case Statement::kVarDeclarations_Kind:
1804 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1805 break;
1806 case Statement::kWhile_Kind:
1807 this->writeWhileStatement((WhileStatement&) s);
1808 break;
1809 default:
Brian Osmanb08cc022020-04-02 11:38:40 -04001810 SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001811 }
1812}
1813
Brian Osmanb08cc022020-04-02 11:38:40 -04001814ByteCodeFunction::ByteCodeFunction(const FunctionDeclaration* declaration)
1815 : fName(declaration->fName) {
Brian Osman80164412019-06-07 13:00:23 -04001816 fParameterCount = 0;
Brian Osmanb08cc022020-04-02 11:38:40 -04001817 for (const auto& p : declaration->fParameters) {
1818 int slots = ByteCodeGenerator::SlotCount(p->fType);
1819 fParameters.push_back({ slots, (bool)(p->fModifiers.fFlags & Modifiers::kOut_Flag) });
1820 fParameterCount += slots;
Brian Osman80164412019-06-07 13:00:23 -04001821 }
1822}
1823
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001824}