blob: 93be7b6708cc4342426d901dfd833bb2718e33ef [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 {
Mike Reed8520e762020-04-30 12:06:23 -040049 { "atan", ByteCodeInstruction::kATan },
Brian Osmanb08cc022020-04-02 11:38:40 -040050 { "cos", ByteCodeInstruction::kCos },
Brian Osman15c98cb2020-02-27 18:36:57 +000051 { "dot", SpecialIntrinsic::kDot },
Mike Reed8520e762020-04-30 12:06:23 -040052 { "fract", ByteCodeInstruction::kFract },
Brian Osmanb08cc022020-04-02 11:38:40 -040053 { "inverse", ByteCodeInstruction::kInverse2x2 },
Mike Klein45be0772020-05-01 09:13:18 -050054 { "length", SpecialIntrinsic::kLength },
Brian Osman8842b372020-05-01 15:07:49 -040055 { "mix", SpecialIntrinsic::kMix },
Florin Malita3facc9c2020-05-04 09:26:15 -040056 { "pow", ByteCodeInstruction::kPow },
Brian Osmanb08cc022020-04-02 11:38:40 -040057 { "sin", ByteCodeInstruction::kSin },
58 { "sqrt", ByteCodeInstruction::kSqrt },
59 { "tan", ByteCodeInstruction::kTan },
Brian Osman8842b372020-05-01 15:07:49 -040060
61 { "lessThan", { ByteCodeInstruction::kCompareFLT,
62 ByteCodeInstruction::kCompareSLT,
63 ByteCodeInstruction::kCompareULT } },
64 { "lessThanEqual", { ByteCodeInstruction::kCompareFLTEQ,
65 ByteCodeInstruction::kCompareSLTEQ,
66 ByteCodeInstruction::kCompareULTEQ } },
67 { "greaterThan", { ByteCodeInstruction::kCompareFGT,
68 ByteCodeInstruction::kCompareSGT,
69 ByteCodeInstruction::kCompareUGT } },
70 { "greaterThanEqual", { ByteCodeInstruction::kCompareFGTEQ,
71 ByteCodeInstruction::kCompareSGTEQ,
72 ByteCodeInstruction::kCompareUGTEQ } },
73 { "equal", { ByteCodeInstruction::kCompareFEQ,
74 ByteCodeInstruction::kCompareIEQ,
75 ByteCodeInstruction::kCompareIEQ } },
76 { "notEqual", { ByteCodeInstruction::kCompareFNEQ,
77 ByteCodeInstruction::kCompareINEQ,
78 ByteCodeInstruction::kCompareINEQ } },
79
80 { "any", SpecialIntrinsic::kAny },
81 { "all", SpecialIntrinsic::kAll },
82 { "not", ByteCodeInstruction::kNotB },
83 } {}
Brian Osmanb08cc022020-04-02 11:38:40 -040084
Ethan Nicholas82162ee2019-05-21 16:05:08 -040085
Brian Osman07c117b2019-05-23 12:51:06 -070086int ByteCodeGenerator::SlotCount(const Type& type) {
Brian Osmanfba386b2019-06-20 14:54:15 -040087 if (type.kind() == Type::kOther_Kind) {
88 return 0;
89 } else if (type.kind() == Type::kStruct_Kind) {
Brian Osman07c117b2019-05-23 12:51:06 -070090 int slots = 0;
91 for (const auto& f : type.fields()) {
92 slots += SlotCount(*f.fType);
93 }
94 SkASSERT(slots <= 255);
95 return slots;
96 } else if (type.kind() == Type::kArray_Kind) {
97 int columns = type.columns();
98 SkASSERT(columns >= 0);
99 int slots = columns * SlotCount(type.componentType());
100 SkASSERT(slots <= 255);
101 return slots;
102 } else {
103 return type.columns() * type.rows();
104 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400105}
106
Brian Osman1c110a02019-10-01 14:53:32 -0400107static inline bool is_uniform(const SkSL::Variable& var) {
108 return var.fModifiers.fFlags & Modifiers::kUniform_Flag;
109}
110
Brian Osmaneadfeb92020-01-09 12:43:03 -0500111static inline bool is_in(const SkSL::Variable& var) {
112 return var.fModifiers.fFlags & Modifiers::kIn_Flag;
113}
Brian Osmanb08cc022020-04-02 11:38:40 -0400114
115void ByteCodeGenerator::gatherUniforms(const Type& type, const String& name) {
116 if (type.kind() == Type::kOther_Kind) {
117 return;
118 } else if (type.kind() == Type::kStruct_Kind) {
119 for (const auto& f : type.fields()) {
120 this->gatherUniforms(*f.fType, name + "." + f.fName);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500121 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400122 } else if (type.kind() == Type::kArray_Kind) {
123 for (int i = 0; i < type.columns(); ++i) {
124 this->gatherUniforms(type.componentType(), String::printf("%s[%d]", name.c_str(), i));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500125 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400126 } else {
127 fOutput->fUniforms.push_back({ name, type_category(type), type.rows(), type.columns(),
128 fOutput->fUniformSlotCount });
129 fOutput->fUniformSlotCount += type.columns() * type.rows();
130 }
131}
132
133bool ByteCodeGenerator::generateCode() {
134 for (const auto& e : fProgram) {
135 switch (e.fKind) {
136 case ProgramElement::kFunction_Kind: {
137 std::unique_ptr<ByteCodeFunction> f = this->writeFunction((FunctionDefinition&) e);
138 if (!f) {
139 return false;
140 }
141 fOutput->fFunctions.push_back(std::move(f));
142 fFunctions.push_back(&(FunctionDefinition&)e);
143 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500144 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400145 case ProgramElement::kVar_Kind: {
146 VarDeclarations& decl = (VarDeclarations&) e;
147 for (const auto& v : decl.fVars) {
148 const Variable* declVar = ((VarDeclaration&) *v).fVar;
149 if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
150 continue;
151 }
152 if (is_uniform(*declVar)) {
153 this->gatherUniforms(declVar->fType, declVar->fName);
154 } else {
155 fOutput->fGlobalSlotCount += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400156 }
157 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400158 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400159 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400160 default:
161 ; // ignore
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400162 }
163 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400164 return 0 == fErrors.errorCount();
165}
166
167std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
168 fFunction = &f;
169 std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
170 fParameterCount = result->fParameterCount;
171 fLoopCount = fMaxLoopCount = 0;
172 fConditionCount = fMaxConditionCount = 0;
173 fStackCount = fMaxStackCount = 0;
174 fCode = &result->fCode;
175
176 this->writeStatement(*f.fBody);
177 if (0 == fErrors.errorCount()) {
178 SkASSERT(fLoopCount == 0);
179 SkASSERT(fConditionCount == 0);
180 SkASSERT(fStackCount == 0);
181 }
182 this->write(ByteCodeInstruction::kReturn, 0);
183 this->write8(0);
184
185 result->fLocalCount = fLocals.size();
186 result->fConditionCount = fMaxConditionCount;
187 result->fLoopCount = fMaxLoopCount;
188 result->fStackCount = fMaxStackCount;
189
190 const Type& returnType = f.fDeclaration.fReturnType;
191 if (returnType != *fContext.fVoid_Type) {
192 result->fReturnCount = SlotCount(returnType);
193 }
194 fLocals.clear();
195 fFunction = nullptr;
196 return result;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400197}
198
Brian Osman0785db02019-05-24 14:19:11 -0400199// A "simple" Swizzle is based on a variable (or a compound variable like a struct or array), and
200// that references consecutive values, such that it can be implemented using normal load/store ops
201// with an offset. Note that all single-component swizzles (of suitable base types) are simple.
202static bool swizzle_is_simple(const Swizzle& s) {
203 switch (s.fBase->fKind) {
204 case Expression::kFieldAccess_Kind:
205 case Expression::kIndex_Kind:
206 case Expression::kVariableReference_Kind:
207 break;
208 default:
209 return false;
210 }
211
212 for (size_t i = 1; i < s.fComponents.size(); ++i) {
213 if (s.fComponents[i] != s.fComponents[i - 1] + 1) {
214 return false;
215 }
216 }
217 return true;
218}
219
Brian Osmanb08cc022020-04-02 11:38:40 -0400220int ByteCodeGenerator::StackUsage(ByteCodeInstruction inst, int count_) {
221 // Ensures that we use count iff we're passed a non-default value. Most instructions have an
222 // implicit count, so the caller shouldn't need to worry about it (or count makes no sense).
223 // The asserts avoids callers thinking they're supplying useful information in that scenario,
224 // or failing to supply necessary information for the ops that need a count.
225 struct CountValue {
226 operator int() {
227 SkASSERT(val != ByteCodeGenerator::kUnusedStackCount);
228 SkDEBUGCODE(used = true);
229 return val;
230 }
231 ~CountValue() {
232 SkASSERT(used || val == ByteCodeGenerator::kUnusedStackCount);
233 }
234 int val;
235 SkDEBUGCODE(bool used = false;)
236 } count = { count_ };
237
238 switch (inst) {
239 // Unary functions/operators that don't change stack depth at all:
240#define VECTOR_UNARY_OP(base) \
241 case ByteCodeInstruction::base: \
242 case ByteCodeInstruction::base ## 2: \
243 case ByteCodeInstruction::base ## 3: \
244 case ByteCodeInstruction::base ## 4: \
245 return 0;
246
247 VECTOR_UNARY_OP(kConvertFtoI)
248 VECTOR_UNARY_OP(kConvertStoF)
249 VECTOR_UNARY_OP(kConvertUtoF)
250
Mike Reed8520e762020-04-30 12:06:23 -0400251 VECTOR_UNARY_OP(kATan)
Brian Osmanb08cc022020-04-02 11:38:40 -0400252 VECTOR_UNARY_OP(kCos)
Mike Reed8520e762020-04-30 12:06:23 -0400253 VECTOR_UNARY_OP(kFract)
Brian Osmanb08cc022020-04-02 11:38:40 -0400254 VECTOR_UNARY_OP(kSin)
255 VECTOR_UNARY_OP(kSqrt)
256 VECTOR_UNARY_OP(kTan)
257
258 VECTOR_UNARY_OP(kNegateF)
259 VECTOR_UNARY_OP(kNegateI)
Brian Osman8842b372020-05-01 15:07:49 -0400260 VECTOR_UNARY_OP(kNotB)
Brian Osmanb08cc022020-04-02 11:38:40 -0400261
262 case ByteCodeInstruction::kInverse2x2:
263 case ByteCodeInstruction::kInverse3x3:
264 case ByteCodeInstruction::kInverse4x4: return 0;
265
266 case ByteCodeInstruction::kClampIndex: return 0;
Brian Osmanb08cc022020-04-02 11:38:40 -0400267 case ByteCodeInstruction::kNegateFN: return 0;
268 case ByteCodeInstruction::kShiftLeft: return 0;
269 case ByteCodeInstruction::kShiftRightS: return 0;
270 case ByteCodeInstruction::kShiftRightU: return 0;
271
272#undef VECTOR_UNARY_OP
273
274 // Binary functions/operators that do a 2 -> 1 reduction (possibly N times)
275#define VECTOR_BINARY_OP(base) \
276 case ByteCodeInstruction::base: return -1; \
277 case ByteCodeInstruction::base ## 2: return -2; \
278 case ByteCodeInstruction::base ## 3: return -3; \
279 case ByteCodeInstruction::base ## 4: return -4;
280
281#define VECTOR_MATRIX_BINARY_OP(base) \
282 VECTOR_BINARY_OP(base) \
283 case ByteCodeInstruction::base ## N: return -count;
284
285 case ByteCodeInstruction::kAndB: return -1;
286 case ByteCodeInstruction::kOrB: return -1;
287 case ByteCodeInstruction::kXorB: return -1;
288
289 VECTOR_BINARY_OP(kAddI)
290 VECTOR_MATRIX_BINARY_OP(kAddF)
291
292 VECTOR_BINARY_OP(kCompareIEQ)
293 VECTOR_MATRIX_BINARY_OP(kCompareFEQ)
294 VECTOR_BINARY_OP(kCompareINEQ)
295 VECTOR_MATRIX_BINARY_OP(kCompareFNEQ)
296 VECTOR_BINARY_OP(kCompareSGT)
297 VECTOR_BINARY_OP(kCompareUGT)
298 VECTOR_BINARY_OP(kCompareFGT)
299 VECTOR_BINARY_OP(kCompareSGTEQ)
300 VECTOR_BINARY_OP(kCompareUGTEQ)
301 VECTOR_BINARY_OP(kCompareFGTEQ)
302 VECTOR_BINARY_OP(kCompareSLT)
303 VECTOR_BINARY_OP(kCompareULT)
304 VECTOR_BINARY_OP(kCompareFLT)
305 VECTOR_BINARY_OP(kCompareSLTEQ)
306 VECTOR_BINARY_OP(kCompareULTEQ)
307 VECTOR_BINARY_OP(kCompareFLTEQ)
308
309 VECTOR_BINARY_OP(kDivideS)
310 VECTOR_BINARY_OP(kDivideU)
311 VECTOR_MATRIX_BINARY_OP(kDivideF)
312 VECTOR_BINARY_OP(kMultiplyI)
313 VECTOR_MATRIX_BINARY_OP(kMultiplyF)
Florin Malita3facc9c2020-05-04 09:26:15 -0400314 VECTOR_BINARY_OP(kPow)
Brian Osmanb08cc022020-04-02 11:38:40 -0400315 VECTOR_BINARY_OP(kRemainderF)
316 VECTOR_BINARY_OP(kRemainderS)
317 VECTOR_BINARY_OP(kRemainderU)
318 VECTOR_BINARY_OP(kSubtractI)
319 VECTOR_MATRIX_BINARY_OP(kSubtractF)
320
321#undef VECTOR_BINARY_OP
322#undef VECTOR_MATRIX_BINARY_OP
323
324 // Ops that push or load data to grow the stack:
325 case ByteCodeInstruction::kDup:
326 case ByteCodeInstruction::kLoad:
327 case ByteCodeInstruction::kLoadGlobal:
328 case ByteCodeInstruction::kLoadUniform:
329 case ByteCodeInstruction::kReadExternal:
330 case ByteCodeInstruction::kPushImmediate:
331 return 1;
332
333 case ByteCodeInstruction::kDup2:
334 case ByteCodeInstruction::kLoad2:
335 case ByteCodeInstruction::kLoadGlobal2:
336 case ByteCodeInstruction::kLoadUniform2:
337 case ByteCodeInstruction::kReadExternal2:
338 return 2;
339
340 case ByteCodeInstruction::kDup3:
341 case ByteCodeInstruction::kLoad3:
342 case ByteCodeInstruction::kLoadGlobal3:
343 case ByteCodeInstruction::kLoadUniform3:
344 case ByteCodeInstruction::kReadExternal3:
345 return 3;
346
347 case ByteCodeInstruction::kDup4:
348 case ByteCodeInstruction::kLoad4:
349 case ByteCodeInstruction::kLoadGlobal4:
350 case ByteCodeInstruction::kLoadUniform4:
351 case ByteCodeInstruction::kReadExternal4:
352 return 4;
353
354 case ByteCodeInstruction::kDupN:
355 case ByteCodeInstruction::kLoadSwizzle:
356 case ByteCodeInstruction::kLoadSwizzleGlobal:
357 case ByteCodeInstruction::kLoadSwizzleUniform:
358 return count;
359
360 // Pushes 'count' values, minus one for the 'address' that's consumed first
361 case ByteCodeInstruction::kLoadExtended:
362 case ByteCodeInstruction::kLoadExtendedGlobal:
363 case ByteCodeInstruction::kLoadExtendedUniform:
364 return count - 1;
365
366 // Ops that pop or store data to shrink the stack:
367 case ByteCodeInstruction::kPop:
368 case ByteCodeInstruction::kStore:
369 case ByteCodeInstruction::kStoreGlobal:
370 case ByteCodeInstruction::kWriteExternal:
371 return -1;
372
373 case ByteCodeInstruction::kPop2:
374 case ByteCodeInstruction::kStore2:
375 case ByteCodeInstruction::kStoreGlobal2:
376 case ByteCodeInstruction::kWriteExternal2:
377 return -2;
378
379 case ByteCodeInstruction::kPop3:
380 case ByteCodeInstruction::kStore3:
381 case ByteCodeInstruction::kStoreGlobal3:
382 case ByteCodeInstruction::kWriteExternal3:
383 return -3;
384
385 case ByteCodeInstruction::kPop4:
386 case ByteCodeInstruction::kStore4:
387 case ByteCodeInstruction::kStoreGlobal4:
388 case ByteCodeInstruction::kWriteExternal4:
389 return -4;
390
391 case ByteCodeInstruction::kPopN:
392 case ByteCodeInstruction::kStoreSwizzle:
393 case ByteCodeInstruction::kStoreSwizzleGlobal:
394 return -count;
395
396 // Consumes 'count' values, plus one for the 'address'
397 case ByteCodeInstruction::kStoreExtended:
398 case ByteCodeInstruction::kStoreExtendedGlobal:
399 case ByteCodeInstruction::kStoreSwizzleIndirect:
400 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal:
401 return -count - 1;
402
403 // Strange ops where the caller computes the delta for us:
404 case ByteCodeInstruction::kCallExternal:
405 case ByteCodeInstruction::kMatrixToMatrix:
406 case ByteCodeInstruction::kMatrixMultiply:
407 case ByteCodeInstruction::kReserve:
408 case ByteCodeInstruction::kReturn:
409 case ByteCodeInstruction::kScalarToMatrix:
410 case ByteCodeInstruction::kSwizzle:
411 return count;
412
413 // Miscellaneous
414
Brian Osman8842b372020-05-01 15:07:49 -0400415 // kMix does a 3 -> 1 reduction (A, B, M -> A -or- B) for each component
416 case ByteCodeInstruction::kMix: return -2;
417 case ByteCodeInstruction::kMix2: return -4;
418 case ByteCodeInstruction::kMix3: return -6;
419 case ByteCodeInstruction::kMix4: return -8;
420
421 // kLerp works the same way (producing lerp(A, B, T) for each component)
422 case ByteCodeInstruction::kLerp: return -2;
423 case ByteCodeInstruction::kLerp2: return -4;
424 case ByteCodeInstruction::kLerp3: return -6;
425 case ByteCodeInstruction::kLerp4: return -8;
426
Brian Osmanb08cc022020-04-02 11:38:40 -0400427 // kCall is net-zero. Max stack depth is adjusted in writeFunctionCall.
428 case ByteCodeInstruction::kCall: return 0;
429 case ByteCodeInstruction::kBranch: return 0;
430 case ByteCodeInstruction::kBranchIfAllFalse: return 0;
431
432 case ByteCodeInstruction::kMaskPush: return -1;
433 case ByteCodeInstruction::kMaskPop: return 0;
434 case ByteCodeInstruction::kMaskNegate: return 0;
435 case ByteCodeInstruction::kMaskBlend: return -count;
436
437 case ByteCodeInstruction::kLoopBegin: return 0;
438 case ByteCodeInstruction::kLoopNext: return 0;
439 case ByteCodeInstruction::kLoopMask: return -1;
440 case ByteCodeInstruction::kLoopEnd: return 0;
441 case ByteCodeInstruction::kLoopBreak: return 0;
442 case ByteCodeInstruction::kLoopContinue: return 0;
443
444 default:
445 ABORT("unsupported instruction %d\n", (int)inst);
446 return 0;
447 }
448}
449
450ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var) {
451 // given that we seldom have more than a couple of variables, linear search is probably the most
452 // efficient way to handle lookups
453 switch (var.fStorage) {
454 case Variable::kLocal_Storage: {
455 for (int i = fLocals.size() - 1; i >= 0; --i) {
456 if (fLocals[i] == &var) {
457 SkASSERT(fParameterCount + i <= 255);
458 return { fParameterCount + i, Storage::kLocal };
459 }
460 }
461 int result = fParameterCount + fLocals.size();
462 fLocals.push_back(&var);
463 for (int i = 0; i < SlotCount(var.fType) - 1; ++i) {
464 fLocals.push_back(nullptr);
465 }
466 SkASSERT(result <= 255);
467 return { result, Storage::kLocal };
468 }
469 case Variable::kParameter_Storage: {
470 int offset = 0;
471 for (const auto& p : fFunction->fDeclaration.fParameters) {
472 if (p == &var) {
473 SkASSERT(offset <= 255);
474 return { offset, Storage::kLocal };
475 }
476 offset += SlotCount(p->fType);
477 }
478 SkASSERT(false);
479 return Location::MakeInvalid();
480 }
481 case Variable::kGlobal_Storage: {
482 if (is_in(var)) {
483 // If you see this error, it means the program is using raw 'in' variables. You
484 // should either specialize the program (Compiler::specialize) to bake in the final
485 // values of the 'in' variables, or not use 'in' variables (maybe you meant to use
486 // 'uniform' instead?).
487 fErrors.error(var.fOffset,
488 "'in' variable is not specialized or has unsupported type");
489 return Location::MakeInvalid();
490 }
491 int offset = 0;
492 bool isUniform = is_uniform(var);
493 for (const auto& e : fProgram) {
494 if (e.fKind == ProgramElement::kVar_Kind) {
495 VarDeclarations& decl = (VarDeclarations&) e;
496 for (const auto& v : decl.fVars) {
497 const Variable* declVar = ((VarDeclaration&) *v).fVar;
498 if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
499 continue;
500 }
501 if (isUniform != is_uniform(*declVar)) {
502 continue;
503 }
504 if (declVar == &var) {
505 SkASSERT(offset <= 255);
506 return { offset, isUniform ? Storage::kUniform : Storage::kGlobal };
507 }
508 offset += SlotCount(declVar->fType);
509 }
510 }
511 }
512 SkASSERT(false);
513 return Location::MakeInvalid();
514 }
515 default:
516 SkASSERT(false);
517 return Location::MakeInvalid();
518 }
519}
520
Brian Osman1c110a02019-10-01 14:53:32 -0400521ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Expression& expr) {
Brian Osman07c117b2019-05-23 12:51:06 -0700522 switch (expr.fKind) {
523 case Expression::kFieldAccess_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400524 const FieldAccess& f = (const FieldAccess&)expr;
525 Location baseLoc = this->getLocation(*f.fBase);
Brian Osman07c117b2019-05-23 12:51:06 -0700526 int offset = 0;
527 for (int i = 0; i < f.fFieldIndex; ++i) {
528 offset += SlotCount(*f.fBase->fType.fields()[i].fType);
529 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400530 if (baseLoc.isOnStack()) {
531 if (offset != 0) {
532 this->write(ByteCodeInstruction::kPushImmediate);
533 this->write32(offset);
534 this->write(ByteCodeInstruction::kAddI);
Ben Wagner470e0ac2020-01-22 16:59:21 -0500535 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400536 return baseLoc;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500537 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400538 return baseLoc + offset;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500539 }
Ben Wagner470e0ac2020-01-22 16:59:21 -0500540 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400541 case Expression::kIndex_Kind: {
542 const IndexExpression& i = (const IndexExpression&)expr;
543 int stride = SlotCount(i.fType);
544 int length = i.fBase->fType.columns();
545 SkASSERT(length <= 255);
546 int offset = -1;
547 if (i.fIndex->isConstant()) {
548 int64_t index = i.fIndex->getConstantInt();
549 if (index < 0 || index >= length) {
550 fErrors.error(i.fIndex->fOffset, "Array index out of bounds.");
551 return Location::MakeInvalid();
552 }
553 offset = index * stride;
554 } else {
555 if (i.fIndex->hasSideEffects()) {
556 // Having a side-effect in an indexer is technically safe for an rvalue,
557 // but with lvalues we have to evaluate the indexer twice, so make it an error.
558 fErrors.error(i.fIndex->fOffset,
559 "Index expressions with side-effects not supported in byte code.");
560 return Location::MakeInvalid();
561 }
562 this->writeExpression(*i.fIndex);
563 this->write(ByteCodeInstruction::kClampIndex);
564 this->write8(length);
565 if (stride != 1) {
566 this->write(ByteCodeInstruction::kPushImmediate);
567 this->write32(stride);
568 this->write(ByteCodeInstruction::kMultiplyI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400569 }
570 }
571 Location baseLoc = this->getLocation(*i.fBase);
572
573 // Are both components known statically?
574 if (!baseLoc.isOnStack() && offset >= 0) {
575 return baseLoc + offset;
576 }
577
578 // At least one component is dynamic (and on the stack).
579
580 // If the other component is zero, we're done
581 if (baseLoc.fSlot == 0 || offset == 0) {
582 return baseLoc.makeOnStack();
583 }
584
585 // Push the non-dynamic component (if any) to the stack, then add the two
586 if (!baseLoc.isOnStack()) {
587 this->write(ByteCodeInstruction::kPushImmediate);
588 this->write32(baseLoc.fSlot);
589 }
590 if (offset >= 0) {
591 this->write(ByteCodeInstruction::kPushImmediate);
592 this->write32(offset);
593 }
594 this->write(ByteCodeInstruction::kAddI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400595 return baseLoc.makeOnStack();
596 }
Brian Osman0785db02019-05-24 14:19:11 -0400597 case Expression::kSwizzle_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400598 const Swizzle& s = (const Swizzle&)expr;
Brian Osman0785db02019-05-24 14:19:11 -0400599 SkASSERT(swizzle_is_simple(s));
Brian Osmanb08cc022020-04-02 11:38:40 -0400600 Location baseLoc = this->getLocation(*s.fBase);
601 int offset = s.fComponents[0];
602 if (baseLoc.isOnStack()) {
603 if (offset != 0) {
604 this->write(ByteCodeInstruction::kPushImmediate);
605 this->write32(offset);
606 this->write(ByteCodeInstruction::kAddI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400607 }
608 return baseLoc;
609 } else {
610 return baseLoc + offset;
611 }
Brian Osman0785db02019-05-24 14:19:11 -0400612 }
Brian Osman07c117b2019-05-23 12:51:06 -0700613 case Expression::kVariableReference_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400614 const Variable& var = ((const VariableReference&)expr).fVariable;
Brian Osman07c117b2019-05-23 12:51:06 -0700615 return this->getLocation(var);
616 }
617 default:
618 SkASSERT(false);
Brian Osmanb08cc022020-04-02 11:38:40 -0400619 return Location::MakeInvalid();
Brian Osman07c117b2019-05-23 12:51:06 -0700620 }
621}
622
Brian Osmanb08cc022020-04-02 11:38:40 -0400623void ByteCodeGenerator::write8(uint8_t b) {
624 fCode->push_back(b);
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500625}
626
Brian Osmanb08cc022020-04-02 11:38:40 -0400627void ByteCodeGenerator::write16(uint16_t i) {
628 size_t n = fCode->size();
629 fCode->resize(n+2);
630 memcpy(fCode->data() + n, &i, 2);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500631}
Ben Wagner470e0ac2020-01-22 16:59:21 -0500632
Brian Osmanb08cc022020-04-02 11:38:40 -0400633void ByteCodeGenerator::write32(uint32_t i) {
634 size_t n = fCode->size();
635 fCode->resize(n+4);
636 memcpy(fCode->data() + n, &i, 4);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500637}
638
Brian Osmanb08cc022020-04-02 11:38:40 -0400639void ByteCodeGenerator::write(ByteCodeInstruction i, int count) {
640 switch (i) {
641 case ByteCodeInstruction::kLoopBegin: this->enterLoop(); break;
642 case ByteCodeInstruction::kLoopEnd: this->exitLoop(); break;
Ethan Nicholas2329da02020-01-24 15:49:33 -0500643
Brian Osmanb08cc022020-04-02 11:38:40 -0400644 case ByteCodeInstruction::kMaskPush: this->enterCondition(); break;
645 case ByteCodeInstruction::kMaskPop:
646 case ByteCodeInstruction::kMaskBlend: this->exitCondition(); break;
647 default: /* Do nothing */ break;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500648 }
Brian Osmanab8f3842020-04-07 09:30:44 -0400649 this->write16((uint16_t)i);
Brian Osmanb08cc022020-04-02 11:38:40 -0400650 fStackCount += StackUsage(i, count);
651 fMaxStackCount = std::max(fMaxStackCount, fStackCount);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500652}
653
Brian Osmanb08cc022020-04-02 11:38:40 -0400654static ByteCodeInstruction vector_instruction(ByteCodeInstruction base, int count) {
655 SkASSERT(count >= 1 && count <= 4);
656 return ((ByteCodeInstruction) ((int) base + 1 - count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500657}
658
Brian Osmanb08cc022020-04-02 11:38:40 -0400659void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
660 ByteCodeInstruction u, ByteCodeInstruction f,
Brian Osmanab8f3842020-04-07 09:30:44 -0400661 int count) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500662 switch (type_category(type)) {
Brian Osman8842b372020-05-01 15:07:49 -0400663 case TypeCategory::kBool:
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500664 case TypeCategory::kSigned:
Brian Osmanb08cc022020-04-02 11:38:40 -0400665 this->write(vector_instruction(s, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500666 break;
667 case TypeCategory::kUnsigned:
Brian Osmanb08cc022020-04-02 11:38:40 -0400668 this->write(vector_instruction(u, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500669 break;
670 case TypeCategory::kFloat: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400671 if (count > 4) {
672 this->write((ByteCodeInstruction)((int)f + 1), count);
Brian Osmanab8f3842020-04-07 09:30:44 -0400673 this->write8(count);
Brian Osmanb08cc022020-04-02 11:38:40 -0400674 } else {
675 this->write(vector_instruction(f, count));
676 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500677 break;
678 }
679 default:
680 SkASSERT(false);
681 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500682}
683
Brian Osmanb08cc022020-04-02 11:38:40 -0400684bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool discard) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400685 if (b.fOperator == Token::Kind::TK_EQ) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500686 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
Brian Osmanb08cc022020-04-02 11:38:40 -0400687 this->writeExpression(*b.fRight);
688 lvalue->store(discard);
689 discard = false;
690 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500691 }
692 const Type& lType = b.fLeft->fType;
693 const Type& rType = b.fRight->fType;
694 bool lVecOrMtx = (lType.kind() == Type::kVector_Kind || lType.kind() == Type::kMatrix_Kind);
695 bool rVecOrMtx = (rType.kind() == Type::kVector_Kind || rType.kind() == Type::kMatrix_Kind);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500696 Token::Kind op;
697 std::unique_ptr<LValue> lvalue;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500698 if (is_assignment(b.fOperator)) {
699 lvalue = this->getLValue(*b.fLeft);
Brian Osmanb08cc022020-04-02 11:38:40 -0400700 lvalue->load();
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500701 op = remove_assignment(b.fOperator);
702 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400703 this->writeExpression(*b.fLeft);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500704 op = b.fOperator;
705 if (!lVecOrMtx && rVecOrMtx) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400706 for (int i = SlotCount(rType); i > 1; --i) {
707 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400708 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500709 }
710 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500711 int count = std::max(SlotCount(lType), SlotCount(rType));
Brian Osmanb08cc022020-04-02 11:38:40 -0400712 SkDEBUGCODE(TypeCategory tc = type_category(lType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500713 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400714 case Token::Kind::TK_LOGICALAND: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400715 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
716 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400717 this->write(ByteCodeInstruction::kMaskPush);
718 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500719 DeferredLocation falseLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -0400720 this->writeExpression(*b.fRight);
721 this->write(ByteCodeInstruction::kAndB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500722 falseLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -0400723 this->write(ByteCodeInstruction::kMaskPop);
724 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500725 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400726 case Token::Kind::TK_LOGICALOR: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400727 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
728 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400729 this->write(ByteCodeInstruction::kNotB);
730 this->write(ByteCodeInstruction::kMaskPush);
731 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500732 DeferredLocation falseLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -0400733 this->writeExpression(*b.fRight);
734 this->write(ByteCodeInstruction::kOrB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500735 falseLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -0400736 this->write(ByteCodeInstruction::kMaskPop);
737 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500738 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400739 case Token::Kind::TK_SHL:
740 case Token::Kind::TK_SHR: {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500741 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
742 tc == SkSL::TypeCategory::kUnsigned));
743 if (!b.fRight->isConstant()) {
744 fErrors.error(b.fRight->fOffset, "Shift amounts must be constant");
Brian Osmanb08cc022020-04-02 11:38:40 -0400745 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500746 }
747 int64_t shift = b.fRight->getConstantInt();
748 if (shift < 0 || shift > 31) {
749 fErrors.error(b.fRight->fOffset, "Shift amount out of range");
Brian Osmanb08cc022020-04-02 11:38:40 -0400750 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500751 }
752
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400753 if (op == Token::Kind::TK_SHL) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400754 this->write(ByteCodeInstruction::kShiftLeft);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500755 } else {
756 this->write(type_category(lType) == TypeCategory::kSigned
Brian Osmanb08cc022020-04-02 11:38:40 -0400757 ? ByteCodeInstruction::kShiftRightS
758 : ByteCodeInstruction::kShiftRightU);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500759 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400760 this->write8(shift);
761 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500762 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500763
764 default:
765 break;
766 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400767 this->writeExpression(*b.fRight);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500768 if (lVecOrMtx && !rVecOrMtx) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400769 for (int i = SlotCount(lType); i > 1; --i) {
770 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400771 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500772 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400773 // Special case for M*V, V*M, M*M (but not V*V!)
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400774 if (op == Token::Kind::TK_STAR && lVecOrMtx && rVecOrMtx &&
Brian Osmanb08cc022020-04-02 11:38:40 -0400775 !(lType.kind() == Type::kVector_Kind && rType.kind() == Type::kVector_Kind)) {
776 this->write(ByteCodeInstruction::kMatrixMultiply,
777 SlotCount(b.fType) - (SlotCount(lType) + SlotCount(rType)));
778 int rCols = rType.columns(),
779 rRows = rType.rows(),
780 lCols = lType.columns(),
781 lRows = lType.rows();
782 // M*V treats the vector as a column
783 if (rType.kind() == Type::kVector_Kind) {
784 std::swap(rCols, rRows);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500785 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400786 SkASSERT(lCols == rRows);
787 SkASSERT(SlotCount(b.fType) == lRows * rCols);
788 this->write8(lCols);
789 this->write8(lRows);
790 this->write8(rCols);
791 } else {
792 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400793 case Token::Kind::TK_EQEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400794 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareIEQ,
795 ByteCodeInstruction::kCompareIEQ,
796 ByteCodeInstruction::kCompareFEQ,
797 count);
798 // Collapse to a single bool
799 for (int i = count; i > 1; --i) {
800 this->write(ByteCodeInstruction::kAndB);
801 }
802 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400803 case Token::Kind::TK_GT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400804 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGT,
805 ByteCodeInstruction::kCompareUGT,
806 ByteCodeInstruction::kCompareFGT,
807 count);
808 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400809 case Token::Kind::TK_GTEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400810 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGTEQ,
811 ByteCodeInstruction::kCompareUGTEQ,
812 ByteCodeInstruction::kCompareFGTEQ,
813 count);
814 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400815 case Token::Kind::TK_LT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400816 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLT,
817 ByteCodeInstruction::kCompareULT,
818 ByteCodeInstruction::kCompareFLT,
819 count);
820 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400821 case Token::Kind::TK_LTEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400822 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLTEQ,
823 ByteCodeInstruction::kCompareULTEQ,
824 ByteCodeInstruction::kCompareFLTEQ,
825 count);
826 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400827 case Token::Kind::TK_MINUS:
Brian Osmanb08cc022020-04-02 11:38:40 -0400828 this->writeTypedInstruction(lType, ByteCodeInstruction::kSubtractI,
829 ByteCodeInstruction::kSubtractI,
830 ByteCodeInstruction::kSubtractF,
831 count);
832 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400833 case Token::Kind::TK_NEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400834 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareINEQ,
835 ByteCodeInstruction::kCompareINEQ,
836 ByteCodeInstruction::kCompareFNEQ,
837 count);
838 // Collapse to a single bool
839 for (int i = count; i > 1; --i) {
840 this->write(ByteCodeInstruction::kOrB);
841 }
842 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400843 case Token::Kind::TK_PERCENT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400844 this->writeTypedInstruction(lType, ByteCodeInstruction::kRemainderS,
845 ByteCodeInstruction::kRemainderU,
846 ByteCodeInstruction::kRemainderF,
847 count);
848 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400849 case Token::Kind::TK_PLUS:
Brian Osmanb08cc022020-04-02 11:38:40 -0400850 this->writeTypedInstruction(lType, ByteCodeInstruction::kAddI,
851 ByteCodeInstruction::kAddI,
852 ByteCodeInstruction::kAddF,
853 count);
854 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400855 case Token::Kind::TK_SLASH:
Brian Osmanb08cc022020-04-02 11:38:40 -0400856 this->writeTypedInstruction(lType, ByteCodeInstruction::kDivideS,
857 ByteCodeInstruction::kDivideU,
858 ByteCodeInstruction::kDivideF,
859 count);
860 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400861 case Token::Kind::TK_STAR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400862 this->writeTypedInstruction(lType, ByteCodeInstruction::kMultiplyI,
863 ByteCodeInstruction::kMultiplyI,
864 ByteCodeInstruction::kMultiplyF,
865 count);
866 break;
867
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400868 case Token::Kind::TK_LOGICALXOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400869 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
870 this->write(ByteCodeInstruction::kXorB);
871 break;
872
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400873 case Token::Kind::TK_BITWISEAND:
Brian Osmanb08cc022020-04-02 11:38:40 -0400874 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
875 tc == SkSL::TypeCategory::kUnsigned));
876 this->write(ByteCodeInstruction::kAndB);
877 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400878 case Token::Kind::TK_BITWISEOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400879 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
880 tc == SkSL::TypeCategory::kUnsigned));
881 this->write(ByteCodeInstruction::kOrB);
882 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400883 case Token::Kind::TK_BITWISEXOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400884 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
885 tc == SkSL::TypeCategory::kUnsigned));
886 this->write(ByteCodeInstruction::kXorB);
887 break;
888
889 default:
890 fErrors.error(b.fOffset, SkSL::String::printf("Unsupported binary operator '%s'",
891 Compiler::OperatorName(op)));
892 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500893 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500894 }
895 if (lvalue) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400896 lvalue->store(discard);
897 discard = false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500898 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400899 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500900}
901
Brian Osmanb08cc022020-04-02 11:38:40 -0400902void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
903 this->write(ByteCodeInstruction::kPushImmediate);
904 this->write32(b.fValue ? ~0 : 0);
905}
906
907void ByteCodeGenerator::writeConstructor(const Constructor& c) {
908 for (const auto& arg : c.fArguments) {
909 this->writeExpression(*arg);
910 }
911 if (c.fArguments.size() == 1) {
912 const Type& inType = c.fArguments[0]->fType;
913 const Type& outType = c.fType;
914 TypeCategory inCategory = type_category(inType);
915 TypeCategory outCategory = type_category(outType);
916 int inCount = SlotCount(inType);
917 int outCount = SlotCount(outType);
918 if (inCategory != outCategory) {
919 SkASSERT(inCount == outCount);
920 if (inCategory == TypeCategory::kFloat) {
921 SkASSERT(outCategory == TypeCategory::kSigned ||
922 outCategory == TypeCategory::kUnsigned);
923 this->write(vector_instruction(ByteCodeInstruction::kConvertFtoI, outCount));
924 } else if (outCategory == TypeCategory::kFloat) {
925 if (inCategory == TypeCategory::kSigned) {
926 this->write(vector_instruction(ByteCodeInstruction::kConvertStoF, outCount));
927 } else {
928 SkASSERT(inCategory == TypeCategory::kUnsigned);
929 this->write(vector_instruction(ByteCodeInstruction::kConvertUtoF, outCount));
930 }
931 } else {
932 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500933 }
934 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400935 if (inType.kind() == Type::kMatrix_Kind && outType.kind() == Type::kMatrix_Kind) {
936 this->write(ByteCodeInstruction::kMatrixToMatrix,
937 SlotCount(outType) - SlotCount(inType));
938 this->write8(inType.columns());
939 this->write8(inType.rows());
940 this->write8(outType.columns());
941 this->write8(outType.rows());
942 } else if (inCount != outCount) {
943 SkASSERT(inCount == 1);
944 if (outType.kind() == Type::kMatrix_Kind) {
945 this->write(ByteCodeInstruction::kScalarToMatrix, SlotCount(outType) - 1);
946 this->write8(outType.columns());
947 this->write8(outType.rows());
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500948 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400949 SkASSERT(outType.kind() == Type::kVector_Kind);
950 for (; inCount != outCount; ++inCount) {
951 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400952 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500953 }
954 }
955 }
956}
957
Brian Osmanb08cc022020-04-02 11:38:40 -0400958void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500959 int argumentCount = 0;
960 for (const auto& arg : f.fArguments) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400961 this->writeExpression(*arg);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500962 argumentCount += SlotCount(arg->fType);
963 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400964 this->write(ByteCodeInstruction::kCallExternal, SlotCount(f.fType) - argumentCount);
965 SkASSERT(argumentCount <= 255);
966 this->write8(argumentCount);
967 this->write8(SlotCount(f.fType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500968 int index = fOutput->fExternalValues.size();
969 fOutput->fExternalValues.push_back(f.fFunction);
970 SkASSERT(index <= 255);
Brian Osmanb08cc022020-04-02 11:38:40 -0400971 this->write8(index);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500972}
973
Brian Osmanb08cc022020-04-02 11:38:40 -0400974void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
975 int count = SlotCount(e.fValue->type());
976 this->write(vector_instruction(ByteCodeInstruction::kReadExternal, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500977 int index = fOutput->fExternalValues.size();
978 fOutput->fExternalValues.push_back(e.fValue);
979 SkASSERT(index <= 255);
Brian Osmanb08cc022020-04-02 11:38:40 -0400980 this->write8(index);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500981}
982
Brian Osmanb08cc022020-04-02 11:38:40 -0400983void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
984 Location location = this->getLocation(expr);
985 int count = SlotCount(expr.fType);
Brian Osmanefb08402020-04-13 16:30:44 -0400986 if (count == 0) {
987 return;
988 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400989 if (location.isOnStack() || count > 4) {
990 if (!location.isOnStack()) {
991 this->write(ByteCodeInstruction::kPushImmediate);
992 this->write32(location.fSlot);
993 }
994 this->write(location.selectLoad(ByteCodeInstruction::kLoadExtended,
995 ByteCodeInstruction::kLoadExtendedGlobal,
996 ByteCodeInstruction::kLoadExtendedUniform),
997 count);
998 this->write8(count);
999 } else {
1000 this->write(vector_instruction(location.selectLoad(ByteCodeInstruction::kLoad,
1001 ByteCodeInstruction::kLoadGlobal,
1002 ByteCodeInstruction::kLoadUniform),
1003 count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001004 this->write8(location.fSlot);
1005 }
1006}
1007
1008static inline uint32_t float_to_bits(float x) {
1009 uint32_t u;
1010 memcpy(&u, &x, sizeof(uint32_t));
1011 return u;
1012}
1013
1014void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
1015 this->write(ByteCodeInstruction::kPushImmediate);
1016 this->write32(float_to_bits(f.fValue));
1017}
1018
Brian Osman8842b372020-05-01 15:07:49 -04001019static bool is_generic_type(const Type* type, const Type* generic) {
1020 const std::vector<const Type*>& concrete(generic->coercibleTypes());
1021 return std::find(concrete.begin(), concrete.end(), type) != concrete.end();
1022}
1023
Brian Osmanb08cc022020-04-02 11:38:40 -04001024void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
1025 auto found = fIntrinsics.find(c.fFunction.fName);
1026 if (found == fIntrinsics.end()) {
1027 fErrors.error(c.fOffset, String::printf("Unsupported intrinsic: '%s'",
1028 String(c.fFunction.fName).c_str()));
1029 return;
1030 }
Mike Klein45be0772020-05-01 09:13:18 -05001031 Intrinsic intrin = found->second;
1032
Brian Osmanb08cc022020-04-02 11:38:40 -04001033 int count = SlotCount(c.fArguments[0]->fType);
Mike Klein45be0772020-05-01 09:13:18 -05001034 if (intrin.is_special) {
1035 switch (intrin.special) {
Brian Osman8842b372020-05-01 15:07:49 -04001036 case SpecialIntrinsic::kAll: {
1037 for (int i = count-1; i --> 0;) {
1038 this->write(ByteCodeInstruction::kAndB);
1039 }
1040 } break;
1041
1042 case SpecialIntrinsic::kAny: {
1043 for (int i = count-1; i --> 0;) {
1044 this->write(ByteCodeInstruction::kOrB);
1045 }
1046 } break;
1047
Brian Osman15c98cb2020-02-27 18:36:57 +00001048 case SpecialIntrinsic::kDot: {
1049 SkASSERT(c.fArguments.size() == 2);
Brian Osmanb08cc022020-04-02 11:38:40 -04001050 SkASSERT(count == SlotCount(c.fArguments[1]->fType));
1051 this->write(vector_instruction(ByteCodeInstruction::kMultiplyF, count));
Mike Klein45be0772020-05-01 09:13:18 -05001052 for (int i = count-1; i --> 0;) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001053 this->write(ByteCodeInstruction::kAddF);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001054 }
Mike Klein45be0772020-05-01 09:13:18 -05001055 } break;
1056
1057 case SpecialIntrinsic::kLength: {
1058 SkASSERT(c.fArguments.size() == 1);
1059 this->write(vector_instruction(ByteCodeInstruction::kDup , count));
1060 this->write(vector_instruction(ByteCodeInstruction::kMultiplyF, count));
1061 for (int i = count-1; i --> 0;) {
1062 this->write(ByteCodeInstruction::kAddF);
1063 }
1064 this->write(ByteCodeInstruction::kSqrt);
1065 } break;
1066
Brian Osman8842b372020-05-01 15:07:49 -04001067 case SpecialIntrinsic::kMix: {
1068 // Two main variants of mix to handle
1069 SkASSERT(c.fArguments.size() == 3);
1070 SkASSERT(count == SlotCount(c.fArguments[1]->fType));
1071 int selectorCount = SlotCount(c.fArguments[2]->fType);
1072
1073 if (is_generic_type(&c.fArguments[2]->fType, fContext.fGenBType_Type.get())) {
1074 // mix(genType, genType, genBoolType)
1075 SkASSERT(selectorCount == count);
1076 this->write(vector_instruction(ByteCodeInstruction::kMix, count));
1077 } else {
1078 // mix(genType, genType, genType) or mix(genType, genType, float)
1079 SkASSERT(selectorCount == 1 || selectorCount == count);
1080 for (int i = selectorCount; i < count; ++i) {
1081 this->write(ByteCodeInstruction::kDup);
1082 }
1083 this->write(vector_instruction(ByteCodeInstruction::kLerp, count));
1084 }
1085 } break;
1086
Brian Osmanb08cc022020-04-02 11:38:40 -04001087 default:
1088 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001089 }
1090 } else {
Brian Osman8842b372020-05-01 15:07:49 -04001091 switch (intrin.inst_f) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001092 case ByteCodeInstruction::kInverse2x2: {
1093 SkASSERT(c.fArguments.size() > 0);
1094 auto op = ByteCodeInstruction::kInverse2x2;
1095 switch (count) {
1096 case 4: break; // float2x2
1097 case 9: op = ByteCodeInstruction::kInverse3x3; break;
1098 case 16: op = ByteCodeInstruction::kInverse4x4; break;
1099 default: SkASSERT(false);
1100 }
1101 this->write(op);
1102 break;
Brian Osman15c98cb2020-02-27 18:36:57 +00001103 }
Mike Klein45be0772020-05-01 09:13:18 -05001104
Brian Osmanb08cc022020-04-02 11:38:40 -04001105 default:
Brian Osman8842b372020-05-01 15:07:49 -04001106 this->writeTypedInstruction(c.fArguments[0]->fType, intrin.inst_s, intrin.inst_u,
1107 intrin.inst_f, count);
1108 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001109 }
1110 }
1111}
1112
Brian Osmanb08cc022020-04-02 11:38:40 -04001113void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001114 // Find the index of the function we're calling. We explicitly do not allow calls to functions
1115 // before they're defined. This is an easy-to-understand rule that prevents recursion.
Brian Osmanb08cc022020-04-02 11:38:40 -04001116 int idx = -1;
1117 for (size_t i = 0; i < fFunctions.size(); ++i) {
1118 if (f.fFunction.matches(fFunctions[i]->fDeclaration)) {
1119 idx = i;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001120 break;
1121 }
1122 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001123 if (idx == -1) {
1124 for (const auto& arg : f.fArguments) {
1125 this->writeExpression(*arg);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001126 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001127 this->writeIntrinsicCall(f);
1128 return;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001129 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001130
1131
1132 if (idx > 255) {
1133 fErrors.error(f.fOffset, "Function count limit exceeded");
1134 return;
1135 } else if (idx >= (int) fFunctions.size()) {
1136 fErrors.error(f.fOffset, "Call to undefined function");
1137 return;
1138 }
1139
1140 // We may need to deal with out parameters, so the sequence is tricky
1141 if (int returnCount = SlotCount(f.fType)) {
1142 this->write(ByteCodeInstruction::kReserve, returnCount);
1143 this->write8(returnCount);
1144 }
1145
1146 int argCount = f.fArguments.size();
1147 std::vector<std::unique_ptr<LValue>> lvalues;
1148 for (int i = 0; i < argCount; ++i) {
1149 const auto& param = f.fFunction.fParameters[i];
1150 const auto& arg = f.fArguments[i];
1151 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1152 lvalues.emplace_back(this->getLValue(*arg));
1153 lvalues.back()->load();
1154 } else {
1155 this->writeExpression(*arg);
1156 }
1157 }
1158
1159 // The space used by the call is based on the callee, but it also unwinds all of that before
1160 // we continue execution. We adjust our max stack depths below.
1161 this->write(ByteCodeInstruction::kCall);
1162 this->write8(idx);
1163
1164 const ByteCodeFunction* callee = fOutput->fFunctions[idx].get();
1165 fMaxLoopCount = std::max(fMaxLoopCount, fLoopCount + callee->fLoopCount);
1166 fMaxConditionCount = std::max(fMaxConditionCount, fConditionCount + callee->fConditionCount);
1167 fMaxStackCount = std::max(fMaxStackCount, fStackCount + callee->fLocalCount
1168 + callee->fStackCount);
1169
1170 // After the called function returns, the stack will still contain our arguments. We have to
1171 // pop them (storing any out parameters back to their lvalues as we go). We glob together slot
1172 // counts for all parameters that aren't out-params, so we can pop them in one big chunk.
1173 int popCount = 0;
1174 auto pop = [&]() {
1175 if (popCount > 4) {
1176 this->write(ByteCodeInstruction::kPopN, popCount);
1177 this->write8(popCount);
1178 } else if (popCount > 0) {
1179 this->write(vector_instruction(ByteCodeInstruction::kPop, popCount));
1180 }
1181 popCount = 0;
1182 };
1183
1184 for (int i = argCount - 1; i >= 0; --i) {
1185 const auto& param = f.fFunction.fParameters[i];
1186 const auto& arg = f.fArguments[i];
1187 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1188 pop();
1189 lvalues.back()->store(true);
1190 lvalues.pop_back();
1191 } else {
1192 popCount += SlotCount(arg->fType);
1193 }
1194 }
1195 pop();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001196}
1197
Brian Osmanb08cc022020-04-02 11:38:40 -04001198void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
1199 this->write(ByteCodeInstruction::kPushImmediate);
1200 this->write32(i.fValue);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001201}
1202
Brian Osmanb08cc022020-04-02 11:38:40 -04001203void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
1204 // not yet implemented
1205 abort();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001206}
1207
Brian Osmanb08cc022020-04-02 11:38:40 -04001208bool ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p, bool discard) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001209 switch (p.fOperator) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001210 case Token::Kind::TK_PLUSPLUS: // fall through
1211 case Token::Kind::TK_MINUSMINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001212 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1213 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
1214 lvalue->load();
1215 this->write(ByteCodeInstruction::kPushImmediate);
1216 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001217 if (p.fOperator == Token::Kind::TK_PLUSPLUS) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001218 this->writeTypedInstruction(p.fType,
1219 ByteCodeInstruction::kAddI,
1220 ByteCodeInstruction::kAddI,
1221 ByteCodeInstruction::kAddF,
1222 1);
1223 } else {
1224 this->writeTypedInstruction(p.fType,
1225 ByteCodeInstruction::kSubtractI,
1226 ByteCodeInstruction::kSubtractI,
1227 ByteCodeInstruction::kSubtractF,
1228 1);
1229 }
1230 lvalue->store(discard);
1231 discard = false;
1232 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001233 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001234 case Token::Kind::TK_MINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001235 this->writeExpression(*p.fOperand);
1236 this->writeTypedInstruction(p.fType,
1237 ByteCodeInstruction::kNegateI,
1238 ByteCodeInstruction::kNegateI,
1239 ByteCodeInstruction::kNegateF,
Brian Osmanab8f3842020-04-07 09:30:44 -04001240 SlotCount(p.fOperand->fType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001241 break;
1242 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001243 case Token::Kind::TK_LOGICALNOT:
1244 case Token::Kind::TK_BITWISENOT: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001245 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1246 SkDEBUGCODE(TypeCategory tc = type_category(p.fOperand->fType));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001247 SkASSERT((p.fOperator == Token::Kind::TK_LOGICALNOT && tc == TypeCategory::kBool) ||
1248 (p.fOperator == Token::Kind::TK_BITWISENOT && (tc == TypeCategory::kSigned ||
Brian Osmanb08cc022020-04-02 11:38:40 -04001249 tc == TypeCategory::kUnsigned)));
1250 this->writeExpression(*p.fOperand);
1251 this->write(ByteCodeInstruction::kNotB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001252 break;
1253 }
1254 default:
1255 SkASSERT(false);
1256 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001257 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001258}
1259
Brian Osmanb08cc022020-04-02 11:38:40 -04001260bool ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p, bool discard) {
1261 switch (p.fOperator) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001262 case Token::Kind::TK_PLUSPLUS: // fall through
1263 case Token::Kind::TK_MINUSMINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001264 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1265 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
1266 lvalue->load();
1267 // If we're not supposed to discard the result, then make a copy *before* the +/-
1268 if (!discard) {
1269 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -04001270 }
1271 this->write(ByteCodeInstruction::kPushImmediate);
1272 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001273 if (p.fOperator == Token::Kind::TK_PLUSPLUS) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001274 this->writeTypedInstruction(p.fType,
1275 ByteCodeInstruction::kAddI,
1276 ByteCodeInstruction::kAddI,
1277 ByteCodeInstruction::kAddF,
1278 1);
1279 } else {
1280 this->writeTypedInstruction(p.fType,
1281 ByteCodeInstruction::kSubtractI,
1282 ByteCodeInstruction::kSubtractI,
1283 ByteCodeInstruction::kSubtractF,
1284 1);
1285 }
1286 // Always consume the result as part of the store
1287 lvalue->store(true);
1288 discard = false;
1289 break;
1290 }
1291 default:
1292 SkASSERT(false);
1293 }
1294 return discard;
1295}
1296
1297void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001298 if (swizzle_is_simple(s)) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001299 this->writeVariableExpression(s);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001300 return;
1301 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001302
1303 switch (s.fBase->fKind) {
1304 case Expression::kVariableReference_Kind: {
1305 Location location = this->getLocation(*s.fBase);
1306 this->write(location.selectLoad(ByteCodeInstruction::kLoadSwizzle,
1307 ByteCodeInstruction::kLoadSwizzleGlobal,
1308 ByteCodeInstruction::kLoadSwizzleUniform),
1309 s.fComponents.size());
1310 this->write8(location.fSlot);
1311 this->write8(s.fComponents.size());
1312 for (int c : s.fComponents) {
1313 this->write8(c);
1314 }
1315 break;
1316 }
1317 default:
1318 this->writeExpression(*s.fBase);
1319 this->write(ByteCodeInstruction::kSwizzle,
1320 s.fComponents.size() - s.fBase->fType.columns());
1321 this->write8(s.fBase->fType.columns());
1322 this->write8(s.fComponents.size());
1323 for (int c : s.fComponents) {
1324 this->write8(c);
1325 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001326 }
1327}
1328
Brian Osmanb08cc022020-04-02 11:38:40 -04001329void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001330 int count = SlotCount(t.fType);
1331 SkASSERT(count == SlotCount(t.fIfTrue->fType));
1332 SkASSERT(count == SlotCount(t.fIfFalse->fType));
1333
Brian Osmanb08cc022020-04-02 11:38:40 -04001334 this->writeExpression(*t.fTest);
1335 this->write(ByteCodeInstruction::kMaskPush);
1336 this->writeExpression(*t.fIfTrue);
1337 this->write(ByteCodeInstruction::kMaskNegate);
1338 this->writeExpression(*t.fIfFalse);
1339 this->write(ByteCodeInstruction::kMaskBlend, count);
1340 this->write8(count);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001341}
1342
Brian Osmanb08cc022020-04-02 11:38:40 -04001343void ByteCodeGenerator::writeExpression(const Expression& e, bool discard) {
1344 switch (e.fKind) {
1345 case Expression::kBinary_Kind:
1346 discard = this->writeBinaryExpression((BinaryExpression&) e, discard);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001347 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001348 case Expression::kBoolLiteral_Kind:
1349 this->writeBoolLiteral((BoolLiteral&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001350 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001351 case Expression::kConstructor_Kind:
1352 this->writeConstructor((Constructor&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001353 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001354 case Expression::kExternalFunctionCall_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001355 this->writeExternalFunctionCall((ExternalFunctionCall&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001356 break;
1357 case Expression::kExternalValue_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001358 this->writeExternalValue((ExternalValueReference&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001359 break;
1360 case Expression::kFieldAccess_Kind:
1361 case Expression::kIndex_Kind:
1362 case Expression::kVariableReference_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001363 this->writeVariableExpression(e);
1364 break;
1365 case Expression::kFloatLiteral_Kind:
1366 this->writeFloatLiteral((FloatLiteral&) e);
1367 break;
1368 case Expression::kFunctionCall_Kind:
1369 this->writeFunctionCall((FunctionCall&) e);
1370 break;
1371 case Expression::kIntLiteral_Kind:
1372 this->writeIntLiteral((IntLiteral&) e);
1373 break;
1374 case Expression::kNullLiteral_Kind:
1375 this->writeNullLiteral((NullLiteral&) e);
1376 break;
1377 case Expression::kPrefix_Kind:
1378 discard = this->writePrefixExpression((PrefixExpression&) e, discard);
1379 break;
1380 case Expression::kPostfix_Kind:
1381 discard = this->writePostfixExpression((PostfixExpression&) e, discard);
1382 break;
1383 case Expression::kSwizzle_Kind:
1384 this->writeSwizzle((Swizzle&) e);
1385 break;
1386 case Expression::kTernary_Kind:
1387 this->writeTernaryExpression((TernaryExpression&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001388 break;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001389 default:
1390#ifdef SK_DEBUG
Brian Osmanb08cc022020-04-02 11:38:40 -04001391 printf("unsupported expression %s\n", e.description().c_str());
Ben Wagner470e0ac2020-01-22 16:59:21 -05001392#endif
Brian Osmanb08cc022020-04-02 11:38:40 -04001393 SkASSERT(false);
1394 }
1395 if (discard) {
1396 int count = SlotCount(e.fType);
1397 if (count > 4) {
1398 this->write(ByteCodeInstruction::kPopN, count);
1399 this->write8(count);
1400 } else if (count != 0) {
1401 this->write(vector_instruction(ByteCodeInstruction::kPop, count));
1402 }
1403 discard = false;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001404 }
Ethan Nicholas7deb1c22020-01-22 10:31:55 -05001405}
1406
Brian Osmanb08cc022020-04-02 11:38:40 -04001407class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
1408public:
1409 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
1410 : INHERITED(*generator)
1411 , fCount(ByteCodeGenerator::SlotCount(value.type()))
1412 , fIndex(index) {}
1413
1414 void load() override {
1415 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001416 fGenerator.write8(fIndex);
1417 }
1418
1419 void store(bool discard) override {
1420 if (!discard) {
1421 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001422 }
1423 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001424 fGenerator.write8(fIndex);
1425 }
1426
1427private:
1428 typedef LValue INHERITED;
1429
1430 int fCount;
1431
1432 int fIndex;
1433};
1434
1435class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
1436public:
1437 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
1438 : INHERITED(*generator)
1439 , fSwizzle(swizzle) {}
1440
1441 void load() override {
1442 fGenerator.writeSwizzle(fSwizzle);
1443 }
1444
1445 void store(bool discard) override {
1446 int count = fSwizzle.fComponents.size();
1447 if (!discard) {
1448 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001449 }
1450 ByteCodeGenerator::Location location = fGenerator.getLocation(*fSwizzle.fBase);
1451 if (location.isOnStack()) {
1452 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreSwizzleIndirect,
1453 ByteCodeInstruction::kStoreSwizzleIndirectGlobal),
1454 count);
1455 } else {
1456 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreSwizzle,
1457 ByteCodeInstruction::kStoreSwizzleGlobal),
1458 count);
1459 fGenerator.write8(location.fSlot);
1460 }
1461 fGenerator.write8(count);
1462 for (int c : fSwizzle.fComponents) {
1463 fGenerator.write8(c);
1464 }
1465 }
1466
1467private:
1468 const Swizzle& fSwizzle;
1469
1470 typedef LValue INHERITED;
1471};
1472
1473class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
1474public:
1475 ByteCodeExpressionLValue(ByteCodeGenerator* generator, const Expression& expr)
1476 : INHERITED(*generator)
1477 , fExpression(expr) {}
1478
1479 void load() override {
1480 fGenerator.writeVariableExpression(fExpression);
1481 }
1482
1483 void store(bool discard) override {
1484 int count = ByteCodeGenerator::SlotCount(fExpression.fType);
1485 if (!discard) {
1486 if (count > 4) {
1487 fGenerator.write(ByteCodeInstruction::kDupN, count);
1488 fGenerator.write8(count);
1489 } else {
1490 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001491 }
1492 }
1493 ByteCodeGenerator::Location location = fGenerator.getLocation(fExpression);
1494 if (location.isOnStack() || count > 4) {
1495 if (!location.isOnStack()) {
1496 fGenerator.write(ByteCodeInstruction::kPushImmediate);
1497 fGenerator.write32(location.fSlot);
1498 }
1499 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreExtended,
1500 ByteCodeInstruction::kStoreExtendedGlobal),
1501 count);
1502 fGenerator.write8(count);
1503 } else {
1504 fGenerator.write(
1505 vector_instruction(location.selectStore(ByteCodeInstruction::kStore,
1506 ByteCodeInstruction::kStoreGlobal),
1507 count));
1508 fGenerator.write8(location.fSlot);
1509 }
1510 }
1511
1512private:
1513 typedef LValue INHERITED;
1514
1515 const Expression& fExpression;
1516};
1517
1518std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
1519 switch (e.fKind) {
1520 case Expression::kExternalValue_Kind: {
1521 ExternalValue* value = ((ExternalValueReference&) e).fValue;
1522 int index = fOutput->fExternalValues.size();
1523 fOutput->fExternalValues.push_back(value);
1524 SkASSERT(index <= 255);
1525 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
1526 }
1527 case Expression::kFieldAccess_Kind:
1528 case Expression::kIndex_Kind:
1529 case Expression::kVariableReference_Kind:
1530 return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
1531 case Expression::kSwizzle_Kind: {
1532 const Swizzle& s = (const Swizzle&) e;
1533 return swizzle_is_simple(s)
1534 ? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e))
1535 : std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s));
1536 }
1537 case Expression::kTernary_Kind:
1538 default:
1539#ifdef SK_DEBUG
1540 ABORT("unsupported lvalue %s\n", e.description().c_str());
1541#endif
1542 return nullptr;
1543 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001544}
1545
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001546void ByteCodeGenerator::writeBlock(const Block& b) {
1547 for (const auto& s : b.fStatements) {
1548 this->writeStatement(*s);
1549 }
1550}
1551
Brian Osmanb08cc022020-04-02 11:38:40 -04001552void ByteCodeGenerator::setBreakTargets() {
1553 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
1554 for (DeferredLocation& b : breaks) {
1555 b.set();
1556 }
1557 fBreakTargets.pop();
1558}
1559
1560void ByteCodeGenerator::setContinueTargets() {
1561 std::vector<DeferredLocation>& continues = fContinueTargets.top();
1562 for (DeferredLocation& c : continues) {
1563 c.set();
1564 }
1565 fContinueTargets.pop();
1566}
1567
1568void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
1569 // TODO: Include BranchIfAllFalse to top-most LoopNext
1570 this->write(ByteCodeInstruction::kLoopBreak);
1571}
1572
1573void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
1574 // TODO: Include BranchIfAllFalse to top-most LoopNext
1575 this->write(ByteCodeInstruction::kLoopContinue);
1576}
1577
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001578void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001579 this->write(ByteCodeInstruction::kLoopBegin);
1580 size_t start = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001581 this->writeStatement(*d.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001582 this->write(ByteCodeInstruction::kLoopNext);
1583 this->writeExpression(*d.fTest);
1584 this->write(ByteCodeInstruction::kLoopMask);
1585 // TODO: Could shorten this with kBranchIfAnyTrue
1586 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001587 DeferredLocation endLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -04001588 this->write(ByteCodeInstruction::kBranch);
1589 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001590 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001591 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001592}
1593
1594void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001595 fContinueTargets.emplace();
1596 fBreakTargets.emplace();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001597 if (f.fInitializer) {
1598 this->writeStatement(*f.fInitializer);
1599 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001600 this->write(ByteCodeInstruction::kLoopBegin);
1601 size_t start = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001602 if (f.fTest) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001603 this->writeExpression(*f.fTest);
1604 this->write(ByteCodeInstruction::kLoopMask);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001605 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001606 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001607 DeferredLocation endLocation(this);
1608 this->writeStatement(*f.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001609 this->write(ByteCodeInstruction::kLoopNext);
Brian Osman569f12f2019-06-13 11:23:57 -04001610 if (f.fNext) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001611 this->writeExpression(*f.fNext, true);
Brian Osman569f12f2019-06-13 11:23:57 -04001612 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001613 this->write(ByteCodeInstruction::kBranch);
1614 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001615 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001616 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001617}
1618
1619void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001620 this->writeExpression(*i.fTest);
1621 this->write(ByteCodeInstruction::kMaskPush);
1622 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001623 DeferredLocation falseLocation(this);
1624 this->writeStatement(*i.fIfTrue);
1625 falseLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001626 if (i.fIfFalse) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001627 this->write(ByteCodeInstruction::kMaskNegate);
1628 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001629 DeferredLocation endLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001630 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -05001631 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001632 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001633 this->write(ByteCodeInstruction::kMaskPop);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001634}
1635
Brian Osmanb08cc022020-04-02 11:38:40 -04001636void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
1637 if (fLoopCount || fConditionCount) {
Brian Osman4a47da72019-07-12 11:30:32 -04001638 fErrors.error(r.fOffset, "return not allowed inside conditional or loop");
1639 return;
1640 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001641 int count = SlotCount(r.fExpression->fType);
1642 this->writeExpression(*r.fExpression);
1643
1644 // Technically, the kReturn also pops fOutput->fLocalCount values from the stack, too, but we
1645 // haven't counted pushing those (they're outside the scope of our stack tracking). Instead,
1646 // we account for those in writeFunction().
1647
1648 // This is all fine because we don't allow conditional returns, so we only return once anyway.
1649 this->write(ByteCodeInstruction::kReturn, -count);
1650 this->write8(count);
1651}
1652
1653void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
1654 // not yet implemented
1655 abort();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001656}
1657
1658void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1659 for (const auto& declStatement : v.fVars) {
1660 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
Brian Osmanb08cc022020-04-02 11:38:40 -04001661 // we need to grab the location even if we don't use it, to ensure it has been allocated
1662 Location location = this->getLocation(*decl.fVar);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001663 if (decl.fValue) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001664 this->writeExpression(*decl.fValue);
1665 int count = SlotCount(decl.fValue->fType);
1666 if (count > 4) {
1667 this->write(ByteCodeInstruction::kPushImmediate);
1668 this->write32(location.fSlot);
1669 this->write(ByteCodeInstruction::kStoreExtended, count);
1670 this->write8(count);
1671 } else {
1672 this->write(vector_instruction(ByteCodeInstruction::kStore, count));
1673 this->write8(location.fSlot);
1674 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001675 }
1676 }
1677}
1678
1679void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001680 this->write(ByteCodeInstruction::kLoopBegin);
1681 size_t cond = fCode->size();
1682 this->writeExpression(*w.fTest);
1683 this->write(ByteCodeInstruction::kLoopMask);
1684 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001685 DeferredLocation endLocation(this);
1686 this->writeStatement(*w.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001687 this->write(ByteCodeInstruction::kLoopNext);
1688 this->write(ByteCodeInstruction::kBranch);
1689 this->write16(cond);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -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::writeStatement(const Statement& s) {
1695 switch (s.fKind) {
1696 case Statement::kBlock_Kind:
1697 this->writeBlock((Block&) s);
1698 break;
1699 case Statement::kBreak_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001700 this->writeBreakStatement((BreakStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001701 break;
1702 case Statement::kContinue_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001703 this->writeContinueStatement((ContinueStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001704 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001705 case Statement::kDiscard_Kind:
1706 // not yet implemented
1707 abort();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001708 case Statement::kDo_Kind:
1709 this->writeDoStatement((DoStatement&) s);
1710 break;
Brian Osman3e29f1d2019-05-28 09:35:05 -04001711 case Statement::kExpression_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001712 this->writeExpression(*((ExpressionStatement&) s).fExpression, true);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001713 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001714 case Statement::kFor_Kind:
1715 this->writeForStatement((ForStatement&) s);
1716 break;
1717 case Statement::kIf_Kind:
1718 this->writeIfStatement((IfStatement&) s);
1719 break;
1720 case Statement::kNop_Kind:
1721 break;
1722 case Statement::kReturn_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001723 this->writeReturnStatement((ReturnStatement&) s);
1724 break;
1725 case Statement::kSwitch_Kind:
1726 this->writeSwitchStatement((SwitchStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001727 break;
1728 case Statement::kVarDeclarations_Kind:
1729 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1730 break;
1731 case Statement::kWhile_Kind:
1732 this->writeWhileStatement((WhileStatement&) s);
1733 break;
1734 default:
Brian Osmanb08cc022020-04-02 11:38:40 -04001735 SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001736 }
1737}
1738
Brian Osmanb08cc022020-04-02 11:38:40 -04001739ByteCodeFunction::ByteCodeFunction(const FunctionDeclaration* declaration)
1740 : fName(declaration->fName) {
Brian Osman80164412019-06-07 13:00:23 -04001741 fParameterCount = 0;
Brian Osmanb08cc022020-04-02 11:38:40 -04001742 for (const auto& p : declaration->fParameters) {
1743 int slots = ByteCodeGenerator::SlotCount(p->fType);
1744 fParameters.push_back({ slots, (bool)(p->fModifiers.fFlags & Modifiers::kOut_Flag) });
1745 fParameterCount += slots;
Brian Osman80164412019-06-07 13:00:23 -04001746 }
1747}
1748
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001749}