blob: 474ea79b99121fcf63d1c6eb00c8d8c17734038a [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 },
Florin Malita3facc9c2020-05-04 09:26:15 -040052 { "pow", ByteCodeInstruction::kPow },
Brian Osmanb08cc022020-04-02 11:38:40 -040053 { "sin", ByteCodeInstruction::kSin },
54 { "sqrt", ByteCodeInstruction::kSqrt },
55 { "tan", ByteCodeInstruction::kTan },
56 } {}
57
Ethan Nicholas82162ee2019-05-21 16:05:08 -040058
Brian Osman07c117b2019-05-23 12:51:06 -070059int ByteCodeGenerator::SlotCount(const Type& type) {
Brian Osmanfba386b2019-06-20 14:54:15 -040060 if (type.kind() == Type::kOther_Kind) {
61 return 0;
62 } else if (type.kind() == Type::kStruct_Kind) {
Brian Osman07c117b2019-05-23 12:51:06 -070063 int slots = 0;
64 for (const auto& f : type.fields()) {
65 slots += SlotCount(*f.fType);
66 }
67 SkASSERT(slots <= 255);
68 return slots;
69 } else if (type.kind() == Type::kArray_Kind) {
70 int columns = type.columns();
71 SkASSERT(columns >= 0);
72 int slots = columns * SlotCount(type.componentType());
73 SkASSERT(slots <= 255);
74 return slots;
75 } else {
76 return type.columns() * type.rows();
77 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040078}
79
Brian Osman1c110a02019-10-01 14:53:32 -040080static inline bool is_uniform(const SkSL::Variable& var) {
81 return var.fModifiers.fFlags & Modifiers::kUniform_Flag;
82}
83
Brian Osmaneadfeb92020-01-09 12:43:03 -050084static inline bool is_in(const SkSL::Variable& var) {
85 return var.fModifiers.fFlags & Modifiers::kIn_Flag;
86}
Brian Osmanb08cc022020-04-02 11:38:40 -040087
88void ByteCodeGenerator::gatherUniforms(const Type& type, const String& name) {
89 if (type.kind() == Type::kOther_Kind) {
90 return;
91 } else if (type.kind() == Type::kStruct_Kind) {
92 for (const auto& f : type.fields()) {
93 this->gatherUniforms(*f.fType, name + "." + f.fName);
Ethan Nicholasb962eff2020-01-23 16:49:41 -050094 }
Brian Osmanb08cc022020-04-02 11:38:40 -040095 } else if (type.kind() == Type::kArray_Kind) {
96 for (int i = 0; i < type.columns(); ++i) {
97 this->gatherUniforms(type.componentType(), String::printf("%s[%d]", name.c_str(), i));
Ethan Nicholasb962eff2020-01-23 16:49:41 -050098 }
Brian Osmanb08cc022020-04-02 11:38:40 -040099 } else {
100 fOutput->fUniforms.push_back({ name, type_category(type), type.rows(), type.columns(),
101 fOutput->fUniformSlotCount });
102 fOutput->fUniformSlotCount += type.columns() * type.rows();
103 }
104}
105
106bool ByteCodeGenerator::generateCode() {
107 for (const auto& e : fProgram) {
108 switch (e.fKind) {
109 case ProgramElement::kFunction_Kind: {
110 std::unique_ptr<ByteCodeFunction> f = this->writeFunction((FunctionDefinition&) e);
111 if (!f) {
112 return false;
113 }
114 fOutput->fFunctions.push_back(std::move(f));
115 fFunctions.push_back(&(FunctionDefinition&)e);
116 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500117 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400118 case ProgramElement::kVar_Kind: {
119 VarDeclarations& decl = (VarDeclarations&) e;
120 for (const auto& v : decl.fVars) {
121 const Variable* declVar = ((VarDeclaration&) *v).fVar;
122 if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
123 continue;
124 }
125 if (is_uniform(*declVar)) {
126 this->gatherUniforms(declVar->fType, declVar->fName);
127 } else {
128 fOutput->fGlobalSlotCount += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400129 }
130 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400131 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400132 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400133 default:
134 ; // ignore
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400135 }
136 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400137 return 0 == fErrors.errorCount();
138}
139
140std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
141 fFunction = &f;
142 std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
143 fParameterCount = result->fParameterCount;
144 fLoopCount = fMaxLoopCount = 0;
145 fConditionCount = fMaxConditionCount = 0;
146 fStackCount = fMaxStackCount = 0;
147 fCode = &result->fCode;
148
149 this->writeStatement(*f.fBody);
150 if (0 == fErrors.errorCount()) {
151 SkASSERT(fLoopCount == 0);
152 SkASSERT(fConditionCount == 0);
153 SkASSERT(fStackCount == 0);
154 }
155 this->write(ByteCodeInstruction::kReturn, 0);
156 this->write8(0);
157
158 result->fLocalCount = fLocals.size();
159 result->fConditionCount = fMaxConditionCount;
160 result->fLoopCount = fMaxLoopCount;
161 result->fStackCount = fMaxStackCount;
162
163 const Type& returnType = f.fDeclaration.fReturnType;
164 if (returnType != *fContext.fVoid_Type) {
165 result->fReturnCount = SlotCount(returnType);
166 }
167 fLocals.clear();
168 fFunction = nullptr;
169 return result;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400170}
171
Brian Osman0785db02019-05-24 14:19:11 -0400172// A "simple" Swizzle is based on a variable (or a compound variable like a struct or array), and
173// that references consecutive values, such that it can be implemented using normal load/store ops
174// with an offset. Note that all single-component swizzles (of suitable base types) are simple.
175static bool swizzle_is_simple(const Swizzle& s) {
176 switch (s.fBase->fKind) {
177 case Expression::kFieldAccess_Kind:
178 case Expression::kIndex_Kind:
179 case Expression::kVariableReference_Kind:
180 break;
181 default:
182 return false;
183 }
184
185 for (size_t i = 1; i < s.fComponents.size(); ++i) {
186 if (s.fComponents[i] != s.fComponents[i - 1] + 1) {
187 return false;
188 }
189 }
190 return true;
191}
192
Brian Osmanb08cc022020-04-02 11:38:40 -0400193int ByteCodeGenerator::StackUsage(ByteCodeInstruction inst, int count_) {
194 // Ensures that we use count iff we're passed a non-default value. Most instructions have an
195 // implicit count, so the caller shouldn't need to worry about it (or count makes no sense).
196 // The asserts avoids callers thinking they're supplying useful information in that scenario,
197 // or failing to supply necessary information for the ops that need a count.
198 struct CountValue {
199 operator int() {
200 SkASSERT(val != ByteCodeGenerator::kUnusedStackCount);
201 SkDEBUGCODE(used = true);
202 return val;
203 }
204 ~CountValue() {
205 SkASSERT(used || val == ByteCodeGenerator::kUnusedStackCount);
206 }
207 int val;
208 SkDEBUGCODE(bool used = false;)
209 } count = { count_ };
210
211 switch (inst) {
212 // Unary functions/operators that don't change stack depth at all:
213#define VECTOR_UNARY_OP(base) \
214 case ByteCodeInstruction::base: \
215 case ByteCodeInstruction::base ## 2: \
216 case ByteCodeInstruction::base ## 3: \
217 case ByteCodeInstruction::base ## 4: \
218 return 0;
219
220 VECTOR_UNARY_OP(kConvertFtoI)
221 VECTOR_UNARY_OP(kConvertStoF)
222 VECTOR_UNARY_OP(kConvertUtoF)
223
Mike Reed8520e762020-04-30 12:06:23 -0400224 VECTOR_UNARY_OP(kATan)
Brian Osmanb08cc022020-04-02 11:38:40 -0400225 VECTOR_UNARY_OP(kCos)
Mike Reed8520e762020-04-30 12:06:23 -0400226 VECTOR_UNARY_OP(kFract)
Brian Osmanb08cc022020-04-02 11:38:40 -0400227 VECTOR_UNARY_OP(kSin)
228 VECTOR_UNARY_OP(kSqrt)
229 VECTOR_UNARY_OP(kTan)
230
231 VECTOR_UNARY_OP(kNegateF)
232 VECTOR_UNARY_OP(kNegateI)
233
234 case ByteCodeInstruction::kInverse2x2:
235 case ByteCodeInstruction::kInverse3x3:
236 case ByteCodeInstruction::kInverse4x4: return 0;
237
238 case ByteCodeInstruction::kClampIndex: return 0;
239 case ByteCodeInstruction::kNotB: return 0;
240 case ByteCodeInstruction::kNegateFN: return 0;
241 case ByteCodeInstruction::kShiftLeft: return 0;
242 case ByteCodeInstruction::kShiftRightS: return 0;
243 case ByteCodeInstruction::kShiftRightU: return 0;
244
245#undef VECTOR_UNARY_OP
246
247 // Binary functions/operators that do a 2 -> 1 reduction (possibly N times)
248#define VECTOR_BINARY_OP(base) \
249 case ByteCodeInstruction::base: return -1; \
250 case ByteCodeInstruction::base ## 2: return -2; \
251 case ByteCodeInstruction::base ## 3: return -3; \
252 case ByteCodeInstruction::base ## 4: return -4;
253
254#define VECTOR_MATRIX_BINARY_OP(base) \
255 VECTOR_BINARY_OP(base) \
256 case ByteCodeInstruction::base ## N: return -count;
257
258 case ByteCodeInstruction::kAndB: return -1;
259 case ByteCodeInstruction::kOrB: return -1;
260 case ByteCodeInstruction::kXorB: return -1;
261
262 VECTOR_BINARY_OP(kAddI)
263 VECTOR_MATRIX_BINARY_OP(kAddF)
264
265 VECTOR_BINARY_OP(kCompareIEQ)
266 VECTOR_MATRIX_BINARY_OP(kCompareFEQ)
267 VECTOR_BINARY_OP(kCompareINEQ)
268 VECTOR_MATRIX_BINARY_OP(kCompareFNEQ)
269 VECTOR_BINARY_OP(kCompareSGT)
270 VECTOR_BINARY_OP(kCompareUGT)
271 VECTOR_BINARY_OP(kCompareFGT)
272 VECTOR_BINARY_OP(kCompareSGTEQ)
273 VECTOR_BINARY_OP(kCompareUGTEQ)
274 VECTOR_BINARY_OP(kCompareFGTEQ)
275 VECTOR_BINARY_OP(kCompareSLT)
276 VECTOR_BINARY_OP(kCompareULT)
277 VECTOR_BINARY_OP(kCompareFLT)
278 VECTOR_BINARY_OP(kCompareSLTEQ)
279 VECTOR_BINARY_OP(kCompareULTEQ)
280 VECTOR_BINARY_OP(kCompareFLTEQ)
281
282 VECTOR_BINARY_OP(kDivideS)
283 VECTOR_BINARY_OP(kDivideU)
284 VECTOR_MATRIX_BINARY_OP(kDivideF)
285 VECTOR_BINARY_OP(kMultiplyI)
286 VECTOR_MATRIX_BINARY_OP(kMultiplyF)
Florin Malita3facc9c2020-05-04 09:26:15 -0400287 VECTOR_BINARY_OP(kPow)
Brian Osmanb08cc022020-04-02 11:38:40 -0400288 VECTOR_BINARY_OP(kRemainderF)
289 VECTOR_BINARY_OP(kRemainderS)
290 VECTOR_BINARY_OP(kRemainderU)
291 VECTOR_BINARY_OP(kSubtractI)
292 VECTOR_MATRIX_BINARY_OP(kSubtractF)
293
294#undef VECTOR_BINARY_OP
295#undef VECTOR_MATRIX_BINARY_OP
296
297 // Ops that push or load data to grow the stack:
298 case ByteCodeInstruction::kDup:
299 case ByteCodeInstruction::kLoad:
300 case ByteCodeInstruction::kLoadGlobal:
301 case ByteCodeInstruction::kLoadUniform:
302 case ByteCodeInstruction::kReadExternal:
303 case ByteCodeInstruction::kPushImmediate:
304 return 1;
305
306 case ByteCodeInstruction::kDup2:
307 case ByteCodeInstruction::kLoad2:
308 case ByteCodeInstruction::kLoadGlobal2:
309 case ByteCodeInstruction::kLoadUniform2:
310 case ByteCodeInstruction::kReadExternal2:
311 return 2;
312
313 case ByteCodeInstruction::kDup3:
314 case ByteCodeInstruction::kLoad3:
315 case ByteCodeInstruction::kLoadGlobal3:
316 case ByteCodeInstruction::kLoadUniform3:
317 case ByteCodeInstruction::kReadExternal3:
318 return 3;
319
320 case ByteCodeInstruction::kDup4:
321 case ByteCodeInstruction::kLoad4:
322 case ByteCodeInstruction::kLoadGlobal4:
323 case ByteCodeInstruction::kLoadUniform4:
324 case ByteCodeInstruction::kReadExternal4:
325 return 4;
326
327 case ByteCodeInstruction::kDupN:
328 case ByteCodeInstruction::kLoadSwizzle:
329 case ByteCodeInstruction::kLoadSwizzleGlobal:
330 case ByteCodeInstruction::kLoadSwizzleUniform:
331 return count;
332
333 // Pushes 'count' values, minus one for the 'address' that's consumed first
334 case ByteCodeInstruction::kLoadExtended:
335 case ByteCodeInstruction::kLoadExtendedGlobal:
336 case ByteCodeInstruction::kLoadExtendedUniform:
337 return count - 1;
338
339 // Ops that pop or store data to shrink the stack:
340 case ByteCodeInstruction::kPop:
341 case ByteCodeInstruction::kStore:
342 case ByteCodeInstruction::kStoreGlobal:
343 case ByteCodeInstruction::kWriteExternal:
344 return -1;
345
346 case ByteCodeInstruction::kPop2:
347 case ByteCodeInstruction::kStore2:
348 case ByteCodeInstruction::kStoreGlobal2:
349 case ByteCodeInstruction::kWriteExternal2:
350 return -2;
351
352 case ByteCodeInstruction::kPop3:
353 case ByteCodeInstruction::kStore3:
354 case ByteCodeInstruction::kStoreGlobal3:
355 case ByteCodeInstruction::kWriteExternal3:
356 return -3;
357
358 case ByteCodeInstruction::kPop4:
359 case ByteCodeInstruction::kStore4:
360 case ByteCodeInstruction::kStoreGlobal4:
361 case ByteCodeInstruction::kWriteExternal4:
362 return -4;
363
364 case ByteCodeInstruction::kPopN:
365 case ByteCodeInstruction::kStoreSwizzle:
366 case ByteCodeInstruction::kStoreSwizzleGlobal:
367 return -count;
368
369 // Consumes 'count' values, plus one for the 'address'
370 case ByteCodeInstruction::kStoreExtended:
371 case ByteCodeInstruction::kStoreExtendedGlobal:
372 case ByteCodeInstruction::kStoreSwizzleIndirect:
373 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal:
374 return -count - 1;
375
376 // Strange ops where the caller computes the delta for us:
377 case ByteCodeInstruction::kCallExternal:
378 case ByteCodeInstruction::kMatrixToMatrix:
379 case ByteCodeInstruction::kMatrixMultiply:
380 case ByteCodeInstruction::kReserve:
381 case ByteCodeInstruction::kReturn:
382 case ByteCodeInstruction::kScalarToMatrix:
383 case ByteCodeInstruction::kSwizzle:
384 return count;
385
386 // Miscellaneous
387
388 // kCall is net-zero. Max stack depth is adjusted in writeFunctionCall.
389 case ByteCodeInstruction::kCall: return 0;
390 case ByteCodeInstruction::kBranch: return 0;
391 case ByteCodeInstruction::kBranchIfAllFalse: return 0;
392
393 case ByteCodeInstruction::kMaskPush: return -1;
394 case ByteCodeInstruction::kMaskPop: return 0;
395 case ByteCodeInstruction::kMaskNegate: return 0;
396 case ByteCodeInstruction::kMaskBlend: return -count;
397
398 case ByteCodeInstruction::kLoopBegin: return 0;
399 case ByteCodeInstruction::kLoopNext: return 0;
400 case ByteCodeInstruction::kLoopMask: return -1;
401 case ByteCodeInstruction::kLoopEnd: return 0;
402 case ByteCodeInstruction::kLoopBreak: return 0;
403 case ByteCodeInstruction::kLoopContinue: return 0;
404
405 default:
406 ABORT("unsupported instruction %d\n", (int)inst);
407 return 0;
408 }
409}
410
411ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var) {
412 // given that we seldom have more than a couple of variables, linear search is probably the most
413 // efficient way to handle lookups
414 switch (var.fStorage) {
415 case Variable::kLocal_Storage: {
416 for (int i = fLocals.size() - 1; i >= 0; --i) {
417 if (fLocals[i] == &var) {
418 SkASSERT(fParameterCount + i <= 255);
419 return { fParameterCount + i, Storage::kLocal };
420 }
421 }
422 int result = fParameterCount + fLocals.size();
423 fLocals.push_back(&var);
424 for (int i = 0; i < SlotCount(var.fType) - 1; ++i) {
425 fLocals.push_back(nullptr);
426 }
427 SkASSERT(result <= 255);
428 return { result, Storage::kLocal };
429 }
430 case Variable::kParameter_Storage: {
431 int offset = 0;
432 for (const auto& p : fFunction->fDeclaration.fParameters) {
433 if (p == &var) {
434 SkASSERT(offset <= 255);
435 return { offset, Storage::kLocal };
436 }
437 offset += SlotCount(p->fType);
438 }
439 SkASSERT(false);
440 return Location::MakeInvalid();
441 }
442 case Variable::kGlobal_Storage: {
443 if (is_in(var)) {
444 // If you see this error, it means the program is using raw 'in' variables. You
445 // should either specialize the program (Compiler::specialize) to bake in the final
446 // values of the 'in' variables, or not use 'in' variables (maybe you meant to use
447 // 'uniform' instead?).
448 fErrors.error(var.fOffset,
449 "'in' variable is not specialized or has unsupported type");
450 return Location::MakeInvalid();
451 }
452 int offset = 0;
453 bool isUniform = is_uniform(var);
454 for (const auto& e : fProgram) {
455 if (e.fKind == ProgramElement::kVar_Kind) {
456 VarDeclarations& decl = (VarDeclarations&) e;
457 for (const auto& v : decl.fVars) {
458 const Variable* declVar = ((VarDeclaration&) *v).fVar;
459 if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
460 continue;
461 }
462 if (isUniform != is_uniform(*declVar)) {
463 continue;
464 }
465 if (declVar == &var) {
466 SkASSERT(offset <= 255);
467 return { offset, isUniform ? Storage::kUniform : Storage::kGlobal };
468 }
469 offset += SlotCount(declVar->fType);
470 }
471 }
472 }
473 SkASSERT(false);
474 return Location::MakeInvalid();
475 }
476 default:
477 SkASSERT(false);
478 return Location::MakeInvalid();
479 }
480}
481
Brian Osman1c110a02019-10-01 14:53:32 -0400482ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Expression& expr) {
Brian Osman07c117b2019-05-23 12:51:06 -0700483 switch (expr.fKind) {
484 case Expression::kFieldAccess_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400485 const FieldAccess& f = (const FieldAccess&)expr;
486 Location baseLoc = this->getLocation(*f.fBase);
Brian Osman07c117b2019-05-23 12:51:06 -0700487 int offset = 0;
488 for (int i = 0; i < f.fFieldIndex; ++i) {
489 offset += SlotCount(*f.fBase->fType.fields()[i].fType);
490 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400491 if (baseLoc.isOnStack()) {
492 if (offset != 0) {
493 this->write(ByteCodeInstruction::kPushImmediate);
494 this->write32(offset);
495 this->write(ByteCodeInstruction::kAddI);
Ben Wagner470e0ac2020-01-22 16:59:21 -0500496 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400497 return baseLoc;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500498 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400499 return baseLoc + offset;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500500 }
Ben Wagner470e0ac2020-01-22 16:59:21 -0500501 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400502 case Expression::kIndex_Kind: {
503 const IndexExpression& i = (const IndexExpression&)expr;
504 int stride = SlotCount(i.fType);
505 int length = i.fBase->fType.columns();
506 SkASSERT(length <= 255);
507 int offset = -1;
508 if (i.fIndex->isConstant()) {
509 int64_t index = i.fIndex->getConstantInt();
510 if (index < 0 || index >= length) {
511 fErrors.error(i.fIndex->fOffset, "Array index out of bounds.");
512 return Location::MakeInvalid();
513 }
514 offset = index * stride;
515 } else {
516 if (i.fIndex->hasSideEffects()) {
517 // Having a side-effect in an indexer is technically safe for an rvalue,
518 // but with lvalues we have to evaluate the indexer twice, so make it an error.
519 fErrors.error(i.fIndex->fOffset,
520 "Index expressions with side-effects not supported in byte code.");
521 return Location::MakeInvalid();
522 }
523 this->writeExpression(*i.fIndex);
524 this->write(ByteCodeInstruction::kClampIndex);
525 this->write8(length);
526 if (stride != 1) {
527 this->write(ByteCodeInstruction::kPushImmediate);
528 this->write32(stride);
529 this->write(ByteCodeInstruction::kMultiplyI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400530 }
531 }
532 Location baseLoc = this->getLocation(*i.fBase);
533
534 // Are both components known statically?
535 if (!baseLoc.isOnStack() && offset >= 0) {
536 return baseLoc + offset;
537 }
538
539 // At least one component is dynamic (and on the stack).
540
541 // If the other component is zero, we're done
542 if (baseLoc.fSlot == 0 || offset == 0) {
543 return baseLoc.makeOnStack();
544 }
545
546 // Push the non-dynamic component (if any) to the stack, then add the two
547 if (!baseLoc.isOnStack()) {
548 this->write(ByteCodeInstruction::kPushImmediate);
549 this->write32(baseLoc.fSlot);
550 }
551 if (offset >= 0) {
552 this->write(ByteCodeInstruction::kPushImmediate);
553 this->write32(offset);
554 }
555 this->write(ByteCodeInstruction::kAddI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400556 return baseLoc.makeOnStack();
557 }
Brian Osman0785db02019-05-24 14:19:11 -0400558 case Expression::kSwizzle_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400559 const Swizzle& s = (const Swizzle&)expr;
Brian Osman0785db02019-05-24 14:19:11 -0400560 SkASSERT(swizzle_is_simple(s));
Brian Osmanb08cc022020-04-02 11:38:40 -0400561 Location baseLoc = this->getLocation(*s.fBase);
562 int offset = s.fComponents[0];
563 if (baseLoc.isOnStack()) {
564 if (offset != 0) {
565 this->write(ByteCodeInstruction::kPushImmediate);
566 this->write32(offset);
567 this->write(ByteCodeInstruction::kAddI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400568 }
569 return baseLoc;
570 } else {
571 return baseLoc + offset;
572 }
Brian Osman0785db02019-05-24 14:19:11 -0400573 }
Brian Osman07c117b2019-05-23 12:51:06 -0700574 case Expression::kVariableReference_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400575 const Variable& var = ((const VariableReference&)expr).fVariable;
Brian Osman07c117b2019-05-23 12:51:06 -0700576 return this->getLocation(var);
577 }
578 default:
579 SkASSERT(false);
Brian Osmanb08cc022020-04-02 11:38:40 -0400580 return Location::MakeInvalid();
Brian Osman07c117b2019-05-23 12:51:06 -0700581 }
582}
583
Brian Osmanb08cc022020-04-02 11:38:40 -0400584void ByteCodeGenerator::write8(uint8_t b) {
585 fCode->push_back(b);
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500586}
587
Brian Osmanb08cc022020-04-02 11:38:40 -0400588void ByteCodeGenerator::write16(uint16_t i) {
589 size_t n = fCode->size();
590 fCode->resize(n+2);
591 memcpy(fCode->data() + n, &i, 2);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500592}
Ben Wagner470e0ac2020-01-22 16:59:21 -0500593
Brian Osmanb08cc022020-04-02 11:38:40 -0400594void ByteCodeGenerator::write32(uint32_t i) {
595 size_t n = fCode->size();
596 fCode->resize(n+4);
597 memcpy(fCode->data() + n, &i, 4);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500598}
599
Brian Osmanb08cc022020-04-02 11:38:40 -0400600void ByteCodeGenerator::write(ByteCodeInstruction i, int count) {
601 switch (i) {
602 case ByteCodeInstruction::kLoopBegin: this->enterLoop(); break;
603 case ByteCodeInstruction::kLoopEnd: this->exitLoop(); break;
Ethan Nicholas2329da02020-01-24 15:49:33 -0500604
Brian Osmanb08cc022020-04-02 11:38:40 -0400605 case ByteCodeInstruction::kMaskPush: this->enterCondition(); break;
606 case ByteCodeInstruction::kMaskPop:
607 case ByteCodeInstruction::kMaskBlend: this->exitCondition(); break;
608 default: /* Do nothing */ break;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500609 }
Brian Osmanab8f3842020-04-07 09:30:44 -0400610 this->write16((uint16_t)i);
Brian Osmanb08cc022020-04-02 11:38:40 -0400611 fStackCount += StackUsage(i, count);
612 fMaxStackCount = std::max(fMaxStackCount, fStackCount);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500613}
614
Brian Osmanb08cc022020-04-02 11:38:40 -0400615static ByteCodeInstruction vector_instruction(ByteCodeInstruction base, int count) {
616 SkASSERT(count >= 1 && count <= 4);
617 return ((ByteCodeInstruction) ((int) base + 1 - count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500618}
619
Brian Osmanb08cc022020-04-02 11:38:40 -0400620void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
621 ByteCodeInstruction u, ByteCodeInstruction f,
Brian Osmanab8f3842020-04-07 09:30:44 -0400622 int count) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500623 switch (type_category(type)) {
624 case TypeCategory::kSigned:
Brian Osmanb08cc022020-04-02 11:38:40 -0400625 this->write(vector_instruction(s, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500626 break;
627 case TypeCategory::kUnsigned:
Brian Osmanb08cc022020-04-02 11:38:40 -0400628 this->write(vector_instruction(u, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500629 break;
630 case TypeCategory::kFloat: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400631 if (count > 4) {
632 this->write((ByteCodeInstruction)((int)f + 1), count);
Brian Osmanab8f3842020-04-07 09:30:44 -0400633 this->write8(count);
Brian Osmanb08cc022020-04-02 11:38:40 -0400634 } else {
635 this->write(vector_instruction(f, count));
636 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500637 break;
638 }
639 default:
640 SkASSERT(false);
641 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500642}
643
Brian Osmanb08cc022020-04-02 11:38:40 -0400644bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool discard) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400645 if (b.fOperator == Token::Kind::TK_EQ) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500646 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
Brian Osmanb08cc022020-04-02 11:38:40 -0400647 this->writeExpression(*b.fRight);
648 lvalue->store(discard);
649 discard = false;
650 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500651 }
652 const Type& lType = b.fLeft->fType;
653 const Type& rType = b.fRight->fType;
654 bool lVecOrMtx = (lType.kind() == Type::kVector_Kind || lType.kind() == Type::kMatrix_Kind);
655 bool rVecOrMtx = (rType.kind() == Type::kVector_Kind || rType.kind() == Type::kMatrix_Kind);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500656 Token::Kind op;
657 std::unique_ptr<LValue> lvalue;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500658 if (is_assignment(b.fOperator)) {
659 lvalue = this->getLValue(*b.fLeft);
Brian Osmanb08cc022020-04-02 11:38:40 -0400660 lvalue->load();
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500661 op = remove_assignment(b.fOperator);
662 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400663 this->writeExpression(*b.fLeft);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500664 op = b.fOperator;
665 if (!lVecOrMtx && rVecOrMtx) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400666 for (int i = SlotCount(rType); i > 1; --i) {
667 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400668 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500669 }
670 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500671 int count = std::max(SlotCount(lType), SlotCount(rType));
Brian Osmanb08cc022020-04-02 11:38:40 -0400672 SkDEBUGCODE(TypeCategory tc = type_category(lType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500673 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400674 case Token::Kind::TK_LOGICALAND: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400675 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
676 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400677 this->write(ByteCodeInstruction::kMaskPush);
678 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500679 DeferredLocation falseLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -0400680 this->writeExpression(*b.fRight);
681 this->write(ByteCodeInstruction::kAndB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500682 falseLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -0400683 this->write(ByteCodeInstruction::kMaskPop);
684 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500685 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400686 case Token::Kind::TK_LOGICALOR: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400687 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
688 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400689 this->write(ByteCodeInstruction::kNotB);
690 this->write(ByteCodeInstruction::kMaskPush);
691 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500692 DeferredLocation falseLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -0400693 this->writeExpression(*b.fRight);
694 this->write(ByteCodeInstruction::kOrB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500695 falseLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -0400696 this->write(ByteCodeInstruction::kMaskPop);
697 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500698 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400699 case Token::Kind::TK_SHL:
700 case Token::Kind::TK_SHR: {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500701 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
702 tc == SkSL::TypeCategory::kUnsigned));
703 if (!b.fRight->isConstant()) {
704 fErrors.error(b.fRight->fOffset, "Shift amounts must be constant");
Brian Osmanb08cc022020-04-02 11:38:40 -0400705 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500706 }
707 int64_t shift = b.fRight->getConstantInt();
708 if (shift < 0 || shift > 31) {
709 fErrors.error(b.fRight->fOffset, "Shift amount out of range");
Brian Osmanb08cc022020-04-02 11:38:40 -0400710 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500711 }
712
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400713 if (op == Token::Kind::TK_SHL) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400714 this->write(ByteCodeInstruction::kShiftLeft);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500715 } else {
716 this->write(type_category(lType) == TypeCategory::kSigned
Brian Osmanb08cc022020-04-02 11:38:40 -0400717 ? ByteCodeInstruction::kShiftRightS
718 : ByteCodeInstruction::kShiftRightU);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500719 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400720 this->write8(shift);
721 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500722 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500723
724 default:
725 break;
726 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400727 this->writeExpression(*b.fRight);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500728 if (lVecOrMtx && !rVecOrMtx) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400729 for (int i = SlotCount(lType); i > 1; --i) {
730 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400731 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500732 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400733 // Special case for M*V, V*M, M*M (but not V*V!)
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400734 if (op == Token::Kind::TK_STAR && lVecOrMtx && rVecOrMtx &&
Brian Osmanb08cc022020-04-02 11:38:40 -0400735 !(lType.kind() == Type::kVector_Kind && rType.kind() == Type::kVector_Kind)) {
736 this->write(ByteCodeInstruction::kMatrixMultiply,
737 SlotCount(b.fType) - (SlotCount(lType) + SlotCount(rType)));
738 int rCols = rType.columns(),
739 rRows = rType.rows(),
740 lCols = lType.columns(),
741 lRows = lType.rows();
742 // M*V treats the vector as a column
743 if (rType.kind() == Type::kVector_Kind) {
744 std::swap(rCols, rRows);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500745 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400746 SkASSERT(lCols == rRows);
747 SkASSERT(SlotCount(b.fType) == lRows * rCols);
748 this->write8(lCols);
749 this->write8(lRows);
750 this->write8(rCols);
751 } else {
752 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400753 case Token::Kind::TK_EQEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400754 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareIEQ,
755 ByteCodeInstruction::kCompareIEQ,
756 ByteCodeInstruction::kCompareFEQ,
757 count);
758 // Collapse to a single bool
759 for (int i = count; i > 1; --i) {
760 this->write(ByteCodeInstruction::kAndB);
761 }
762 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400763 case Token::Kind::TK_GT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400764 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGT,
765 ByteCodeInstruction::kCompareUGT,
766 ByteCodeInstruction::kCompareFGT,
767 count);
768 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400769 case Token::Kind::TK_GTEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400770 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGTEQ,
771 ByteCodeInstruction::kCompareUGTEQ,
772 ByteCodeInstruction::kCompareFGTEQ,
773 count);
774 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400775 case Token::Kind::TK_LT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400776 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLT,
777 ByteCodeInstruction::kCompareULT,
778 ByteCodeInstruction::kCompareFLT,
779 count);
780 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400781 case Token::Kind::TK_LTEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400782 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLTEQ,
783 ByteCodeInstruction::kCompareULTEQ,
784 ByteCodeInstruction::kCompareFLTEQ,
785 count);
786 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400787 case Token::Kind::TK_MINUS:
Brian Osmanb08cc022020-04-02 11:38:40 -0400788 this->writeTypedInstruction(lType, ByteCodeInstruction::kSubtractI,
789 ByteCodeInstruction::kSubtractI,
790 ByteCodeInstruction::kSubtractF,
791 count);
792 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400793 case Token::Kind::TK_NEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400794 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareINEQ,
795 ByteCodeInstruction::kCompareINEQ,
796 ByteCodeInstruction::kCompareFNEQ,
797 count);
798 // Collapse to a single bool
799 for (int i = count; i > 1; --i) {
800 this->write(ByteCodeInstruction::kOrB);
801 }
802 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400803 case Token::Kind::TK_PERCENT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400804 this->writeTypedInstruction(lType, ByteCodeInstruction::kRemainderS,
805 ByteCodeInstruction::kRemainderU,
806 ByteCodeInstruction::kRemainderF,
807 count);
808 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400809 case Token::Kind::TK_PLUS:
Brian Osmanb08cc022020-04-02 11:38:40 -0400810 this->writeTypedInstruction(lType, ByteCodeInstruction::kAddI,
811 ByteCodeInstruction::kAddI,
812 ByteCodeInstruction::kAddF,
813 count);
814 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400815 case Token::Kind::TK_SLASH:
Brian Osmanb08cc022020-04-02 11:38:40 -0400816 this->writeTypedInstruction(lType, ByteCodeInstruction::kDivideS,
817 ByteCodeInstruction::kDivideU,
818 ByteCodeInstruction::kDivideF,
819 count);
820 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400821 case Token::Kind::TK_STAR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400822 this->writeTypedInstruction(lType, ByteCodeInstruction::kMultiplyI,
823 ByteCodeInstruction::kMultiplyI,
824 ByteCodeInstruction::kMultiplyF,
825 count);
826 break;
827
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400828 case Token::Kind::TK_LOGICALXOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400829 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
830 this->write(ByteCodeInstruction::kXorB);
831 break;
832
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400833 case Token::Kind::TK_BITWISEAND:
Brian Osmanb08cc022020-04-02 11:38:40 -0400834 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
835 tc == SkSL::TypeCategory::kUnsigned));
836 this->write(ByteCodeInstruction::kAndB);
837 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400838 case Token::Kind::TK_BITWISEOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400839 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
840 tc == SkSL::TypeCategory::kUnsigned));
841 this->write(ByteCodeInstruction::kOrB);
842 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400843 case Token::Kind::TK_BITWISEXOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400844 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
845 tc == SkSL::TypeCategory::kUnsigned));
846 this->write(ByteCodeInstruction::kXorB);
847 break;
848
849 default:
850 fErrors.error(b.fOffset, SkSL::String::printf("Unsupported binary operator '%s'",
851 Compiler::OperatorName(op)));
852 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500853 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500854 }
855 if (lvalue) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400856 lvalue->store(discard);
857 discard = false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500858 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400859 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500860}
861
Brian Osmanb08cc022020-04-02 11:38:40 -0400862void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
863 this->write(ByteCodeInstruction::kPushImmediate);
864 this->write32(b.fValue ? ~0 : 0);
865}
866
867void ByteCodeGenerator::writeConstructor(const Constructor& c) {
868 for (const auto& arg : c.fArguments) {
869 this->writeExpression(*arg);
870 }
871 if (c.fArguments.size() == 1) {
872 const Type& inType = c.fArguments[0]->fType;
873 const Type& outType = c.fType;
874 TypeCategory inCategory = type_category(inType);
875 TypeCategory outCategory = type_category(outType);
876 int inCount = SlotCount(inType);
877 int outCount = SlotCount(outType);
878 if (inCategory != outCategory) {
879 SkASSERT(inCount == outCount);
880 if (inCategory == TypeCategory::kFloat) {
881 SkASSERT(outCategory == TypeCategory::kSigned ||
882 outCategory == TypeCategory::kUnsigned);
883 this->write(vector_instruction(ByteCodeInstruction::kConvertFtoI, outCount));
884 } else if (outCategory == TypeCategory::kFloat) {
885 if (inCategory == TypeCategory::kSigned) {
886 this->write(vector_instruction(ByteCodeInstruction::kConvertStoF, outCount));
887 } else {
888 SkASSERT(inCategory == TypeCategory::kUnsigned);
889 this->write(vector_instruction(ByteCodeInstruction::kConvertUtoF, outCount));
890 }
891 } else {
892 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500893 }
894 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400895 if (inType.kind() == Type::kMatrix_Kind && outType.kind() == Type::kMatrix_Kind) {
896 this->write(ByteCodeInstruction::kMatrixToMatrix,
897 SlotCount(outType) - SlotCount(inType));
898 this->write8(inType.columns());
899 this->write8(inType.rows());
900 this->write8(outType.columns());
901 this->write8(outType.rows());
902 } else if (inCount != outCount) {
903 SkASSERT(inCount == 1);
904 if (outType.kind() == Type::kMatrix_Kind) {
905 this->write(ByteCodeInstruction::kScalarToMatrix, SlotCount(outType) - 1);
906 this->write8(outType.columns());
907 this->write8(outType.rows());
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500908 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400909 SkASSERT(outType.kind() == Type::kVector_Kind);
910 for (; inCount != outCount; ++inCount) {
911 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400912 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500913 }
914 }
915 }
916}
917
Brian Osmanb08cc022020-04-02 11:38:40 -0400918void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500919 int argumentCount = 0;
920 for (const auto& arg : f.fArguments) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400921 this->writeExpression(*arg);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500922 argumentCount += SlotCount(arg->fType);
923 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400924 this->write(ByteCodeInstruction::kCallExternal, SlotCount(f.fType) - argumentCount);
925 SkASSERT(argumentCount <= 255);
926 this->write8(argumentCount);
927 this->write8(SlotCount(f.fType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500928 int index = fOutput->fExternalValues.size();
929 fOutput->fExternalValues.push_back(f.fFunction);
930 SkASSERT(index <= 255);
Brian Osmanb08cc022020-04-02 11:38:40 -0400931 this->write8(index);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500932}
933
Brian Osmanb08cc022020-04-02 11:38:40 -0400934void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
935 int count = SlotCount(e.fValue->type());
936 this->write(vector_instruction(ByteCodeInstruction::kReadExternal, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500937 int index = fOutput->fExternalValues.size();
938 fOutput->fExternalValues.push_back(e.fValue);
939 SkASSERT(index <= 255);
Brian Osmanb08cc022020-04-02 11:38:40 -0400940 this->write8(index);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500941}
942
Brian Osmanb08cc022020-04-02 11:38:40 -0400943void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
944 Location location = this->getLocation(expr);
945 int count = SlotCount(expr.fType);
Brian Osmanefb08402020-04-13 16:30:44 -0400946 if (count == 0) {
947 return;
948 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400949 if (location.isOnStack() || count > 4) {
950 if (!location.isOnStack()) {
951 this->write(ByteCodeInstruction::kPushImmediate);
952 this->write32(location.fSlot);
953 }
954 this->write(location.selectLoad(ByteCodeInstruction::kLoadExtended,
955 ByteCodeInstruction::kLoadExtendedGlobal,
956 ByteCodeInstruction::kLoadExtendedUniform),
957 count);
958 this->write8(count);
959 } else {
960 this->write(vector_instruction(location.selectLoad(ByteCodeInstruction::kLoad,
961 ByteCodeInstruction::kLoadGlobal,
962 ByteCodeInstruction::kLoadUniform),
963 count));
Brian Osmanb08cc022020-04-02 11:38:40 -0400964 this->write8(location.fSlot);
965 }
966}
967
968static inline uint32_t float_to_bits(float x) {
969 uint32_t u;
970 memcpy(&u, &x, sizeof(uint32_t));
971 return u;
972}
973
974void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
975 this->write(ByteCodeInstruction::kPushImmediate);
976 this->write32(float_to_bits(f.fValue));
977}
978
979void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
980 auto found = fIntrinsics.find(c.fFunction.fName);
981 if (found == fIntrinsics.end()) {
982 fErrors.error(c.fOffset, String::printf("Unsupported intrinsic: '%s'",
983 String(c.fFunction.fName).c_str()));
984 return;
985 }
Mike Klein45be0772020-05-01 09:13:18 -0500986 Intrinsic intrin = found->second;
987
Brian Osmanb08cc022020-04-02 11:38:40 -0400988 int count = SlotCount(c.fArguments[0]->fType);
Mike Klein45be0772020-05-01 09:13:18 -0500989 if (intrin.is_special) {
990 switch (intrin.special) {
Brian Osman15c98cb2020-02-27 18:36:57 +0000991 case SpecialIntrinsic::kDot: {
992 SkASSERT(c.fArguments.size() == 2);
Brian Osmanb08cc022020-04-02 11:38:40 -0400993 SkASSERT(count == SlotCount(c.fArguments[1]->fType));
994 this->write(vector_instruction(ByteCodeInstruction::kMultiplyF, count));
Mike Klein45be0772020-05-01 09:13:18 -0500995 for (int i = count-1; i --> 0;) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400996 this->write(ByteCodeInstruction::kAddF);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500997 }
Mike Klein45be0772020-05-01 09:13:18 -0500998 } break;
999
1000 case SpecialIntrinsic::kLength: {
1001 SkASSERT(c.fArguments.size() == 1);
1002 this->write(vector_instruction(ByteCodeInstruction::kDup , count));
1003 this->write(vector_instruction(ByteCodeInstruction::kMultiplyF, count));
1004 for (int i = count-1; i --> 0;) {
1005 this->write(ByteCodeInstruction::kAddF);
1006 }
1007 this->write(ByteCodeInstruction::kSqrt);
1008 } break;
1009
Brian Osmanb08cc022020-04-02 11:38:40 -04001010 default:
1011 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001012 }
1013 } else {
Mike Klein45be0772020-05-01 09:13:18 -05001014 switch (intrin.instruction) {
Mike Reed8520e762020-04-30 12:06:23 -04001015 case ByteCodeInstruction::kATan:
Brian Osmanb08cc022020-04-02 11:38:40 -04001016 case ByteCodeInstruction::kCos:
Mike Reed8520e762020-04-30 12:06:23 -04001017 case ByteCodeInstruction::kFract:
Florin Malita3facc9c2020-05-04 09:26:15 -04001018 case ByteCodeInstruction::kPow:
Brian Osmanb08cc022020-04-02 11:38:40 -04001019 case ByteCodeInstruction::kSin:
Brian Osmanb08cc022020-04-02 11:38:40 -04001020 case ByteCodeInstruction::kSqrt:
Brian Osmanab8f3842020-04-07 09:30:44 -04001021 case ByteCodeInstruction::kTan:
Brian Osmanb08cc022020-04-02 11:38:40 -04001022 SkASSERT(c.fArguments.size() > 0);
Mike Klein45be0772020-05-01 09:13:18 -05001023 this->write(vector_instruction(intrin.instruction, count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001024 break;
Mike Klein45be0772020-05-01 09:13:18 -05001025
Brian Osmanb08cc022020-04-02 11:38:40 -04001026 case ByteCodeInstruction::kInverse2x2: {
1027 SkASSERT(c.fArguments.size() > 0);
1028 auto op = ByteCodeInstruction::kInverse2x2;
1029 switch (count) {
1030 case 4: break; // float2x2
1031 case 9: op = ByteCodeInstruction::kInverse3x3; break;
1032 case 16: op = ByteCodeInstruction::kInverse4x4; break;
1033 default: SkASSERT(false);
1034 }
1035 this->write(op);
1036 break;
Brian Osman15c98cb2020-02-27 18:36:57 +00001037 }
Mike Klein45be0772020-05-01 09:13:18 -05001038
Brian Osmanb08cc022020-04-02 11:38:40 -04001039 default:
1040 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001041 }
1042 }
1043}
1044
Brian Osmanb08cc022020-04-02 11:38:40 -04001045void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001046 // Find the index of the function we're calling. We explicitly do not allow calls to functions
1047 // before they're defined. This is an easy-to-understand rule that prevents recursion.
Brian Osmanb08cc022020-04-02 11:38:40 -04001048 int idx = -1;
1049 for (size_t i = 0; i < fFunctions.size(); ++i) {
1050 if (f.fFunction.matches(fFunctions[i]->fDeclaration)) {
1051 idx = i;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001052 break;
1053 }
1054 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001055 if (idx == -1) {
1056 for (const auto& arg : f.fArguments) {
1057 this->writeExpression(*arg);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001058 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001059 this->writeIntrinsicCall(f);
1060 return;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001061 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001062
1063
1064 if (idx > 255) {
1065 fErrors.error(f.fOffset, "Function count limit exceeded");
1066 return;
1067 } else if (idx >= (int) fFunctions.size()) {
1068 fErrors.error(f.fOffset, "Call to undefined function");
1069 return;
1070 }
1071
1072 // We may need to deal with out parameters, so the sequence is tricky
1073 if (int returnCount = SlotCount(f.fType)) {
1074 this->write(ByteCodeInstruction::kReserve, returnCount);
1075 this->write8(returnCount);
1076 }
1077
1078 int argCount = f.fArguments.size();
1079 std::vector<std::unique_ptr<LValue>> lvalues;
1080 for (int i = 0; i < argCount; ++i) {
1081 const auto& param = f.fFunction.fParameters[i];
1082 const auto& arg = f.fArguments[i];
1083 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1084 lvalues.emplace_back(this->getLValue(*arg));
1085 lvalues.back()->load();
1086 } else {
1087 this->writeExpression(*arg);
1088 }
1089 }
1090
1091 // The space used by the call is based on the callee, but it also unwinds all of that before
1092 // we continue execution. We adjust our max stack depths below.
1093 this->write(ByteCodeInstruction::kCall);
1094 this->write8(idx);
1095
1096 const ByteCodeFunction* callee = fOutput->fFunctions[idx].get();
1097 fMaxLoopCount = std::max(fMaxLoopCount, fLoopCount + callee->fLoopCount);
1098 fMaxConditionCount = std::max(fMaxConditionCount, fConditionCount + callee->fConditionCount);
1099 fMaxStackCount = std::max(fMaxStackCount, fStackCount + callee->fLocalCount
1100 + callee->fStackCount);
1101
1102 // After the called function returns, the stack will still contain our arguments. We have to
1103 // pop them (storing any out parameters back to their lvalues as we go). We glob together slot
1104 // counts for all parameters that aren't out-params, so we can pop them in one big chunk.
1105 int popCount = 0;
1106 auto pop = [&]() {
1107 if (popCount > 4) {
1108 this->write(ByteCodeInstruction::kPopN, popCount);
1109 this->write8(popCount);
1110 } else if (popCount > 0) {
1111 this->write(vector_instruction(ByteCodeInstruction::kPop, popCount));
1112 }
1113 popCount = 0;
1114 };
1115
1116 for (int i = argCount - 1; i >= 0; --i) {
1117 const auto& param = f.fFunction.fParameters[i];
1118 const auto& arg = f.fArguments[i];
1119 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1120 pop();
1121 lvalues.back()->store(true);
1122 lvalues.pop_back();
1123 } else {
1124 popCount += SlotCount(arg->fType);
1125 }
1126 }
1127 pop();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001128}
1129
Brian Osmanb08cc022020-04-02 11:38:40 -04001130void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
1131 this->write(ByteCodeInstruction::kPushImmediate);
1132 this->write32(i.fValue);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001133}
1134
Brian Osmanb08cc022020-04-02 11:38:40 -04001135void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
1136 // not yet implemented
1137 abort();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001138}
1139
Brian Osmanb08cc022020-04-02 11:38:40 -04001140bool ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p, bool discard) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001141 switch (p.fOperator) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001142 case Token::Kind::TK_PLUSPLUS: // fall through
1143 case Token::Kind::TK_MINUSMINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001144 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1145 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
1146 lvalue->load();
1147 this->write(ByteCodeInstruction::kPushImmediate);
1148 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001149 if (p.fOperator == Token::Kind::TK_PLUSPLUS) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001150 this->writeTypedInstruction(p.fType,
1151 ByteCodeInstruction::kAddI,
1152 ByteCodeInstruction::kAddI,
1153 ByteCodeInstruction::kAddF,
1154 1);
1155 } else {
1156 this->writeTypedInstruction(p.fType,
1157 ByteCodeInstruction::kSubtractI,
1158 ByteCodeInstruction::kSubtractI,
1159 ByteCodeInstruction::kSubtractF,
1160 1);
1161 }
1162 lvalue->store(discard);
1163 discard = false;
1164 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001165 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001166 case Token::Kind::TK_MINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001167 this->writeExpression(*p.fOperand);
1168 this->writeTypedInstruction(p.fType,
1169 ByteCodeInstruction::kNegateI,
1170 ByteCodeInstruction::kNegateI,
1171 ByteCodeInstruction::kNegateF,
Brian Osmanab8f3842020-04-07 09:30:44 -04001172 SlotCount(p.fOperand->fType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001173 break;
1174 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001175 case Token::Kind::TK_LOGICALNOT:
1176 case Token::Kind::TK_BITWISENOT: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001177 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1178 SkDEBUGCODE(TypeCategory tc = type_category(p.fOperand->fType));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001179 SkASSERT((p.fOperator == Token::Kind::TK_LOGICALNOT && tc == TypeCategory::kBool) ||
1180 (p.fOperator == Token::Kind::TK_BITWISENOT && (tc == TypeCategory::kSigned ||
Brian Osmanb08cc022020-04-02 11:38:40 -04001181 tc == TypeCategory::kUnsigned)));
1182 this->writeExpression(*p.fOperand);
1183 this->write(ByteCodeInstruction::kNotB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001184 break;
1185 }
1186 default:
1187 SkASSERT(false);
1188 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001189 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001190}
1191
Brian Osmanb08cc022020-04-02 11:38:40 -04001192bool ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p, bool discard) {
1193 switch (p.fOperator) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001194 case Token::Kind::TK_PLUSPLUS: // fall through
1195 case Token::Kind::TK_MINUSMINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001196 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1197 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
1198 lvalue->load();
1199 // If we're not supposed to discard the result, then make a copy *before* the +/-
1200 if (!discard) {
1201 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -04001202 }
1203 this->write(ByteCodeInstruction::kPushImmediate);
1204 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001205 if (p.fOperator == Token::Kind::TK_PLUSPLUS) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001206 this->writeTypedInstruction(p.fType,
1207 ByteCodeInstruction::kAddI,
1208 ByteCodeInstruction::kAddI,
1209 ByteCodeInstruction::kAddF,
1210 1);
1211 } else {
1212 this->writeTypedInstruction(p.fType,
1213 ByteCodeInstruction::kSubtractI,
1214 ByteCodeInstruction::kSubtractI,
1215 ByteCodeInstruction::kSubtractF,
1216 1);
1217 }
1218 // Always consume the result as part of the store
1219 lvalue->store(true);
1220 discard = false;
1221 break;
1222 }
1223 default:
1224 SkASSERT(false);
1225 }
1226 return discard;
1227}
1228
1229void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001230 if (swizzle_is_simple(s)) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001231 this->writeVariableExpression(s);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001232 return;
1233 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001234
1235 switch (s.fBase->fKind) {
1236 case Expression::kVariableReference_Kind: {
1237 Location location = this->getLocation(*s.fBase);
1238 this->write(location.selectLoad(ByteCodeInstruction::kLoadSwizzle,
1239 ByteCodeInstruction::kLoadSwizzleGlobal,
1240 ByteCodeInstruction::kLoadSwizzleUniform),
1241 s.fComponents.size());
1242 this->write8(location.fSlot);
1243 this->write8(s.fComponents.size());
1244 for (int c : s.fComponents) {
1245 this->write8(c);
1246 }
1247 break;
1248 }
1249 default:
1250 this->writeExpression(*s.fBase);
1251 this->write(ByteCodeInstruction::kSwizzle,
1252 s.fComponents.size() - s.fBase->fType.columns());
1253 this->write8(s.fBase->fType.columns());
1254 this->write8(s.fComponents.size());
1255 for (int c : s.fComponents) {
1256 this->write8(c);
1257 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001258 }
1259}
1260
Brian Osmanb08cc022020-04-02 11:38:40 -04001261void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001262 int count = SlotCount(t.fType);
1263 SkASSERT(count == SlotCount(t.fIfTrue->fType));
1264 SkASSERT(count == SlotCount(t.fIfFalse->fType));
1265
Brian Osmanb08cc022020-04-02 11:38:40 -04001266 this->writeExpression(*t.fTest);
1267 this->write(ByteCodeInstruction::kMaskPush);
1268 this->writeExpression(*t.fIfTrue);
1269 this->write(ByteCodeInstruction::kMaskNegate);
1270 this->writeExpression(*t.fIfFalse);
1271 this->write(ByteCodeInstruction::kMaskBlend, count);
1272 this->write8(count);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001273}
1274
Brian Osmanb08cc022020-04-02 11:38:40 -04001275void ByteCodeGenerator::writeExpression(const Expression& e, bool discard) {
1276 switch (e.fKind) {
1277 case Expression::kBinary_Kind:
1278 discard = this->writeBinaryExpression((BinaryExpression&) e, discard);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001279 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001280 case Expression::kBoolLiteral_Kind:
1281 this->writeBoolLiteral((BoolLiteral&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001282 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001283 case Expression::kConstructor_Kind:
1284 this->writeConstructor((Constructor&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001285 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001286 case Expression::kExternalFunctionCall_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001287 this->writeExternalFunctionCall((ExternalFunctionCall&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001288 break;
1289 case Expression::kExternalValue_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001290 this->writeExternalValue((ExternalValueReference&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001291 break;
1292 case Expression::kFieldAccess_Kind:
1293 case Expression::kIndex_Kind:
1294 case Expression::kVariableReference_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001295 this->writeVariableExpression(e);
1296 break;
1297 case Expression::kFloatLiteral_Kind:
1298 this->writeFloatLiteral((FloatLiteral&) e);
1299 break;
1300 case Expression::kFunctionCall_Kind:
1301 this->writeFunctionCall((FunctionCall&) e);
1302 break;
1303 case Expression::kIntLiteral_Kind:
1304 this->writeIntLiteral((IntLiteral&) e);
1305 break;
1306 case Expression::kNullLiteral_Kind:
1307 this->writeNullLiteral((NullLiteral&) e);
1308 break;
1309 case Expression::kPrefix_Kind:
1310 discard = this->writePrefixExpression((PrefixExpression&) e, discard);
1311 break;
1312 case Expression::kPostfix_Kind:
1313 discard = this->writePostfixExpression((PostfixExpression&) e, discard);
1314 break;
1315 case Expression::kSwizzle_Kind:
1316 this->writeSwizzle((Swizzle&) e);
1317 break;
1318 case Expression::kTernary_Kind:
1319 this->writeTernaryExpression((TernaryExpression&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001320 break;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001321 default:
1322#ifdef SK_DEBUG
Brian Osmanb08cc022020-04-02 11:38:40 -04001323 printf("unsupported expression %s\n", e.description().c_str());
Ben Wagner470e0ac2020-01-22 16:59:21 -05001324#endif
Brian Osmanb08cc022020-04-02 11:38:40 -04001325 SkASSERT(false);
1326 }
1327 if (discard) {
1328 int count = SlotCount(e.fType);
1329 if (count > 4) {
1330 this->write(ByteCodeInstruction::kPopN, count);
1331 this->write8(count);
1332 } else if (count != 0) {
1333 this->write(vector_instruction(ByteCodeInstruction::kPop, count));
1334 }
1335 discard = false;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001336 }
Ethan Nicholas7deb1c22020-01-22 10:31:55 -05001337}
1338
Brian Osmanb08cc022020-04-02 11:38:40 -04001339class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
1340public:
1341 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
1342 : INHERITED(*generator)
1343 , fCount(ByteCodeGenerator::SlotCount(value.type()))
1344 , fIndex(index) {}
1345
1346 void load() override {
1347 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001348 fGenerator.write8(fIndex);
1349 }
1350
1351 void store(bool discard) override {
1352 if (!discard) {
1353 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001354 }
1355 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001356 fGenerator.write8(fIndex);
1357 }
1358
1359private:
1360 typedef LValue INHERITED;
1361
1362 int fCount;
1363
1364 int fIndex;
1365};
1366
1367class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
1368public:
1369 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
1370 : INHERITED(*generator)
1371 , fSwizzle(swizzle) {}
1372
1373 void load() override {
1374 fGenerator.writeSwizzle(fSwizzle);
1375 }
1376
1377 void store(bool discard) override {
1378 int count = fSwizzle.fComponents.size();
1379 if (!discard) {
1380 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001381 }
1382 ByteCodeGenerator::Location location = fGenerator.getLocation(*fSwizzle.fBase);
1383 if (location.isOnStack()) {
1384 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreSwizzleIndirect,
1385 ByteCodeInstruction::kStoreSwizzleIndirectGlobal),
1386 count);
1387 } else {
1388 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreSwizzle,
1389 ByteCodeInstruction::kStoreSwizzleGlobal),
1390 count);
1391 fGenerator.write8(location.fSlot);
1392 }
1393 fGenerator.write8(count);
1394 for (int c : fSwizzle.fComponents) {
1395 fGenerator.write8(c);
1396 }
1397 }
1398
1399private:
1400 const Swizzle& fSwizzle;
1401
1402 typedef LValue INHERITED;
1403};
1404
1405class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
1406public:
1407 ByteCodeExpressionLValue(ByteCodeGenerator* generator, const Expression& expr)
1408 : INHERITED(*generator)
1409 , fExpression(expr) {}
1410
1411 void load() override {
1412 fGenerator.writeVariableExpression(fExpression);
1413 }
1414
1415 void store(bool discard) override {
1416 int count = ByteCodeGenerator::SlotCount(fExpression.fType);
1417 if (!discard) {
1418 if (count > 4) {
1419 fGenerator.write(ByteCodeInstruction::kDupN, count);
1420 fGenerator.write8(count);
1421 } else {
1422 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001423 }
1424 }
1425 ByteCodeGenerator::Location location = fGenerator.getLocation(fExpression);
1426 if (location.isOnStack() || count > 4) {
1427 if (!location.isOnStack()) {
1428 fGenerator.write(ByteCodeInstruction::kPushImmediate);
1429 fGenerator.write32(location.fSlot);
1430 }
1431 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreExtended,
1432 ByteCodeInstruction::kStoreExtendedGlobal),
1433 count);
1434 fGenerator.write8(count);
1435 } else {
1436 fGenerator.write(
1437 vector_instruction(location.selectStore(ByteCodeInstruction::kStore,
1438 ByteCodeInstruction::kStoreGlobal),
1439 count));
1440 fGenerator.write8(location.fSlot);
1441 }
1442 }
1443
1444private:
1445 typedef LValue INHERITED;
1446
1447 const Expression& fExpression;
1448};
1449
1450std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
1451 switch (e.fKind) {
1452 case Expression::kExternalValue_Kind: {
1453 ExternalValue* value = ((ExternalValueReference&) e).fValue;
1454 int index = fOutput->fExternalValues.size();
1455 fOutput->fExternalValues.push_back(value);
1456 SkASSERT(index <= 255);
1457 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
1458 }
1459 case Expression::kFieldAccess_Kind:
1460 case Expression::kIndex_Kind:
1461 case Expression::kVariableReference_Kind:
1462 return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
1463 case Expression::kSwizzle_Kind: {
1464 const Swizzle& s = (const Swizzle&) e;
1465 return swizzle_is_simple(s)
1466 ? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e))
1467 : std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s));
1468 }
1469 case Expression::kTernary_Kind:
1470 default:
1471#ifdef SK_DEBUG
1472 ABORT("unsupported lvalue %s\n", e.description().c_str());
1473#endif
1474 return nullptr;
1475 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001476}
1477
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001478void ByteCodeGenerator::writeBlock(const Block& b) {
1479 for (const auto& s : b.fStatements) {
1480 this->writeStatement(*s);
1481 }
1482}
1483
Brian Osmanb08cc022020-04-02 11:38:40 -04001484void ByteCodeGenerator::setBreakTargets() {
1485 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
1486 for (DeferredLocation& b : breaks) {
1487 b.set();
1488 }
1489 fBreakTargets.pop();
1490}
1491
1492void ByteCodeGenerator::setContinueTargets() {
1493 std::vector<DeferredLocation>& continues = fContinueTargets.top();
1494 for (DeferredLocation& c : continues) {
1495 c.set();
1496 }
1497 fContinueTargets.pop();
1498}
1499
1500void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
1501 // TODO: Include BranchIfAllFalse to top-most LoopNext
1502 this->write(ByteCodeInstruction::kLoopBreak);
1503}
1504
1505void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
1506 // TODO: Include BranchIfAllFalse to top-most LoopNext
1507 this->write(ByteCodeInstruction::kLoopContinue);
1508}
1509
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001510void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001511 this->write(ByteCodeInstruction::kLoopBegin);
1512 size_t start = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001513 this->writeStatement(*d.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001514 this->write(ByteCodeInstruction::kLoopNext);
1515 this->writeExpression(*d.fTest);
1516 this->write(ByteCodeInstruction::kLoopMask);
1517 // TODO: Could shorten this with kBranchIfAnyTrue
1518 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001519 DeferredLocation endLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -04001520 this->write(ByteCodeInstruction::kBranch);
1521 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001522 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001523 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001524}
1525
1526void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001527 fContinueTargets.emplace();
1528 fBreakTargets.emplace();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001529 if (f.fInitializer) {
1530 this->writeStatement(*f.fInitializer);
1531 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001532 this->write(ByteCodeInstruction::kLoopBegin);
1533 size_t start = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001534 if (f.fTest) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001535 this->writeExpression(*f.fTest);
1536 this->write(ByteCodeInstruction::kLoopMask);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001537 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001538 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001539 DeferredLocation endLocation(this);
1540 this->writeStatement(*f.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001541 this->write(ByteCodeInstruction::kLoopNext);
Brian Osman569f12f2019-06-13 11:23:57 -04001542 if (f.fNext) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001543 this->writeExpression(*f.fNext, true);
Brian Osman569f12f2019-06-13 11:23:57 -04001544 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001545 this->write(ByteCodeInstruction::kBranch);
1546 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001547 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001548 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001549}
1550
1551void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001552 this->writeExpression(*i.fTest);
1553 this->write(ByteCodeInstruction::kMaskPush);
1554 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001555 DeferredLocation falseLocation(this);
1556 this->writeStatement(*i.fIfTrue);
1557 falseLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001558 if (i.fIfFalse) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001559 this->write(ByteCodeInstruction::kMaskNegate);
1560 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001561 DeferredLocation endLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001562 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -05001563 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001564 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001565 this->write(ByteCodeInstruction::kMaskPop);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001566}
1567
Brian Osmanb08cc022020-04-02 11:38:40 -04001568void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
1569 if (fLoopCount || fConditionCount) {
Brian Osman4a47da72019-07-12 11:30:32 -04001570 fErrors.error(r.fOffset, "return not allowed inside conditional or loop");
1571 return;
1572 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001573 int count = SlotCount(r.fExpression->fType);
1574 this->writeExpression(*r.fExpression);
1575
1576 // Technically, the kReturn also pops fOutput->fLocalCount values from the stack, too, but we
1577 // haven't counted pushing those (they're outside the scope of our stack tracking). Instead,
1578 // we account for those in writeFunction().
1579
1580 // This is all fine because we don't allow conditional returns, so we only return once anyway.
1581 this->write(ByteCodeInstruction::kReturn, -count);
1582 this->write8(count);
1583}
1584
1585void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
1586 // not yet implemented
1587 abort();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001588}
1589
1590void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1591 for (const auto& declStatement : v.fVars) {
1592 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
Brian Osmanb08cc022020-04-02 11:38:40 -04001593 // we need to grab the location even if we don't use it, to ensure it has been allocated
1594 Location location = this->getLocation(*decl.fVar);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001595 if (decl.fValue) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001596 this->writeExpression(*decl.fValue);
1597 int count = SlotCount(decl.fValue->fType);
1598 if (count > 4) {
1599 this->write(ByteCodeInstruction::kPushImmediate);
1600 this->write32(location.fSlot);
1601 this->write(ByteCodeInstruction::kStoreExtended, count);
1602 this->write8(count);
1603 } else {
1604 this->write(vector_instruction(ByteCodeInstruction::kStore, count));
1605 this->write8(location.fSlot);
1606 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001607 }
1608 }
1609}
1610
1611void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001612 this->write(ByteCodeInstruction::kLoopBegin);
1613 size_t cond = fCode->size();
1614 this->writeExpression(*w.fTest);
1615 this->write(ByteCodeInstruction::kLoopMask);
1616 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001617 DeferredLocation endLocation(this);
1618 this->writeStatement(*w.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001619 this->write(ByteCodeInstruction::kLoopNext);
1620 this->write(ByteCodeInstruction::kBranch);
1621 this->write16(cond);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001622 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001623 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001624}
1625
1626void ByteCodeGenerator::writeStatement(const Statement& s) {
1627 switch (s.fKind) {
1628 case Statement::kBlock_Kind:
1629 this->writeBlock((Block&) s);
1630 break;
1631 case Statement::kBreak_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001632 this->writeBreakStatement((BreakStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001633 break;
1634 case Statement::kContinue_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001635 this->writeContinueStatement((ContinueStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001636 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001637 case Statement::kDiscard_Kind:
1638 // not yet implemented
1639 abort();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001640 case Statement::kDo_Kind:
1641 this->writeDoStatement((DoStatement&) s);
1642 break;
Brian Osman3e29f1d2019-05-28 09:35:05 -04001643 case Statement::kExpression_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001644 this->writeExpression(*((ExpressionStatement&) s).fExpression, true);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001645 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001646 case Statement::kFor_Kind:
1647 this->writeForStatement((ForStatement&) s);
1648 break;
1649 case Statement::kIf_Kind:
1650 this->writeIfStatement((IfStatement&) s);
1651 break;
1652 case Statement::kNop_Kind:
1653 break;
1654 case Statement::kReturn_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001655 this->writeReturnStatement((ReturnStatement&) s);
1656 break;
1657 case Statement::kSwitch_Kind:
1658 this->writeSwitchStatement((SwitchStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001659 break;
1660 case Statement::kVarDeclarations_Kind:
1661 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1662 break;
1663 case Statement::kWhile_Kind:
1664 this->writeWhileStatement((WhileStatement&) s);
1665 break;
1666 default:
Brian Osmanb08cc022020-04-02 11:38:40 -04001667 SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001668 }
1669}
1670
Brian Osmanb08cc022020-04-02 11:38:40 -04001671ByteCodeFunction::ByteCodeFunction(const FunctionDeclaration* declaration)
1672 : fName(declaration->fName) {
Brian Osman80164412019-06-07 13:00:23 -04001673 fParameterCount = 0;
Brian Osmanb08cc022020-04-02 11:38:40 -04001674 for (const auto& p : declaration->fParameters) {
1675 int slots = ByteCodeGenerator::SlotCount(p->fType);
1676 fParameters.push_back({ slots, (bool)(p->fModifiers.fFlags & Modifiers::kOut_Flag) });
1677 fParameterCount += slots;
Brian Osman80164412019-06-07 13:00:23 -04001678 }
1679}
1680
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001681}