blob: 2659647e9acd29762ef090a6388178e6e5578a69 [file] [log] [blame]
Mike Reed8520e762020-04-30 12:06:23 -04001/*
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04002 * Copyright 2019 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/sksl/SkSLByteCodeGenerator.h"
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04009
Brian Osmanb08cc022020-04-02 11:38:40 -040010#include <algorithm>
11
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040012namespace SkSL {
13
Brian Osmanb08cc022020-04-02 11:38:40 -040014static TypeCategory type_category(const Type& type) {
15 switch (type.kind()) {
16 case Type::Kind::kVector_Kind:
17 case Type::Kind::kMatrix_Kind:
18 return type_category(type.componentType());
19 default:
20 if (type.fName == "bool") {
21 return TypeCategory::kBool;
22 } else if (type.fName == "int" ||
23 type.fName == "short" ||
24 type.fName == "$intLiteral") {
25 return TypeCategory::kSigned;
26 } else if (type.fName == "uint" ||
27 type.fName == "ushort") {
28 return TypeCategory::kUnsigned;
29 } else {
30 SkASSERT(type.fName == "float" ||
31 type.fName == "half" ||
32 type.fName == "$floatLiteral");
33 return TypeCategory::kFloat;
34 }
35 ABORT("unsupported type: %s\n", type.displayName().c_str());
36 }
37}
38
39
40ByteCodeGenerator::ByteCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
41 ByteCode* output)
Ethan Nicholas82162ee2019-05-21 16:05:08 -040042 : INHERITED(program, errors, nullptr)
Brian Osmanb08cc022020-04-02 11:38:40 -040043 , fContext(*context)
Ethan Nicholasae9633b2019-05-24 12:46:34 -040044 , fOutput(output)
45 , fIntrinsics {
Mike Reed8520e762020-04-30 12:06:23 -040046 { "atan", ByteCodeInstruction::kATan },
Brian Osmanb08cc022020-04-02 11:38:40 -040047 { "cos", ByteCodeInstruction::kCos },
Brian Osman15c98cb2020-02-27 18:36:57 +000048 { "dot", SpecialIntrinsic::kDot },
Mike Reed8520e762020-04-30 12:06:23 -040049 { "fract", ByteCodeInstruction::kFract },
Brian Osmanb08cc022020-04-02 11:38:40 -040050 { "inverse", ByteCodeInstruction::kInverse2x2 },
Mike Klein45be0772020-05-01 09:13:18 -050051 { "length", SpecialIntrinsic::kLength },
Brian Osman8842b372020-05-01 15:07:49 -040052 { "mix", SpecialIntrinsic::kMix },
Florin Malita3facc9c2020-05-04 09:26:15 -040053 { "pow", ByteCodeInstruction::kPow },
Brian Osmanb08cc022020-04-02 11:38:40 -040054 { "sin", ByteCodeInstruction::kSin },
55 { "sqrt", ByteCodeInstruction::kSqrt },
56 { "tan", ByteCodeInstruction::kTan },
Brian Osman8842b372020-05-01 15:07:49 -040057
58 { "lessThan", { ByteCodeInstruction::kCompareFLT,
59 ByteCodeInstruction::kCompareSLT,
60 ByteCodeInstruction::kCompareULT } },
61 { "lessThanEqual", { ByteCodeInstruction::kCompareFLTEQ,
62 ByteCodeInstruction::kCompareSLTEQ,
63 ByteCodeInstruction::kCompareULTEQ } },
64 { "greaterThan", { ByteCodeInstruction::kCompareFGT,
65 ByteCodeInstruction::kCompareSGT,
66 ByteCodeInstruction::kCompareUGT } },
67 { "greaterThanEqual", { ByteCodeInstruction::kCompareFGTEQ,
68 ByteCodeInstruction::kCompareSGTEQ,
69 ByteCodeInstruction::kCompareUGTEQ } },
70 { "equal", { ByteCodeInstruction::kCompareFEQ,
71 ByteCodeInstruction::kCompareIEQ,
72 ByteCodeInstruction::kCompareIEQ } },
73 { "notEqual", { ByteCodeInstruction::kCompareFNEQ,
74 ByteCodeInstruction::kCompareINEQ,
75 ByteCodeInstruction::kCompareINEQ } },
76
77 { "any", SpecialIntrinsic::kAny },
78 { "all", SpecialIntrinsic::kAll },
79 { "not", ByteCodeInstruction::kNotB },
80 } {}
Brian Osmanb08cc022020-04-02 11:38:40 -040081
Ethan Nicholas82162ee2019-05-21 16:05:08 -040082
Brian Osman07c117b2019-05-23 12:51:06 -070083int ByteCodeGenerator::SlotCount(const Type& type) {
Brian Osmanfba386b2019-06-20 14:54:15 -040084 if (type.kind() == Type::kOther_Kind) {
85 return 0;
86 } else if (type.kind() == Type::kStruct_Kind) {
Brian Osman07c117b2019-05-23 12:51:06 -070087 int slots = 0;
88 for (const auto& f : type.fields()) {
89 slots += SlotCount(*f.fType);
90 }
91 SkASSERT(slots <= 255);
92 return slots;
93 } else if (type.kind() == Type::kArray_Kind) {
94 int columns = type.columns();
95 SkASSERT(columns >= 0);
96 int slots = columns * SlotCount(type.componentType());
97 SkASSERT(slots <= 255);
98 return slots;
99 } else {
100 return type.columns() * type.rows();
101 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400102}
103
Brian Osman1c110a02019-10-01 14:53:32 -0400104static inline bool is_uniform(const SkSL::Variable& var) {
105 return var.fModifiers.fFlags & Modifiers::kUniform_Flag;
106}
107
Brian Osmaneadfeb92020-01-09 12:43:03 -0500108static inline bool is_in(const SkSL::Variable& var) {
109 return var.fModifiers.fFlags & Modifiers::kIn_Flag;
110}
Brian Osmanb08cc022020-04-02 11:38:40 -0400111
112void ByteCodeGenerator::gatherUniforms(const Type& type, const String& name) {
113 if (type.kind() == Type::kOther_Kind) {
114 return;
115 } else if (type.kind() == Type::kStruct_Kind) {
116 for (const auto& f : type.fields()) {
117 this->gatherUniforms(*f.fType, name + "." + f.fName);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500118 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400119 } else if (type.kind() == Type::kArray_Kind) {
120 for (int i = 0; i < type.columns(); ++i) {
121 this->gatherUniforms(type.componentType(), String::printf("%s[%d]", name.c_str(), i));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500122 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400123 } else {
124 fOutput->fUniforms.push_back({ name, type_category(type), type.rows(), type.columns(),
125 fOutput->fUniformSlotCount });
126 fOutput->fUniformSlotCount += type.columns() * type.rows();
127 }
128}
129
130bool ByteCodeGenerator::generateCode() {
131 for (const auto& e : fProgram) {
132 switch (e.fKind) {
133 case ProgramElement::kFunction_Kind: {
134 std::unique_ptr<ByteCodeFunction> f = this->writeFunction((FunctionDefinition&) e);
135 if (!f) {
136 return false;
137 }
138 fOutput->fFunctions.push_back(std::move(f));
139 fFunctions.push_back(&(FunctionDefinition&)e);
140 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500141 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400142 case ProgramElement::kVar_Kind: {
143 VarDeclarations& decl = (VarDeclarations&) e;
144 for (const auto& v : decl.fVars) {
145 const Variable* declVar = ((VarDeclaration&) *v).fVar;
146 if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
147 continue;
148 }
149 if (is_uniform(*declVar)) {
150 this->gatherUniforms(declVar->fType, declVar->fName);
151 } else {
152 fOutput->fGlobalSlotCount += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400153 }
154 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400155 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400156 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400157 default:
158 ; // ignore
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400159 }
160 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400161 return 0 == fErrors.errorCount();
162}
163
164std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
165 fFunction = &f;
166 std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
167 fParameterCount = result->fParameterCount;
168 fLoopCount = fMaxLoopCount = 0;
169 fConditionCount = fMaxConditionCount = 0;
170 fStackCount = fMaxStackCount = 0;
171 fCode = &result->fCode;
172
173 this->writeStatement(*f.fBody);
174 if (0 == fErrors.errorCount()) {
175 SkASSERT(fLoopCount == 0);
176 SkASSERT(fConditionCount == 0);
177 SkASSERT(fStackCount == 0);
178 }
179 this->write(ByteCodeInstruction::kReturn, 0);
180 this->write8(0);
181
182 result->fLocalCount = fLocals.size();
183 result->fConditionCount = fMaxConditionCount;
184 result->fLoopCount = fMaxLoopCount;
185 result->fStackCount = fMaxStackCount;
186
187 const Type& returnType = f.fDeclaration.fReturnType;
188 if (returnType != *fContext.fVoid_Type) {
189 result->fReturnCount = SlotCount(returnType);
190 }
191 fLocals.clear();
192 fFunction = nullptr;
193 return result;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400194}
195
Brian Osman0785db02019-05-24 14:19:11 -0400196// A "simple" Swizzle is based on a variable (or a compound variable like a struct or array), and
197// that references consecutive values, such that it can be implemented using normal load/store ops
198// with an offset. Note that all single-component swizzles (of suitable base types) are simple.
199static bool swizzle_is_simple(const Swizzle& s) {
200 switch (s.fBase->fKind) {
201 case Expression::kFieldAccess_Kind:
202 case Expression::kIndex_Kind:
203 case Expression::kVariableReference_Kind:
204 break;
205 default:
206 return false;
207 }
208
209 for (size_t i = 1; i < s.fComponents.size(); ++i) {
210 if (s.fComponents[i] != s.fComponents[i - 1] + 1) {
211 return false;
212 }
213 }
214 return true;
215}
216
Brian Osmanb08cc022020-04-02 11:38:40 -0400217int ByteCodeGenerator::StackUsage(ByteCodeInstruction inst, int count_) {
218 // Ensures that we use count iff we're passed a non-default value. Most instructions have an
219 // implicit count, so the caller shouldn't need to worry about it (or count makes no sense).
220 // The asserts avoids callers thinking they're supplying useful information in that scenario,
221 // or failing to supply necessary information for the ops that need a count.
222 struct CountValue {
223 operator int() {
224 SkASSERT(val != ByteCodeGenerator::kUnusedStackCount);
225 SkDEBUGCODE(used = true);
226 return val;
227 }
228 ~CountValue() {
229 SkASSERT(used || val == ByteCodeGenerator::kUnusedStackCount);
230 }
231 int val;
232 SkDEBUGCODE(bool used = false;)
233 } count = { count_ };
234
235 switch (inst) {
236 // Unary functions/operators that don't change stack depth at all:
237#define VECTOR_UNARY_OP(base) \
238 case ByteCodeInstruction::base: \
239 case ByteCodeInstruction::base ## 2: \
240 case ByteCodeInstruction::base ## 3: \
241 case ByteCodeInstruction::base ## 4: \
242 return 0;
243
244 VECTOR_UNARY_OP(kConvertFtoI)
245 VECTOR_UNARY_OP(kConvertStoF)
246 VECTOR_UNARY_OP(kConvertUtoF)
247
Mike Reed8520e762020-04-30 12:06:23 -0400248 VECTOR_UNARY_OP(kATan)
Brian Osmanb08cc022020-04-02 11:38:40 -0400249 VECTOR_UNARY_OP(kCos)
Mike Reed8520e762020-04-30 12:06:23 -0400250 VECTOR_UNARY_OP(kFract)
Brian Osmanb08cc022020-04-02 11:38:40 -0400251 VECTOR_UNARY_OP(kSin)
252 VECTOR_UNARY_OP(kSqrt)
253 VECTOR_UNARY_OP(kTan)
254
255 VECTOR_UNARY_OP(kNegateF)
256 VECTOR_UNARY_OP(kNegateI)
Brian Osman8842b372020-05-01 15:07:49 -0400257 VECTOR_UNARY_OP(kNotB)
Brian Osmanb08cc022020-04-02 11:38:40 -0400258
259 case ByteCodeInstruction::kInverse2x2:
260 case ByteCodeInstruction::kInverse3x3:
261 case ByteCodeInstruction::kInverse4x4: return 0;
262
263 case ByteCodeInstruction::kClampIndex: return 0;
Brian Osmanb08cc022020-04-02 11:38:40 -0400264 case ByteCodeInstruction::kNegateFN: return 0;
265 case ByteCodeInstruction::kShiftLeft: return 0;
266 case ByteCodeInstruction::kShiftRightS: return 0;
267 case ByteCodeInstruction::kShiftRightU: return 0;
268
269#undef VECTOR_UNARY_OP
270
271 // Binary functions/operators that do a 2 -> 1 reduction (possibly N times)
272#define VECTOR_BINARY_OP(base) \
273 case ByteCodeInstruction::base: return -1; \
274 case ByteCodeInstruction::base ## 2: return -2; \
275 case ByteCodeInstruction::base ## 3: return -3; \
276 case ByteCodeInstruction::base ## 4: return -4;
277
278#define VECTOR_MATRIX_BINARY_OP(base) \
279 VECTOR_BINARY_OP(base) \
280 case ByteCodeInstruction::base ## N: return -count;
281
282 case ByteCodeInstruction::kAndB: return -1;
283 case ByteCodeInstruction::kOrB: return -1;
284 case ByteCodeInstruction::kXorB: return -1;
285
286 VECTOR_BINARY_OP(kAddI)
287 VECTOR_MATRIX_BINARY_OP(kAddF)
288
289 VECTOR_BINARY_OP(kCompareIEQ)
290 VECTOR_MATRIX_BINARY_OP(kCompareFEQ)
291 VECTOR_BINARY_OP(kCompareINEQ)
292 VECTOR_MATRIX_BINARY_OP(kCompareFNEQ)
293 VECTOR_BINARY_OP(kCompareSGT)
294 VECTOR_BINARY_OP(kCompareUGT)
295 VECTOR_BINARY_OP(kCompareFGT)
296 VECTOR_BINARY_OP(kCompareSGTEQ)
297 VECTOR_BINARY_OP(kCompareUGTEQ)
298 VECTOR_BINARY_OP(kCompareFGTEQ)
299 VECTOR_BINARY_OP(kCompareSLT)
300 VECTOR_BINARY_OP(kCompareULT)
301 VECTOR_BINARY_OP(kCompareFLT)
302 VECTOR_BINARY_OP(kCompareSLTEQ)
303 VECTOR_BINARY_OP(kCompareULTEQ)
304 VECTOR_BINARY_OP(kCompareFLTEQ)
305
306 VECTOR_BINARY_OP(kDivideS)
307 VECTOR_BINARY_OP(kDivideU)
308 VECTOR_MATRIX_BINARY_OP(kDivideF)
309 VECTOR_BINARY_OP(kMultiplyI)
310 VECTOR_MATRIX_BINARY_OP(kMultiplyF)
Florin Malita3facc9c2020-05-04 09:26:15 -0400311 VECTOR_BINARY_OP(kPow)
Brian Osmanb08cc022020-04-02 11:38:40 -0400312 VECTOR_BINARY_OP(kRemainderF)
313 VECTOR_BINARY_OP(kRemainderS)
314 VECTOR_BINARY_OP(kRemainderU)
315 VECTOR_BINARY_OP(kSubtractI)
316 VECTOR_MATRIX_BINARY_OP(kSubtractF)
317
318#undef VECTOR_BINARY_OP
319#undef VECTOR_MATRIX_BINARY_OP
320
321 // Ops that push or load data to grow the stack:
322 case ByteCodeInstruction::kDup:
323 case ByteCodeInstruction::kLoad:
324 case ByteCodeInstruction::kLoadGlobal:
325 case ByteCodeInstruction::kLoadUniform:
326 case ByteCodeInstruction::kReadExternal:
327 case ByteCodeInstruction::kPushImmediate:
328 return 1;
329
330 case ByteCodeInstruction::kDup2:
331 case ByteCodeInstruction::kLoad2:
332 case ByteCodeInstruction::kLoadGlobal2:
333 case ByteCodeInstruction::kLoadUniform2:
334 case ByteCodeInstruction::kReadExternal2:
335 return 2;
336
337 case ByteCodeInstruction::kDup3:
338 case ByteCodeInstruction::kLoad3:
339 case ByteCodeInstruction::kLoadGlobal3:
340 case ByteCodeInstruction::kLoadUniform3:
341 case ByteCodeInstruction::kReadExternal3:
342 return 3;
343
344 case ByteCodeInstruction::kDup4:
345 case ByteCodeInstruction::kLoad4:
346 case ByteCodeInstruction::kLoadGlobal4:
347 case ByteCodeInstruction::kLoadUniform4:
348 case ByteCodeInstruction::kReadExternal4:
349 return 4;
350
351 case ByteCodeInstruction::kDupN:
352 case ByteCodeInstruction::kLoadSwizzle:
353 case ByteCodeInstruction::kLoadSwizzleGlobal:
354 case ByteCodeInstruction::kLoadSwizzleUniform:
355 return count;
356
357 // Pushes 'count' values, minus one for the 'address' that's consumed first
358 case ByteCodeInstruction::kLoadExtended:
359 case ByteCodeInstruction::kLoadExtendedGlobal:
360 case ByteCodeInstruction::kLoadExtendedUniform:
361 return count - 1;
362
363 // Ops that pop or store data to shrink the stack:
364 case ByteCodeInstruction::kPop:
365 case ByteCodeInstruction::kStore:
366 case ByteCodeInstruction::kStoreGlobal:
367 case ByteCodeInstruction::kWriteExternal:
368 return -1;
369
370 case ByteCodeInstruction::kPop2:
371 case ByteCodeInstruction::kStore2:
372 case ByteCodeInstruction::kStoreGlobal2:
373 case ByteCodeInstruction::kWriteExternal2:
374 return -2;
375
376 case ByteCodeInstruction::kPop3:
377 case ByteCodeInstruction::kStore3:
378 case ByteCodeInstruction::kStoreGlobal3:
379 case ByteCodeInstruction::kWriteExternal3:
380 return -3;
381
382 case ByteCodeInstruction::kPop4:
383 case ByteCodeInstruction::kStore4:
384 case ByteCodeInstruction::kStoreGlobal4:
385 case ByteCodeInstruction::kWriteExternal4:
386 return -4;
387
388 case ByteCodeInstruction::kPopN:
389 case ByteCodeInstruction::kStoreSwizzle:
390 case ByteCodeInstruction::kStoreSwizzleGlobal:
391 return -count;
392
393 // Consumes 'count' values, plus one for the 'address'
394 case ByteCodeInstruction::kStoreExtended:
395 case ByteCodeInstruction::kStoreExtendedGlobal:
396 case ByteCodeInstruction::kStoreSwizzleIndirect:
397 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal:
398 return -count - 1;
399
400 // Strange ops where the caller computes the delta for us:
401 case ByteCodeInstruction::kCallExternal:
402 case ByteCodeInstruction::kMatrixToMatrix:
403 case ByteCodeInstruction::kMatrixMultiply:
404 case ByteCodeInstruction::kReserve:
405 case ByteCodeInstruction::kReturn:
406 case ByteCodeInstruction::kScalarToMatrix:
407 case ByteCodeInstruction::kSwizzle:
408 return count;
409
410 // Miscellaneous
411
Brian Osman8842b372020-05-01 15:07:49 -0400412 // kMix does a 3 -> 1 reduction (A, B, M -> A -or- B) for each component
413 case ByteCodeInstruction::kMix: return -2;
414 case ByteCodeInstruction::kMix2: return -4;
415 case ByteCodeInstruction::kMix3: return -6;
416 case ByteCodeInstruction::kMix4: return -8;
417
418 // kLerp works the same way (producing lerp(A, B, T) for each component)
419 case ByteCodeInstruction::kLerp: return -2;
420 case ByteCodeInstruction::kLerp2: return -4;
421 case ByteCodeInstruction::kLerp3: return -6;
422 case ByteCodeInstruction::kLerp4: return -8;
423
Brian Osmanb08cc022020-04-02 11:38:40 -0400424 // kCall is net-zero. Max stack depth is adjusted in writeFunctionCall.
425 case ByteCodeInstruction::kCall: return 0;
426 case ByteCodeInstruction::kBranch: return 0;
427 case ByteCodeInstruction::kBranchIfAllFalse: return 0;
428
429 case ByteCodeInstruction::kMaskPush: return -1;
430 case ByteCodeInstruction::kMaskPop: return 0;
431 case ByteCodeInstruction::kMaskNegate: return 0;
432 case ByteCodeInstruction::kMaskBlend: return -count;
433
434 case ByteCodeInstruction::kLoopBegin: return 0;
435 case ByteCodeInstruction::kLoopNext: return 0;
436 case ByteCodeInstruction::kLoopMask: return -1;
437 case ByteCodeInstruction::kLoopEnd: return 0;
438 case ByteCodeInstruction::kLoopBreak: return 0;
439 case ByteCodeInstruction::kLoopContinue: return 0;
440
441 default:
442 ABORT("unsupported instruction %d\n", (int)inst);
443 return 0;
444 }
445}
446
447ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var) {
448 // given that we seldom have more than a couple of variables, linear search is probably the most
449 // efficient way to handle lookups
450 switch (var.fStorage) {
451 case Variable::kLocal_Storage: {
452 for (int i = fLocals.size() - 1; i >= 0; --i) {
453 if (fLocals[i] == &var) {
454 SkASSERT(fParameterCount + i <= 255);
455 return { fParameterCount + i, Storage::kLocal };
456 }
457 }
458 int result = fParameterCount + fLocals.size();
459 fLocals.push_back(&var);
460 for (int i = 0; i < SlotCount(var.fType) - 1; ++i) {
461 fLocals.push_back(nullptr);
462 }
463 SkASSERT(result <= 255);
464 return { result, Storage::kLocal };
465 }
466 case Variable::kParameter_Storage: {
467 int offset = 0;
468 for (const auto& p : fFunction->fDeclaration.fParameters) {
469 if (p == &var) {
470 SkASSERT(offset <= 255);
471 return { offset, Storage::kLocal };
472 }
473 offset += SlotCount(p->fType);
474 }
475 SkASSERT(false);
476 return Location::MakeInvalid();
477 }
478 case Variable::kGlobal_Storage: {
479 if (is_in(var)) {
480 // If you see this error, it means the program is using raw 'in' variables. You
481 // should either specialize the program (Compiler::specialize) to bake in the final
482 // values of the 'in' variables, or not use 'in' variables (maybe you meant to use
483 // 'uniform' instead?).
484 fErrors.error(var.fOffset,
485 "'in' variable is not specialized or has unsupported type");
486 return Location::MakeInvalid();
487 }
488 int offset = 0;
489 bool isUniform = is_uniform(var);
490 for (const auto& e : fProgram) {
491 if (e.fKind == ProgramElement::kVar_Kind) {
492 VarDeclarations& decl = (VarDeclarations&) e;
493 for (const auto& v : decl.fVars) {
494 const Variable* declVar = ((VarDeclaration&) *v).fVar;
495 if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
496 continue;
497 }
498 if (isUniform != is_uniform(*declVar)) {
499 continue;
500 }
501 if (declVar == &var) {
502 SkASSERT(offset <= 255);
503 return { offset, isUniform ? Storage::kUniform : Storage::kGlobal };
504 }
505 offset += SlotCount(declVar->fType);
506 }
507 }
508 }
509 SkASSERT(false);
510 return Location::MakeInvalid();
511 }
512 default:
513 SkASSERT(false);
514 return Location::MakeInvalid();
515 }
516}
517
Brian Osman1c110a02019-10-01 14:53:32 -0400518ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Expression& expr) {
Brian Osman07c117b2019-05-23 12:51:06 -0700519 switch (expr.fKind) {
520 case Expression::kFieldAccess_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400521 const FieldAccess& f = (const FieldAccess&)expr;
522 Location baseLoc = this->getLocation(*f.fBase);
Brian Osman07c117b2019-05-23 12:51:06 -0700523 int offset = 0;
524 for (int i = 0; i < f.fFieldIndex; ++i) {
525 offset += SlotCount(*f.fBase->fType.fields()[i].fType);
526 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400527 if (baseLoc.isOnStack()) {
528 if (offset != 0) {
529 this->write(ByteCodeInstruction::kPushImmediate);
530 this->write32(offset);
531 this->write(ByteCodeInstruction::kAddI);
Ben Wagner470e0ac2020-01-22 16:59:21 -0500532 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400533 return baseLoc;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500534 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400535 return baseLoc + offset;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500536 }
Ben Wagner470e0ac2020-01-22 16:59:21 -0500537 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400538 case Expression::kIndex_Kind: {
539 const IndexExpression& i = (const IndexExpression&)expr;
540 int stride = SlotCount(i.fType);
541 int length = i.fBase->fType.columns();
542 SkASSERT(length <= 255);
543 int offset = -1;
544 if (i.fIndex->isConstant()) {
545 int64_t index = i.fIndex->getConstantInt();
546 if (index < 0 || index >= length) {
547 fErrors.error(i.fIndex->fOffset, "Array index out of bounds.");
548 return Location::MakeInvalid();
549 }
550 offset = index * stride;
551 } else {
552 if (i.fIndex->hasSideEffects()) {
553 // Having a side-effect in an indexer is technically safe for an rvalue,
554 // but with lvalues we have to evaluate the indexer twice, so make it an error.
555 fErrors.error(i.fIndex->fOffset,
556 "Index expressions with side-effects not supported in byte code.");
557 return Location::MakeInvalid();
558 }
559 this->writeExpression(*i.fIndex);
560 this->write(ByteCodeInstruction::kClampIndex);
561 this->write8(length);
562 if (stride != 1) {
563 this->write(ByteCodeInstruction::kPushImmediate);
564 this->write32(stride);
565 this->write(ByteCodeInstruction::kMultiplyI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400566 }
567 }
568 Location baseLoc = this->getLocation(*i.fBase);
569
570 // Are both components known statically?
571 if (!baseLoc.isOnStack() && offset >= 0) {
572 return baseLoc + offset;
573 }
574
575 // At least one component is dynamic (and on the stack).
576
577 // If the other component is zero, we're done
578 if (baseLoc.fSlot == 0 || offset == 0) {
579 return baseLoc.makeOnStack();
580 }
581
582 // Push the non-dynamic component (if any) to the stack, then add the two
583 if (!baseLoc.isOnStack()) {
584 this->write(ByteCodeInstruction::kPushImmediate);
585 this->write32(baseLoc.fSlot);
586 }
587 if (offset >= 0) {
588 this->write(ByteCodeInstruction::kPushImmediate);
589 this->write32(offset);
590 }
591 this->write(ByteCodeInstruction::kAddI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400592 return baseLoc.makeOnStack();
593 }
Brian Osman0785db02019-05-24 14:19:11 -0400594 case Expression::kSwizzle_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400595 const Swizzle& s = (const Swizzle&)expr;
Brian Osman0785db02019-05-24 14:19:11 -0400596 SkASSERT(swizzle_is_simple(s));
Brian Osmanb08cc022020-04-02 11:38:40 -0400597 Location baseLoc = this->getLocation(*s.fBase);
598 int offset = s.fComponents[0];
599 if (baseLoc.isOnStack()) {
600 if (offset != 0) {
601 this->write(ByteCodeInstruction::kPushImmediate);
602 this->write32(offset);
603 this->write(ByteCodeInstruction::kAddI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400604 }
605 return baseLoc;
606 } else {
607 return baseLoc + offset;
608 }
Brian Osman0785db02019-05-24 14:19:11 -0400609 }
Brian Osman07c117b2019-05-23 12:51:06 -0700610 case Expression::kVariableReference_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400611 const Variable& var = ((const VariableReference&)expr).fVariable;
Brian Osman07c117b2019-05-23 12:51:06 -0700612 return this->getLocation(var);
613 }
614 default:
615 SkASSERT(false);
Brian Osmanb08cc022020-04-02 11:38:40 -0400616 return Location::MakeInvalid();
Brian Osman07c117b2019-05-23 12:51:06 -0700617 }
618}
619
Brian Osmanb08cc022020-04-02 11:38:40 -0400620void ByteCodeGenerator::write8(uint8_t b) {
621 fCode->push_back(b);
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500622}
623
Brian Osmanb08cc022020-04-02 11:38:40 -0400624void ByteCodeGenerator::write16(uint16_t i) {
625 size_t n = fCode->size();
626 fCode->resize(n+2);
627 memcpy(fCode->data() + n, &i, 2);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500628}
Ben Wagner470e0ac2020-01-22 16:59:21 -0500629
Brian Osmanb08cc022020-04-02 11:38:40 -0400630void ByteCodeGenerator::write32(uint32_t i) {
631 size_t n = fCode->size();
632 fCode->resize(n+4);
633 memcpy(fCode->data() + n, &i, 4);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500634}
635
Brian Osmanb08cc022020-04-02 11:38:40 -0400636void ByteCodeGenerator::write(ByteCodeInstruction i, int count) {
637 switch (i) {
638 case ByteCodeInstruction::kLoopBegin: this->enterLoop(); break;
639 case ByteCodeInstruction::kLoopEnd: this->exitLoop(); break;
Ethan Nicholas2329da02020-01-24 15:49:33 -0500640
Brian Osmanb08cc022020-04-02 11:38:40 -0400641 case ByteCodeInstruction::kMaskPush: this->enterCondition(); break;
642 case ByteCodeInstruction::kMaskPop:
643 case ByteCodeInstruction::kMaskBlend: this->exitCondition(); break;
644 default: /* Do nothing */ break;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500645 }
Brian Osmanab8f3842020-04-07 09:30:44 -0400646 this->write16((uint16_t)i);
Brian Osmanb08cc022020-04-02 11:38:40 -0400647 fStackCount += StackUsage(i, count);
648 fMaxStackCount = std::max(fMaxStackCount, fStackCount);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500649}
650
Brian Osmanb08cc022020-04-02 11:38:40 -0400651static ByteCodeInstruction vector_instruction(ByteCodeInstruction base, int count) {
652 SkASSERT(count >= 1 && count <= 4);
653 return ((ByteCodeInstruction) ((int) base + 1 - count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500654}
655
Brian Osmanb08cc022020-04-02 11:38:40 -0400656void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
657 ByteCodeInstruction u, ByteCodeInstruction f,
Brian Osmanab8f3842020-04-07 09:30:44 -0400658 int count) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500659 switch (type_category(type)) {
Brian Osman8842b372020-05-01 15:07:49 -0400660 case TypeCategory::kBool:
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500661 case TypeCategory::kSigned:
Brian Osmanb08cc022020-04-02 11:38:40 -0400662 this->write(vector_instruction(s, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500663 break;
664 case TypeCategory::kUnsigned:
Brian Osmanb08cc022020-04-02 11:38:40 -0400665 this->write(vector_instruction(u, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500666 break;
667 case TypeCategory::kFloat: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400668 if (count > 4) {
669 this->write((ByteCodeInstruction)((int)f + 1), count);
Brian Osmanab8f3842020-04-07 09:30:44 -0400670 this->write8(count);
Brian Osmanb08cc022020-04-02 11:38:40 -0400671 } else {
672 this->write(vector_instruction(f, count));
673 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500674 break;
675 }
676 default:
677 SkASSERT(false);
678 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500679}
680
Brian Osmanb08cc022020-04-02 11:38:40 -0400681bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool discard) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400682 if (b.fOperator == Token::Kind::TK_EQ) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500683 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
Brian Osmanb08cc022020-04-02 11:38:40 -0400684 this->writeExpression(*b.fRight);
685 lvalue->store(discard);
686 discard = false;
687 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500688 }
689 const Type& lType = b.fLeft->fType;
690 const Type& rType = b.fRight->fType;
691 bool lVecOrMtx = (lType.kind() == Type::kVector_Kind || lType.kind() == Type::kMatrix_Kind);
692 bool rVecOrMtx = (rType.kind() == Type::kVector_Kind || rType.kind() == Type::kMatrix_Kind);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500693 Token::Kind op;
694 std::unique_ptr<LValue> lvalue;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500695 if (is_assignment(b.fOperator)) {
696 lvalue = this->getLValue(*b.fLeft);
Brian Osmanb08cc022020-04-02 11:38:40 -0400697 lvalue->load();
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500698 op = remove_assignment(b.fOperator);
699 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400700 this->writeExpression(*b.fLeft);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500701 op = b.fOperator;
702 if (!lVecOrMtx && rVecOrMtx) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400703 for (int i = SlotCount(rType); i > 1; --i) {
704 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400705 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500706 }
707 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500708 int count = std::max(SlotCount(lType), SlotCount(rType));
Brian Osmanb08cc022020-04-02 11:38:40 -0400709 SkDEBUGCODE(TypeCategory tc = type_category(lType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500710 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400711 case Token::Kind::TK_LOGICALAND: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400712 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
713 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400714 this->write(ByteCodeInstruction::kMaskPush);
715 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500716 DeferredLocation falseLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -0400717 this->writeExpression(*b.fRight);
718 this->write(ByteCodeInstruction::kAndB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500719 falseLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -0400720 this->write(ByteCodeInstruction::kMaskPop);
721 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500722 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400723 case Token::Kind::TK_LOGICALOR: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400724 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
725 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400726 this->write(ByteCodeInstruction::kNotB);
727 this->write(ByteCodeInstruction::kMaskPush);
728 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500729 DeferredLocation falseLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -0400730 this->writeExpression(*b.fRight);
731 this->write(ByteCodeInstruction::kOrB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500732 falseLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -0400733 this->write(ByteCodeInstruction::kMaskPop);
734 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500735 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400736 case Token::Kind::TK_SHL:
737 case Token::Kind::TK_SHR: {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500738 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
739 tc == SkSL::TypeCategory::kUnsigned));
740 if (!b.fRight->isConstant()) {
741 fErrors.error(b.fRight->fOffset, "Shift amounts must be constant");
Brian Osmanb08cc022020-04-02 11:38:40 -0400742 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500743 }
744 int64_t shift = b.fRight->getConstantInt();
745 if (shift < 0 || shift > 31) {
746 fErrors.error(b.fRight->fOffset, "Shift amount out of range");
Brian Osmanb08cc022020-04-02 11:38:40 -0400747 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500748 }
749
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400750 if (op == Token::Kind::TK_SHL) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400751 this->write(ByteCodeInstruction::kShiftLeft);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500752 } else {
753 this->write(type_category(lType) == TypeCategory::kSigned
Brian Osmanb08cc022020-04-02 11:38:40 -0400754 ? ByteCodeInstruction::kShiftRightS
755 : ByteCodeInstruction::kShiftRightU);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500756 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400757 this->write8(shift);
758 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500759 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500760
761 default:
762 break;
763 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400764 this->writeExpression(*b.fRight);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500765 if (lVecOrMtx && !rVecOrMtx) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400766 for (int i = SlotCount(lType); i > 1; --i) {
767 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400768 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500769 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400770 // Special case for M*V, V*M, M*M (but not V*V!)
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400771 if (op == Token::Kind::TK_STAR && lVecOrMtx && rVecOrMtx &&
Brian Osmanb08cc022020-04-02 11:38:40 -0400772 !(lType.kind() == Type::kVector_Kind && rType.kind() == Type::kVector_Kind)) {
773 this->write(ByteCodeInstruction::kMatrixMultiply,
774 SlotCount(b.fType) - (SlotCount(lType) + SlotCount(rType)));
775 int rCols = rType.columns(),
776 rRows = rType.rows(),
777 lCols = lType.columns(),
778 lRows = lType.rows();
779 // M*V treats the vector as a column
780 if (rType.kind() == Type::kVector_Kind) {
781 std::swap(rCols, rRows);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500782 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400783 SkASSERT(lCols == rRows);
784 SkASSERT(SlotCount(b.fType) == lRows * rCols);
785 this->write8(lCols);
786 this->write8(lRows);
787 this->write8(rCols);
788 } else {
789 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400790 case Token::Kind::TK_EQEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400791 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareIEQ,
792 ByteCodeInstruction::kCompareIEQ,
793 ByteCodeInstruction::kCompareFEQ,
794 count);
795 // Collapse to a single bool
796 for (int i = count; i > 1; --i) {
797 this->write(ByteCodeInstruction::kAndB);
798 }
799 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400800 case Token::Kind::TK_GT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400801 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGT,
802 ByteCodeInstruction::kCompareUGT,
803 ByteCodeInstruction::kCompareFGT,
804 count);
805 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400806 case Token::Kind::TK_GTEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400807 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGTEQ,
808 ByteCodeInstruction::kCompareUGTEQ,
809 ByteCodeInstruction::kCompareFGTEQ,
810 count);
811 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400812 case Token::Kind::TK_LT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400813 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLT,
814 ByteCodeInstruction::kCompareULT,
815 ByteCodeInstruction::kCompareFLT,
816 count);
817 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400818 case Token::Kind::TK_LTEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400819 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLTEQ,
820 ByteCodeInstruction::kCompareULTEQ,
821 ByteCodeInstruction::kCompareFLTEQ,
822 count);
823 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400824 case Token::Kind::TK_MINUS:
Brian Osmanb08cc022020-04-02 11:38:40 -0400825 this->writeTypedInstruction(lType, ByteCodeInstruction::kSubtractI,
826 ByteCodeInstruction::kSubtractI,
827 ByteCodeInstruction::kSubtractF,
828 count);
829 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400830 case Token::Kind::TK_NEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400831 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareINEQ,
832 ByteCodeInstruction::kCompareINEQ,
833 ByteCodeInstruction::kCompareFNEQ,
834 count);
835 // Collapse to a single bool
836 for (int i = count; i > 1; --i) {
837 this->write(ByteCodeInstruction::kOrB);
838 }
839 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400840 case Token::Kind::TK_PERCENT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400841 this->writeTypedInstruction(lType, ByteCodeInstruction::kRemainderS,
842 ByteCodeInstruction::kRemainderU,
843 ByteCodeInstruction::kRemainderF,
844 count);
845 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400846 case Token::Kind::TK_PLUS:
Brian Osmanb08cc022020-04-02 11:38:40 -0400847 this->writeTypedInstruction(lType, ByteCodeInstruction::kAddI,
848 ByteCodeInstruction::kAddI,
849 ByteCodeInstruction::kAddF,
850 count);
851 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400852 case Token::Kind::TK_SLASH:
Brian Osmanb08cc022020-04-02 11:38:40 -0400853 this->writeTypedInstruction(lType, ByteCodeInstruction::kDivideS,
854 ByteCodeInstruction::kDivideU,
855 ByteCodeInstruction::kDivideF,
856 count);
857 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400858 case Token::Kind::TK_STAR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400859 this->writeTypedInstruction(lType, ByteCodeInstruction::kMultiplyI,
860 ByteCodeInstruction::kMultiplyI,
861 ByteCodeInstruction::kMultiplyF,
862 count);
863 break;
864
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400865 case Token::Kind::TK_LOGICALXOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400866 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
867 this->write(ByteCodeInstruction::kXorB);
868 break;
869
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400870 case Token::Kind::TK_BITWISEAND:
Brian Osmanb08cc022020-04-02 11:38:40 -0400871 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
872 tc == SkSL::TypeCategory::kUnsigned));
873 this->write(ByteCodeInstruction::kAndB);
874 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400875 case Token::Kind::TK_BITWISEOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400876 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
877 tc == SkSL::TypeCategory::kUnsigned));
878 this->write(ByteCodeInstruction::kOrB);
879 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400880 case Token::Kind::TK_BITWISEXOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400881 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
882 tc == SkSL::TypeCategory::kUnsigned));
883 this->write(ByteCodeInstruction::kXorB);
884 break;
885
886 default:
887 fErrors.error(b.fOffset, SkSL::String::printf("Unsupported binary operator '%s'",
888 Compiler::OperatorName(op)));
889 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500890 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500891 }
892 if (lvalue) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400893 lvalue->store(discard);
894 discard = false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500895 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400896 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500897}
898
Brian Osmanb08cc022020-04-02 11:38:40 -0400899void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
900 this->write(ByteCodeInstruction::kPushImmediate);
901 this->write32(b.fValue ? ~0 : 0);
902}
903
904void ByteCodeGenerator::writeConstructor(const Constructor& c) {
905 for (const auto& arg : c.fArguments) {
906 this->writeExpression(*arg);
907 }
908 if (c.fArguments.size() == 1) {
909 const Type& inType = c.fArguments[0]->fType;
910 const Type& outType = c.fType;
911 TypeCategory inCategory = type_category(inType);
912 TypeCategory outCategory = type_category(outType);
913 int inCount = SlotCount(inType);
914 int outCount = SlotCount(outType);
915 if (inCategory != outCategory) {
916 SkASSERT(inCount == outCount);
917 if (inCategory == TypeCategory::kFloat) {
918 SkASSERT(outCategory == TypeCategory::kSigned ||
919 outCategory == TypeCategory::kUnsigned);
920 this->write(vector_instruction(ByteCodeInstruction::kConvertFtoI, outCount));
921 } else if (outCategory == TypeCategory::kFloat) {
922 if (inCategory == TypeCategory::kSigned) {
923 this->write(vector_instruction(ByteCodeInstruction::kConvertStoF, outCount));
924 } else {
925 SkASSERT(inCategory == TypeCategory::kUnsigned);
926 this->write(vector_instruction(ByteCodeInstruction::kConvertUtoF, outCount));
927 }
928 } else {
929 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500930 }
931 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400932 if (inType.kind() == Type::kMatrix_Kind && outType.kind() == Type::kMatrix_Kind) {
933 this->write(ByteCodeInstruction::kMatrixToMatrix,
934 SlotCount(outType) - SlotCount(inType));
935 this->write8(inType.columns());
936 this->write8(inType.rows());
937 this->write8(outType.columns());
938 this->write8(outType.rows());
939 } else if (inCount != outCount) {
940 SkASSERT(inCount == 1);
941 if (outType.kind() == Type::kMatrix_Kind) {
942 this->write(ByteCodeInstruction::kScalarToMatrix, SlotCount(outType) - 1);
943 this->write8(outType.columns());
944 this->write8(outType.rows());
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500945 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400946 SkASSERT(outType.kind() == Type::kVector_Kind);
947 for (; inCount != outCount; ++inCount) {
948 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400949 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500950 }
951 }
952 }
953}
954
Brian Osmanb08cc022020-04-02 11:38:40 -0400955void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500956 int argumentCount = 0;
957 for (const auto& arg : f.fArguments) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400958 this->writeExpression(*arg);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500959 argumentCount += SlotCount(arg->fType);
960 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400961 this->write(ByteCodeInstruction::kCallExternal, SlotCount(f.fType) - argumentCount);
962 SkASSERT(argumentCount <= 255);
963 this->write8(argumentCount);
964 this->write8(SlotCount(f.fType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500965 int index = fOutput->fExternalValues.size();
966 fOutput->fExternalValues.push_back(f.fFunction);
967 SkASSERT(index <= 255);
Brian Osmanb08cc022020-04-02 11:38:40 -0400968 this->write8(index);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500969}
970
Brian Osmanb08cc022020-04-02 11:38:40 -0400971void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
972 int count = SlotCount(e.fValue->type());
973 this->write(vector_instruction(ByteCodeInstruction::kReadExternal, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500974 int index = fOutput->fExternalValues.size();
975 fOutput->fExternalValues.push_back(e.fValue);
976 SkASSERT(index <= 255);
Brian Osmanb08cc022020-04-02 11:38:40 -0400977 this->write8(index);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500978}
979
Brian Osmanb08cc022020-04-02 11:38:40 -0400980void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
981 Location location = this->getLocation(expr);
982 int count = SlotCount(expr.fType);
Brian Osmanefb08402020-04-13 16:30:44 -0400983 if (count == 0) {
984 return;
985 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400986 if (location.isOnStack() || count > 4) {
987 if (!location.isOnStack()) {
988 this->write(ByteCodeInstruction::kPushImmediate);
989 this->write32(location.fSlot);
990 }
991 this->write(location.selectLoad(ByteCodeInstruction::kLoadExtended,
992 ByteCodeInstruction::kLoadExtendedGlobal,
993 ByteCodeInstruction::kLoadExtendedUniform),
994 count);
995 this->write8(count);
996 } else {
997 this->write(vector_instruction(location.selectLoad(ByteCodeInstruction::kLoad,
998 ByteCodeInstruction::kLoadGlobal,
999 ByteCodeInstruction::kLoadUniform),
1000 count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001001 this->write8(location.fSlot);
1002 }
1003}
1004
1005static inline uint32_t float_to_bits(float x) {
1006 uint32_t u;
1007 memcpy(&u, &x, sizeof(uint32_t));
1008 return u;
1009}
1010
1011void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
1012 this->write(ByteCodeInstruction::kPushImmediate);
1013 this->write32(float_to_bits(f.fValue));
1014}
1015
Brian Osman8842b372020-05-01 15:07:49 -04001016static bool is_generic_type(const Type* type, const Type* generic) {
1017 const std::vector<const Type*>& concrete(generic->coercibleTypes());
1018 return std::find(concrete.begin(), concrete.end(), type) != concrete.end();
1019}
1020
Brian Osmanb08cc022020-04-02 11:38:40 -04001021void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
1022 auto found = fIntrinsics.find(c.fFunction.fName);
1023 if (found == fIntrinsics.end()) {
1024 fErrors.error(c.fOffset, String::printf("Unsupported intrinsic: '%s'",
1025 String(c.fFunction.fName).c_str()));
1026 return;
1027 }
Mike Klein45be0772020-05-01 09:13:18 -05001028 Intrinsic intrin = found->second;
1029
Brian Osmanb08cc022020-04-02 11:38:40 -04001030 int count = SlotCount(c.fArguments[0]->fType);
Mike Klein45be0772020-05-01 09:13:18 -05001031 if (intrin.is_special) {
1032 switch (intrin.special) {
Brian Osman8842b372020-05-01 15:07:49 -04001033 case SpecialIntrinsic::kAll: {
1034 for (int i = count-1; i --> 0;) {
1035 this->write(ByteCodeInstruction::kAndB);
1036 }
1037 } break;
1038
1039 case SpecialIntrinsic::kAny: {
1040 for (int i = count-1; i --> 0;) {
1041 this->write(ByteCodeInstruction::kOrB);
1042 }
1043 } break;
1044
Brian Osman15c98cb2020-02-27 18:36:57 +00001045 case SpecialIntrinsic::kDot: {
1046 SkASSERT(c.fArguments.size() == 2);
Brian Osmanb08cc022020-04-02 11:38:40 -04001047 SkASSERT(count == SlotCount(c.fArguments[1]->fType));
1048 this->write(vector_instruction(ByteCodeInstruction::kMultiplyF, count));
Mike Klein45be0772020-05-01 09:13:18 -05001049 for (int i = count-1; i --> 0;) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001050 this->write(ByteCodeInstruction::kAddF);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001051 }
Mike Klein45be0772020-05-01 09:13:18 -05001052 } break;
1053
1054 case SpecialIntrinsic::kLength: {
1055 SkASSERT(c.fArguments.size() == 1);
1056 this->write(vector_instruction(ByteCodeInstruction::kDup , count));
1057 this->write(vector_instruction(ByteCodeInstruction::kMultiplyF, count));
1058 for (int i = count-1; i --> 0;) {
1059 this->write(ByteCodeInstruction::kAddF);
1060 }
1061 this->write(ByteCodeInstruction::kSqrt);
1062 } break;
1063
Brian Osman8842b372020-05-01 15:07:49 -04001064 case SpecialIntrinsic::kMix: {
1065 // Two main variants of mix to handle
1066 SkASSERT(c.fArguments.size() == 3);
1067 SkASSERT(count == SlotCount(c.fArguments[1]->fType));
1068 int selectorCount = SlotCount(c.fArguments[2]->fType);
1069
1070 if (is_generic_type(&c.fArguments[2]->fType, fContext.fGenBType_Type.get())) {
1071 // mix(genType, genType, genBoolType)
1072 SkASSERT(selectorCount == count);
1073 this->write(vector_instruction(ByteCodeInstruction::kMix, count));
1074 } else {
1075 // mix(genType, genType, genType) or mix(genType, genType, float)
1076 SkASSERT(selectorCount == 1 || selectorCount == count);
1077 for (int i = selectorCount; i < count; ++i) {
1078 this->write(ByteCodeInstruction::kDup);
1079 }
1080 this->write(vector_instruction(ByteCodeInstruction::kLerp, count));
1081 }
1082 } break;
1083
Brian Osmanb08cc022020-04-02 11:38:40 -04001084 default:
1085 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001086 }
1087 } else {
Brian Osman8842b372020-05-01 15:07:49 -04001088 switch (intrin.inst_f) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001089 case ByteCodeInstruction::kInverse2x2: {
1090 SkASSERT(c.fArguments.size() > 0);
1091 auto op = ByteCodeInstruction::kInverse2x2;
1092 switch (count) {
1093 case 4: break; // float2x2
1094 case 9: op = ByteCodeInstruction::kInverse3x3; break;
1095 case 16: op = ByteCodeInstruction::kInverse4x4; break;
1096 default: SkASSERT(false);
1097 }
1098 this->write(op);
1099 break;
Brian Osman15c98cb2020-02-27 18:36:57 +00001100 }
Mike Klein45be0772020-05-01 09:13:18 -05001101
Brian Osmanb08cc022020-04-02 11:38:40 -04001102 default:
Brian Osman8842b372020-05-01 15:07:49 -04001103 this->writeTypedInstruction(c.fArguments[0]->fType, intrin.inst_s, intrin.inst_u,
1104 intrin.inst_f, count);
1105 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001106 }
1107 }
1108}
1109
Brian Osmanb08cc022020-04-02 11:38:40 -04001110void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001111 // Find the index of the function we're calling. We explicitly do not allow calls to functions
1112 // before they're defined. This is an easy-to-understand rule that prevents recursion.
Brian Osmanb08cc022020-04-02 11:38:40 -04001113 int idx = -1;
1114 for (size_t i = 0; i < fFunctions.size(); ++i) {
1115 if (f.fFunction.matches(fFunctions[i]->fDeclaration)) {
1116 idx = i;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001117 break;
1118 }
1119 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001120 if (idx == -1) {
1121 for (const auto& arg : f.fArguments) {
1122 this->writeExpression(*arg);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001123 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001124 this->writeIntrinsicCall(f);
1125 return;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001126 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001127
1128
1129 if (idx > 255) {
1130 fErrors.error(f.fOffset, "Function count limit exceeded");
1131 return;
1132 } else if (idx >= (int) fFunctions.size()) {
1133 fErrors.error(f.fOffset, "Call to undefined function");
1134 return;
1135 }
1136
1137 // We may need to deal with out parameters, so the sequence is tricky
1138 if (int returnCount = SlotCount(f.fType)) {
1139 this->write(ByteCodeInstruction::kReserve, returnCount);
1140 this->write8(returnCount);
1141 }
1142
1143 int argCount = f.fArguments.size();
1144 std::vector<std::unique_ptr<LValue>> lvalues;
1145 for (int i = 0; i < argCount; ++i) {
1146 const auto& param = f.fFunction.fParameters[i];
1147 const auto& arg = f.fArguments[i];
1148 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1149 lvalues.emplace_back(this->getLValue(*arg));
1150 lvalues.back()->load();
1151 } else {
1152 this->writeExpression(*arg);
1153 }
1154 }
1155
1156 // The space used by the call is based on the callee, but it also unwinds all of that before
1157 // we continue execution. We adjust our max stack depths below.
1158 this->write(ByteCodeInstruction::kCall);
1159 this->write8(idx);
1160
1161 const ByteCodeFunction* callee = fOutput->fFunctions[idx].get();
1162 fMaxLoopCount = std::max(fMaxLoopCount, fLoopCount + callee->fLoopCount);
1163 fMaxConditionCount = std::max(fMaxConditionCount, fConditionCount + callee->fConditionCount);
1164 fMaxStackCount = std::max(fMaxStackCount, fStackCount + callee->fLocalCount
1165 + callee->fStackCount);
1166
1167 // After the called function returns, the stack will still contain our arguments. We have to
1168 // pop them (storing any out parameters back to their lvalues as we go). We glob together slot
1169 // counts for all parameters that aren't out-params, so we can pop them in one big chunk.
1170 int popCount = 0;
1171 auto pop = [&]() {
1172 if (popCount > 4) {
1173 this->write(ByteCodeInstruction::kPopN, popCount);
1174 this->write8(popCount);
1175 } else if (popCount > 0) {
1176 this->write(vector_instruction(ByteCodeInstruction::kPop, popCount));
1177 }
1178 popCount = 0;
1179 };
1180
1181 for (int i = argCount - 1; i >= 0; --i) {
1182 const auto& param = f.fFunction.fParameters[i];
1183 const auto& arg = f.fArguments[i];
1184 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1185 pop();
1186 lvalues.back()->store(true);
1187 lvalues.pop_back();
1188 } else {
1189 popCount += SlotCount(arg->fType);
1190 }
1191 }
1192 pop();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001193}
1194
Brian Osmanb08cc022020-04-02 11:38:40 -04001195void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
1196 this->write(ByteCodeInstruction::kPushImmediate);
1197 this->write32(i.fValue);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001198}
1199
Brian Osmanb08cc022020-04-02 11:38:40 -04001200void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
1201 // not yet implemented
1202 abort();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001203}
1204
Brian Osmanb08cc022020-04-02 11:38:40 -04001205bool ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p, bool discard) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001206 switch (p.fOperator) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001207 case Token::Kind::TK_PLUSPLUS: // fall through
1208 case Token::Kind::TK_MINUSMINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001209 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1210 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
1211 lvalue->load();
1212 this->write(ByteCodeInstruction::kPushImmediate);
1213 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001214 if (p.fOperator == Token::Kind::TK_PLUSPLUS) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001215 this->writeTypedInstruction(p.fType,
1216 ByteCodeInstruction::kAddI,
1217 ByteCodeInstruction::kAddI,
1218 ByteCodeInstruction::kAddF,
1219 1);
1220 } else {
1221 this->writeTypedInstruction(p.fType,
1222 ByteCodeInstruction::kSubtractI,
1223 ByteCodeInstruction::kSubtractI,
1224 ByteCodeInstruction::kSubtractF,
1225 1);
1226 }
1227 lvalue->store(discard);
1228 discard = false;
1229 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001230 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001231 case Token::Kind::TK_MINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001232 this->writeExpression(*p.fOperand);
1233 this->writeTypedInstruction(p.fType,
1234 ByteCodeInstruction::kNegateI,
1235 ByteCodeInstruction::kNegateI,
1236 ByteCodeInstruction::kNegateF,
Brian Osmanab8f3842020-04-07 09:30:44 -04001237 SlotCount(p.fOperand->fType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001238 break;
1239 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001240 case Token::Kind::TK_LOGICALNOT:
1241 case Token::Kind::TK_BITWISENOT: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001242 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1243 SkDEBUGCODE(TypeCategory tc = type_category(p.fOperand->fType));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001244 SkASSERT((p.fOperator == Token::Kind::TK_LOGICALNOT && tc == TypeCategory::kBool) ||
1245 (p.fOperator == Token::Kind::TK_BITWISENOT && (tc == TypeCategory::kSigned ||
Brian Osmanb08cc022020-04-02 11:38:40 -04001246 tc == TypeCategory::kUnsigned)));
1247 this->writeExpression(*p.fOperand);
1248 this->write(ByteCodeInstruction::kNotB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001249 break;
1250 }
1251 default:
1252 SkASSERT(false);
1253 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001254 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001255}
1256
Brian Osmanb08cc022020-04-02 11:38:40 -04001257bool ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p, bool discard) {
1258 switch (p.fOperator) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001259 case Token::Kind::TK_PLUSPLUS: // fall through
1260 case Token::Kind::TK_MINUSMINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001261 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1262 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
1263 lvalue->load();
1264 // If we're not supposed to discard the result, then make a copy *before* the +/-
1265 if (!discard) {
1266 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -04001267 }
1268 this->write(ByteCodeInstruction::kPushImmediate);
1269 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001270 if (p.fOperator == Token::Kind::TK_PLUSPLUS) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001271 this->writeTypedInstruction(p.fType,
1272 ByteCodeInstruction::kAddI,
1273 ByteCodeInstruction::kAddI,
1274 ByteCodeInstruction::kAddF,
1275 1);
1276 } else {
1277 this->writeTypedInstruction(p.fType,
1278 ByteCodeInstruction::kSubtractI,
1279 ByteCodeInstruction::kSubtractI,
1280 ByteCodeInstruction::kSubtractF,
1281 1);
1282 }
1283 // Always consume the result as part of the store
1284 lvalue->store(true);
1285 discard = false;
1286 break;
1287 }
1288 default:
1289 SkASSERT(false);
1290 }
1291 return discard;
1292}
1293
1294void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001295 if (swizzle_is_simple(s)) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001296 this->writeVariableExpression(s);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001297 return;
1298 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001299
1300 switch (s.fBase->fKind) {
1301 case Expression::kVariableReference_Kind: {
1302 Location location = this->getLocation(*s.fBase);
1303 this->write(location.selectLoad(ByteCodeInstruction::kLoadSwizzle,
1304 ByteCodeInstruction::kLoadSwizzleGlobal,
1305 ByteCodeInstruction::kLoadSwizzleUniform),
1306 s.fComponents.size());
1307 this->write8(location.fSlot);
1308 this->write8(s.fComponents.size());
1309 for (int c : s.fComponents) {
1310 this->write8(c);
1311 }
1312 break;
1313 }
1314 default:
1315 this->writeExpression(*s.fBase);
1316 this->write(ByteCodeInstruction::kSwizzle,
1317 s.fComponents.size() - s.fBase->fType.columns());
1318 this->write8(s.fBase->fType.columns());
1319 this->write8(s.fComponents.size());
1320 for (int c : s.fComponents) {
1321 this->write8(c);
1322 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001323 }
1324}
1325
Brian Osmanb08cc022020-04-02 11:38:40 -04001326void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001327 int count = SlotCount(t.fType);
1328 SkASSERT(count == SlotCount(t.fIfTrue->fType));
1329 SkASSERT(count == SlotCount(t.fIfFalse->fType));
1330
Brian Osmanb08cc022020-04-02 11:38:40 -04001331 this->writeExpression(*t.fTest);
1332 this->write(ByteCodeInstruction::kMaskPush);
1333 this->writeExpression(*t.fIfTrue);
1334 this->write(ByteCodeInstruction::kMaskNegate);
1335 this->writeExpression(*t.fIfFalse);
1336 this->write(ByteCodeInstruction::kMaskBlend, count);
1337 this->write8(count);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001338}
1339
Brian Osmanb08cc022020-04-02 11:38:40 -04001340void ByteCodeGenerator::writeExpression(const Expression& e, bool discard) {
1341 switch (e.fKind) {
1342 case Expression::kBinary_Kind:
1343 discard = this->writeBinaryExpression((BinaryExpression&) e, discard);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001344 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001345 case Expression::kBoolLiteral_Kind:
1346 this->writeBoolLiteral((BoolLiteral&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001347 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001348 case Expression::kConstructor_Kind:
1349 this->writeConstructor((Constructor&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001350 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001351 case Expression::kExternalFunctionCall_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001352 this->writeExternalFunctionCall((ExternalFunctionCall&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001353 break;
1354 case Expression::kExternalValue_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001355 this->writeExternalValue((ExternalValueReference&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001356 break;
1357 case Expression::kFieldAccess_Kind:
1358 case Expression::kIndex_Kind:
1359 case Expression::kVariableReference_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001360 this->writeVariableExpression(e);
1361 break;
1362 case Expression::kFloatLiteral_Kind:
1363 this->writeFloatLiteral((FloatLiteral&) e);
1364 break;
1365 case Expression::kFunctionCall_Kind:
1366 this->writeFunctionCall((FunctionCall&) e);
1367 break;
1368 case Expression::kIntLiteral_Kind:
1369 this->writeIntLiteral((IntLiteral&) e);
1370 break;
1371 case Expression::kNullLiteral_Kind:
1372 this->writeNullLiteral((NullLiteral&) e);
1373 break;
1374 case Expression::kPrefix_Kind:
1375 discard = this->writePrefixExpression((PrefixExpression&) e, discard);
1376 break;
1377 case Expression::kPostfix_Kind:
1378 discard = this->writePostfixExpression((PostfixExpression&) e, discard);
1379 break;
1380 case Expression::kSwizzle_Kind:
1381 this->writeSwizzle((Swizzle&) e);
1382 break;
1383 case Expression::kTernary_Kind:
1384 this->writeTernaryExpression((TernaryExpression&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001385 break;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001386 default:
1387#ifdef SK_DEBUG
Brian Osmanb08cc022020-04-02 11:38:40 -04001388 printf("unsupported expression %s\n", e.description().c_str());
Ben Wagner470e0ac2020-01-22 16:59:21 -05001389#endif
Brian Osmanb08cc022020-04-02 11:38:40 -04001390 SkASSERT(false);
1391 }
1392 if (discard) {
1393 int count = SlotCount(e.fType);
1394 if (count > 4) {
1395 this->write(ByteCodeInstruction::kPopN, count);
1396 this->write8(count);
1397 } else if (count != 0) {
1398 this->write(vector_instruction(ByteCodeInstruction::kPop, count));
1399 }
1400 discard = false;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001401 }
Ethan Nicholas7deb1c22020-01-22 10:31:55 -05001402}
1403
Brian Osmanb08cc022020-04-02 11:38:40 -04001404class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
1405public:
1406 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
1407 : INHERITED(*generator)
1408 , fCount(ByteCodeGenerator::SlotCount(value.type()))
1409 , fIndex(index) {}
1410
1411 void load() override {
1412 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001413 fGenerator.write8(fIndex);
1414 }
1415
1416 void store(bool discard) override {
1417 if (!discard) {
1418 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001419 }
1420 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001421 fGenerator.write8(fIndex);
1422 }
1423
1424private:
1425 typedef LValue INHERITED;
1426
1427 int fCount;
1428
1429 int fIndex;
1430};
1431
1432class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
1433public:
1434 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
1435 : INHERITED(*generator)
1436 , fSwizzle(swizzle) {}
1437
1438 void load() override {
1439 fGenerator.writeSwizzle(fSwizzle);
1440 }
1441
1442 void store(bool discard) override {
1443 int count = fSwizzle.fComponents.size();
1444 if (!discard) {
1445 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001446 }
1447 ByteCodeGenerator::Location location = fGenerator.getLocation(*fSwizzle.fBase);
1448 if (location.isOnStack()) {
1449 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreSwizzleIndirect,
1450 ByteCodeInstruction::kStoreSwizzleIndirectGlobal),
1451 count);
1452 } else {
1453 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreSwizzle,
1454 ByteCodeInstruction::kStoreSwizzleGlobal),
1455 count);
1456 fGenerator.write8(location.fSlot);
1457 }
1458 fGenerator.write8(count);
1459 for (int c : fSwizzle.fComponents) {
1460 fGenerator.write8(c);
1461 }
1462 }
1463
1464private:
1465 const Swizzle& fSwizzle;
1466
1467 typedef LValue INHERITED;
1468};
1469
1470class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
1471public:
1472 ByteCodeExpressionLValue(ByteCodeGenerator* generator, const Expression& expr)
1473 : INHERITED(*generator)
1474 , fExpression(expr) {}
1475
1476 void load() override {
1477 fGenerator.writeVariableExpression(fExpression);
1478 }
1479
1480 void store(bool discard) override {
1481 int count = ByteCodeGenerator::SlotCount(fExpression.fType);
1482 if (!discard) {
1483 if (count > 4) {
1484 fGenerator.write(ByteCodeInstruction::kDupN, count);
1485 fGenerator.write8(count);
1486 } else {
1487 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001488 }
1489 }
1490 ByteCodeGenerator::Location location = fGenerator.getLocation(fExpression);
1491 if (location.isOnStack() || count > 4) {
1492 if (!location.isOnStack()) {
1493 fGenerator.write(ByteCodeInstruction::kPushImmediate);
1494 fGenerator.write32(location.fSlot);
1495 }
1496 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreExtended,
1497 ByteCodeInstruction::kStoreExtendedGlobal),
1498 count);
1499 fGenerator.write8(count);
1500 } else {
1501 fGenerator.write(
1502 vector_instruction(location.selectStore(ByteCodeInstruction::kStore,
1503 ByteCodeInstruction::kStoreGlobal),
1504 count));
1505 fGenerator.write8(location.fSlot);
1506 }
1507 }
1508
1509private:
1510 typedef LValue INHERITED;
1511
1512 const Expression& fExpression;
1513};
1514
1515std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
1516 switch (e.fKind) {
1517 case Expression::kExternalValue_Kind: {
1518 ExternalValue* value = ((ExternalValueReference&) e).fValue;
1519 int index = fOutput->fExternalValues.size();
1520 fOutput->fExternalValues.push_back(value);
1521 SkASSERT(index <= 255);
1522 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
1523 }
1524 case Expression::kFieldAccess_Kind:
1525 case Expression::kIndex_Kind:
1526 case Expression::kVariableReference_Kind:
1527 return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
1528 case Expression::kSwizzle_Kind: {
1529 const Swizzle& s = (const Swizzle&) e;
1530 return swizzle_is_simple(s)
1531 ? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e))
1532 : std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s));
1533 }
1534 case Expression::kTernary_Kind:
1535 default:
1536#ifdef SK_DEBUG
1537 ABORT("unsupported lvalue %s\n", e.description().c_str());
1538#endif
1539 return nullptr;
1540 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001541}
1542
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001543void ByteCodeGenerator::writeBlock(const Block& b) {
1544 for (const auto& s : b.fStatements) {
1545 this->writeStatement(*s);
1546 }
1547}
1548
Brian Osmanb08cc022020-04-02 11:38:40 -04001549void ByteCodeGenerator::setBreakTargets() {
1550 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
1551 for (DeferredLocation& b : breaks) {
1552 b.set();
1553 }
1554 fBreakTargets.pop();
1555}
1556
1557void ByteCodeGenerator::setContinueTargets() {
1558 std::vector<DeferredLocation>& continues = fContinueTargets.top();
1559 for (DeferredLocation& c : continues) {
1560 c.set();
1561 }
1562 fContinueTargets.pop();
1563}
1564
1565void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
1566 // TODO: Include BranchIfAllFalse to top-most LoopNext
1567 this->write(ByteCodeInstruction::kLoopBreak);
1568}
1569
1570void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
1571 // TODO: Include BranchIfAllFalse to top-most LoopNext
1572 this->write(ByteCodeInstruction::kLoopContinue);
1573}
1574
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001575void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001576 this->write(ByteCodeInstruction::kLoopBegin);
1577 size_t start = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001578 this->writeStatement(*d.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001579 this->write(ByteCodeInstruction::kLoopNext);
1580 this->writeExpression(*d.fTest);
1581 this->write(ByteCodeInstruction::kLoopMask);
1582 // TODO: Could shorten this with kBranchIfAnyTrue
1583 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001584 DeferredLocation endLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -04001585 this->write(ByteCodeInstruction::kBranch);
1586 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001587 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001588 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001589}
1590
1591void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001592 fContinueTargets.emplace();
1593 fBreakTargets.emplace();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001594 if (f.fInitializer) {
1595 this->writeStatement(*f.fInitializer);
1596 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001597 this->write(ByteCodeInstruction::kLoopBegin);
1598 size_t start = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001599 if (f.fTest) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001600 this->writeExpression(*f.fTest);
1601 this->write(ByteCodeInstruction::kLoopMask);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001602 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001603 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001604 DeferredLocation endLocation(this);
1605 this->writeStatement(*f.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001606 this->write(ByteCodeInstruction::kLoopNext);
Brian Osman569f12f2019-06-13 11:23:57 -04001607 if (f.fNext) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001608 this->writeExpression(*f.fNext, true);
Brian Osman569f12f2019-06-13 11:23:57 -04001609 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001610 this->write(ByteCodeInstruction::kBranch);
1611 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001612 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001613 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001614}
1615
1616void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001617 this->writeExpression(*i.fTest);
1618 this->write(ByteCodeInstruction::kMaskPush);
1619 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001620 DeferredLocation falseLocation(this);
1621 this->writeStatement(*i.fIfTrue);
1622 falseLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001623 if (i.fIfFalse) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001624 this->write(ByteCodeInstruction::kMaskNegate);
1625 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001626 DeferredLocation endLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001627 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -05001628 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001629 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001630 this->write(ByteCodeInstruction::kMaskPop);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001631}
1632
Brian Osmanb08cc022020-04-02 11:38:40 -04001633void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
1634 if (fLoopCount || fConditionCount) {
Brian Osman4a47da72019-07-12 11:30:32 -04001635 fErrors.error(r.fOffset, "return not allowed inside conditional or loop");
1636 return;
1637 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001638 int count = SlotCount(r.fExpression->fType);
1639 this->writeExpression(*r.fExpression);
1640
1641 // Technically, the kReturn also pops fOutput->fLocalCount values from the stack, too, but we
1642 // haven't counted pushing those (they're outside the scope of our stack tracking). Instead,
1643 // we account for those in writeFunction().
1644
1645 // This is all fine because we don't allow conditional returns, so we only return once anyway.
1646 this->write(ByteCodeInstruction::kReturn, -count);
1647 this->write8(count);
1648}
1649
1650void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
1651 // not yet implemented
1652 abort();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001653}
1654
1655void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1656 for (const auto& declStatement : v.fVars) {
1657 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
Brian Osmanb08cc022020-04-02 11:38:40 -04001658 // we need to grab the location even if we don't use it, to ensure it has been allocated
1659 Location location = this->getLocation(*decl.fVar);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001660 if (decl.fValue) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001661 this->writeExpression(*decl.fValue);
1662 int count = SlotCount(decl.fValue->fType);
1663 if (count > 4) {
1664 this->write(ByteCodeInstruction::kPushImmediate);
1665 this->write32(location.fSlot);
1666 this->write(ByteCodeInstruction::kStoreExtended, count);
1667 this->write8(count);
1668 } else {
1669 this->write(vector_instruction(ByteCodeInstruction::kStore, count));
1670 this->write8(location.fSlot);
1671 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001672 }
1673 }
1674}
1675
1676void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001677 this->write(ByteCodeInstruction::kLoopBegin);
1678 size_t cond = fCode->size();
1679 this->writeExpression(*w.fTest);
1680 this->write(ByteCodeInstruction::kLoopMask);
1681 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001682 DeferredLocation endLocation(this);
1683 this->writeStatement(*w.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001684 this->write(ByteCodeInstruction::kLoopNext);
1685 this->write(ByteCodeInstruction::kBranch);
1686 this->write16(cond);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001687 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001688 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001689}
1690
1691void ByteCodeGenerator::writeStatement(const Statement& s) {
1692 switch (s.fKind) {
1693 case Statement::kBlock_Kind:
1694 this->writeBlock((Block&) s);
1695 break;
1696 case Statement::kBreak_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001697 this->writeBreakStatement((BreakStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001698 break;
1699 case Statement::kContinue_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001700 this->writeContinueStatement((ContinueStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001701 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001702 case Statement::kDiscard_Kind:
1703 // not yet implemented
1704 abort();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001705 case Statement::kDo_Kind:
1706 this->writeDoStatement((DoStatement&) s);
1707 break;
Brian Osman3e29f1d2019-05-28 09:35:05 -04001708 case Statement::kExpression_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001709 this->writeExpression(*((ExpressionStatement&) s).fExpression, true);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001710 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001711 case Statement::kFor_Kind:
1712 this->writeForStatement((ForStatement&) s);
1713 break;
1714 case Statement::kIf_Kind:
1715 this->writeIfStatement((IfStatement&) s);
1716 break;
1717 case Statement::kNop_Kind:
1718 break;
1719 case Statement::kReturn_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001720 this->writeReturnStatement((ReturnStatement&) s);
1721 break;
1722 case Statement::kSwitch_Kind:
1723 this->writeSwitchStatement((SwitchStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001724 break;
1725 case Statement::kVarDeclarations_Kind:
1726 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1727 break;
1728 case Statement::kWhile_Kind:
1729 this->writeWhileStatement((WhileStatement&) s);
1730 break;
1731 default:
Brian Osmanb08cc022020-04-02 11:38:40 -04001732 SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001733 }
1734}
1735
Brian Osmanb08cc022020-04-02 11:38:40 -04001736ByteCodeFunction::ByteCodeFunction(const FunctionDeclaration* declaration)
1737 : fName(declaration->fName) {
Brian Osman80164412019-06-07 13:00:23 -04001738 fParameterCount = 0;
Brian Osmanb08cc022020-04-02 11:38:40 -04001739 for (const auto& p : declaration->fParameters) {
1740 int slots = ByteCodeGenerator::SlotCount(p->fType);
1741 fParameters.push_back({ slots, (bool)(p->fModifiers.fFlags & Modifiers::kOut_Flag) });
1742 fParameterCount += slots;
Brian Osman80164412019-06-07 13:00:23 -04001743 }
1744}
1745
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001746}