blob: 3c598822d5a66644b762cea6a789ac2477ca3b92 [file] [log] [blame]
Mike Reed8520e762020-04-30 12:06:23 -04001/*
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04002 * Copyright 2019 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/sksl/SkSLByteCodeGenerator.h"
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04009
Brian Osmanb08cc022020-04-02 11:38:40 -040010#include <algorithm>
11
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040012namespace SkSL {
13
Brian Osmanb08cc022020-04-02 11:38:40 -040014static TypeCategory type_category(const Type& type) {
15 switch (type.kind()) {
16 case Type::Kind::kVector_Kind:
17 case Type::Kind::kMatrix_Kind:
18 return type_category(type.componentType());
19 default:
20 if (type.fName == "bool") {
21 return TypeCategory::kBool;
22 } else if (type.fName == "int" ||
23 type.fName == "short" ||
24 type.fName == "$intLiteral") {
25 return TypeCategory::kSigned;
26 } else if (type.fName == "uint" ||
27 type.fName == "ushort") {
28 return TypeCategory::kUnsigned;
29 } else {
30 SkASSERT(type.fName == "float" ||
31 type.fName == "half" ||
32 type.fName == "$floatLiteral");
33 return TypeCategory::kFloat;
34 }
35 ABORT("unsupported type: %s\n", type.displayName().c_str());
36 }
37}
38
39
40ByteCodeGenerator::ByteCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
41 ByteCode* output)
Ethan Nicholas82162ee2019-05-21 16:05:08 -040042 : INHERITED(program, errors, nullptr)
Brian Osmanb08cc022020-04-02 11:38:40 -040043 , fContext(*context)
Ethan Nicholasae9633b2019-05-24 12:46:34 -040044 , fOutput(output)
Brian Osman3479a952020-05-04 10:22:53 -040045 // If you're adding new intrinsics here, ensure that they're declared in sksl_interp.inc, so
46 // they're available to "generic" interpreter programs (eg particles).
47 // You can probably copy the declarations from sksl_gpu.inc.
Ethan Nicholasae9633b2019-05-24 12:46:34 -040048 , fIntrinsics {
Brian Osman2a4871b2020-06-19 11:29:58 -040049 { "atan", ByteCodeInstruction::kATan },
50 { "ceil", ByteCodeInstruction::kCeil },
51 { "clamp", SpecialIntrinsic::kClamp },
52 { "cos", ByteCodeInstruction::kCos },
53 { "dot", SpecialIntrinsic::kDot },
54 { "floor", ByteCodeInstruction::kFloor },
55 { "fract", ByteCodeInstruction::kFract },
56 { "inverse", ByteCodeInstruction::kInverse2x2 },
57 { "length", SpecialIntrinsic::kLength },
58 { "max", SpecialIntrinsic::kMax },
59 { "min", SpecialIntrinsic::kMin },
60 { "mix", SpecialIntrinsic::kMix },
61 { "normalize", SpecialIntrinsic::kNormalize },
62 { "pow", ByteCodeInstruction::kPow },
63 { "sample", SpecialIntrinsic::kSample },
64 { "saturate", SpecialIntrinsic::kSaturate },
65 { "sin", ByteCodeInstruction::kSin },
66 { "sqrt", ByteCodeInstruction::kSqrt },
67 { "tan", ByteCodeInstruction::kTan },
Brian Osman8842b372020-05-01 15:07:49 -040068
69 { "lessThan", { ByteCodeInstruction::kCompareFLT,
70 ByteCodeInstruction::kCompareSLT,
71 ByteCodeInstruction::kCompareULT } },
72 { "lessThanEqual", { ByteCodeInstruction::kCompareFLTEQ,
73 ByteCodeInstruction::kCompareSLTEQ,
74 ByteCodeInstruction::kCompareULTEQ } },
75 { "greaterThan", { ByteCodeInstruction::kCompareFGT,
76 ByteCodeInstruction::kCompareSGT,
77 ByteCodeInstruction::kCompareUGT } },
78 { "greaterThanEqual", { ByteCodeInstruction::kCompareFGTEQ,
79 ByteCodeInstruction::kCompareSGTEQ,
80 ByteCodeInstruction::kCompareUGTEQ } },
81 { "equal", { ByteCodeInstruction::kCompareFEQ,
82 ByteCodeInstruction::kCompareIEQ,
83 ByteCodeInstruction::kCompareIEQ } },
84 { "notEqual", { ByteCodeInstruction::kCompareFNEQ,
85 ByteCodeInstruction::kCompareINEQ,
86 ByteCodeInstruction::kCompareINEQ } },
87
88 { "any", SpecialIntrinsic::kAny },
89 { "all", SpecialIntrinsic::kAll },
90 { "not", ByteCodeInstruction::kNotB },
91 } {}
Brian Osmanb08cc022020-04-02 11:38:40 -040092
Ethan Nicholas82162ee2019-05-21 16:05:08 -040093
Brian Osman07c117b2019-05-23 12:51:06 -070094int ByteCodeGenerator::SlotCount(const Type& type) {
Brian Osmanfba386b2019-06-20 14:54:15 -040095 if (type.kind() == Type::kOther_Kind) {
96 return 0;
97 } else if (type.kind() == Type::kStruct_Kind) {
Brian Osman07c117b2019-05-23 12:51:06 -070098 int slots = 0;
99 for (const auto& f : type.fields()) {
100 slots += SlotCount(*f.fType);
101 }
102 SkASSERT(slots <= 255);
103 return slots;
104 } else if (type.kind() == Type::kArray_Kind) {
105 int columns = type.columns();
106 SkASSERT(columns >= 0);
107 int slots = columns * SlotCount(type.componentType());
108 SkASSERT(slots <= 255);
109 return slots;
110 } else {
111 return type.columns() * type.rows();
112 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400113}
114
Brian Osman1c110a02019-10-01 14:53:32 -0400115static inline bool is_uniform(const SkSL::Variable& var) {
116 return var.fModifiers.fFlags & Modifiers::kUniform_Flag;
117}
118
Brian Osmaneadfeb92020-01-09 12:43:03 -0500119static inline bool is_in(const SkSL::Variable& var) {
120 return var.fModifiers.fFlags & Modifiers::kIn_Flag;
121}
Brian Osmanb08cc022020-04-02 11:38:40 -0400122
123void ByteCodeGenerator::gatherUniforms(const Type& type, const String& name) {
124 if (type.kind() == Type::kOther_Kind) {
125 return;
126 } else if (type.kind() == Type::kStruct_Kind) {
127 for (const auto& f : type.fields()) {
128 this->gatherUniforms(*f.fType, name + "." + f.fName);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500129 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400130 } else if (type.kind() == Type::kArray_Kind) {
131 for (int i = 0; i < type.columns(); ++i) {
132 this->gatherUniforms(type.componentType(), String::printf("%s[%d]", name.c_str(), i));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500133 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400134 } else {
135 fOutput->fUniforms.push_back({ name, type_category(type), type.rows(), type.columns(),
136 fOutput->fUniformSlotCount });
137 fOutput->fUniformSlotCount += type.columns() * type.rows();
138 }
139}
140
141bool ByteCodeGenerator::generateCode() {
142 for (const auto& e : fProgram) {
143 switch (e.fKind) {
144 case ProgramElement::kFunction_Kind: {
145 std::unique_ptr<ByteCodeFunction> f = this->writeFunction((FunctionDefinition&) e);
146 if (!f) {
147 return false;
148 }
149 fOutput->fFunctions.push_back(std::move(f));
150 fFunctions.push_back(&(FunctionDefinition&)e);
151 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500152 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400153 case ProgramElement::kVar_Kind: {
154 VarDeclarations& decl = (VarDeclarations&) e;
155 for (const auto& v : decl.fVars) {
156 const Variable* declVar = ((VarDeclaration&) *v).fVar;
Brian Osmana43d8202020-06-17 16:50:39 -0400157 if (declVar->fType == *fContext.fFragmentProcessor_Type) {
158 fOutput->fChildFPCount++;
159 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400160 if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
161 continue;
162 }
163 if (is_uniform(*declVar)) {
164 this->gatherUniforms(declVar->fType, declVar->fName);
165 } else {
166 fOutput->fGlobalSlotCount += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400167 }
168 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400169 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400170 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400171 default:
172 ; // ignore
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400173 }
174 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400175 return 0 == fErrors.errorCount();
176}
177
178std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
179 fFunction = &f;
180 std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
181 fParameterCount = result->fParameterCount;
182 fLoopCount = fMaxLoopCount = 0;
183 fConditionCount = fMaxConditionCount = 0;
184 fStackCount = fMaxStackCount = 0;
185 fCode = &result->fCode;
186
187 this->writeStatement(*f.fBody);
188 if (0 == fErrors.errorCount()) {
189 SkASSERT(fLoopCount == 0);
190 SkASSERT(fConditionCount == 0);
191 SkASSERT(fStackCount == 0);
192 }
193 this->write(ByteCodeInstruction::kReturn, 0);
194 this->write8(0);
195
196 result->fLocalCount = fLocals.size();
197 result->fConditionCount = fMaxConditionCount;
198 result->fLoopCount = fMaxLoopCount;
199 result->fStackCount = fMaxStackCount;
200
201 const Type& returnType = f.fDeclaration.fReturnType;
202 if (returnType != *fContext.fVoid_Type) {
203 result->fReturnCount = SlotCount(returnType);
204 }
205 fLocals.clear();
206 fFunction = nullptr;
207 return result;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400208}
209
Brian Osman0785db02019-05-24 14:19:11 -0400210// A "simple" Swizzle is based on a variable (or a compound variable like a struct or array), and
211// that references consecutive values, such that it can be implemented using normal load/store ops
212// with an offset. Note that all single-component swizzles (of suitable base types) are simple.
213static bool swizzle_is_simple(const Swizzle& s) {
214 switch (s.fBase->fKind) {
215 case Expression::kFieldAccess_Kind:
216 case Expression::kIndex_Kind:
217 case Expression::kVariableReference_Kind:
218 break;
219 default:
220 return false;
221 }
222
223 for (size_t i = 1; i < s.fComponents.size(); ++i) {
224 if (s.fComponents[i] != s.fComponents[i - 1] + 1) {
225 return false;
226 }
227 }
228 return true;
229}
230
Brian Osmanb08cc022020-04-02 11:38:40 -0400231int ByteCodeGenerator::StackUsage(ByteCodeInstruction inst, int count_) {
232 // Ensures that we use count iff we're passed a non-default value. Most instructions have an
233 // implicit count, so the caller shouldn't need to worry about it (or count makes no sense).
234 // The asserts avoids callers thinking they're supplying useful information in that scenario,
235 // or failing to supply necessary information for the ops that need a count.
236 struct CountValue {
237 operator int() {
238 SkASSERT(val != ByteCodeGenerator::kUnusedStackCount);
239 SkDEBUGCODE(used = true);
240 return val;
241 }
242 ~CountValue() {
243 SkASSERT(used || val == ByteCodeGenerator::kUnusedStackCount);
244 }
245 int val;
246 SkDEBUGCODE(bool used = false;)
247 } count = { count_ };
248
249 switch (inst) {
250 // Unary functions/operators that don't change stack depth at all:
251#define VECTOR_UNARY_OP(base) \
252 case ByteCodeInstruction::base: \
253 case ByteCodeInstruction::base ## 2: \
254 case ByteCodeInstruction::base ## 3: \
255 case ByteCodeInstruction::base ## 4: \
256 return 0;
257
258 VECTOR_UNARY_OP(kConvertFtoI)
259 VECTOR_UNARY_OP(kConvertStoF)
260 VECTOR_UNARY_OP(kConvertUtoF)
261
Mike Reed8520e762020-04-30 12:06:23 -0400262 VECTOR_UNARY_OP(kATan)
Brian Osman89bf7342020-06-18 17:11:16 -0400263 VECTOR_UNARY_OP(kCeil)
Brian Osmanb08cc022020-04-02 11:38:40 -0400264 VECTOR_UNARY_OP(kCos)
Brian Osman89bf7342020-06-18 17:11:16 -0400265 VECTOR_UNARY_OP(kFloor)
Mike Reed8520e762020-04-30 12:06:23 -0400266 VECTOR_UNARY_OP(kFract)
Brian Osmanb08cc022020-04-02 11:38:40 -0400267 VECTOR_UNARY_OP(kSin)
268 VECTOR_UNARY_OP(kSqrt)
269 VECTOR_UNARY_OP(kTan)
270
271 VECTOR_UNARY_OP(kNegateF)
272 VECTOR_UNARY_OP(kNegateI)
Brian Osman8842b372020-05-01 15:07:49 -0400273 VECTOR_UNARY_OP(kNotB)
Brian Osmanb08cc022020-04-02 11:38:40 -0400274
275 case ByteCodeInstruction::kInverse2x2:
276 case ByteCodeInstruction::kInverse3x3:
277 case ByteCodeInstruction::kInverse4x4: return 0;
278
279 case ByteCodeInstruction::kClampIndex: return 0;
Brian Osmanb08cc022020-04-02 11:38:40 -0400280 case ByteCodeInstruction::kNegateFN: return 0;
281 case ByteCodeInstruction::kShiftLeft: return 0;
282 case ByteCodeInstruction::kShiftRightS: return 0;
283 case ByteCodeInstruction::kShiftRightU: return 0;
284
285#undef VECTOR_UNARY_OP
286
287 // Binary functions/operators that do a 2 -> 1 reduction (possibly N times)
288#define VECTOR_BINARY_OP(base) \
289 case ByteCodeInstruction::base: return -1; \
290 case ByteCodeInstruction::base ## 2: return -2; \
291 case ByteCodeInstruction::base ## 3: return -3; \
292 case ByteCodeInstruction::base ## 4: return -4;
293
294#define VECTOR_MATRIX_BINARY_OP(base) \
295 VECTOR_BINARY_OP(base) \
296 case ByteCodeInstruction::base ## N: return -count;
297
298 case ByteCodeInstruction::kAndB: return -1;
299 case ByteCodeInstruction::kOrB: return -1;
300 case ByteCodeInstruction::kXorB: return -1;
301
302 VECTOR_BINARY_OP(kAddI)
303 VECTOR_MATRIX_BINARY_OP(kAddF)
304
305 VECTOR_BINARY_OP(kCompareIEQ)
306 VECTOR_MATRIX_BINARY_OP(kCompareFEQ)
307 VECTOR_BINARY_OP(kCompareINEQ)
308 VECTOR_MATRIX_BINARY_OP(kCompareFNEQ)
309 VECTOR_BINARY_OP(kCompareSGT)
310 VECTOR_BINARY_OP(kCompareUGT)
311 VECTOR_BINARY_OP(kCompareFGT)
312 VECTOR_BINARY_OP(kCompareSGTEQ)
313 VECTOR_BINARY_OP(kCompareUGTEQ)
314 VECTOR_BINARY_OP(kCompareFGTEQ)
315 VECTOR_BINARY_OP(kCompareSLT)
316 VECTOR_BINARY_OP(kCompareULT)
317 VECTOR_BINARY_OP(kCompareFLT)
318 VECTOR_BINARY_OP(kCompareSLTEQ)
319 VECTOR_BINARY_OP(kCompareULTEQ)
320 VECTOR_BINARY_OP(kCompareFLTEQ)
321
322 VECTOR_BINARY_OP(kDivideS)
323 VECTOR_BINARY_OP(kDivideU)
324 VECTOR_MATRIX_BINARY_OP(kDivideF)
Brian Osmand5f937b2020-05-04 12:07:29 -0400325 VECTOR_BINARY_OP(kMaxF)
326 VECTOR_BINARY_OP(kMaxS)
327 VECTOR_BINARY_OP(kMinF)
328 VECTOR_BINARY_OP(kMinS)
Brian Osmanb08cc022020-04-02 11:38:40 -0400329 VECTOR_BINARY_OP(kMultiplyI)
330 VECTOR_MATRIX_BINARY_OP(kMultiplyF)
Florin Malita3facc9c2020-05-04 09:26:15 -0400331 VECTOR_BINARY_OP(kPow)
Brian Osmanb08cc022020-04-02 11:38:40 -0400332 VECTOR_BINARY_OP(kRemainderF)
333 VECTOR_BINARY_OP(kRemainderS)
334 VECTOR_BINARY_OP(kRemainderU)
335 VECTOR_BINARY_OP(kSubtractI)
336 VECTOR_MATRIX_BINARY_OP(kSubtractF)
337
338#undef VECTOR_BINARY_OP
339#undef VECTOR_MATRIX_BINARY_OP
340
341 // Ops that push or load data to grow the stack:
342 case ByteCodeInstruction::kDup:
343 case ByteCodeInstruction::kLoad:
344 case ByteCodeInstruction::kLoadGlobal:
345 case ByteCodeInstruction::kLoadUniform:
346 case ByteCodeInstruction::kReadExternal:
347 case ByteCodeInstruction::kPushImmediate:
348 return 1;
349
350 case ByteCodeInstruction::kDup2:
351 case ByteCodeInstruction::kLoad2:
352 case ByteCodeInstruction::kLoadGlobal2:
353 case ByteCodeInstruction::kLoadUniform2:
354 case ByteCodeInstruction::kReadExternal2:
355 return 2;
356
357 case ByteCodeInstruction::kDup3:
358 case ByteCodeInstruction::kLoad3:
359 case ByteCodeInstruction::kLoadGlobal3:
360 case ByteCodeInstruction::kLoadUniform3:
361 case ByteCodeInstruction::kReadExternal3:
362 return 3;
363
364 case ByteCodeInstruction::kDup4:
365 case ByteCodeInstruction::kLoad4:
366 case ByteCodeInstruction::kLoadGlobal4:
367 case ByteCodeInstruction::kLoadUniform4:
368 case ByteCodeInstruction::kReadExternal4:
369 return 4;
370
371 case ByteCodeInstruction::kDupN:
Brian Osmanb08cc022020-04-02 11:38:40 -0400372 return count;
373
374 // Pushes 'count' values, minus one for the 'address' that's consumed first
375 case ByteCodeInstruction::kLoadExtended:
376 case ByteCodeInstruction::kLoadExtendedGlobal:
377 case ByteCodeInstruction::kLoadExtendedUniform:
378 return count - 1;
379
380 // Ops that pop or store data to shrink the stack:
381 case ByteCodeInstruction::kPop:
382 case ByteCodeInstruction::kStore:
383 case ByteCodeInstruction::kStoreGlobal:
384 case ByteCodeInstruction::kWriteExternal:
385 return -1;
386
387 case ByteCodeInstruction::kPop2:
388 case ByteCodeInstruction::kStore2:
389 case ByteCodeInstruction::kStoreGlobal2:
390 case ByteCodeInstruction::kWriteExternal2:
391 return -2;
392
393 case ByteCodeInstruction::kPop3:
394 case ByteCodeInstruction::kStore3:
395 case ByteCodeInstruction::kStoreGlobal3:
396 case ByteCodeInstruction::kWriteExternal3:
397 return -3;
398
399 case ByteCodeInstruction::kPop4:
400 case ByteCodeInstruction::kStore4:
401 case ByteCodeInstruction::kStoreGlobal4:
402 case ByteCodeInstruction::kWriteExternal4:
403 return -4;
404
405 case ByteCodeInstruction::kPopN:
Brian Osmanb08cc022020-04-02 11:38:40 -0400406 return -count;
407
408 // Consumes 'count' values, plus one for the 'address'
409 case ByteCodeInstruction::kStoreExtended:
410 case ByteCodeInstruction::kStoreExtendedGlobal:
Brian Osmanb08cc022020-04-02 11:38:40 -0400411 return -count - 1;
412
413 // Strange ops where the caller computes the delta for us:
414 case ByteCodeInstruction::kCallExternal:
415 case ByteCodeInstruction::kMatrixToMatrix:
416 case ByteCodeInstruction::kMatrixMultiply:
417 case ByteCodeInstruction::kReserve:
418 case ByteCodeInstruction::kReturn:
419 case ByteCodeInstruction::kScalarToMatrix:
420 case ByteCodeInstruction::kSwizzle:
421 return count;
422
423 // Miscellaneous
424
Brian Osmana43d8202020-06-17 16:50:39 -0400425 // (X, Y) -> (R, G, B, A)
426 case ByteCodeInstruction::kSampleExplicit: return 4 - 2;
427 // (float3x3) -> (R, G, B, A)
428 case ByteCodeInstruction::kSampleMatrix: return 4 - 9;
429
Brian Osman8842b372020-05-01 15:07:49 -0400430 // kMix does a 3 -> 1 reduction (A, B, M -> A -or- B) for each component
431 case ByteCodeInstruction::kMix: return -2;
432 case ByteCodeInstruction::kMix2: return -4;
433 case ByteCodeInstruction::kMix3: return -6;
434 case ByteCodeInstruction::kMix4: return -8;
435
436 // kLerp works the same way (producing lerp(A, B, T) for each component)
437 case ByteCodeInstruction::kLerp: return -2;
438 case ByteCodeInstruction::kLerp2: return -4;
439 case ByteCodeInstruction::kLerp3: return -6;
440 case ByteCodeInstruction::kLerp4: return -8;
441
Brian Osmanb08cc022020-04-02 11:38:40 -0400442 // kCall is net-zero. Max stack depth is adjusted in writeFunctionCall.
443 case ByteCodeInstruction::kCall: return 0;
444 case ByteCodeInstruction::kBranch: return 0;
445 case ByteCodeInstruction::kBranchIfAllFalse: return 0;
446
447 case ByteCodeInstruction::kMaskPush: return -1;
448 case ByteCodeInstruction::kMaskPop: return 0;
449 case ByteCodeInstruction::kMaskNegate: return 0;
450 case ByteCodeInstruction::kMaskBlend: return -count;
451
452 case ByteCodeInstruction::kLoopBegin: return 0;
453 case ByteCodeInstruction::kLoopNext: return 0;
454 case ByteCodeInstruction::kLoopMask: return -1;
455 case ByteCodeInstruction::kLoopEnd: return 0;
456 case ByteCodeInstruction::kLoopBreak: return 0;
457 case ByteCodeInstruction::kLoopContinue: return 0;
Brian Osmanb08cc022020-04-02 11:38:40 -0400458 }
Brian Osmand5f937b2020-05-04 12:07:29 -0400459
460 SkUNREACHABLE;
Brian Osmanb08cc022020-04-02 11:38:40 -0400461}
462
463ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var) {
464 // given that we seldom have more than a couple of variables, linear search is probably the most
465 // efficient way to handle lookups
466 switch (var.fStorage) {
467 case Variable::kLocal_Storage: {
468 for (int i = fLocals.size() - 1; i >= 0; --i) {
469 if (fLocals[i] == &var) {
470 SkASSERT(fParameterCount + i <= 255);
471 return { fParameterCount + i, Storage::kLocal };
472 }
473 }
474 int result = fParameterCount + fLocals.size();
475 fLocals.push_back(&var);
476 for (int i = 0; i < SlotCount(var.fType) - 1; ++i) {
477 fLocals.push_back(nullptr);
478 }
479 SkASSERT(result <= 255);
480 return { result, Storage::kLocal };
481 }
482 case Variable::kParameter_Storage: {
483 int offset = 0;
484 for (const auto& p : fFunction->fDeclaration.fParameters) {
485 if (p == &var) {
486 SkASSERT(offset <= 255);
487 return { offset, Storage::kLocal };
488 }
489 offset += SlotCount(p->fType);
490 }
491 SkASSERT(false);
492 return Location::MakeInvalid();
493 }
494 case Variable::kGlobal_Storage: {
Brian Osmana43d8202020-06-17 16:50:39 -0400495 if (var.fType == *fContext.fFragmentProcessor_Type) {
496 int offset = 0;
497 for (const auto& e : fProgram) {
498 if (e.fKind == ProgramElement::kVar_Kind) {
499 VarDeclarations& decl = (VarDeclarations&) e;
500 for (const auto& v : decl.fVars) {
501 const Variable* declVar = ((VarDeclaration&) *v).fVar;
502 if (declVar->fType != *fContext.fFragmentProcessor_Type) {
503 continue;
504 }
505 if (declVar == &var) {
506 SkASSERT(offset <= 255);
507 return { offset, Storage::kChildFP };
508 }
509 offset++;
510 }
511 }
512 }
513 SkASSERT(false);
514 return Location::MakeInvalid();
515 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400516 if (is_in(var)) {
517 // If you see this error, it means the program is using raw 'in' variables. You
518 // should either specialize the program (Compiler::specialize) to bake in the final
519 // values of the 'in' variables, or not use 'in' variables (maybe you meant to use
520 // 'uniform' instead?).
521 fErrors.error(var.fOffset,
522 "'in' variable is not specialized or has unsupported type");
523 return Location::MakeInvalid();
524 }
525 int offset = 0;
526 bool isUniform = is_uniform(var);
527 for (const auto& e : fProgram) {
528 if (e.fKind == ProgramElement::kVar_Kind) {
529 VarDeclarations& decl = (VarDeclarations&) e;
530 for (const auto& v : decl.fVars) {
531 const Variable* declVar = ((VarDeclaration&) *v).fVar;
532 if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
533 continue;
534 }
535 if (isUniform != is_uniform(*declVar)) {
536 continue;
537 }
538 if (declVar == &var) {
539 SkASSERT(offset <= 255);
540 return { offset, isUniform ? Storage::kUniform : Storage::kGlobal };
541 }
542 offset += SlotCount(declVar->fType);
543 }
544 }
545 }
546 SkASSERT(false);
547 return Location::MakeInvalid();
548 }
549 default:
550 SkASSERT(false);
551 return Location::MakeInvalid();
552 }
553}
554
Brian Osman1c110a02019-10-01 14:53:32 -0400555ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Expression& expr) {
Brian Osman07c117b2019-05-23 12:51:06 -0700556 switch (expr.fKind) {
557 case Expression::kFieldAccess_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400558 const FieldAccess& f = (const FieldAccess&)expr;
559 Location baseLoc = this->getLocation(*f.fBase);
Brian Osman07c117b2019-05-23 12:51:06 -0700560 int offset = 0;
561 for (int i = 0; i < f.fFieldIndex; ++i) {
562 offset += SlotCount(*f.fBase->fType.fields()[i].fType);
563 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400564 if (baseLoc.isOnStack()) {
565 if (offset != 0) {
566 this->write(ByteCodeInstruction::kPushImmediate);
567 this->write32(offset);
568 this->write(ByteCodeInstruction::kAddI);
Ben Wagner470e0ac2020-01-22 16:59:21 -0500569 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400570 return baseLoc;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500571 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400572 return baseLoc + offset;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500573 }
Ben Wagner470e0ac2020-01-22 16:59:21 -0500574 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400575 case Expression::kIndex_Kind: {
576 const IndexExpression& i = (const IndexExpression&)expr;
577 int stride = SlotCount(i.fType);
578 int length = i.fBase->fType.columns();
579 SkASSERT(length <= 255);
580 int offset = -1;
581 if (i.fIndex->isConstant()) {
582 int64_t index = i.fIndex->getConstantInt();
583 if (index < 0 || index >= length) {
584 fErrors.error(i.fIndex->fOffset, "Array index out of bounds.");
585 return Location::MakeInvalid();
586 }
587 offset = index * stride;
588 } else {
589 if (i.fIndex->hasSideEffects()) {
590 // Having a side-effect in an indexer is technically safe for an rvalue,
591 // but with lvalues we have to evaluate the indexer twice, so make it an error.
592 fErrors.error(i.fIndex->fOffset,
593 "Index expressions with side-effects not supported in byte code.");
594 return Location::MakeInvalid();
595 }
596 this->writeExpression(*i.fIndex);
597 this->write(ByteCodeInstruction::kClampIndex);
598 this->write8(length);
599 if (stride != 1) {
600 this->write(ByteCodeInstruction::kPushImmediate);
601 this->write32(stride);
602 this->write(ByteCodeInstruction::kMultiplyI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400603 }
604 }
605 Location baseLoc = this->getLocation(*i.fBase);
606
607 // Are both components known statically?
608 if (!baseLoc.isOnStack() && offset >= 0) {
609 return baseLoc + offset;
610 }
611
612 // At least one component is dynamic (and on the stack).
613
614 // If the other component is zero, we're done
615 if (baseLoc.fSlot == 0 || offset == 0) {
616 return baseLoc.makeOnStack();
617 }
618
619 // Push the non-dynamic component (if any) to the stack, then add the two
620 if (!baseLoc.isOnStack()) {
621 this->write(ByteCodeInstruction::kPushImmediate);
622 this->write32(baseLoc.fSlot);
623 }
624 if (offset >= 0) {
625 this->write(ByteCodeInstruction::kPushImmediate);
626 this->write32(offset);
627 }
628 this->write(ByteCodeInstruction::kAddI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400629 return baseLoc.makeOnStack();
630 }
Brian Osman0785db02019-05-24 14:19:11 -0400631 case Expression::kSwizzle_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400632 const Swizzle& s = (const Swizzle&)expr;
Brian Osman0785db02019-05-24 14:19:11 -0400633 SkASSERT(swizzle_is_simple(s));
Brian Osmanb08cc022020-04-02 11:38:40 -0400634 Location baseLoc = this->getLocation(*s.fBase);
635 int offset = s.fComponents[0];
636 if (baseLoc.isOnStack()) {
637 if (offset != 0) {
638 this->write(ByteCodeInstruction::kPushImmediate);
639 this->write32(offset);
640 this->write(ByteCodeInstruction::kAddI);
Brian Osmanb08cc022020-04-02 11:38:40 -0400641 }
642 return baseLoc;
643 } else {
644 return baseLoc + offset;
645 }
Brian Osman0785db02019-05-24 14:19:11 -0400646 }
Brian Osman07c117b2019-05-23 12:51:06 -0700647 case Expression::kVariableReference_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400648 const Variable& var = ((const VariableReference&)expr).fVariable;
Brian Osman07c117b2019-05-23 12:51:06 -0700649 return this->getLocation(var);
650 }
651 default:
652 SkASSERT(false);
Brian Osmanb08cc022020-04-02 11:38:40 -0400653 return Location::MakeInvalid();
Brian Osman07c117b2019-05-23 12:51:06 -0700654 }
655}
656
Brian Osmanb08cc022020-04-02 11:38:40 -0400657void ByteCodeGenerator::write8(uint8_t b) {
658 fCode->push_back(b);
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500659}
660
Brian Osmanb08cc022020-04-02 11:38:40 -0400661void ByteCodeGenerator::write16(uint16_t i) {
662 size_t n = fCode->size();
663 fCode->resize(n+2);
664 memcpy(fCode->data() + n, &i, 2);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500665}
Ben Wagner470e0ac2020-01-22 16:59:21 -0500666
Brian Osmanb08cc022020-04-02 11:38:40 -0400667void ByteCodeGenerator::write32(uint32_t i) {
668 size_t n = fCode->size();
669 fCode->resize(n+4);
670 memcpy(fCode->data() + n, &i, 4);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500671}
672
Brian Osmanb08cc022020-04-02 11:38:40 -0400673void ByteCodeGenerator::write(ByteCodeInstruction i, int count) {
674 switch (i) {
675 case ByteCodeInstruction::kLoopBegin: this->enterLoop(); break;
676 case ByteCodeInstruction::kLoopEnd: this->exitLoop(); break;
Ethan Nicholas2329da02020-01-24 15:49:33 -0500677
Brian Osmanb08cc022020-04-02 11:38:40 -0400678 case ByteCodeInstruction::kMaskPush: this->enterCondition(); break;
679 case ByteCodeInstruction::kMaskPop:
680 case ByteCodeInstruction::kMaskBlend: this->exitCondition(); break;
681 default: /* Do nothing */ break;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500682 }
Brian Osmanab8f3842020-04-07 09:30:44 -0400683 this->write16((uint16_t)i);
Brian Osmanb08cc022020-04-02 11:38:40 -0400684 fStackCount += StackUsage(i, count);
685 fMaxStackCount = std::max(fMaxStackCount, fStackCount);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500686}
687
Brian Osmanb08cc022020-04-02 11:38:40 -0400688static ByteCodeInstruction vector_instruction(ByteCodeInstruction base, int count) {
689 SkASSERT(count >= 1 && count <= 4);
690 return ((ByteCodeInstruction) ((int) base + 1 - count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500691}
692
Brian Osmanb08cc022020-04-02 11:38:40 -0400693void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
694 ByteCodeInstruction u, ByteCodeInstruction f,
Brian Osmanab8f3842020-04-07 09:30:44 -0400695 int count) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500696 switch (type_category(type)) {
Brian Osman8842b372020-05-01 15:07:49 -0400697 case TypeCategory::kBool:
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500698 case TypeCategory::kSigned:
Brian Osmanb08cc022020-04-02 11:38:40 -0400699 this->write(vector_instruction(s, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500700 break;
701 case TypeCategory::kUnsigned:
Brian Osmanb08cc022020-04-02 11:38:40 -0400702 this->write(vector_instruction(u, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500703 break;
704 case TypeCategory::kFloat: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400705 if (count > 4) {
706 this->write((ByteCodeInstruction)((int)f + 1), count);
Brian Osmanab8f3842020-04-07 09:30:44 -0400707 this->write8(count);
Brian Osmanb08cc022020-04-02 11:38:40 -0400708 } else {
709 this->write(vector_instruction(f, count));
710 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500711 break;
712 }
713 default:
714 SkASSERT(false);
715 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500716}
717
Brian Osmanb08cc022020-04-02 11:38:40 -0400718bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool discard) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400719 if (b.fOperator == Token::Kind::TK_EQ) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500720 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
Brian Osmanb08cc022020-04-02 11:38:40 -0400721 this->writeExpression(*b.fRight);
722 lvalue->store(discard);
723 discard = false;
724 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500725 }
726 const Type& lType = b.fLeft->fType;
727 const Type& rType = b.fRight->fType;
728 bool lVecOrMtx = (lType.kind() == Type::kVector_Kind || lType.kind() == Type::kMatrix_Kind);
729 bool rVecOrMtx = (rType.kind() == Type::kVector_Kind || rType.kind() == Type::kMatrix_Kind);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500730 Token::Kind op;
731 std::unique_ptr<LValue> lvalue;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500732 if (is_assignment(b.fOperator)) {
733 lvalue = this->getLValue(*b.fLeft);
Brian Osmanb08cc022020-04-02 11:38:40 -0400734 lvalue->load();
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500735 op = remove_assignment(b.fOperator);
736 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400737 this->writeExpression(*b.fLeft);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500738 op = b.fOperator;
739 if (!lVecOrMtx && rVecOrMtx) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400740 for (int i = SlotCount(rType); i > 1; --i) {
741 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400742 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500743 }
744 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500745 int count = std::max(SlotCount(lType), SlotCount(rType));
Brian Osmanb08cc022020-04-02 11:38:40 -0400746 SkDEBUGCODE(TypeCategory tc = type_category(lType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500747 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400748 case Token::Kind::TK_LOGICALAND: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400749 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
750 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400751 this->write(ByteCodeInstruction::kMaskPush);
752 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500753 DeferredLocation falseLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -0400754 this->writeExpression(*b.fRight);
755 this->write(ByteCodeInstruction::kAndB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500756 falseLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -0400757 this->write(ByteCodeInstruction::kMaskPop);
758 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500759 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400760 case Token::Kind::TK_LOGICALOR: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400761 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
762 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400763 this->write(ByteCodeInstruction::kNotB);
764 this->write(ByteCodeInstruction::kMaskPush);
765 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500766 DeferredLocation falseLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -0400767 this->writeExpression(*b.fRight);
768 this->write(ByteCodeInstruction::kOrB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500769 falseLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -0400770 this->write(ByteCodeInstruction::kMaskPop);
771 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500772 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400773 case Token::Kind::TK_SHL:
774 case Token::Kind::TK_SHR: {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500775 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
776 tc == SkSL::TypeCategory::kUnsigned));
777 if (!b.fRight->isConstant()) {
778 fErrors.error(b.fRight->fOffset, "Shift amounts must be constant");
Brian Osmanb08cc022020-04-02 11:38:40 -0400779 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500780 }
781 int64_t shift = b.fRight->getConstantInt();
782 if (shift < 0 || shift > 31) {
783 fErrors.error(b.fRight->fOffset, "Shift amount out of range");
Brian Osmanb08cc022020-04-02 11:38:40 -0400784 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500785 }
786
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400787 if (op == Token::Kind::TK_SHL) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400788 this->write(ByteCodeInstruction::kShiftLeft);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500789 } else {
790 this->write(type_category(lType) == TypeCategory::kSigned
Brian Osmanb08cc022020-04-02 11:38:40 -0400791 ? ByteCodeInstruction::kShiftRightS
792 : ByteCodeInstruction::kShiftRightU);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500793 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400794 this->write8(shift);
795 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500796 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500797
798 default:
799 break;
800 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400801 this->writeExpression(*b.fRight);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500802 if (lVecOrMtx && !rVecOrMtx) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400803 for (int i = SlotCount(lType); i > 1; --i) {
804 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400805 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500806 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400807 // Special case for M*V, V*M, M*M (but not V*V!)
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400808 if (op == Token::Kind::TK_STAR && lVecOrMtx && rVecOrMtx &&
Brian Osmanb08cc022020-04-02 11:38:40 -0400809 !(lType.kind() == Type::kVector_Kind && rType.kind() == Type::kVector_Kind)) {
810 this->write(ByteCodeInstruction::kMatrixMultiply,
811 SlotCount(b.fType) - (SlotCount(lType) + SlotCount(rType)));
812 int rCols = rType.columns(),
813 rRows = rType.rows(),
814 lCols = lType.columns(),
815 lRows = lType.rows();
816 // M*V treats the vector as a column
817 if (rType.kind() == Type::kVector_Kind) {
818 std::swap(rCols, rRows);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500819 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400820 SkASSERT(lCols == rRows);
821 SkASSERT(SlotCount(b.fType) == lRows * rCols);
822 this->write8(lCols);
823 this->write8(lRows);
824 this->write8(rCols);
825 } else {
826 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400827 case Token::Kind::TK_EQEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400828 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareIEQ,
829 ByteCodeInstruction::kCompareIEQ,
830 ByteCodeInstruction::kCompareFEQ,
831 count);
832 // Collapse to a single bool
833 for (int i = count; i > 1; --i) {
834 this->write(ByteCodeInstruction::kAndB);
835 }
836 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400837 case Token::Kind::TK_GT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400838 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGT,
839 ByteCodeInstruction::kCompareUGT,
840 ByteCodeInstruction::kCompareFGT,
841 count);
842 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400843 case Token::Kind::TK_GTEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400844 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGTEQ,
845 ByteCodeInstruction::kCompareUGTEQ,
846 ByteCodeInstruction::kCompareFGTEQ,
847 count);
848 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400849 case Token::Kind::TK_LT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400850 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLT,
851 ByteCodeInstruction::kCompareULT,
852 ByteCodeInstruction::kCompareFLT,
853 count);
854 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400855 case Token::Kind::TK_LTEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400856 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLTEQ,
857 ByteCodeInstruction::kCompareULTEQ,
858 ByteCodeInstruction::kCompareFLTEQ,
859 count);
860 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400861 case Token::Kind::TK_MINUS:
Brian Osmanb08cc022020-04-02 11:38:40 -0400862 this->writeTypedInstruction(lType, ByteCodeInstruction::kSubtractI,
863 ByteCodeInstruction::kSubtractI,
864 ByteCodeInstruction::kSubtractF,
865 count);
866 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400867 case Token::Kind::TK_NEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400868 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareINEQ,
869 ByteCodeInstruction::kCompareINEQ,
870 ByteCodeInstruction::kCompareFNEQ,
871 count);
872 // Collapse to a single bool
873 for (int i = count; i > 1; --i) {
874 this->write(ByteCodeInstruction::kOrB);
875 }
876 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400877 case Token::Kind::TK_PERCENT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400878 this->writeTypedInstruction(lType, ByteCodeInstruction::kRemainderS,
879 ByteCodeInstruction::kRemainderU,
880 ByteCodeInstruction::kRemainderF,
881 count);
882 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400883 case Token::Kind::TK_PLUS:
Brian Osmanb08cc022020-04-02 11:38:40 -0400884 this->writeTypedInstruction(lType, ByteCodeInstruction::kAddI,
885 ByteCodeInstruction::kAddI,
886 ByteCodeInstruction::kAddF,
887 count);
888 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400889 case Token::Kind::TK_SLASH:
Brian Osmanb08cc022020-04-02 11:38:40 -0400890 this->writeTypedInstruction(lType, ByteCodeInstruction::kDivideS,
891 ByteCodeInstruction::kDivideU,
892 ByteCodeInstruction::kDivideF,
893 count);
894 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400895 case Token::Kind::TK_STAR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400896 this->writeTypedInstruction(lType, ByteCodeInstruction::kMultiplyI,
897 ByteCodeInstruction::kMultiplyI,
898 ByteCodeInstruction::kMultiplyF,
899 count);
900 break;
901
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400902 case Token::Kind::TK_LOGICALXOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400903 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
904 this->write(ByteCodeInstruction::kXorB);
905 break;
906
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400907 case Token::Kind::TK_BITWISEAND:
Brian Osmanb08cc022020-04-02 11:38:40 -0400908 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
909 tc == SkSL::TypeCategory::kUnsigned));
910 this->write(ByteCodeInstruction::kAndB);
911 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400912 case Token::Kind::TK_BITWISEOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400913 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
914 tc == SkSL::TypeCategory::kUnsigned));
915 this->write(ByteCodeInstruction::kOrB);
916 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400917 case Token::Kind::TK_BITWISEXOR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400918 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
919 tc == SkSL::TypeCategory::kUnsigned));
920 this->write(ByteCodeInstruction::kXorB);
921 break;
922
923 default:
924 fErrors.error(b.fOffset, SkSL::String::printf("Unsupported binary operator '%s'",
925 Compiler::OperatorName(op)));
926 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500927 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500928 }
929 if (lvalue) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400930 lvalue->store(discard);
931 discard = false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500932 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400933 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500934}
935
Brian Osmanb08cc022020-04-02 11:38:40 -0400936void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
937 this->write(ByteCodeInstruction::kPushImmediate);
938 this->write32(b.fValue ? ~0 : 0);
939}
940
941void ByteCodeGenerator::writeConstructor(const Constructor& c) {
942 for (const auto& arg : c.fArguments) {
943 this->writeExpression(*arg);
944 }
945 if (c.fArguments.size() == 1) {
946 const Type& inType = c.fArguments[0]->fType;
947 const Type& outType = c.fType;
948 TypeCategory inCategory = type_category(inType);
949 TypeCategory outCategory = type_category(outType);
950 int inCount = SlotCount(inType);
951 int outCount = SlotCount(outType);
952 if (inCategory != outCategory) {
953 SkASSERT(inCount == outCount);
954 if (inCategory == TypeCategory::kFloat) {
955 SkASSERT(outCategory == TypeCategory::kSigned ||
956 outCategory == TypeCategory::kUnsigned);
957 this->write(vector_instruction(ByteCodeInstruction::kConvertFtoI, outCount));
958 } else if (outCategory == TypeCategory::kFloat) {
959 if (inCategory == TypeCategory::kSigned) {
960 this->write(vector_instruction(ByteCodeInstruction::kConvertStoF, outCount));
961 } else {
962 SkASSERT(inCategory == TypeCategory::kUnsigned);
963 this->write(vector_instruction(ByteCodeInstruction::kConvertUtoF, outCount));
964 }
965 } else {
966 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500967 }
968 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400969 if (inType.kind() == Type::kMatrix_Kind && outType.kind() == Type::kMatrix_Kind) {
970 this->write(ByteCodeInstruction::kMatrixToMatrix,
971 SlotCount(outType) - SlotCount(inType));
972 this->write8(inType.columns());
973 this->write8(inType.rows());
974 this->write8(outType.columns());
975 this->write8(outType.rows());
976 } else if (inCount != outCount) {
977 SkASSERT(inCount == 1);
978 if (outType.kind() == Type::kMatrix_Kind) {
979 this->write(ByteCodeInstruction::kScalarToMatrix, SlotCount(outType) - 1);
980 this->write8(outType.columns());
981 this->write8(outType.rows());
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500982 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400983 SkASSERT(outType.kind() == Type::kVector_Kind);
984 for (; inCount != outCount; ++inCount) {
985 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -0400986 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500987 }
988 }
989 }
990}
991
Brian Osmanb08cc022020-04-02 11:38:40 -0400992void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500993 int argumentCount = 0;
994 for (const auto& arg : f.fArguments) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400995 this->writeExpression(*arg);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500996 argumentCount += SlotCount(arg->fType);
997 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400998 this->write(ByteCodeInstruction::kCallExternal, SlotCount(f.fType) - argumentCount);
999 SkASSERT(argumentCount <= 255);
1000 this->write8(argumentCount);
1001 this->write8(SlotCount(f.fType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001002 int index = fOutput->fExternalValues.size();
1003 fOutput->fExternalValues.push_back(f.fFunction);
1004 SkASSERT(index <= 255);
Brian Osmanb08cc022020-04-02 11:38:40 -04001005 this->write8(index);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001006}
1007
Brian Osmanb08cc022020-04-02 11:38:40 -04001008void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
1009 int count = SlotCount(e.fValue->type());
1010 this->write(vector_instruction(ByteCodeInstruction::kReadExternal, count));
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001011 int index = fOutput->fExternalValues.size();
1012 fOutput->fExternalValues.push_back(e.fValue);
1013 SkASSERT(index <= 255);
Brian Osmanb08cc022020-04-02 11:38:40 -04001014 this->write8(index);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001015}
1016
Brian Osmanb08cc022020-04-02 11:38:40 -04001017void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
1018 Location location = this->getLocation(expr);
1019 int count = SlotCount(expr.fType);
Brian Osmanefb08402020-04-13 16:30:44 -04001020 if (count == 0) {
1021 return;
1022 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001023 if (location.isOnStack() || count > 4) {
1024 if (!location.isOnStack()) {
1025 this->write(ByteCodeInstruction::kPushImmediate);
1026 this->write32(location.fSlot);
1027 }
1028 this->write(location.selectLoad(ByteCodeInstruction::kLoadExtended,
1029 ByteCodeInstruction::kLoadExtendedGlobal,
1030 ByteCodeInstruction::kLoadExtendedUniform),
1031 count);
1032 this->write8(count);
1033 } else {
1034 this->write(vector_instruction(location.selectLoad(ByteCodeInstruction::kLoad,
1035 ByteCodeInstruction::kLoadGlobal,
1036 ByteCodeInstruction::kLoadUniform),
1037 count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001038 this->write8(location.fSlot);
1039 }
1040}
1041
1042static inline uint32_t float_to_bits(float x) {
1043 uint32_t u;
1044 memcpy(&u, &x, sizeof(uint32_t));
1045 return u;
1046}
1047
1048void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
1049 this->write(ByteCodeInstruction::kPushImmediate);
1050 this->write32(float_to_bits(f.fValue));
1051}
1052
Brian Osman8842b372020-05-01 15:07:49 -04001053static bool is_generic_type(const Type* type, const Type* generic) {
1054 const std::vector<const Type*>& concrete(generic->coercibleTypes());
1055 return std::find(concrete.begin(), concrete.end(), type) != concrete.end();
1056}
1057
Brian Osmanb08cc022020-04-02 11:38:40 -04001058void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
1059 auto found = fIntrinsics.find(c.fFunction.fName);
1060 if (found == fIntrinsics.end()) {
1061 fErrors.error(c.fOffset, String::printf("Unsupported intrinsic: '%s'",
1062 String(c.fFunction.fName).c_str()));
1063 return;
1064 }
Mike Klein45be0772020-05-01 09:13:18 -05001065 Intrinsic intrin = found->second;
Brian Osmanb08cc022020-04-02 11:38:40 -04001066 int count = SlotCount(c.fArguments[0]->fType);
Brian Osmand5f937b2020-05-04 12:07:29 -04001067
1068 // Several intrinsics have variants where one argument is either scalar, or the same size as
1069 // the first argument. Call dupSmallerType(SlotCount(argType)) to ensure equal component count.
1070 auto dupSmallerType = [count, this](int smallCount) {
1071 SkASSERT(smallCount == 1 || smallCount == count);
1072 for (int i = smallCount; i < count; ++i) {
1073 this->write(ByteCodeInstruction::kDup);
1074 }
1075 };
1076
Brian Osmana43d8202020-06-17 16:50:39 -04001077 if (intrin.is_special && intrin.special == SpecialIntrinsic::kSample) {
1078 // Sample is very special, the first argument is an FP, which can't be pushed to the stack
1079 if (c.fArguments.size() != 2 ||
1080 c.fArguments[0]->fType != *fContext.fFragmentProcessor_Type ||
1081 (c.fArguments[1]->fType != *fContext.fFloat2_Type &&
1082 c.fArguments[1]->fType != *fContext.fFloat3x3_Type)) {
1083 fErrors.error(c.fOffset, "Unsupported form of sample");
1084 return;
1085 }
1086
1087 // Write our coords or matrix
1088 this->writeExpression(*c.fArguments[1]);
1089
1090 this->write(c.fArguments[1]->fType == *fContext.fFloat3x3_Type
1091 ? ByteCodeInstruction::kSampleMatrix
1092 : ByteCodeInstruction::kSampleExplicit);
1093
1094 Location childLoc = this->getLocation(*c.fArguments[0]);
1095 SkASSERT(childLoc.fStorage == Storage::kChildFP);
1096 this->write8(childLoc.fSlot);
1097 return;
1098 }
1099
Brian Osmand5f937b2020-05-04 12:07:29 -04001100 if (intrin.is_special && (intrin.special == SpecialIntrinsic::kClamp ||
1101 intrin.special == SpecialIntrinsic::kSaturate)) {
1102 // These intrinsics are extra-special, we need instructions interleaved with arguments
1103 bool saturate = (intrin.special == SpecialIntrinsic::kSaturate);
1104 SkASSERT(c.fArguments.size() == (saturate ? 1 : 3));
1105 int limitCount = saturate ? 1 : SlotCount(c.fArguments[1]->fType);
1106
1107 // 'x'
1108 this->writeExpression(*c.fArguments[0]);
1109
1110 // 'minVal'
1111 if (saturate) {
1112 this->write(ByteCodeInstruction::kPushImmediate);
1113 this->write32(float_to_bits(0.0f));
1114 } else {
1115 this->writeExpression(*c.fArguments[1]);
1116 }
1117 dupSmallerType(limitCount);
1118 this->writeTypedInstruction(c.fArguments[0]->fType,
1119 ByteCodeInstruction::kMaxS,
1120 ByteCodeInstruction::kMaxS,
1121 ByteCodeInstruction::kMaxF,
1122 count);
1123
1124 // 'maxVal'
1125 if (saturate) {
1126 this->write(ByteCodeInstruction::kPushImmediate);
1127 this->write32(float_to_bits(1.0f));
1128 } else {
1129 SkASSERT(limitCount == SlotCount(c.fArguments[2]->fType));
1130 this->writeExpression(*c.fArguments[2]);
1131 }
1132 dupSmallerType(limitCount);
1133 this->writeTypedInstruction(c.fArguments[0]->fType,
1134 ByteCodeInstruction::kMinS,
1135 ByteCodeInstruction::kMinS,
1136 ByteCodeInstruction::kMinF,
1137 count);
1138 return;
1139 }
1140
1141 // All other intrinsics can handle their arguments being on the stack in order
1142 for (const auto& arg : c.fArguments) {
1143 this->writeExpression(*arg);
1144 }
1145
Mike Klein45be0772020-05-01 09:13:18 -05001146 if (intrin.is_special) {
1147 switch (intrin.special) {
Brian Osman8842b372020-05-01 15:07:49 -04001148 case SpecialIntrinsic::kAll: {
1149 for (int i = count-1; i --> 0;) {
1150 this->write(ByteCodeInstruction::kAndB);
1151 }
1152 } break;
1153
1154 case SpecialIntrinsic::kAny: {
1155 for (int i = count-1; i --> 0;) {
1156 this->write(ByteCodeInstruction::kOrB);
1157 }
1158 } break;
1159
Brian Osman15c98cb2020-02-27 18:36:57 +00001160 case SpecialIntrinsic::kDot: {
1161 SkASSERT(c.fArguments.size() == 2);
Brian Osmanb08cc022020-04-02 11:38:40 -04001162 SkASSERT(count == SlotCount(c.fArguments[1]->fType));
1163 this->write(vector_instruction(ByteCodeInstruction::kMultiplyF, count));
Mike Klein45be0772020-05-01 09:13:18 -05001164 for (int i = count-1; i --> 0;) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001165 this->write(ByteCodeInstruction::kAddF);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001166 }
Mike Klein45be0772020-05-01 09:13:18 -05001167 } break;
1168
1169 case SpecialIntrinsic::kLength: {
1170 SkASSERT(c.fArguments.size() == 1);
1171 this->write(vector_instruction(ByteCodeInstruction::kDup , count));
1172 this->write(vector_instruction(ByteCodeInstruction::kMultiplyF, count));
1173 for (int i = count-1; i --> 0;) {
1174 this->write(ByteCodeInstruction::kAddF);
1175 }
1176 this->write(ByteCodeInstruction::kSqrt);
1177 } break;
1178
Brian Osmand5f937b2020-05-04 12:07:29 -04001179 case SpecialIntrinsic::kMax:
1180 case SpecialIntrinsic::kMin: {
1181 SkASSERT(c.fArguments.size() == 2);
1182 // There are variants where the second argument is scalar
1183 dupSmallerType(SlotCount(c.fArguments[1]->fType));
1184 if (intrin.special == SpecialIntrinsic::kMax) {
1185 this->writeTypedInstruction(c.fArguments[0]->fType,
1186 ByteCodeInstruction::kMaxS,
1187 ByteCodeInstruction::kMaxS,
1188 ByteCodeInstruction::kMaxF,
1189 count);
1190 } else {
1191 this->writeTypedInstruction(c.fArguments[0]->fType,
1192 ByteCodeInstruction::kMinS,
1193 ByteCodeInstruction::kMinS,
1194 ByteCodeInstruction::kMinF,
1195 count);
1196 }
1197 } break;
1198
Brian Osman8842b372020-05-01 15:07:49 -04001199 case SpecialIntrinsic::kMix: {
1200 // Two main variants of mix to handle
1201 SkASSERT(c.fArguments.size() == 3);
1202 SkASSERT(count == SlotCount(c.fArguments[1]->fType));
1203 int selectorCount = SlotCount(c.fArguments[2]->fType);
1204
1205 if (is_generic_type(&c.fArguments[2]->fType, fContext.fGenBType_Type.get())) {
1206 // mix(genType, genType, genBoolType)
1207 SkASSERT(selectorCount == count);
1208 this->write(vector_instruction(ByteCodeInstruction::kMix, count));
1209 } else {
1210 // mix(genType, genType, genType) or mix(genType, genType, float)
Brian Osmand5f937b2020-05-04 12:07:29 -04001211 dupSmallerType(selectorCount);
Brian Osman8842b372020-05-01 15:07:49 -04001212 this->write(vector_instruction(ByteCodeInstruction::kLerp, count));
1213 }
1214 } break;
1215
Brian Osman2a4871b2020-06-19 11:29:58 -04001216 case SpecialIntrinsic::kNormalize: {
1217 SkASSERT(c.fArguments.size() == 1);
1218 this->write(vector_instruction(ByteCodeInstruction::kDup , count));
1219 this->write(vector_instruction(ByteCodeInstruction::kDup , count));
1220 this->write(vector_instruction(ByteCodeInstruction::kMultiplyF, count));
1221 for (int i = count-1; i --> 0;) {
1222 this->write(ByteCodeInstruction::kAddF);
1223 }
1224 this->write(ByteCodeInstruction::kSqrt);
1225 dupSmallerType(1);
1226 this->write(vector_instruction(ByteCodeInstruction::kDivideF, count));
1227 } break;
1228
Brian Osmanb08cc022020-04-02 11:38:40 -04001229 default:
1230 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001231 }
1232 } else {
Brian Osman8842b372020-05-01 15:07:49 -04001233 switch (intrin.inst_f) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001234 case ByteCodeInstruction::kInverse2x2: {
1235 SkASSERT(c.fArguments.size() > 0);
1236 auto op = ByteCodeInstruction::kInverse2x2;
1237 switch (count) {
1238 case 4: break; // float2x2
1239 case 9: op = ByteCodeInstruction::kInverse3x3; break;
1240 case 16: op = ByteCodeInstruction::kInverse4x4; break;
1241 default: SkASSERT(false);
1242 }
1243 this->write(op);
1244 break;
Brian Osman15c98cb2020-02-27 18:36:57 +00001245 }
Mike Klein45be0772020-05-01 09:13:18 -05001246
Brian Osmanb08cc022020-04-02 11:38:40 -04001247 default:
Brian Osman8842b372020-05-01 15:07:49 -04001248 this->writeTypedInstruction(c.fArguments[0]->fType, intrin.inst_s, intrin.inst_u,
1249 intrin.inst_f, count);
1250 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001251 }
1252 }
1253}
1254
Brian Osmanb08cc022020-04-02 11:38:40 -04001255void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001256 // Find the index of the function we're calling. We explicitly do not allow calls to functions
1257 // before they're defined. This is an easy-to-understand rule that prevents recursion.
Brian Osmanb08cc022020-04-02 11:38:40 -04001258 int idx = -1;
1259 for (size_t i = 0; i < fFunctions.size(); ++i) {
1260 if (f.fFunction.matches(fFunctions[i]->fDeclaration)) {
1261 idx = i;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001262 break;
1263 }
1264 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001265 if (idx == -1) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001266 this->writeIntrinsicCall(f);
1267 return;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001268 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001269
1270
1271 if (idx > 255) {
1272 fErrors.error(f.fOffset, "Function count limit exceeded");
1273 return;
1274 } else if (idx >= (int) fFunctions.size()) {
1275 fErrors.error(f.fOffset, "Call to undefined function");
1276 return;
1277 }
1278
1279 // We may need to deal with out parameters, so the sequence is tricky
1280 if (int returnCount = SlotCount(f.fType)) {
1281 this->write(ByteCodeInstruction::kReserve, returnCount);
1282 this->write8(returnCount);
1283 }
1284
1285 int argCount = f.fArguments.size();
1286 std::vector<std::unique_ptr<LValue>> lvalues;
1287 for (int i = 0; i < argCount; ++i) {
1288 const auto& param = f.fFunction.fParameters[i];
1289 const auto& arg = f.fArguments[i];
1290 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1291 lvalues.emplace_back(this->getLValue(*arg));
1292 lvalues.back()->load();
1293 } else {
1294 this->writeExpression(*arg);
1295 }
1296 }
1297
1298 // The space used by the call is based on the callee, but it also unwinds all of that before
1299 // we continue execution. We adjust our max stack depths below.
1300 this->write(ByteCodeInstruction::kCall);
1301 this->write8(idx);
1302
1303 const ByteCodeFunction* callee = fOutput->fFunctions[idx].get();
1304 fMaxLoopCount = std::max(fMaxLoopCount, fLoopCount + callee->fLoopCount);
1305 fMaxConditionCount = std::max(fMaxConditionCount, fConditionCount + callee->fConditionCount);
1306 fMaxStackCount = std::max(fMaxStackCount, fStackCount + callee->fLocalCount
1307 + callee->fStackCount);
1308
1309 // After the called function returns, the stack will still contain our arguments. We have to
1310 // pop them (storing any out parameters back to their lvalues as we go). We glob together slot
1311 // counts for all parameters that aren't out-params, so we can pop them in one big chunk.
1312 int popCount = 0;
1313 auto pop = [&]() {
1314 if (popCount > 4) {
1315 this->write(ByteCodeInstruction::kPopN, popCount);
1316 this->write8(popCount);
1317 } else if (popCount > 0) {
1318 this->write(vector_instruction(ByteCodeInstruction::kPop, popCount));
1319 }
1320 popCount = 0;
1321 };
1322
1323 for (int i = argCount - 1; i >= 0; --i) {
1324 const auto& param = f.fFunction.fParameters[i];
1325 const auto& arg = f.fArguments[i];
1326 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1327 pop();
1328 lvalues.back()->store(true);
1329 lvalues.pop_back();
1330 } else {
1331 popCount += SlotCount(arg->fType);
1332 }
1333 }
1334 pop();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001335}
1336
Brian Osmanb08cc022020-04-02 11:38:40 -04001337void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
1338 this->write(ByteCodeInstruction::kPushImmediate);
1339 this->write32(i.fValue);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001340}
1341
Brian Osmanb08cc022020-04-02 11:38:40 -04001342void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
1343 // not yet implemented
1344 abort();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001345}
1346
Brian Osmanb08cc022020-04-02 11:38:40 -04001347bool ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p, bool discard) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001348 switch (p.fOperator) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001349 case Token::Kind::TK_PLUSPLUS: // fall through
1350 case Token::Kind::TK_MINUSMINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001351 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1352 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
1353 lvalue->load();
1354 this->write(ByteCodeInstruction::kPushImmediate);
1355 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001356 if (p.fOperator == Token::Kind::TK_PLUSPLUS) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001357 this->writeTypedInstruction(p.fType,
1358 ByteCodeInstruction::kAddI,
1359 ByteCodeInstruction::kAddI,
1360 ByteCodeInstruction::kAddF,
1361 1);
1362 } else {
1363 this->writeTypedInstruction(p.fType,
1364 ByteCodeInstruction::kSubtractI,
1365 ByteCodeInstruction::kSubtractI,
1366 ByteCodeInstruction::kSubtractF,
1367 1);
1368 }
1369 lvalue->store(discard);
1370 discard = false;
1371 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001372 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001373 case Token::Kind::TK_MINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001374 this->writeExpression(*p.fOperand);
1375 this->writeTypedInstruction(p.fType,
1376 ByteCodeInstruction::kNegateI,
1377 ByteCodeInstruction::kNegateI,
1378 ByteCodeInstruction::kNegateF,
Brian Osmanab8f3842020-04-07 09:30:44 -04001379 SlotCount(p.fOperand->fType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001380 break;
1381 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001382 case Token::Kind::TK_LOGICALNOT:
1383 case Token::Kind::TK_BITWISENOT: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001384 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1385 SkDEBUGCODE(TypeCategory tc = type_category(p.fOperand->fType));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001386 SkASSERT((p.fOperator == Token::Kind::TK_LOGICALNOT && tc == TypeCategory::kBool) ||
1387 (p.fOperator == Token::Kind::TK_BITWISENOT && (tc == TypeCategory::kSigned ||
Brian Osmanb08cc022020-04-02 11:38:40 -04001388 tc == TypeCategory::kUnsigned)));
1389 this->writeExpression(*p.fOperand);
1390 this->write(ByteCodeInstruction::kNotB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001391 break;
1392 }
1393 default:
1394 SkASSERT(false);
1395 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001396 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001397}
1398
Brian Osmanb08cc022020-04-02 11:38:40 -04001399bool ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p, bool discard) {
1400 switch (p.fOperator) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001401 case Token::Kind::TK_PLUSPLUS: // fall through
1402 case Token::Kind::TK_MINUSMINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001403 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1404 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
1405 lvalue->load();
1406 // If we're not supposed to discard the result, then make a copy *before* the +/-
1407 if (!discard) {
1408 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -04001409 }
1410 this->write(ByteCodeInstruction::kPushImmediate);
1411 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001412 if (p.fOperator == Token::Kind::TK_PLUSPLUS) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001413 this->writeTypedInstruction(p.fType,
1414 ByteCodeInstruction::kAddI,
1415 ByteCodeInstruction::kAddI,
1416 ByteCodeInstruction::kAddF,
1417 1);
1418 } else {
1419 this->writeTypedInstruction(p.fType,
1420 ByteCodeInstruction::kSubtractI,
1421 ByteCodeInstruction::kSubtractI,
1422 ByteCodeInstruction::kSubtractF,
1423 1);
1424 }
1425 // Always consume the result as part of the store
1426 lvalue->store(true);
1427 discard = false;
1428 break;
1429 }
1430 default:
1431 SkASSERT(false);
1432 }
1433 return discard;
1434}
1435
1436void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001437 if (swizzle_is_simple(s)) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001438 this->writeVariableExpression(s);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001439 return;
1440 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001441
Brian Osman3711c662020-06-18 14:42:21 -04001442 this->writeExpression(*s.fBase);
1443 this->write(ByteCodeInstruction::kSwizzle, s.fComponents.size() - s.fBase->fType.columns());
1444 this->write8(s.fBase->fType.columns());
1445 this->write8(s.fComponents.size());
1446 for (int c : s.fComponents) {
1447 this->write8(c);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001448 }
1449}
1450
Brian Osmanb08cc022020-04-02 11:38:40 -04001451void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001452 int count = SlotCount(t.fType);
1453 SkASSERT(count == SlotCount(t.fIfTrue->fType));
1454 SkASSERT(count == SlotCount(t.fIfFalse->fType));
1455
Brian Osmanb08cc022020-04-02 11:38:40 -04001456 this->writeExpression(*t.fTest);
1457 this->write(ByteCodeInstruction::kMaskPush);
1458 this->writeExpression(*t.fIfTrue);
1459 this->write(ByteCodeInstruction::kMaskNegate);
1460 this->writeExpression(*t.fIfFalse);
1461 this->write(ByteCodeInstruction::kMaskBlend, count);
1462 this->write8(count);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001463}
1464
Brian Osmanb08cc022020-04-02 11:38:40 -04001465void ByteCodeGenerator::writeExpression(const Expression& e, bool discard) {
1466 switch (e.fKind) {
1467 case Expression::kBinary_Kind:
1468 discard = this->writeBinaryExpression((BinaryExpression&) e, discard);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001469 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001470 case Expression::kBoolLiteral_Kind:
1471 this->writeBoolLiteral((BoolLiteral&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001472 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001473 case Expression::kConstructor_Kind:
1474 this->writeConstructor((Constructor&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001475 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001476 case Expression::kExternalFunctionCall_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001477 this->writeExternalFunctionCall((ExternalFunctionCall&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001478 break;
1479 case Expression::kExternalValue_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001480 this->writeExternalValue((ExternalValueReference&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001481 break;
1482 case Expression::kFieldAccess_Kind:
1483 case Expression::kIndex_Kind:
1484 case Expression::kVariableReference_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001485 this->writeVariableExpression(e);
1486 break;
1487 case Expression::kFloatLiteral_Kind:
1488 this->writeFloatLiteral((FloatLiteral&) e);
1489 break;
1490 case Expression::kFunctionCall_Kind:
1491 this->writeFunctionCall((FunctionCall&) e);
1492 break;
1493 case Expression::kIntLiteral_Kind:
1494 this->writeIntLiteral((IntLiteral&) e);
1495 break;
1496 case Expression::kNullLiteral_Kind:
1497 this->writeNullLiteral((NullLiteral&) e);
1498 break;
1499 case Expression::kPrefix_Kind:
1500 discard = this->writePrefixExpression((PrefixExpression&) e, discard);
1501 break;
1502 case Expression::kPostfix_Kind:
1503 discard = this->writePostfixExpression((PostfixExpression&) e, discard);
1504 break;
1505 case Expression::kSwizzle_Kind:
1506 this->writeSwizzle((Swizzle&) e);
1507 break;
1508 case Expression::kTernary_Kind:
1509 this->writeTernaryExpression((TernaryExpression&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001510 break;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001511 default:
1512#ifdef SK_DEBUG
Brian Osmanb08cc022020-04-02 11:38:40 -04001513 printf("unsupported expression %s\n", e.description().c_str());
Ben Wagner470e0ac2020-01-22 16:59:21 -05001514#endif
Brian Osmanb08cc022020-04-02 11:38:40 -04001515 SkASSERT(false);
1516 }
1517 if (discard) {
1518 int count = SlotCount(e.fType);
1519 if (count > 4) {
1520 this->write(ByteCodeInstruction::kPopN, count);
1521 this->write8(count);
1522 } else if (count != 0) {
1523 this->write(vector_instruction(ByteCodeInstruction::kPop, count));
1524 }
1525 discard = false;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001526 }
Ethan Nicholas7deb1c22020-01-22 10:31:55 -05001527}
1528
Brian Osmanb08cc022020-04-02 11:38:40 -04001529class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
1530public:
1531 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
1532 : INHERITED(*generator)
1533 , fCount(ByteCodeGenerator::SlotCount(value.type()))
1534 , fIndex(index) {}
1535
1536 void load() override {
1537 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001538 fGenerator.write8(fIndex);
1539 }
1540
1541 void store(bool discard) override {
1542 if (!discard) {
1543 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001544 }
1545 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001546 fGenerator.write8(fIndex);
1547 }
1548
1549private:
1550 typedef LValue INHERITED;
1551
1552 int fCount;
1553
1554 int fIndex;
1555};
1556
1557class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
1558public:
1559 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
1560 : INHERITED(*generator)
1561 , fSwizzle(swizzle) {}
1562
1563 void load() override {
1564 fGenerator.writeSwizzle(fSwizzle);
1565 }
1566
1567 void store(bool discard) override {
1568 int count = fSwizzle.fComponents.size();
1569 if (!discard) {
1570 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001571 }
Brian Osman304dfa32020-06-18 15:53:51 -04001572 // We already have the correct number of values on the stack, thanks to type checking.
1573 // The algorithm: Walk down the values on the stack, doing 'count' single-element stores.
1574 // For each value, use the corresponding swizzle component to offset the store location.
1575 //
1576 // Static locations: We (wastefully) call getLocation every time, but get good byte code.
1577 // Note that we could (but don't) store adjacent/sequential values with fewer instructions.
1578 //
1579 // Dynamic locations: ... are bad. We have to recompute the base address on each iteration,
1580 // because the stack doesn't let us retain that address between stores. Dynamic locations
1581 // are rare though, and swizzled writes to those are even rarer, so we just live with this.
1582 for (int i = count; i-- > 0;) {
1583 ByteCodeGenerator::Location location = fGenerator.getLocation(*fSwizzle.fBase);
1584 if (!location.isOnStack()) {
1585 fGenerator.write(location.selectStore(ByteCodeInstruction::kStore,
1586 ByteCodeInstruction::kStoreGlobal));
1587 fGenerator.write8(location.fSlot + fSwizzle.fComponents[i]);
1588 } else {
1589 fGenerator.write(ByteCodeInstruction::kPushImmediate);
1590 fGenerator.write32(fSwizzle.fComponents[i]);
1591 fGenerator.write(ByteCodeInstruction::kAddI);
1592 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreExtended,
1593 ByteCodeInstruction::kStoreExtendedGlobal),
1594 1);
1595 fGenerator.write8(1);
1596 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001597 }
1598 }
1599
1600private:
1601 const Swizzle& fSwizzle;
1602
1603 typedef LValue INHERITED;
1604};
1605
1606class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
1607public:
1608 ByteCodeExpressionLValue(ByteCodeGenerator* generator, const Expression& expr)
1609 : INHERITED(*generator)
1610 , fExpression(expr) {}
1611
1612 void load() override {
1613 fGenerator.writeVariableExpression(fExpression);
1614 }
1615
1616 void store(bool discard) override {
1617 int count = ByteCodeGenerator::SlotCount(fExpression.fType);
1618 if (!discard) {
1619 if (count > 4) {
1620 fGenerator.write(ByteCodeInstruction::kDupN, count);
1621 fGenerator.write8(count);
1622 } else {
1623 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001624 }
1625 }
1626 ByteCodeGenerator::Location location = fGenerator.getLocation(fExpression);
1627 if (location.isOnStack() || count > 4) {
1628 if (!location.isOnStack()) {
1629 fGenerator.write(ByteCodeInstruction::kPushImmediate);
1630 fGenerator.write32(location.fSlot);
1631 }
1632 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreExtended,
1633 ByteCodeInstruction::kStoreExtendedGlobal),
1634 count);
1635 fGenerator.write8(count);
1636 } else {
1637 fGenerator.write(
1638 vector_instruction(location.selectStore(ByteCodeInstruction::kStore,
1639 ByteCodeInstruction::kStoreGlobal),
1640 count));
1641 fGenerator.write8(location.fSlot);
1642 }
1643 }
1644
1645private:
1646 typedef LValue INHERITED;
1647
1648 const Expression& fExpression;
1649};
1650
1651std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
1652 switch (e.fKind) {
1653 case Expression::kExternalValue_Kind: {
1654 ExternalValue* value = ((ExternalValueReference&) e).fValue;
1655 int index = fOutput->fExternalValues.size();
1656 fOutput->fExternalValues.push_back(value);
1657 SkASSERT(index <= 255);
1658 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
1659 }
1660 case Expression::kFieldAccess_Kind:
1661 case Expression::kIndex_Kind:
1662 case Expression::kVariableReference_Kind:
1663 return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
1664 case Expression::kSwizzle_Kind: {
1665 const Swizzle& s = (const Swizzle&) e;
1666 return swizzle_is_simple(s)
1667 ? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e))
1668 : std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s));
1669 }
1670 case Expression::kTernary_Kind:
1671 default:
1672#ifdef SK_DEBUG
1673 ABORT("unsupported lvalue %s\n", e.description().c_str());
1674#endif
1675 return nullptr;
1676 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001677}
1678
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001679void ByteCodeGenerator::writeBlock(const Block& b) {
1680 for (const auto& s : b.fStatements) {
1681 this->writeStatement(*s);
1682 }
1683}
1684
Brian Osmanb08cc022020-04-02 11:38:40 -04001685void ByteCodeGenerator::setBreakTargets() {
1686 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
1687 for (DeferredLocation& b : breaks) {
1688 b.set();
1689 }
1690 fBreakTargets.pop();
1691}
1692
1693void ByteCodeGenerator::setContinueTargets() {
1694 std::vector<DeferredLocation>& continues = fContinueTargets.top();
1695 for (DeferredLocation& c : continues) {
1696 c.set();
1697 }
1698 fContinueTargets.pop();
1699}
1700
1701void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
1702 // TODO: Include BranchIfAllFalse to top-most LoopNext
1703 this->write(ByteCodeInstruction::kLoopBreak);
1704}
1705
1706void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
1707 // TODO: Include BranchIfAllFalse to top-most LoopNext
1708 this->write(ByteCodeInstruction::kLoopContinue);
1709}
1710
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001711void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001712 this->write(ByteCodeInstruction::kLoopBegin);
1713 size_t start = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001714 this->writeStatement(*d.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001715 this->write(ByteCodeInstruction::kLoopNext);
1716 this->writeExpression(*d.fTest);
1717 this->write(ByteCodeInstruction::kLoopMask);
1718 // TODO: Could shorten this with kBranchIfAnyTrue
1719 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001720 DeferredLocation endLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -04001721 this->write(ByteCodeInstruction::kBranch);
1722 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001723 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001724 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001725}
1726
1727void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001728 fContinueTargets.emplace();
1729 fBreakTargets.emplace();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001730 if (f.fInitializer) {
1731 this->writeStatement(*f.fInitializer);
1732 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001733 this->write(ByteCodeInstruction::kLoopBegin);
1734 size_t start = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001735 if (f.fTest) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001736 this->writeExpression(*f.fTest);
1737 this->write(ByteCodeInstruction::kLoopMask);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001738 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001739 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001740 DeferredLocation endLocation(this);
1741 this->writeStatement(*f.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001742 this->write(ByteCodeInstruction::kLoopNext);
Brian Osman569f12f2019-06-13 11:23:57 -04001743 if (f.fNext) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001744 this->writeExpression(*f.fNext, true);
Brian Osman569f12f2019-06-13 11:23:57 -04001745 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001746 this->write(ByteCodeInstruction::kBranch);
1747 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001748 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001749 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001750}
1751
1752void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001753 this->writeExpression(*i.fTest);
1754 this->write(ByteCodeInstruction::kMaskPush);
1755 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001756 DeferredLocation falseLocation(this);
1757 this->writeStatement(*i.fIfTrue);
1758 falseLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001759 if (i.fIfFalse) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001760 this->write(ByteCodeInstruction::kMaskNegate);
1761 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001762 DeferredLocation endLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001763 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -05001764 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001765 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001766 this->write(ByteCodeInstruction::kMaskPop);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001767}
1768
Brian Osmanb08cc022020-04-02 11:38:40 -04001769void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
1770 if (fLoopCount || fConditionCount) {
Brian Osman4a47da72019-07-12 11:30:32 -04001771 fErrors.error(r.fOffset, "return not allowed inside conditional or loop");
1772 return;
1773 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001774 int count = SlotCount(r.fExpression->fType);
1775 this->writeExpression(*r.fExpression);
1776
1777 // Technically, the kReturn also pops fOutput->fLocalCount values from the stack, too, but we
1778 // haven't counted pushing those (they're outside the scope of our stack tracking). Instead,
1779 // we account for those in writeFunction().
1780
1781 // This is all fine because we don't allow conditional returns, so we only return once anyway.
1782 this->write(ByteCodeInstruction::kReturn, -count);
1783 this->write8(count);
1784}
1785
1786void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
1787 // not yet implemented
1788 abort();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001789}
1790
1791void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1792 for (const auto& declStatement : v.fVars) {
1793 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
Brian Osmanb08cc022020-04-02 11:38:40 -04001794 // we need to grab the location even if we don't use it, to ensure it has been allocated
1795 Location location = this->getLocation(*decl.fVar);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001796 if (decl.fValue) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001797 this->writeExpression(*decl.fValue);
1798 int count = SlotCount(decl.fValue->fType);
1799 if (count > 4) {
1800 this->write(ByteCodeInstruction::kPushImmediate);
1801 this->write32(location.fSlot);
1802 this->write(ByteCodeInstruction::kStoreExtended, count);
1803 this->write8(count);
1804 } else {
1805 this->write(vector_instruction(ByteCodeInstruction::kStore, count));
1806 this->write8(location.fSlot);
1807 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001808 }
1809 }
1810}
1811
1812void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001813 this->write(ByteCodeInstruction::kLoopBegin);
1814 size_t cond = fCode->size();
1815 this->writeExpression(*w.fTest);
1816 this->write(ByteCodeInstruction::kLoopMask);
1817 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001818 DeferredLocation endLocation(this);
1819 this->writeStatement(*w.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001820 this->write(ByteCodeInstruction::kLoopNext);
1821 this->write(ByteCodeInstruction::kBranch);
1822 this->write16(cond);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001823 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001824 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001825}
1826
1827void ByteCodeGenerator::writeStatement(const Statement& s) {
1828 switch (s.fKind) {
1829 case Statement::kBlock_Kind:
1830 this->writeBlock((Block&) s);
1831 break;
1832 case Statement::kBreak_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001833 this->writeBreakStatement((BreakStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001834 break;
1835 case Statement::kContinue_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001836 this->writeContinueStatement((ContinueStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001837 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001838 case Statement::kDiscard_Kind:
1839 // not yet implemented
1840 abort();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001841 case Statement::kDo_Kind:
1842 this->writeDoStatement((DoStatement&) s);
1843 break;
Brian Osman3e29f1d2019-05-28 09:35:05 -04001844 case Statement::kExpression_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001845 this->writeExpression(*((ExpressionStatement&) s).fExpression, true);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001846 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001847 case Statement::kFor_Kind:
1848 this->writeForStatement((ForStatement&) s);
1849 break;
1850 case Statement::kIf_Kind:
1851 this->writeIfStatement((IfStatement&) s);
1852 break;
1853 case Statement::kNop_Kind:
1854 break;
1855 case Statement::kReturn_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001856 this->writeReturnStatement((ReturnStatement&) s);
1857 break;
1858 case Statement::kSwitch_Kind:
1859 this->writeSwitchStatement((SwitchStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001860 break;
1861 case Statement::kVarDeclarations_Kind:
1862 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1863 break;
1864 case Statement::kWhile_Kind:
1865 this->writeWhileStatement((WhileStatement&) s);
1866 break;
1867 default:
Brian Osmanb08cc022020-04-02 11:38:40 -04001868 SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001869 }
1870}
1871
Brian Osmanb08cc022020-04-02 11:38:40 -04001872ByteCodeFunction::ByteCodeFunction(const FunctionDeclaration* declaration)
1873 : fName(declaration->fName) {
Brian Osman80164412019-06-07 13:00:23 -04001874 fParameterCount = 0;
Brian Osmanb08cc022020-04-02 11:38:40 -04001875 for (const auto& p : declaration->fParameters) {
1876 int slots = ByteCodeGenerator::SlotCount(p->fType);
1877 fParameters.push_back({ slots, (bool)(p->fModifiers.fFlags & Modifiers::kOut_Flag) });
1878 fParameterCount += slots;
Brian Osman80164412019-06-07 13:00:23 -04001879 }
1880}
1881
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001882}