blob: b05fe2b93b0dc19d3119527f43d305d5c41f419c [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 },
Brian Osmana43d8202020-06-17 16:50:39 -040060 { "sample", SpecialIntrinsic::kSample },
Brian Osmand5f937b2020-05-04 12:07:29 -040061 { "saturate", SpecialIntrinsic::kSaturate },
62 { "sin", ByteCodeInstruction::kSin },
63 { "sqrt", ByteCodeInstruction::kSqrt },
64 { "tan", ByteCodeInstruction::kTan },
Brian Osman8842b372020-05-01 15:07:49 -040065
66 { "lessThan", { ByteCodeInstruction::kCompareFLT,
67 ByteCodeInstruction::kCompareSLT,
68 ByteCodeInstruction::kCompareULT } },
69 { "lessThanEqual", { ByteCodeInstruction::kCompareFLTEQ,
70 ByteCodeInstruction::kCompareSLTEQ,
71 ByteCodeInstruction::kCompareULTEQ } },
72 { "greaterThan", { ByteCodeInstruction::kCompareFGT,
73 ByteCodeInstruction::kCompareSGT,
74 ByteCodeInstruction::kCompareUGT } },
75 { "greaterThanEqual", { ByteCodeInstruction::kCompareFGTEQ,
76 ByteCodeInstruction::kCompareSGTEQ,
77 ByteCodeInstruction::kCompareUGTEQ } },
78 { "equal", { ByteCodeInstruction::kCompareFEQ,
79 ByteCodeInstruction::kCompareIEQ,
80 ByteCodeInstruction::kCompareIEQ } },
81 { "notEqual", { ByteCodeInstruction::kCompareFNEQ,
82 ByteCodeInstruction::kCompareINEQ,
83 ByteCodeInstruction::kCompareINEQ } },
84
85 { "any", SpecialIntrinsic::kAny },
86 { "all", SpecialIntrinsic::kAll },
87 { "not", ByteCodeInstruction::kNotB },
88 } {}
Brian Osmanb08cc022020-04-02 11:38:40 -040089
Ethan Nicholas82162ee2019-05-21 16:05:08 -040090
Brian Osman07c117b2019-05-23 12:51:06 -070091int ByteCodeGenerator::SlotCount(const Type& type) {
Brian Osmanfba386b2019-06-20 14:54:15 -040092 if (type.kind() == Type::kOther_Kind) {
93 return 0;
94 } else if (type.kind() == Type::kStruct_Kind) {
Brian Osman07c117b2019-05-23 12:51:06 -070095 int slots = 0;
96 for (const auto& f : type.fields()) {
97 slots += SlotCount(*f.fType);
98 }
99 SkASSERT(slots <= 255);
100 return slots;
101 } else if (type.kind() == Type::kArray_Kind) {
102 int columns = type.columns();
103 SkASSERT(columns >= 0);
104 int slots = columns * SlotCount(type.componentType());
105 SkASSERT(slots <= 255);
106 return slots;
107 } else {
108 return type.columns() * type.rows();
109 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400110}
111
Brian Osman1c110a02019-10-01 14:53:32 -0400112static inline bool is_uniform(const SkSL::Variable& var) {
113 return var.fModifiers.fFlags & Modifiers::kUniform_Flag;
114}
115
Brian Osmaneadfeb92020-01-09 12:43:03 -0500116static inline bool is_in(const SkSL::Variable& var) {
117 return var.fModifiers.fFlags & Modifiers::kIn_Flag;
118}
Brian Osmanb08cc022020-04-02 11:38:40 -0400119
120void ByteCodeGenerator::gatherUniforms(const Type& type, const String& name) {
121 if (type.kind() == Type::kOther_Kind) {
122 return;
123 } else if (type.kind() == Type::kStruct_Kind) {
124 for (const auto& f : type.fields()) {
125 this->gatherUniforms(*f.fType, name + "." + f.fName);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500126 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400127 } else if (type.kind() == Type::kArray_Kind) {
128 for (int i = 0; i < type.columns(); ++i) {
129 this->gatherUniforms(type.componentType(), String::printf("%s[%d]", name.c_str(), i));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500130 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400131 } else {
132 fOutput->fUniforms.push_back({ name, type_category(type), type.rows(), type.columns(),
133 fOutput->fUniformSlotCount });
134 fOutput->fUniformSlotCount += type.columns() * type.rows();
135 }
136}
137
138bool ByteCodeGenerator::generateCode() {
139 for (const auto& e : fProgram) {
140 switch (e.fKind) {
141 case ProgramElement::kFunction_Kind: {
142 std::unique_ptr<ByteCodeFunction> f = this->writeFunction((FunctionDefinition&) e);
143 if (!f) {
144 return false;
145 }
146 fOutput->fFunctions.push_back(std::move(f));
147 fFunctions.push_back(&(FunctionDefinition&)e);
148 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500149 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400150 case ProgramElement::kVar_Kind: {
151 VarDeclarations& decl = (VarDeclarations&) e;
152 for (const auto& v : decl.fVars) {
153 const Variable* declVar = ((VarDeclaration&) *v).fVar;
Brian Osmana43d8202020-06-17 16:50:39 -0400154 if (declVar->fType == *fContext.fFragmentProcessor_Type) {
155 fOutput->fChildFPCount++;
156 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400157 if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
158 continue;
159 }
160 if (is_uniform(*declVar)) {
161 this->gatherUniforms(declVar->fType, declVar->fName);
162 } else {
163 fOutput->fGlobalSlotCount += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400164 }
165 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400166 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400167 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400168 default:
169 ; // ignore
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400170 }
171 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400172 return 0 == fErrors.errorCount();
173}
174
175std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
176 fFunction = &f;
177 std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
178 fParameterCount = result->fParameterCount;
179 fLoopCount = fMaxLoopCount = 0;
180 fConditionCount = fMaxConditionCount = 0;
181 fStackCount = fMaxStackCount = 0;
182 fCode = &result->fCode;
183
184 this->writeStatement(*f.fBody);
185 if (0 == fErrors.errorCount()) {
186 SkASSERT(fLoopCount == 0);
187 SkASSERT(fConditionCount == 0);
188 SkASSERT(fStackCount == 0);
189 }
190 this->write(ByteCodeInstruction::kReturn, 0);
191 this->write8(0);
192
193 result->fLocalCount = fLocals.size();
194 result->fConditionCount = fMaxConditionCount;
195 result->fLoopCount = fMaxLoopCount;
196 result->fStackCount = fMaxStackCount;
197
198 const Type& returnType = f.fDeclaration.fReturnType;
199 if (returnType != *fContext.fVoid_Type) {
200 result->fReturnCount = SlotCount(returnType);
201 }
202 fLocals.clear();
203 fFunction = nullptr;
204 return result;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400205}
206
Brian Osman0785db02019-05-24 14:19:11 -0400207// A "simple" Swizzle is based on a variable (or a compound variable like a struct or array), and
208// that references consecutive values, such that it can be implemented using normal load/store ops
209// with an offset. Note that all single-component swizzles (of suitable base types) are simple.
210static bool swizzle_is_simple(const Swizzle& s) {
211 switch (s.fBase->fKind) {
212 case Expression::kFieldAccess_Kind:
213 case Expression::kIndex_Kind:
214 case Expression::kVariableReference_Kind:
215 break;
216 default:
217 return false;
218 }
219
220 for (size_t i = 1; i < s.fComponents.size(); ++i) {
221 if (s.fComponents[i] != s.fComponents[i - 1] + 1) {
222 return false;
223 }
224 }
225 return true;
226}
227
Brian Osmanb08cc022020-04-02 11:38:40 -0400228int ByteCodeGenerator::StackUsage(ByteCodeInstruction inst, int count_) {
229 // Ensures that we use count iff we're passed a non-default value. Most instructions have an
230 // implicit count, so the caller shouldn't need to worry about it (or count makes no sense).
231 // The asserts avoids callers thinking they're supplying useful information in that scenario,
232 // or failing to supply necessary information for the ops that need a count.
233 struct CountValue {
234 operator int() {
235 SkASSERT(val != ByteCodeGenerator::kUnusedStackCount);
236 SkDEBUGCODE(used = true);
237 return val;
238 }
239 ~CountValue() {
240 SkASSERT(used || val == ByteCodeGenerator::kUnusedStackCount);
241 }
242 int val;
243 SkDEBUGCODE(bool used = false;)
244 } count = { count_ };
245
246 switch (inst) {
247 // Unary functions/operators that don't change stack depth at all:
248#define VECTOR_UNARY_OP(base) \
249 case ByteCodeInstruction::base: \
250 case ByteCodeInstruction::base ## 2: \
251 case ByteCodeInstruction::base ## 3: \
252 case ByteCodeInstruction::base ## 4: \
253 return 0;
254
255 VECTOR_UNARY_OP(kConvertFtoI)
256 VECTOR_UNARY_OP(kConvertStoF)
257 VECTOR_UNARY_OP(kConvertUtoF)
258
Mike Reed8520e762020-04-30 12:06:23 -0400259 VECTOR_UNARY_OP(kATan)
Brian Osmanb08cc022020-04-02 11:38:40 -0400260 VECTOR_UNARY_OP(kCos)
Mike Reed8520e762020-04-30 12:06:23 -0400261 VECTOR_UNARY_OP(kFract)
Brian Osmanb08cc022020-04-02 11:38:40 -0400262 VECTOR_UNARY_OP(kSin)
263 VECTOR_UNARY_OP(kSqrt)
264 VECTOR_UNARY_OP(kTan)
265
266 VECTOR_UNARY_OP(kNegateF)
267 VECTOR_UNARY_OP(kNegateI)
Brian Osman8842b372020-05-01 15:07:49 -0400268 VECTOR_UNARY_OP(kNotB)
Brian Osmanb08cc022020-04-02 11:38:40 -0400269
270 case ByteCodeInstruction::kInverse2x2:
271 case ByteCodeInstruction::kInverse3x3:
272 case ByteCodeInstruction::kInverse4x4: return 0;
273
274 case ByteCodeInstruction::kClampIndex: return 0;
Brian Osmanb08cc022020-04-02 11:38:40 -0400275 case ByteCodeInstruction::kNegateFN: return 0;
276 case ByteCodeInstruction::kShiftLeft: return 0;
277 case ByteCodeInstruction::kShiftRightS: return 0;
278 case ByteCodeInstruction::kShiftRightU: return 0;
279
280#undef VECTOR_UNARY_OP
281
282 // Binary functions/operators that do a 2 -> 1 reduction (possibly N times)
283#define VECTOR_BINARY_OP(base) \
284 case ByteCodeInstruction::base: return -1; \
285 case ByteCodeInstruction::base ## 2: return -2; \
286 case ByteCodeInstruction::base ## 3: return -3; \
287 case ByteCodeInstruction::base ## 4: return -4;
288
289#define VECTOR_MATRIX_BINARY_OP(base) \
290 VECTOR_BINARY_OP(base) \
291 case ByteCodeInstruction::base ## N: return -count;
292
293 case ByteCodeInstruction::kAndB: return -1;
294 case ByteCodeInstruction::kOrB: return -1;
295 case ByteCodeInstruction::kXorB: return -1;
296
297 VECTOR_BINARY_OP(kAddI)
298 VECTOR_MATRIX_BINARY_OP(kAddF)
299
300 VECTOR_BINARY_OP(kCompareIEQ)
301 VECTOR_MATRIX_BINARY_OP(kCompareFEQ)
302 VECTOR_BINARY_OP(kCompareINEQ)
303 VECTOR_MATRIX_BINARY_OP(kCompareFNEQ)
304 VECTOR_BINARY_OP(kCompareSGT)
305 VECTOR_BINARY_OP(kCompareUGT)
306 VECTOR_BINARY_OP(kCompareFGT)
307 VECTOR_BINARY_OP(kCompareSGTEQ)
308 VECTOR_BINARY_OP(kCompareUGTEQ)
309 VECTOR_BINARY_OP(kCompareFGTEQ)
310 VECTOR_BINARY_OP(kCompareSLT)
311 VECTOR_BINARY_OP(kCompareULT)
312 VECTOR_BINARY_OP(kCompareFLT)
313 VECTOR_BINARY_OP(kCompareSLTEQ)
314 VECTOR_BINARY_OP(kCompareULTEQ)
315 VECTOR_BINARY_OP(kCompareFLTEQ)
316
317 VECTOR_BINARY_OP(kDivideS)
318 VECTOR_BINARY_OP(kDivideU)
319 VECTOR_MATRIX_BINARY_OP(kDivideF)
Brian Osmand5f937b2020-05-04 12:07:29 -0400320 VECTOR_BINARY_OP(kMaxF)
321 VECTOR_BINARY_OP(kMaxS)
322 VECTOR_BINARY_OP(kMinF)
323 VECTOR_BINARY_OP(kMinS)
Brian Osmanb08cc022020-04-02 11:38:40 -0400324 VECTOR_BINARY_OP(kMultiplyI)
325 VECTOR_MATRIX_BINARY_OP(kMultiplyF)
Florin Malita3facc9c2020-05-04 09:26:15 -0400326 VECTOR_BINARY_OP(kPow)
Brian Osmanb08cc022020-04-02 11:38:40 -0400327 VECTOR_BINARY_OP(kRemainderF)
328 VECTOR_BINARY_OP(kRemainderS)
329 VECTOR_BINARY_OP(kRemainderU)
330 VECTOR_BINARY_OP(kSubtractI)
331 VECTOR_MATRIX_BINARY_OP(kSubtractF)
332
333#undef VECTOR_BINARY_OP
334#undef VECTOR_MATRIX_BINARY_OP
335
336 // Ops that push or load data to grow the stack:
337 case ByteCodeInstruction::kDup:
338 case ByteCodeInstruction::kLoad:
339 case ByteCodeInstruction::kLoadGlobal:
340 case ByteCodeInstruction::kLoadUniform:
341 case ByteCodeInstruction::kReadExternal:
342 case ByteCodeInstruction::kPushImmediate:
343 return 1;
344
345 case ByteCodeInstruction::kDup2:
346 case ByteCodeInstruction::kLoad2:
347 case ByteCodeInstruction::kLoadGlobal2:
348 case ByteCodeInstruction::kLoadUniform2:
349 case ByteCodeInstruction::kReadExternal2:
350 return 2;
351
352 case ByteCodeInstruction::kDup3:
353 case ByteCodeInstruction::kLoad3:
354 case ByteCodeInstruction::kLoadGlobal3:
355 case ByteCodeInstruction::kLoadUniform3:
356 case ByteCodeInstruction::kReadExternal3:
357 return 3;
358
359 case ByteCodeInstruction::kDup4:
360 case ByteCodeInstruction::kLoad4:
361 case ByteCodeInstruction::kLoadGlobal4:
362 case ByteCodeInstruction::kLoadUniform4:
363 case ByteCodeInstruction::kReadExternal4:
364 return 4;
365
366 case ByteCodeInstruction::kDupN:
367 case ByteCodeInstruction::kLoadSwizzle:
368 case ByteCodeInstruction::kLoadSwizzleGlobal:
369 case ByteCodeInstruction::kLoadSwizzleUniform:
370 return count;
371
372 // Pushes 'count' values, minus one for the 'address' that's consumed first
373 case ByteCodeInstruction::kLoadExtended:
374 case ByteCodeInstruction::kLoadExtendedGlobal:
375 case ByteCodeInstruction::kLoadExtendedUniform:
376 return count - 1;
377
378 // Ops that pop or store data to shrink the stack:
379 case ByteCodeInstruction::kPop:
380 case ByteCodeInstruction::kStore:
381 case ByteCodeInstruction::kStoreGlobal:
382 case ByteCodeInstruction::kWriteExternal:
383 return -1;
384
385 case ByteCodeInstruction::kPop2:
386 case ByteCodeInstruction::kStore2:
387 case ByteCodeInstruction::kStoreGlobal2:
388 case ByteCodeInstruction::kWriteExternal2:
389 return -2;
390
391 case ByteCodeInstruction::kPop3:
392 case ByteCodeInstruction::kStore3:
393 case ByteCodeInstruction::kStoreGlobal3:
394 case ByteCodeInstruction::kWriteExternal3:
395 return -3;
396
397 case ByteCodeInstruction::kPop4:
398 case ByteCodeInstruction::kStore4:
399 case ByteCodeInstruction::kStoreGlobal4:
400 case ByteCodeInstruction::kWriteExternal4:
401 return -4;
402
403 case ByteCodeInstruction::kPopN:
404 case ByteCodeInstruction::kStoreSwizzle:
405 case ByteCodeInstruction::kStoreSwizzleGlobal:
406 return -count;
407
408 // Consumes 'count' values, plus one for the 'address'
409 case ByteCodeInstruction::kStoreExtended:
410 case ByteCodeInstruction::kStoreExtendedGlobal:
411 case ByteCodeInstruction::kStoreSwizzleIndirect:
412 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal:
413 return -count - 1;
414
415 // Strange ops where the caller computes the delta for us:
416 case ByteCodeInstruction::kCallExternal:
417 case ByteCodeInstruction::kMatrixToMatrix:
418 case ByteCodeInstruction::kMatrixMultiply:
419 case ByteCodeInstruction::kReserve:
420 case ByteCodeInstruction::kReturn:
421 case ByteCodeInstruction::kScalarToMatrix:
422 case ByteCodeInstruction::kSwizzle:
423 return count;
424
425 // Miscellaneous
426
Brian Osmana43d8202020-06-17 16:50:39 -0400427 // (X, Y) -> (R, G, B, A)
428 case ByteCodeInstruction::kSampleExplicit: return 4 - 2;
429 // (float3x3) -> (R, G, B, A)
430 case ByteCodeInstruction::kSampleMatrix: return 4 - 9;
431
Brian Osman8842b372020-05-01 15:07:49 -0400432 // kMix does a 3 -> 1 reduction (A, B, M -> A -or- B) for each component
433 case ByteCodeInstruction::kMix: return -2;
434 case ByteCodeInstruction::kMix2: return -4;
435 case ByteCodeInstruction::kMix3: return -6;
436 case ByteCodeInstruction::kMix4: return -8;
437
438 // kLerp works the same way (producing lerp(A, B, T) for each component)
439 case ByteCodeInstruction::kLerp: return -2;
440 case ByteCodeInstruction::kLerp2: return -4;
441 case ByteCodeInstruction::kLerp3: return -6;
442 case ByteCodeInstruction::kLerp4: return -8;
443
Brian Osmanb08cc022020-04-02 11:38:40 -0400444 // kCall is net-zero. Max stack depth is adjusted in writeFunctionCall.
445 case ByteCodeInstruction::kCall: return 0;
446 case ByteCodeInstruction::kBranch: return 0;
447 case ByteCodeInstruction::kBranchIfAllFalse: return 0;
448
449 case ByteCodeInstruction::kMaskPush: return -1;
450 case ByteCodeInstruction::kMaskPop: return 0;
451 case ByteCodeInstruction::kMaskNegate: return 0;
452 case ByteCodeInstruction::kMaskBlend: return -count;
453
454 case ByteCodeInstruction::kLoopBegin: return 0;
455 case ByteCodeInstruction::kLoopNext: return 0;
456 case ByteCodeInstruction::kLoopMask: return -1;
457 case ByteCodeInstruction::kLoopEnd: return 0;
458 case ByteCodeInstruction::kLoopBreak: return 0;
459 case ByteCodeInstruction::kLoopContinue: return 0;
Brian Osmanb08cc022020-04-02 11:38:40 -0400460 }
Brian Osmand5f937b2020-05-04 12:07:29 -0400461
462 SkUNREACHABLE;
Brian Osmanb08cc022020-04-02 11:38:40 -0400463}
464
465ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var) {
466 // given that we seldom have more than a couple of variables, linear search is probably the most
467 // efficient way to handle lookups
468 switch (var.fStorage) {
469 case Variable::kLocal_Storage: {
470 for (int i = fLocals.size() - 1; i >= 0; --i) {
471 if (fLocals[i] == &var) {
472 SkASSERT(fParameterCount + i <= 255);
473 return { fParameterCount + i, Storage::kLocal };
474 }
475 }
476 int result = fParameterCount + fLocals.size();
477 fLocals.push_back(&var);
478 for (int i = 0; i < SlotCount(var.fType) - 1; ++i) {
479 fLocals.push_back(nullptr);
480 }
481 SkASSERT(result <= 255);
482 return { result, Storage::kLocal };
483 }
484 case Variable::kParameter_Storage: {
485 int offset = 0;
486 for (const auto& p : fFunction->fDeclaration.fParameters) {
487 if (p == &var) {
488 SkASSERT(offset <= 255);
489 return { offset, Storage::kLocal };
490 }
491 offset += SlotCount(p->fType);
492 }
493 SkASSERT(false);
494 return Location::MakeInvalid();
495 }
496 case Variable::kGlobal_Storage: {
Brian Osmana43d8202020-06-17 16:50:39 -0400497 if (var.fType == *fContext.fFragmentProcessor_Type) {
498 int offset = 0;
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->fType != *fContext.fFragmentProcessor_Type) {
505 continue;
506 }
507 if (declVar == &var) {
508 SkASSERT(offset <= 255);
509 return { offset, Storage::kChildFP };
510 }
511 offset++;
512 }
513 }
514 }
515 SkASSERT(false);
516 return Location::MakeInvalid();
517 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400518 if (is_in(var)) {
519 // If you see this error, it means the program is using raw 'in' variables. You
520 // should either specialize the program (Compiler::specialize) to bake in the final
521 // values of the 'in' variables, or not use 'in' variables (maybe you meant to use
522 // 'uniform' instead?).
523 fErrors.error(var.fOffset,
524 "'in' variable is not specialized or has unsupported type");
525 return Location::MakeInvalid();
526 }
527 int offset = 0;
528 bool isUniform = is_uniform(var);
529 for (const auto& e : fProgram) {
530 if (e.fKind == ProgramElement::kVar_Kind) {
531 VarDeclarations& decl = (VarDeclarations&) e;
532 for (const auto& v : decl.fVars) {
533 const Variable* declVar = ((VarDeclaration&) *v).fVar;
534 if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
535 continue;
536 }
537 if (isUniform != is_uniform(*declVar)) {
538 continue;
539 }
540 if (declVar == &var) {
541 SkASSERT(offset <= 255);
542 return { offset, isUniform ? Storage::kUniform : Storage::kGlobal };
543 }
544 offset += SlotCount(declVar->fType);
545 }
546 }
547 }
548 SkASSERT(false);
549 return Location::MakeInvalid();
550 }
551 default:
552 SkASSERT(false);
553 return Location::MakeInvalid();
554 }
555}
556
Brian Osman1c110a02019-10-01 14:53:32 -0400557ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Expression& expr) {
Brian Osman07c117b2019-05-23 12:51:06 -0700558 switch (expr.fKind) {
559 case Expression::kFieldAccess_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400560 const FieldAccess& f = (const FieldAccess&)expr;
561 Location baseLoc = this->getLocation(*f.fBase);
Brian Osman07c117b2019-05-23 12:51:06 -0700562 int offset = 0;
563 for (int i = 0; i < f.fFieldIndex; ++i) {
564 offset += SlotCount(*f.fBase->fType.fields()[i].fType);
565 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400566 if (baseLoc.isOnStack()) {
567 if (offset != 0) {
568 this->write(ByteCodeInstruction::kPushImmediate);
569 this->write32(offset);
570 this->write(ByteCodeInstruction::kAddI);
Ben Wagner470e0ac2020-01-22 16:59:21 -0500571 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400572 return baseLoc;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500573 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400574 return baseLoc + offset;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500575 }
Ben Wagner470e0ac2020-01-22 16:59:21 -0500576 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400577 case Expression::kIndex_Kind: {
578 const IndexExpression& i = (const IndexExpression&)expr;
579 int stride = SlotCount(i.fType);
580 int length = i.fBase->fType.columns();
581 SkASSERT(length <= 255);
582 int offset = -1;
583 if (i.fIndex->isConstant()) {
584 int64_t index = i.fIndex->getConstantInt();
585 if (index < 0 || index >= length) {
586 fErrors.error(i.fIndex->fOffset, "Array index out of bounds.");
587 return Location::MakeInvalid();
588 }
589 offset = index * stride;
590 } else {
591 if (i.fIndex->hasSideEffects()) {
592 // Having a side-effect in an indexer is technically safe for an rvalue,
593 // but with lvalues we have to evaluate the indexer twice, so make it an error.
594 fErrors.error(i.fIndex->fOffset,
595 "Index expressions with side-effects not supported in byte code.");
596 return Location::MakeInvalid();
597 }
598 this->writeExpression(*i.fIndex);
599 this->write(ByteCodeInstruction::kClampIndex);
600 this->write8(length);
601 if (stride != 1) {
602 this->write(ByteCodeInstruction::kPushImmediate);
603 this->write32(stride);
604 this->write(ByteCodeInstruction::kMultiplyI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400605 }
606 }
607 Location baseLoc = this->getLocation(*i.fBase);
608
609 // Are both components known statically?
610 if (!baseLoc.isOnStack() && offset >= 0) {
611 return baseLoc + offset;
612 }
613
614 // At least one component is dynamic (and on the stack).
615
616 // If the other component is zero, we're done
617 if (baseLoc.fSlot == 0 || offset == 0) {
618 return baseLoc.makeOnStack();
619 }
620
621 // Push the non-dynamic component (if any) to the stack, then add the two
622 if (!baseLoc.isOnStack()) {
623 this->write(ByteCodeInstruction::kPushImmediate);
624 this->write32(baseLoc.fSlot);
625 }
626 if (offset >= 0) {
627 this->write(ByteCodeInstruction::kPushImmediate);
628 this->write32(offset);
629 }
630 this->write(ByteCodeInstruction::kAddI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400631 return baseLoc.makeOnStack();
632 }
Brian Osman0785db02019-05-24 14:19:11 -0400633 case Expression::kSwizzle_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400634 const Swizzle& s = (const Swizzle&)expr;
Brian Osman0785db02019-05-24 14:19:11 -0400635 SkASSERT(swizzle_is_simple(s));
Brian Osmanb08cc022020-04-02 11:38:40 -0400636 Location baseLoc = this->getLocation(*s.fBase);
637 int offset = s.fComponents[0];
638 if (baseLoc.isOnStack()) {
639 if (offset != 0) {
640 this->write(ByteCodeInstruction::kPushImmediate);
641 this->write32(offset);
642 this->write(ByteCodeInstruction::kAddI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400643 }
644 return baseLoc;
645 } else {
646 return baseLoc + offset;
647 }
Brian Osman0785db02019-05-24 14:19:11 -0400648 }
Brian Osman07c117b2019-05-23 12:51:06 -0700649 case Expression::kVariableReference_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400650 const Variable& var = ((const VariableReference&)expr).fVariable;
Brian Osman07c117b2019-05-23 12:51:06 -0700651 return this->getLocation(var);
652 }
653 default:
654 SkASSERT(false);
Brian Osmanb08cc022020-04-02 11:38:40 -0400655 return Location::MakeInvalid();
Brian Osman07c117b2019-05-23 12:51:06 -0700656 }
657}
658
Brian Osmanb08cc022020-04-02 11:38:40 -0400659void ByteCodeGenerator::write8(uint8_t b) {
660 fCode->push_back(b);
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500661}
662
Brian Osmanb08cc022020-04-02 11:38:40 -0400663void ByteCodeGenerator::write16(uint16_t i) {
664 size_t n = fCode->size();
665 fCode->resize(n+2);
666 memcpy(fCode->data() + n, &i, 2);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500667}
Ben Wagner470e0ac2020-01-22 16:59:21 -0500668
Brian Osmanb08cc022020-04-02 11:38:40 -0400669void ByteCodeGenerator::write32(uint32_t i) {
670 size_t n = fCode->size();
671 fCode->resize(n+4);
672 memcpy(fCode->data() + n, &i, 4);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500673}
674
Brian Osmanb08cc022020-04-02 11:38:40 -0400675void ByteCodeGenerator::write(ByteCodeInstruction i, int count) {
676 switch (i) {
677 case ByteCodeInstruction::kLoopBegin: this->enterLoop(); break;
678 case ByteCodeInstruction::kLoopEnd: this->exitLoop(); break;
Ethan Nicholas2329da02020-01-24 15:49:33 -0500679
Brian Osmanb08cc022020-04-02 11:38:40 -0400680 case ByteCodeInstruction::kMaskPush: this->enterCondition(); break;
681 case ByteCodeInstruction::kMaskPop:
682 case ByteCodeInstruction::kMaskBlend: this->exitCondition(); break;
683 default: /* Do nothing */ break;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500684 }
Brian Osmanab8f3842020-04-07 09:30:44 -0400685 this->write16((uint16_t)i);
Brian Osmanb08cc022020-04-02 11:38:40 -0400686 fStackCount += StackUsage(i, count);
687 fMaxStackCount = std::max(fMaxStackCount, fStackCount);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500688}
689
Brian Osmanb08cc022020-04-02 11:38:40 -0400690static ByteCodeInstruction vector_instruction(ByteCodeInstruction base, int count) {
691 SkASSERT(count >= 1 && count <= 4);
692 return ((ByteCodeInstruction) ((int) base + 1 - count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500693}
694
Brian Osmanb08cc022020-04-02 11:38:40 -0400695void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
696 ByteCodeInstruction u, ByteCodeInstruction f,
Brian Osmanab8f3842020-04-07 09:30:44 -0400697 int count) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500698 switch (type_category(type)) {
Brian Osman8842b372020-05-01 15:07:49 -0400699 case TypeCategory::kBool:
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500700 case TypeCategory::kSigned:
Brian Osmanb08cc022020-04-02 11:38:40 -0400701 this->write(vector_instruction(s, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500702 break;
703 case TypeCategory::kUnsigned:
Brian Osmanb08cc022020-04-02 11:38:40 -0400704 this->write(vector_instruction(u, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500705 break;
706 case TypeCategory::kFloat: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400707 if (count > 4) {
708 this->write((ByteCodeInstruction)((int)f + 1), count);
Brian Osmanab8f3842020-04-07 09:30:44 -0400709 this->write8(count);
Brian Osmanb08cc022020-04-02 11:38:40 -0400710 } else {
711 this->write(vector_instruction(f, count));
712 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500713 break;
714 }
715 default:
716 SkASSERT(false);
717 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500718}
719
Brian Osmanb08cc022020-04-02 11:38:40 -0400720bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool discard) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400721 if (b.fOperator == Token::Kind::TK_EQ) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500722 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
Brian Osmanb08cc022020-04-02 11:38:40 -0400723 this->writeExpression(*b.fRight);
724 lvalue->store(discard);
725 discard = false;
726 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500727 }
728 const Type& lType = b.fLeft->fType;
729 const Type& rType = b.fRight->fType;
730 bool lVecOrMtx = (lType.kind() == Type::kVector_Kind || lType.kind() == Type::kMatrix_Kind);
731 bool rVecOrMtx = (rType.kind() == Type::kVector_Kind || rType.kind() == Type::kMatrix_Kind);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500732 Token::Kind op;
733 std::unique_ptr<LValue> lvalue;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500734 if (is_assignment(b.fOperator)) {
735 lvalue = this->getLValue(*b.fLeft);
Brian Osmanb08cc022020-04-02 11:38:40 -0400736 lvalue->load();
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500737 op = remove_assignment(b.fOperator);
738 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400739 this->writeExpression(*b.fLeft);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500740 op = b.fOperator;
741 if (!lVecOrMtx && rVecOrMtx) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400742 for (int i = SlotCount(rType); i > 1; --i) {
743 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400744 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500745 }
746 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500747 int count = std::max(SlotCount(lType), SlotCount(rType));
Brian Osmanb08cc022020-04-02 11:38:40 -0400748 SkDEBUGCODE(TypeCategory tc = type_category(lType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500749 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400750 case Token::Kind::TK_LOGICALAND: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400751 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
752 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400753 this->write(ByteCodeInstruction::kMaskPush);
754 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500755 DeferredLocation falseLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -0400756 this->writeExpression(*b.fRight);
757 this->write(ByteCodeInstruction::kAndB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500758 falseLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -0400759 this->write(ByteCodeInstruction::kMaskPop);
760 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500761 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400762 case Token::Kind::TK_LOGICALOR: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400763 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
764 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400765 this->write(ByteCodeInstruction::kNotB);
766 this->write(ByteCodeInstruction::kMaskPush);
767 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500768 DeferredLocation falseLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -0400769 this->writeExpression(*b.fRight);
770 this->write(ByteCodeInstruction::kOrB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500771 falseLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -0400772 this->write(ByteCodeInstruction::kMaskPop);
773 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500774 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400775 case Token::Kind::TK_SHL:
776 case Token::Kind::TK_SHR: {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500777 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
778 tc == SkSL::TypeCategory::kUnsigned));
779 if (!b.fRight->isConstant()) {
780 fErrors.error(b.fRight->fOffset, "Shift amounts must be constant");
Brian Osmanb08cc022020-04-02 11:38:40 -0400781 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500782 }
783 int64_t shift = b.fRight->getConstantInt();
784 if (shift < 0 || shift > 31) {
785 fErrors.error(b.fRight->fOffset, "Shift amount out of range");
Brian Osmanb08cc022020-04-02 11:38:40 -0400786 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500787 }
788
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400789 if (op == Token::Kind::TK_SHL) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400790 this->write(ByteCodeInstruction::kShiftLeft);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500791 } else {
792 this->write(type_category(lType) == TypeCategory::kSigned
Brian Osmanb08cc022020-04-02 11:38:40 -0400793 ? ByteCodeInstruction::kShiftRightS
794 : ByteCodeInstruction::kShiftRightU);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500795 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400796 this->write8(shift);
797 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500798 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500799
800 default:
801 break;
802 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400803 this->writeExpression(*b.fRight);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500804 if (lVecOrMtx && !rVecOrMtx) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400805 for (int i = SlotCount(lType); i > 1; --i) {
806 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400807 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500808 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400809 // Special case for M*V, V*M, M*M (but not V*V!)
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400810 if (op == Token::Kind::TK_STAR && lVecOrMtx && rVecOrMtx &&
Brian Osmanb08cc022020-04-02 11:38:40 -0400811 !(lType.kind() == Type::kVector_Kind && rType.kind() == Type::kVector_Kind)) {
812 this->write(ByteCodeInstruction::kMatrixMultiply,
813 SlotCount(b.fType) - (SlotCount(lType) + SlotCount(rType)));
814 int rCols = rType.columns(),
815 rRows = rType.rows(),
816 lCols = lType.columns(),
817 lRows = lType.rows();
818 // M*V treats the vector as a column
819 if (rType.kind() == Type::kVector_Kind) {
820 std::swap(rCols, rRows);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500821 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400822 SkASSERT(lCols == rRows);
823 SkASSERT(SlotCount(b.fType) == lRows * rCols);
824 this->write8(lCols);
825 this->write8(lRows);
826 this->write8(rCols);
827 } else {
828 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400829 case Token::Kind::TK_EQEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400830 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareIEQ,
831 ByteCodeInstruction::kCompareIEQ,
832 ByteCodeInstruction::kCompareFEQ,
833 count);
834 // Collapse to a single bool
835 for (int i = count; i > 1; --i) {
836 this->write(ByteCodeInstruction::kAndB);
837 }
838 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400839 case Token::Kind::TK_GT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400840 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGT,
841 ByteCodeInstruction::kCompareUGT,
842 ByteCodeInstruction::kCompareFGT,
843 count);
844 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400845 case Token::Kind::TK_GTEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400846 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGTEQ,
847 ByteCodeInstruction::kCompareUGTEQ,
848 ByteCodeInstruction::kCompareFGTEQ,
849 count);
850 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400851 case Token::Kind::TK_LT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400852 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLT,
853 ByteCodeInstruction::kCompareULT,
854 ByteCodeInstruction::kCompareFLT,
855 count);
856 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400857 case Token::Kind::TK_LTEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400858 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLTEQ,
859 ByteCodeInstruction::kCompareULTEQ,
860 ByteCodeInstruction::kCompareFLTEQ,
861 count);
862 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400863 case Token::Kind::TK_MINUS:
Brian Osmanb08cc022020-04-02 11:38:40 -0400864 this->writeTypedInstruction(lType, ByteCodeInstruction::kSubtractI,
865 ByteCodeInstruction::kSubtractI,
866 ByteCodeInstruction::kSubtractF,
867 count);
868 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400869 case Token::Kind::TK_NEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400870 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareINEQ,
871 ByteCodeInstruction::kCompareINEQ,
872 ByteCodeInstruction::kCompareFNEQ,
873 count);
874 // Collapse to a single bool
875 for (int i = count; i > 1; --i) {
876 this->write(ByteCodeInstruction::kOrB);
877 }
878 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400879 case Token::Kind::TK_PERCENT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400880 this->writeTypedInstruction(lType, ByteCodeInstruction::kRemainderS,
881 ByteCodeInstruction::kRemainderU,
882 ByteCodeInstruction::kRemainderF,
883 count);
884 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400885 case Token::Kind::TK_PLUS:
Brian Osmanb08cc022020-04-02 11:38:40 -0400886 this->writeTypedInstruction(lType, ByteCodeInstruction::kAddI,
887 ByteCodeInstruction::kAddI,
888 ByteCodeInstruction::kAddF,
889 count);
890 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400891 case Token::Kind::TK_SLASH:
Brian Osmanb08cc022020-04-02 11:38:40 -0400892 this->writeTypedInstruction(lType, ByteCodeInstruction::kDivideS,
893 ByteCodeInstruction::kDivideU,
894 ByteCodeInstruction::kDivideF,
895 count);
896 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400897 case Token::Kind::TK_STAR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400898 this->writeTypedInstruction(lType, ByteCodeInstruction::kMultiplyI,
899 ByteCodeInstruction::kMultiplyI,
900 ByteCodeInstruction::kMultiplyF,
901 count);
902 break;
903
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400904 case Token::Kind::TK_LOGICALXOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400905 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
906 this->write(ByteCodeInstruction::kXorB);
907 break;
908
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400909 case Token::Kind::TK_BITWISEAND:
Brian Osmanb08cc022020-04-02 11:38:40 -0400910 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
911 tc == SkSL::TypeCategory::kUnsigned));
912 this->write(ByteCodeInstruction::kAndB);
913 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400914 case Token::Kind::TK_BITWISEOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400915 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
916 tc == SkSL::TypeCategory::kUnsigned));
917 this->write(ByteCodeInstruction::kOrB);
918 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400919 case Token::Kind::TK_BITWISEXOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400920 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
921 tc == SkSL::TypeCategory::kUnsigned));
922 this->write(ByteCodeInstruction::kXorB);
923 break;
924
925 default:
926 fErrors.error(b.fOffset, SkSL::String::printf("Unsupported binary operator '%s'",
927 Compiler::OperatorName(op)));
928 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500929 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500930 }
931 if (lvalue) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400932 lvalue->store(discard);
933 discard = false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500934 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400935 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500936}
937
Brian Osmanb08cc022020-04-02 11:38:40 -0400938void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
939 this->write(ByteCodeInstruction::kPushImmediate);
940 this->write32(b.fValue ? ~0 : 0);
941}
942
943void ByteCodeGenerator::writeConstructor(const Constructor& c) {
944 for (const auto& arg : c.fArguments) {
945 this->writeExpression(*arg);
946 }
947 if (c.fArguments.size() == 1) {
948 const Type& inType = c.fArguments[0]->fType;
949 const Type& outType = c.fType;
950 TypeCategory inCategory = type_category(inType);
951 TypeCategory outCategory = type_category(outType);
952 int inCount = SlotCount(inType);
953 int outCount = SlotCount(outType);
954 if (inCategory != outCategory) {
955 SkASSERT(inCount == outCount);
956 if (inCategory == TypeCategory::kFloat) {
957 SkASSERT(outCategory == TypeCategory::kSigned ||
958 outCategory == TypeCategory::kUnsigned);
959 this->write(vector_instruction(ByteCodeInstruction::kConvertFtoI, outCount));
960 } else if (outCategory == TypeCategory::kFloat) {
961 if (inCategory == TypeCategory::kSigned) {
962 this->write(vector_instruction(ByteCodeInstruction::kConvertStoF, outCount));
963 } else {
964 SkASSERT(inCategory == TypeCategory::kUnsigned);
965 this->write(vector_instruction(ByteCodeInstruction::kConvertUtoF, outCount));
966 }
967 } else {
968 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500969 }
970 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400971 if (inType.kind() == Type::kMatrix_Kind && outType.kind() == Type::kMatrix_Kind) {
972 this->write(ByteCodeInstruction::kMatrixToMatrix,
973 SlotCount(outType) - SlotCount(inType));
974 this->write8(inType.columns());
975 this->write8(inType.rows());
976 this->write8(outType.columns());
977 this->write8(outType.rows());
978 } else if (inCount != outCount) {
979 SkASSERT(inCount == 1);
980 if (outType.kind() == Type::kMatrix_Kind) {
981 this->write(ByteCodeInstruction::kScalarToMatrix, SlotCount(outType) - 1);
982 this->write8(outType.columns());
983 this->write8(outType.rows());
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500984 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400985 SkASSERT(outType.kind() == Type::kVector_Kind);
986 for (; inCount != outCount; ++inCount) {
987 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400988 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500989 }
990 }
991 }
992}
993
Brian Osmanb08cc022020-04-02 11:38:40 -0400994void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500995 int argumentCount = 0;
996 for (const auto& arg : f.fArguments) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400997 this->writeExpression(*arg);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500998 argumentCount += SlotCount(arg->fType);
999 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001000 this->write(ByteCodeInstruction::kCallExternal, SlotCount(f.fType) - argumentCount);
1001 SkASSERT(argumentCount <= 255);
1002 this->write8(argumentCount);
1003 this->write8(SlotCount(f.fType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001004 int index = fOutput->fExternalValues.size();
1005 fOutput->fExternalValues.push_back(f.fFunction);
1006 SkASSERT(index <= 255);
Brian Osmanb08cc022020-04-02 11:38:40 -04001007 this->write8(index);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001008}
1009
Brian Osmanb08cc022020-04-02 11:38:40 -04001010void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
1011 int count = SlotCount(e.fValue->type());
1012 this->write(vector_instruction(ByteCodeInstruction::kReadExternal, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001013 int index = fOutput->fExternalValues.size();
1014 fOutput->fExternalValues.push_back(e.fValue);
1015 SkASSERT(index <= 255);
Brian Osmanb08cc022020-04-02 11:38:40 -04001016 this->write8(index);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001017}
1018
Brian Osmanb08cc022020-04-02 11:38:40 -04001019void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
1020 Location location = this->getLocation(expr);
1021 int count = SlotCount(expr.fType);
Brian Osmanefb08402020-04-13 16:30:44 -04001022 if (count == 0) {
1023 return;
1024 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001025 if (location.isOnStack() || count > 4) {
1026 if (!location.isOnStack()) {
1027 this->write(ByteCodeInstruction::kPushImmediate);
1028 this->write32(location.fSlot);
1029 }
1030 this->write(location.selectLoad(ByteCodeInstruction::kLoadExtended,
1031 ByteCodeInstruction::kLoadExtendedGlobal,
1032 ByteCodeInstruction::kLoadExtendedUniform),
1033 count);
1034 this->write8(count);
1035 } else {
1036 this->write(vector_instruction(location.selectLoad(ByteCodeInstruction::kLoad,
1037 ByteCodeInstruction::kLoadGlobal,
1038 ByteCodeInstruction::kLoadUniform),
1039 count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001040 this->write8(location.fSlot);
1041 }
1042}
1043
1044static inline uint32_t float_to_bits(float x) {
1045 uint32_t u;
1046 memcpy(&u, &x, sizeof(uint32_t));
1047 return u;
1048}
1049
1050void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
1051 this->write(ByteCodeInstruction::kPushImmediate);
1052 this->write32(float_to_bits(f.fValue));
1053}
1054
Brian Osman8842b372020-05-01 15:07:49 -04001055static bool is_generic_type(const Type* type, const Type* generic) {
1056 const std::vector<const Type*>& concrete(generic->coercibleTypes());
1057 return std::find(concrete.begin(), concrete.end(), type) != concrete.end();
1058}
1059
Brian Osmanb08cc022020-04-02 11:38:40 -04001060void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
1061 auto found = fIntrinsics.find(c.fFunction.fName);
1062 if (found == fIntrinsics.end()) {
1063 fErrors.error(c.fOffset, String::printf("Unsupported intrinsic: '%s'",
1064 String(c.fFunction.fName).c_str()));
1065 return;
1066 }
Mike Klein45be0772020-05-01 09:13:18 -05001067 Intrinsic intrin = found->second;
Brian Osmanb08cc022020-04-02 11:38:40 -04001068 int count = SlotCount(c.fArguments[0]->fType);
Brian Osmand5f937b2020-05-04 12:07:29 -04001069
1070 // Several intrinsics have variants where one argument is either scalar, or the same size as
1071 // the first argument. Call dupSmallerType(SlotCount(argType)) to ensure equal component count.
1072 auto dupSmallerType = [count, this](int smallCount) {
1073 SkASSERT(smallCount == 1 || smallCount == count);
1074 for (int i = smallCount; i < count; ++i) {
1075 this->write(ByteCodeInstruction::kDup);
1076 }
1077 };
1078
Brian Osmana43d8202020-06-17 16:50:39 -04001079 if (intrin.is_special && intrin.special == SpecialIntrinsic::kSample) {
1080 // Sample is very special, the first argument is an FP, which can't be pushed to the stack
1081 if (c.fArguments.size() != 2 ||
1082 c.fArguments[0]->fType != *fContext.fFragmentProcessor_Type ||
1083 (c.fArguments[1]->fType != *fContext.fFloat2_Type &&
1084 c.fArguments[1]->fType != *fContext.fFloat3x3_Type)) {
1085 fErrors.error(c.fOffset, "Unsupported form of sample");
1086 return;
1087 }
1088
1089 // Write our coords or matrix
1090 this->writeExpression(*c.fArguments[1]);
1091
1092 this->write(c.fArguments[1]->fType == *fContext.fFloat3x3_Type
1093 ? ByteCodeInstruction::kSampleMatrix
1094 : ByteCodeInstruction::kSampleExplicit);
1095
1096 Location childLoc = this->getLocation(*c.fArguments[0]);
1097 SkASSERT(childLoc.fStorage == Storage::kChildFP);
1098 this->write8(childLoc.fSlot);
1099 return;
1100 }
1101
Brian Osmand5f937b2020-05-04 12:07:29 -04001102 if (intrin.is_special && (intrin.special == SpecialIntrinsic::kClamp ||
1103 intrin.special == SpecialIntrinsic::kSaturate)) {
1104 // These intrinsics are extra-special, we need instructions interleaved with arguments
1105 bool saturate = (intrin.special == SpecialIntrinsic::kSaturate);
1106 SkASSERT(c.fArguments.size() == (saturate ? 1 : 3));
1107 int limitCount = saturate ? 1 : SlotCount(c.fArguments[1]->fType);
1108
1109 // 'x'
1110 this->writeExpression(*c.fArguments[0]);
1111
1112 // 'minVal'
1113 if (saturate) {
1114 this->write(ByteCodeInstruction::kPushImmediate);
1115 this->write32(float_to_bits(0.0f));
1116 } else {
1117 this->writeExpression(*c.fArguments[1]);
1118 }
1119 dupSmallerType(limitCount);
1120 this->writeTypedInstruction(c.fArguments[0]->fType,
1121 ByteCodeInstruction::kMaxS,
1122 ByteCodeInstruction::kMaxS,
1123 ByteCodeInstruction::kMaxF,
1124 count);
1125
1126 // 'maxVal'
1127 if (saturate) {
1128 this->write(ByteCodeInstruction::kPushImmediate);
1129 this->write32(float_to_bits(1.0f));
1130 } else {
1131 SkASSERT(limitCount == SlotCount(c.fArguments[2]->fType));
1132 this->writeExpression(*c.fArguments[2]);
1133 }
1134 dupSmallerType(limitCount);
1135 this->writeTypedInstruction(c.fArguments[0]->fType,
1136 ByteCodeInstruction::kMinS,
1137 ByteCodeInstruction::kMinS,
1138 ByteCodeInstruction::kMinF,
1139 count);
1140 return;
1141 }
1142
1143 // All other intrinsics can handle their arguments being on the stack in order
1144 for (const auto& arg : c.fArguments) {
1145 this->writeExpression(*arg);
1146 }
1147
Mike Klein45be0772020-05-01 09:13:18 -05001148 if (intrin.is_special) {
1149 switch (intrin.special) {
Brian Osman8842b372020-05-01 15:07:49 -04001150 case SpecialIntrinsic::kAll: {
1151 for (int i = count-1; i --> 0;) {
1152 this->write(ByteCodeInstruction::kAndB);
1153 }
1154 } break;
1155
1156 case SpecialIntrinsic::kAny: {
1157 for (int i = count-1; i --> 0;) {
1158 this->write(ByteCodeInstruction::kOrB);
1159 }
1160 } break;
1161
Brian Osman15c98cb2020-02-27 18:36:57 +00001162 case SpecialIntrinsic::kDot: {
1163 SkASSERT(c.fArguments.size() == 2);
Brian Osmanb08cc022020-04-02 11:38:40 -04001164 SkASSERT(count == SlotCount(c.fArguments[1]->fType));
1165 this->write(vector_instruction(ByteCodeInstruction::kMultiplyF, count));
Mike Klein45be0772020-05-01 09:13:18 -05001166 for (int i = count-1; i --> 0;) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001167 this->write(ByteCodeInstruction::kAddF);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001168 }
Mike Klein45be0772020-05-01 09:13:18 -05001169 } break;
1170
1171 case SpecialIntrinsic::kLength: {
1172 SkASSERT(c.fArguments.size() == 1);
1173 this->write(vector_instruction(ByteCodeInstruction::kDup , count));
1174 this->write(vector_instruction(ByteCodeInstruction::kMultiplyF, count));
1175 for (int i = count-1; i --> 0;) {
1176 this->write(ByteCodeInstruction::kAddF);
1177 }
1178 this->write(ByteCodeInstruction::kSqrt);
1179 } break;
1180
Brian Osmand5f937b2020-05-04 12:07:29 -04001181 case SpecialIntrinsic::kMax:
1182 case SpecialIntrinsic::kMin: {
1183 SkASSERT(c.fArguments.size() == 2);
1184 // There are variants where the second argument is scalar
1185 dupSmallerType(SlotCount(c.fArguments[1]->fType));
1186 if (intrin.special == SpecialIntrinsic::kMax) {
1187 this->writeTypedInstruction(c.fArguments[0]->fType,
1188 ByteCodeInstruction::kMaxS,
1189 ByteCodeInstruction::kMaxS,
1190 ByteCodeInstruction::kMaxF,
1191 count);
1192 } else {
1193 this->writeTypedInstruction(c.fArguments[0]->fType,
1194 ByteCodeInstruction::kMinS,
1195 ByteCodeInstruction::kMinS,
1196 ByteCodeInstruction::kMinF,
1197 count);
1198 }
1199 } break;
1200
Brian Osman8842b372020-05-01 15:07:49 -04001201 case SpecialIntrinsic::kMix: {
1202 // Two main variants of mix to handle
1203 SkASSERT(c.fArguments.size() == 3);
1204 SkASSERT(count == SlotCount(c.fArguments[1]->fType));
1205 int selectorCount = SlotCount(c.fArguments[2]->fType);
1206
1207 if (is_generic_type(&c.fArguments[2]->fType, fContext.fGenBType_Type.get())) {
1208 // mix(genType, genType, genBoolType)
1209 SkASSERT(selectorCount == count);
1210 this->write(vector_instruction(ByteCodeInstruction::kMix, count));
1211 } else {
1212 // mix(genType, genType, genType) or mix(genType, genType, float)
Brian Osmand5f937b2020-05-04 12:07:29 -04001213 dupSmallerType(selectorCount);
Brian Osman8842b372020-05-01 15:07:49 -04001214 this->write(vector_instruction(ByteCodeInstruction::kLerp, count));
1215 }
1216 } break;
1217
Brian Osmanb08cc022020-04-02 11:38:40 -04001218 default:
1219 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001220 }
1221 } else {
Brian Osman8842b372020-05-01 15:07:49 -04001222 switch (intrin.inst_f) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001223 case ByteCodeInstruction::kInverse2x2: {
1224 SkASSERT(c.fArguments.size() > 0);
1225 auto op = ByteCodeInstruction::kInverse2x2;
1226 switch (count) {
1227 case 4: break; // float2x2
1228 case 9: op = ByteCodeInstruction::kInverse3x3; break;
1229 case 16: op = ByteCodeInstruction::kInverse4x4; break;
1230 default: SkASSERT(false);
1231 }
1232 this->write(op);
1233 break;
Brian Osman15c98cb2020-02-27 18:36:57 +00001234 }
Mike Klein45be0772020-05-01 09:13:18 -05001235
Brian Osmanb08cc022020-04-02 11:38:40 -04001236 default:
Brian Osman8842b372020-05-01 15:07:49 -04001237 this->writeTypedInstruction(c.fArguments[0]->fType, intrin.inst_s, intrin.inst_u,
1238 intrin.inst_f, count);
1239 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001240 }
1241 }
1242}
1243
Brian Osmanb08cc022020-04-02 11:38:40 -04001244void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001245 // Find the index of the function we're calling. We explicitly do not allow calls to functions
1246 // before they're defined. This is an easy-to-understand rule that prevents recursion.
Brian Osmanb08cc022020-04-02 11:38:40 -04001247 int idx = -1;
1248 for (size_t i = 0; i < fFunctions.size(); ++i) {
1249 if (f.fFunction.matches(fFunctions[i]->fDeclaration)) {
1250 idx = i;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001251 break;
1252 }
1253 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001254 if (idx == -1) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001255 this->writeIntrinsicCall(f);
1256 return;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001257 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001258
1259
1260 if (idx > 255) {
1261 fErrors.error(f.fOffset, "Function count limit exceeded");
1262 return;
1263 } else if (idx >= (int) fFunctions.size()) {
1264 fErrors.error(f.fOffset, "Call to undefined function");
1265 return;
1266 }
1267
1268 // We may need to deal with out parameters, so the sequence is tricky
1269 if (int returnCount = SlotCount(f.fType)) {
1270 this->write(ByteCodeInstruction::kReserve, returnCount);
1271 this->write8(returnCount);
1272 }
1273
1274 int argCount = f.fArguments.size();
1275 std::vector<std::unique_ptr<LValue>> lvalues;
1276 for (int i = 0; i < argCount; ++i) {
1277 const auto& param = f.fFunction.fParameters[i];
1278 const auto& arg = f.fArguments[i];
1279 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1280 lvalues.emplace_back(this->getLValue(*arg));
1281 lvalues.back()->load();
1282 } else {
1283 this->writeExpression(*arg);
1284 }
1285 }
1286
1287 // The space used by the call is based on the callee, but it also unwinds all of that before
1288 // we continue execution. We adjust our max stack depths below.
1289 this->write(ByteCodeInstruction::kCall);
1290 this->write8(idx);
1291
1292 const ByteCodeFunction* callee = fOutput->fFunctions[idx].get();
1293 fMaxLoopCount = std::max(fMaxLoopCount, fLoopCount + callee->fLoopCount);
1294 fMaxConditionCount = std::max(fMaxConditionCount, fConditionCount + callee->fConditionCount);
1295 fMaxStackCount = std::max(fMaxStackCount, fStackCount + callee->fLocalCount
1296 + callee->fStackCount);
1297
1298 // After the called function returns, the stack will still contain our arguments. We have to
1299 // pop them (storing any out parameters back to their lvalues as we go). We glob together slot
1300 // counts for all parameters that aren't out-params, so we can pop them in one big chunk.
1301 int popCount = 0;
1302 auto pop = [&]() {
1303 if (popCount > 4) {
1304 this->write(ByteCodeInstruction::kPopN, popCount);
1305 this->write8(popCount);
1306 } else if (popCount > 0) {
1307 this->write(vector_instruction(ByteCodeInstruction::kPop, popCount));
1308 }
1309 popCount = 0;
1310 };
1311
1312 for (int i = argCount - 1; i >= 0; --i) {
1313 const auto& param = f.fFunction.fParameters[i];
1314 const auto& arg = f.fArguments[i];
1315 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1316 pop();
1317 lvalues.back()->store(true);
1318 lvalues.pop_back();
1319 } else {
1320 popCount += SlotCount(arg->fType);
1321 }
1322 }
1323 pop();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001324}
1325
Brian Osmanb08cc022020-04-02 11:38:40 -04001326void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
1327 this->write(ByteCodeInstruction::kPushImmediate);
1328 this->write32(i.fValue);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001329}
1330
Brian Osmanb08cc022020-04-02 11:38:40 -04001331void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
1332 // not yet implemented
1333 abort();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001334}
1335
Brian Osmanb08cc022020-04-02 11:38:40 -04001336bool ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p, bool discard) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001337 switch (p.fOperator) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001338 case Token::Kind::TK_PLUSPLUS: // fall through
1339 case Token::Kind::TK_MINUSMINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001340 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1341 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
1342 lvalue->load();
1343 this->write(ByteCodeInstruction::kPushImmediate);
1344 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001345 if (p.fOperator == Token::Kind::TK_PLUSPLUS) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001346 this->writeTypedInstruction(p.fType,
1347 ByteCodeInstruction::kAddI,
1348 ByteCodeInstruction::kAddI,
1349 ByteCodeInstruction::kAddF,
1350 1);
1351 } else {
1352 this->writeTypedInstruction(p.fType,
1353 ByteCodeInstruction::kSubtractI,
1354 ByteCodeInstruction::kSubtractI,
1355 ByteCodeInstruction::kSubtractF,
1356 1);
1357 }
1358 lvalue->store(discard);
1359 discard = false;
1360 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001361 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001362 case Token::Kind::TK_MINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001363 this->writeExpression(*p.fOperand);
1364 this->writeTypedInstruction(p.fType,
1365 ByteCodeInstruction::kNegateI,
1366 ByteCodeInstruction::kNegateI,
1367 ByteCodeInstruction::kNegateF,
Brian Osmanab8f3842020-04-07 09:30:44 -04001368 SlotCount(p.fOperand->fType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001369 break;
1370 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001371 case Token::Kind::TK_LOGICALNOT:
1372 case Token::Kind::TK_BITWISENOT: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001373 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1374 SkDEBUGCODE(TypeCategory tc = type_category(p.fOperand->fType));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001375 SkASSERT((p.fOperator == Token::Kind::TK_LOGICALNOT && tc == TypeCategory::kBool) ||
1376 (p.fOperator == Token::Kind::TK_BITWISENOT && (tc == TypeCategory::kSigned ||
Brian Osmanb08cc022020-04-02 11:38:40 -04001377 tc == TypeCategory::kUnsigned)));
1378 this->writeExpression(*p.fOperand);
1379 this->write(ByteCodeInstruction::kNotB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001380 break;
1381 }
1382 default:
1383 SkASSERT(false);
1384 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001385 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001386}
1387
Brian Osmanb08cc022020-04-02 11:38:40 -04001388bool ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p, bool discard) {
1389 switch (p.fOperator) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001390 case Token::Kind::TK_PLUSPLUS: // fall through
1391 case Token::Kind::TK_MINUSMINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001392 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1393 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
1394 lvalue->load();
1395 // If we're not supposed to discard the result, then make a copy *before* the +/-
1396 if (!discard) {
1397 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -04001398 }
1399 this->write(ByteCodeInstruction::kPushImmediate);
1400 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001401 if (p.fOperator == Token::Kind::TK_PLUSPLUS) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001402 this->writeTypedInstruction(p.fType,
1403 ByteCodeInstruction::kAddI,
1404 ByteCodeInstruction::kAddI,
1405 ByteCodeInstruction::kAddF,
1406 1);
1407 } else {
1408 this->writeTypedInstruction(p.fType,
1409 ByteCodeInstruction::kSubtractI,
1410 ByteCodeInstruction::kSubtractI,
1411 ByteCodeInstruction::kSubtractF,
1412 1);
1413 }
1414 // Always consume the result as part of the store
1415 lvalue->store(true);
1416 discard = false;
1417 break;
1418 }
1419 default:
1420 SkASSERT(false);
1421 }
1422 return discard;
1423}
1424
1425void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001426 if (swizzle_is_simple(s)) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001427 this->writeVariableExpression(s);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001428 return;
1429 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001430
1431 switch (s.fBase->fKind) {
1432 case Expression::kVariableReference_Kind: {
1433 Location location = this->getLocation(*s.fBase);
1434 this->write(location.selectLoad(ByteCodeInstruction::kLoadSwizzle,
1435 ByteCodeInstruction::kLoadSwizzleGlobal,
1436 ByteCodeInstruction::kLoadSwizzleUniform),
1437 s.fComponents.size());
1438 this->write8(location.fSlot);
1439 this->write8(s.fComponents.size());
1440 for (int c : s.fComponents) {
1441 this->write8(c);
1442 }
1443 break;
1444 }
1445 default:
1446 this->writeExpression(*s.fBase);
1447 this->write(ByteCodeInstruction::kSwizzle,
1448 s.fComponents.size() - s.fBase->fType.columns());
1449 this->write8(s.fBase->fType.columns());
1450 this->write8(s.fComponents.size());
1451 for (int c : s.fComponents) {
1452 this->write8(c);
1453 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001454 }
1455}
1456
Brian Osmanb08cc022020-04-02 11:38:40 -04001457void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001458 int count = SlotCount(t.fType);
1459 SkASSERT(count == SlotCount(t.fIfTrue->fType));
1460 SkASSERT(count == SlotCount(t.fIfFalse->fType));
1461
Brian Osmanb08cc022020-04-02 11:38:40 -04001462 this->writeExpression(*t.fTest);
1463 this->write(ByteCodeInstruction::kMaskPush);
1464 this->writeExpression(*t.fIfTrue);
1465 this->write(ByteCodeInstruction::kMaskNegate);
1466 this->writeExpression(*t.fIfFalse);
1467 this->write(ByteCodeInstruction::kMaskBlend, count);
1468 this->write8(count);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001469}
1470
Brian Osmanb08cc022020-04-02 11:38:40 -04001471void ByteCodeGenerator::writeExpression(const Expression& e, bool discard) {
1472 switch (e.fKind) {
1473 case Expression::kBinary_Kind:
1474 discard = this->writeBinaryExpression((BinaryExpression&) e, discard);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001475 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001476 case Expression::kBoolLiteral_Kind:
1477 this->writeBoolLiteral((BoolLiteral&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001478 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001479 case Expression::kConstructor_Kind:
1480 this->writeConstructor((Constructor&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001481 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001482 case Expression::kExternalFunctionCall_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001483 this->writeExternalFunctionCall((ExternalFunctionCall&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001484 break;
1485 case Expression::kExternalValue_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001486 this->writeExternalValue((ExternalValueReference&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001487 break;
1488 case Expression::kFieldAccess_Kind:
1489 case Expression::kIndex_Kind:
1490 case Expression::kVariableReference_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001491 this->writeVariableExpression(e);
1492 break;
1493 case Expression::kFloatLiteral_Kind:
1494 this->writeFloatLiteral((FloatLiteral&) e);
1495 break;
1496 case Expression::kFunctionCall_Kind:
1497 this->writeFunctionCall((FunctionCall&) e);
1498 break;
1499 case Expression::kIntLiteral_Kind:
1500 this->writeIntLiteral((IntLiteral&) e);
1501 break;
1502 case Expression::kNullLiteral_Kind:
1503 this->writeNullLiteral((NullLiteral&) e);
1504 break;
1505 case Expression::kPrefix_Kind:
1506 discard = this->writePrefixExpression((PrefixExpression&) e, discard);
1507 break;
1508 case Expression::kPostfix_Kind:
1509 discard = this->writePostfixExpression((PostfixExpression&) e, discard);
1510 break;
1511 case Expression::kSwizzle_Kind:
1512 this->writeSwizzle((Swizzle&) e);
1513 break;
1514 case Expression::kTernary_Kind:
1515 this->writeTernaryExpression((TernaryExpression&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001516 break;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001517 default:
1518#ifdef SK_DEBUG
Brian Osmanb08cc022020-04-02 11:38:40 -04001519 printf("unsupported expression %s\n", e.description().c_str());
Ben Wagner470e0ac2020-01-22 16:59:21 -05001520#endif
Brian Osmanb08cc022020-04-02 11:38:40 -04001521 SkASSERT(false);
1522 }
1523 if (discard) {
1524 int count = SlotCount(e.fType);
1525 if (count > 4) {
1526 this->write(ByteCodeInstruction::kPopN, count);
1527 this->write8(count);
1528 } else if (count != 0) {
1529 this->write(vector_instruction(ByteCodeInstruction::kPop, count));
1530 }
1531 discard = false;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001532 }
Ethan Nicholas7deb1c22020-01-22 10:31:55 -05001533}
1534
Brian Osmanb08cc022020-04-02 11:38:40 -04001535class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
1536public:
1537 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
1538 : INHERITED(*generator)
1539 , fCount(ByteCodeGenerator::SlotCount(value.type()))
1540 , fIndex(index) {}
1541
1542 void load() override {
1543 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001544 fGenerator.write8(fIndex);
1545 }
1546
1547 void store(bool discard) override {
1548 if (!discard) {
1549 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001550 }
1551 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001552 fGenerator.write8(fIndex);
1553 }
1554
1555private:
1556 typedef LValue INHERITED;
1557
1558 int fCount;
1559
1560 int fIndex;
1561};
1562
1563class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
1564public:
1565 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
1566 : INHERITED(*generator)
1567 , fSwizzle(swizzle) {}
1568
1569 void load() override {
1570 fGenerator.writeSwizzle(fSwizzle);
1571 }
1572
1573 void store(bool discard) override {
1574 int count = fSwizzle.fComponents.size();
1575 if (!discard) {
1576 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001577 }
1578 ByteCodeGenerator::Location location = fGenerator.getLocation(*fSwizzle.fBase);
1579 if (location.isOnStack()) {
1580 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreSwizzleIndirect,
1581 ByteCodeInstruction::kStoreSwizzleIndirectGlobal),
1582 count);
1583 } else {
1584 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreSwizzle,
1585 ByteCodeInstruction::kStoreSwizzleGlobal),
1586 count);
1587 fGenerator.write8(location.fSlot);
1588 }
1589 fGenerator.write8(count);
1590 for (int c : fSwizzle.fComponents) {
1591 fGenerator.write8(c);
1592 }
1593 }
1594
1595private:
1596 const Swizzle& fSwizzle;
1597
1598 typedef LValue INHERITED;
1599};
1600
1601class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
1602public:
1603 ByteCodeExpressionLValue(ByteCodeGenerator* generator, const Expression& expr)
1604 : INHERITED(*generator)
1605 , fExpression(expr) {}
1606
1607 void load() override {
1608 fGenerator.writeVariableExpression(fExpression);
1609 }
1610
1611 void store(bool discard) override {
1612 int count = ByteCodeGenerator::SlotCount(fExpression.fType);
1613 if (!discard) {
1614 if (count > 4) {
1615 fGenerator.write(ByteCodeInstruction::kDupN, count);
1616 fGenerator.write8(count);
1617 } else {
1618 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001619 }
1620 }
1621 ByteCodeGenerator::Location location = fGenerator.getLocation(fExpression);
1622 if (location.isOnStack() || count > 4) {
1623 if (!location.isOnStack()) {
1624 fGenerator.write(ByteCodeInstruction::kPushImmediate);
1625 fGenerator.write32(location.fSlot);
1626 }
1627 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreExtended,
1628 ByteCodeInstruction::kStoreExtendedGlobal),
1629 count);
1630 fGenerator.write8(count);
1631 } else {
1632 fGenerator.write(
1633 vector_instruction(location.selectStore(ByteCodeInstruction::kStore,
1634 ByteCodeInstruction::kStoreGlobal),
1635 count));
1636 fGenerator.write8(location.fSlot);
1637 }
1638 }
1639
1640private:
1641 typedef LValue INHERITED;
1642
1643 const Expression& fExpression;
1644};
1645
1646std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
1647 switch (e.fKind) {
1648 case Expression::kExternalValue_Kind: {
1649 ExternalValue* value = ((ExternalValueReference&) e).fValue;
1650 int index = fOutput->fExternalValues.size();
1651 fOutput->fExternalValues.push_back(value);
1652 SkASSERT(index <= 255);
1653 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
1654 }
1655 case Expression::kFieldAccess_Kind:
1656 case Expression::kIndex_Kind:
1657 case Expression::kVariableReference_Kind:
1658 return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
1659 case Expression::kSwizzle_Kind: {
1660 const Swizzle& s = (const Swizzle&) e;
1661 return swizzle_is_simple(s)
1662 ? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e))
1663 : std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s));
1664 }
1665 case Expression::kTernary_Kind:
1666 default:
1667#ifdef SK_DEBUG
1668 ABORT("unsupported lvalue %s\n", e.description().c_str());
1669#endif
1670 return nullptr;
1671 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001672}
1673
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001674void ByteCodeGenerator::writeBlock(const Block& b) {
1675 for (const auto& s : b.fStatements) {
1676 this->writeStatement(*s);
1677 }
1678}
1679
Brian Osmanb08cc022020-04-02 11:38:40 -04001680void ByteCodeGenerator::setBreakTargets() {
1681 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
1682 for (DeferredLocation& b : breaks) {
1683 b.set();
1684 }
1685 fBreakTargets.pop();
1686}
1687
1688void ByteCodeGenerator::setContinueTargets() {
1689 std::vector<DeferredLocation>& continues = fContinueTargets.top();
1690 for (DeferredLocation& c : continues) {
1691 c.set();
1692 }
1693 fContinueTargets.pop();
1694}
1695
1696void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
1697 // TODO: Include BranchIfAllFalse to top-most LoopNext
1698 this->write(ByteCodeInstruction::kLoopBreak);
1699}
1700
1701void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
1702 // TODO: Include BranchIfAllFalse to top-most LoopNext
1703 this->write(ByteCodeInstruction::kLoopContinue);
1704}
1705
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001706void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001707 this->write(ByteCodeInstruction::kLoopBegin);
1708 size_t start = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001709 this->writeStatement(*d.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001710 this->write(ByteCodeInstruction::kLoopNext);
1711 this->writeExpression(*d.fTest);
1712 this->write(ByteCodeInstruction::kLoopMask);
1713 // TODO: Could shorten this with kBranchIfAnyTrue
1714 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001715 DeferredLocation endLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -04001716 this->write(ByteCodeInstruction::kBranch);
1717 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001718 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001719 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001720}
1721
1722void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001723 fContinueTargets.emplace();
1724 fBreakTargets.emplace();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001725 if (f.fInitializer) {
1726 this->writeStatement(*f.fInitializer);
1727 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001728 this->write(ByteCodeInstruction::kLoopBegin);
1729 size_t start = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001730 if (f.fTest) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001731 this->writeExpression(*f.fTest);
1732 this->write(ByteCodeInstruction::kLoopMask);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001733 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001734 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001735 DeferredLocation endLocation(this);
1736 this->writeStatement(*f.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001737 this->write(ByteCodeInstruction::kLoopNext);
Brian Osman569f12f2019-06-13 11:23:57 -04001738 if (f.fNext) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001739 this->writeExpression(*f.fNext, true);
Brian Osman569f12f2019-06-13 11:23:57 -04001740 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001741 this->write(ByteCodeInstruction::kBranch);
1742 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001743 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001744 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001745}
1746
1747void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001748 this->writeExpression(*i.fTest);
1749 this->write(ByteCodeInstruction::kMaskPush);
1750 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001751 DeferredLocation falseLocation(this);
1752 this->writeStatement(*i.fIfTrue);
1753 falseLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001754 if (i.fIfFalse) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001755 this->write(ByteCodeInstruction::kMaskNegate);
1756 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001757 DeferredLocation endLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001758 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -05001759 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001760 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001761 this->write(ByteCodeInstruction::kMaskPop);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001762}
1763
Brian Osmanb08cc022020-04-02 11:38:40 -04001764void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
1765 if (fLoopCount || fConditionCount) {
Brian Osman4a47da72019-07-12 11:30:32 -04001766 fErrors.error(r.fOffset, "return not allowed inside conditional or loop");
1767 return;
1768 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001769 int count = SlotCount(r.fExpression->fType);
1770 this->writeExpression(*r.fExpression);
1771
1772 // Technically, the kReturn also pops fOutput->fLocalCount values from the stack, too, but we
1773 // haven't counted pushing those (they're outside the scope of our stack tracking). Instead,
1774 // we account for those in writeFunction().
1775
1776 // This is all fine because we don't allow conditional returns, so we only return once anyway.
1777 this->write(ByteCodeInstruction::kReturn, -count);
1778 this->write8(count);
1779}
1780
1781void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
1782 // not yet implemented
1783 abort();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001784}
1785
1786void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1787 for (const auto& declStatement : v.fVars) {
1788 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
Brian Osmanb08cc022020-04-02 11:38:40 -04001789 // we need to grab the location even if we don't use it, to ensure it has been allocated
1790 Location location = this->getLocation(*decl.fVar);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001791 if (decl.fValue) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001792 this->writeExpression(*decl.fValue);
1793 int count = SlotCount(decl.fValue->fType);
1794 if (count > 4) {
1795 this->write(ByteCodeInstruction::kPushImmediate);
1796 this->write32(location.fSlot);
1797 this->write(ByteCodeInstruction::kStoreExtended, count);
1798 this->write8(count);
1799 } else {
1800 this->write(vector_instruction(ByteCodeInstruction::kStore, count));
1801 this->write8(location.fSlot);
1802 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001803 }
1804 }
1805}
1806
1807void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001808 this->write(ByteCodeInstruction::kLoopBegin);
1809 size_t cond = fCode->size();
1810 this->writeExpression(*w.fTest);
1811 this->write(ByteCodeInstruction::kLoopMask);
1812 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001813 DeferredLocation endLocation(this);
1814 this->writeStatement(*w.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001815 this->write(ByteCodeInstruction::kLoopNext);
1816 this->write(ByteCodeInstruction::kBranch);
1817 this->write16(cond);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001818 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001819 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001820}
1821
1822void ByteCodeGenerator::writeStatement(const Statement& s) {
1823 switch (s.fKind) {
1824 case Statement::kBlock_Kind:
1825 this->writeBlock((Block&) s);
1826 break;
1827 case Statement::kBreak_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001828 this->writeBreakStatement((BreakStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001829 break;
1830 case Statement::kContinue_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001831 this->writeContinueStatement((ContinueStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001832 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001833 case Statement::kDiscard_Kind:
1834 // not yet implemented
1835 abort();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001836 case Statement::kDo_Kind:
1837 this->writeDoStatement((DoStatement&) s);
1838 break;
Brian Osman3e29f1d2019-05-28 09:35:05 -04001839 case Statement::kExpression_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001840 this->writeExpression(*((ExpressionStatement&) s).fExpression, true);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001841 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001842 case Statement::kFor_Kind:
1843 this->writeForStatement((ForStatement&) s);
1844 break;
1845 case Statement::kIf_Kind:
1846 this->writeIfStatement((IfStatement&) s);
1847 break;
1848 case Statement::kNop_Kind:
1849 break;
1850 case Statement::kReturn_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001851 this->writeReturnStatement((ReturnStatement&) s);
1852 break;
1853 case Statement::kSwitch_Kind:
1854 this->writeSwitchStatement((SwitchStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001855 break;
1856 case Statement::kVarDeclarations_Kind:
1857 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1858 break;
1859 case Statement::kWhile_Kind:
1860 this->writeWhileStatement((WhileStatement&) s);
1861 break;
1862 default:
Brian Osmanb08cc022020-04-02 11:38:40 -04001863 SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001864 }
1865}
1866
Brian Osmanb08cc022020-04-02 11:38:40 -04001867ByteCodeFunction::ByteCodeFunction(const FunctionDeclaration* declaration)
1868 : fName(declaration->fName) {
Brian Osman80164412019-06-07 13:00:23 -04001869 fParameterCount = 0;
Brian Osmanb08cc022020-04-02 11:38:40 -04001870 for (const auto& p : declaration->fParameters) {
1871 int slots = ByteCodeGenerator::SlotCount(p->fType);
1872 fParameters.push_back({ slots, (bool)(p->fModifiers.fFlags & Modifiers::kOut_Flag) });
1873 fParameterCount += slots;
Brian Osman80164412019-06-07 13:00:23 -04001874 }
1875}
1876
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001877}