blob: 1d8f87fcf9fff072d1b8fac4deb430bdd29aa7fa [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 Osman02f8b072020-06-19 14:04:48 -04001023 if (location.isOnStack()) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001024 this->write(location.selectLoad(ByteCodeInstruction::kLoadExtended,
1025 ByteCodeInstruction::kLoadExtendedGlobal,
1026 ByteCodeInstruction::kLoadExtendedUniform),
1027 count);
1028 this->write8(count);
1029 } else {
Brian Osman02f8b072020-06-19 14:04:48 -04001030 while (count) {
1031 int loadCount = std::min(count, 4);
1032 this->write(vector_instruction(location.selectLoad(ByteCodeInstruction::kLoad,
1033 ByteCodeInstruction::kLoadGlobal,
1034 ByteCodeInstruction::kLoadUniform),
1035 loadCount));
1036 this->write8(location.fSlot);
1037 count -= loadCount;
1038 location.fSlot += loadCount;
1039 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001040 }
1041}
1042
1043static inline uint32_t float_to_bits(float x) {
1044 uint32_t u;
1045 memcpy(&u, &x, sizeof(uint32_t));
1046 return u;
1047}
1048
1049void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
1050 this->write(ByteCodeInstruction::kPushImmediate);
1051 this->write32(float_to_bits(f.fValue));
1052}
1053
Brian Osman8842b372020-05-01 15:07:49 -04001054static bool is_generic_type(const Type* type, const Type* generic) {
1055 const std::vector<const Type*>& concrete(generic->coercibleTypes());
1056 return std::find(concrete.begin(), concrete.end(), type) != concrete.end();
1057}
1058
Brian Osmanb08cc022020-04-02 11:38:40 -04001059void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
1060 auto found = fIntrinsics.find(c.fFunction.fName);
1061 if (found == fIntrinsics.end()) {
1062 fErrors.error(c.fOffset, String::printf("Unsupported intrinsic: '%s'",
1063 String(c.fFunction.fName).c_str()));
1064 return;
1065 }
Mike Klein45be0772020-05-01 09:13:18 -05001066 Intrinsic intrin = found->second;
Brian Osmanb08cc022020-04-02 11:38:40 -04001067 int count = SlotCount(c.fArguments[0]->fType);
Brian Osmand5f937b2020-05-04 12:07:29 -04001068
1069 // Several intrinsics have variants where one argument is either scalar, or the same size as
1070 // the first argument. Call dupSmallerType(SlotCount(argType)) to ensure equal component count.
1071 auto dupSmallerType = [count, this](int smallCount) {
1072 SkASSERT(smallCount == 1 || smallCount == count);
1073 for (int i = smallCount; i < count; ++i) {
1074 this->write(ByteCodeInstruction::kDup);
1075 }
1076 };
1077
Brian Osmana43d8202020-06-17 16:50:39 -04001078 if (intrin.is_special && intrin.special == SpecialIntrinsic::kSample) {
1079 // Sample is very special, the first argument is an FP, which can't be pushed to the stack
1080 if (c.fArguments.size() != 2 ||
1081 c.fArguments[0]->fType != *fContext.fFragmentProcessor_Type ||
1082 (c.fArguments[1]->fType != *fContext.fFloat2_Type &&
1083 c.fArguments[1]->fType != *fContext.fFloat3x3_Type)) {
1084 fErrors.error(c.fOffset, "Unsupported form of sample");
1085 return;
1086 }
1087
1088 // Write our coords or matrix
1089 this->writeExpression(*c.fArguments[1]);
1090
1091 this->write(c.fArguments[1]->fType == *fContext.fFloat3x3_Type
1092 ? ByteCodeInstruction::kSampleMatrix
1093 : ByteCodeInstruction::kSampleExplicit);
1094
1095 Location childLoc = this->getLocation(*c.fArguments[0]);
1096 SkASSERT(childLoc.fStorage == Storage::kChildFP);
1097 this->write8(childLoc.fSlot);
1098 return;
1099 }
1100
Brian Osmand5f937b2020-05-04 12:07:29 -04001101 if (intrin.is_special && (intrin.special == SpecialIntrinsic::kClamp ||
1102 intrin.special == SpecialIntrinsic::kSaturate)) {
1103 // These intrinsics are extra-special, we need instructions interleaved with arguments
1104 bool saturate = (intrin.special == SpecialIntrinsic::kSaturate);
1105 SkASSERT(c.fArguments.size() == (saturate ? 1 : 3));
1106 int limitCount = saturate ? 1 : SlotCount(c.fArguments[1]->fType);
1107
1108 // 'x'
1109 this->writeExpression(*c.fArguments[0]);
1110
1111 // 'minVal'
1112 if (saturate) {
1113 this->write(ByteCodeInstruction::kPushImmediate);
1114 this->write32(float_to_bits(0.0f));
1115 } else {
1116 this->writeExpression(*c.fArguments[1]);
1117 }
1118 dupSmallerType(limitCount);
1119 this->writeTypedInstruction(c.fArguments[0]->fType,
1120 ByteCodeInstruction::kMaxS,
1121 ByteCodeInstruction::kMaxS,
1122 ByteCodeInstruction::kMaxF,
1123 count);
1124
1125 // 'maxVal'
1126 if (saturate) {
1127 this->write(ByteCodeInstruction::kPushImmediate);
1128 this->write32(float_to_bits(1.0f));
1129 } else {
1130 SkASSERT(limitCount == SlotCount(c.fArguments[2]->fType));
1131 this->writeExpression(*c.fArguments[2]);
1132 }
1133 dupSmallerType(limitCount);
1134 this->writeTypedInstruction(c.fArguments[0]->fType,
1135 ByteCodeInstruction::kMinS,
1136 ByteCodeInstruction::kMinS,
1137 ByteCodeInstruction::kMinF,
1138 count);
1139 return;
1140 }
1141
1142 // All other intrinsics can handle their arguments being on the stack in order
1143 for (const auto& arg : c.fArguments) {
1144 this->writeExpression(*arg);
1145 }
1146
Mike Klein45be0772020-05-01 09:13:18 -05001147 if (intrin.is_special) {
1148 switch (intrin.special) {
Brian Osman8842b372020-05-01 15:07:49 -04001149 case SpecialIntrinsic::kAll: {
1150 for (int i = count-1; i --> 0;) {
1151 this->write(ByteCodeInstruction::kAndB);
1152 }
1153 } break;
1154
1155 case SpecialIntrinsic::kAny: {
1156 for (int i = count-1; i --> 0;) {
1157 this->write(ByteCodeInstruction::kOrB);
1158 }
1159 } break;
1160
Brian Osman15c98cb2020-02-27 18:36:57 +00001161 case SpecialIntrinsic::kDot: {
1162 SkASSERT(c.fArguments.size() == 2);
Brian Osmanb08cc022020-04-02 11:38:40 -04001163 SkASSERT(count == SlotCount(c.fArguments[1]->fType));
1164 this->write(vector_instruction(ByteCodeInstruction::kMultiplyF, count));
Mike Klein45be0772020-05-01 09:13:18 -05001165 for (int i = count-1; i --> 0;) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001166 this->write(ByteCodeInstruction::kAddF);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001167 }
Mike Klein45be0772020-05-01 09:13:18 -05001168 } break;
1169
1170 case SpecialIntrinsic::kLength: {
1171 SkASSERT(c.fArguments.size() == 1);
1172 this->write(vector_instruction(ByteCodeInstruction::kDup , count));
1173 this->write(vector_instruction(ByteCodeInstruction::kMultiplyF, count));
1174 for (int i = count-1; i --> 0;) {
1175 this->write(ByteCodeInstruction::kAddF);
1176 }
1177 this->write(ByteCodeInstruction::kSqrt);
1178 } break;
1179
Brian Osmand5f937b2020-05-04 12:07:29 -04001180 case SpecialIntrinsic::kMax:
1181 case SpecialIntrinsic::kMin: {
1182 SkASSERT(c.fArguments.size() == 2);
1183 // There are variants where the second argument is scalar
1184 dupSmallerType(SlotCount(c.fArguments[1]->fType));
1185 if (intrin.special == SpecialIntrinsic::kMax) {
1186 this->writeTypedInstruction(c.fArguments[0]->fType,
1187 ByteCodeInstruction::kMaxS,
1188 ByteCodeInstruction::kMaxS,
1189 ByteCodeInstruction::kMaxF,
1190 count);
1191 } else {
1192 this->writeTypedInstruction(c.fArguments[0]->fType,
1193 ByteCodeInstruction::kMinS,
1194 ByteCodeInstruction::kMinS,
1195 ByteCodeInstruction::kMinF,
1196 count);
1197 }
1198 } break;
1199
Brian Osman8842b372020-05-01 15:07:49 -04001200 case SpecialIntrinsic::kMix: {
1201 // Two main variants of mix to handle
1202 SkASSERT(c.fArguments.size() == 3);
1203 SkASSERT(count == SlotCount(c.fArguments[1]->fType));
1204 int selectorCount = SlotCount(c.fArguments[2]->fType);
1205
1206 if (is_generic_type(&c.fArguments[2]->fType, fContext.fGenBType_Type.get())) {
1207 // mix(genType, genType, genBoolType)
1208 SkASSERT(selectorCount == count);
1209 this->write(vector_instruction(ByteCodeInstruction::kMix, count));
1210 } else {
1211 // mix(genType, genType, genType) or mix(genType, genType, float)
Brian Osmand5f937b2020-05-04 12:07:29 -04001212 dupSmallerType(selectorCount);
Brian Osman8842b372020-05-01 15:07:49 -04001213 this->write(vector_instruction(ByteCodeInstruction::kLerp, count));
1214 }
1215 } break;
1216
Brian Osman2a4871b2020-06-19 11:29:58 -04001217 case SpecialIntrinsic::kNormalize: {
1218 SkASSERT(c.fArguments.size() == 1);
1219 this->write(vector_instruction(ByteCodeInstruction::kDup , count));
1220 this->write(vector_instruction(ByteCodeInstruction::kDup , count));
1221 this->write(vector_instruction(ByteCodeInstruction::kMultiplyF, count));
1222 for (int i = count-1; i --> 0;) {
1223 this->write(ByteCodeInstruction::kAddF);
1224 }
1225 this->write(ByteCodeInstruction::kSqrt);
1226 dupSmallerType(1);
1227 this->write(vector_instruction(ByteCodeInstruction::kDivideF, count));
1228 } break;
1229
Brian Osmanb08cc022020-04-02 11:38:40 -04001230 default:
1231 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001232 }
1233 } else {
Brian Osman8842b372020-05-01 15:07:49 -04001234 switch (intrin.inst_f) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001235 case ByteCodeInstruction::kInverse2x2: {
1236 SkASSERT(c.fArguments.size() > 0);
1237 auto op = ByteCodeInstruction::kInverse2x2;
1238 switch (count) {
1239 case 4: break; // float2x2
1240 case 9: op = ByteCodeInstruction::kInverse3x3; break;
1241 case 16: op = ByteCodeInstruction::kInverse4x4; break;
1242 default: SkASSERT(false);
1243 }
1244 this->write(op);
1245 break;
Brian Osman15c98cb2020-02-27 18:36:57 +00001246 }
Mike Klein45be0772020-05-01 09:13:18 -05001247
Brian Osmanb08cc022020-04-02 11:38:40 -04001248 default:
Brian Osman8842b372020-05-01 15:07:49 -04001249 this->writeTypedInstruction(c.fArguments[0]->fType, intrin.inst_s, intrin.inst_u,
1250 intrin.inst_f, count);
1251 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001252 }
1253 }
1254}
1255
Brian Osmanb08cc022020-04-02 11:38:40 -04001256void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001257 // Find the index of the function we're calling. We explicitly do not allow calls to functions
1258 // before they're defined. This is an easy-to-understand rule that prevents recursion.
Brian Osmanb08cc022020-04-02 11:38:40 -04001259 int idx = -1;
1260 for (size_t i = 0; i < fFunctions.size(); ++i) {
1261 if (f.fFunction.matches(fFunctions[i]->fDeclaration)) {
1262 idx = i;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001263 break;
1264 }
1265 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001266 if (idx == -1) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001267 this->writeIntrinsicCall(f);
1268 return;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001269 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001270
1271
1272 if (idx > 255) {
1273 fErrors.error(f.fOffset, "Function count limit exceeded");
1274 return;
1275 } else if (idx >= (int) fFunctions.size()) {
1276 fErrors.error(f.fOffset, "Call to undefined function");
1277 return;
1278 }
1279
1280 // We may need to deal with out parameters, so the sequence is tricky
1281 if (int returnCount = SlotCount(f.fType)) {
1282 this->write(ByteCodeInstruction::kReserve, returnCount);
1283 this->write8(returnCount);
1284 }
1285
1286 int argCount = f.fArguments.size();
1287 std::vector<std::unique_ptr<LValue>> lvalues;
1288 for (int i = 0; i < argCount; ++i) {
1289 const auto& param = f.fFunction.fParameters[i];
1290 const auto& arg = f.fArguments[i];
1291 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1292 lvalues.emplace_back(this->getLValue(*arg));
1293 lvalues.back()->load();
1294 } else {
1295 this->writeExpression(*arg);
1296 }
1297 }
1298
1299 // The space used by the call is based on the callee, but it also unwinds all of that before
1300 // we continue execution. We adjust our max stack depths below.
1301 this->write(ByteCodeInstruction::kCall);
1302 this->write8(idx);
1303
1304 const ByteCodeFunction* callee = fOutput->fFunctions[idx].get();
1305 fMaxLoopCount = std::max(fMaxLoopCount, fLoopCount + callee->fLoopCount);
1306 fMaxConditionCount = std::max(fMaxConditionCount, fConditionCount + callee->fConditionCount);
1307 fMaxStackCount = std::max(fMaxStackCount, fStackCount + callee->fLocalCount
1308 + callee->fStackCount);
1309
1310 // After the called function returns, the stack will still contain our arguments. We have to
1311 // pop them (storing any out parameters back to their lvalues as we go). We glob together slot
1312 // counts for all parameters that aren't out-params, so we can pop them in one big chunk.
1313 int popCount = 0;
1314 auto pop = [&]() {
1315 if (popCount > 4) {
1316 this->write(ByteCodeInstruction::kPopN, popCount);
1317 this->write8(popCount);
1318 } else if (popCount > 0) {
1319 this->write(vector_instruction(ByteCodeInstruction::kPop, popCount));
1320 }
1321 popCount = 0;
1322 };
1323
1324 for (int i = argCount - 1; i >= 0; --i) {
1325 const auto& param = f.fFunction.fParameters[i];
1326 const auto& arg = f.fArguments[i];
1327 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1328 pop();
1329 lvalues.back()->store(true);
1330 lvalues.pop_back();
1331 } else {
1332 popCount += SlotCount(arg->fType);
1333 }
1334 }
1335 pop();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001336}
1337
Brian Osmanb08cc022020-04-02 11:38:40 -04001338void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
1339 this->write(ByteCodeInstruction::kPushImmediate);
1340 this->write32(i.fValue);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001341}
1342
Brian Osmanb08cc022020-04-02 11:38:40 -04001343void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
1344 // not yet implemented
1345 abort();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001346}
1347
Brian Osmanb08cc022020-04-02 11:38:40 -04001348bool ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p, bool discard) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001349 switch (p.fOperator) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001350 case Token::Kind::TK_PLUSPLUS: // fall through
1351 case Token::Kind::TK_MINUSMINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001352 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1353 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
1354 lvalue->load();
1355 this->write(ByteCodeInstruction::kPushImmediate);
1356 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001357 if (p.fOperator == Token::Kind::TK_PLUSPLUS) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001358 this->writeTypedInstruction(p.fType,
1359 ByteCodeInstruction::kAddI,
1360 ByteCodeInstruction::kAddI,
1361 ByteCodeInstruction::kAddF,
1362 1);
1363 } else {
1364 this->writeTypedInstruction(p.fType,
1365 ByteCodeInstruction::kSubtractI,
1366 ByteCodeInstruction::kSubtractI,
1367 ByteCodeInstruction::kSubtractF,
1368 1);
1369 }
1370 lvalue->store(discard);
1371 discard = false;
1372 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001373 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001374 case Token::Kind::TK_MINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001375 this->writeExpression(*p.fOperand);
1376 this->writeTypedInstruction(p.fType,
1377 ByteCodeInstruction::kNegateI,
1378 ByteCodeInstruction::kNegateI,
1379 ByteCodeInstruction::kNegateF,
Brian Osmanab8f3842020-04-07 09:30:44 -04001380 SlotCount(p.fOperand->fType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001381 break;
1382 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001383 case Token::Kind::TK_LOGICALNOT:
1384 case Token::Kind::TK_BITWISENOT: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001385 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1386 SkDEBUGCODE(TypeCategory tc = type_category(p.fOperand->fType));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001387 SkASSERT((p.fOperator == Token::Kind::TK_LOGICALNOT && tc == TypeCategory::kBool) ||
1388 (p.fOperator == Token::Kind::TK_BITWISENOT && (tc == TypeCategory::kSigned ||
Brian Osmanb08cc022020-04-02 11:38:40 -04001389 tc == TypeCategory::kUnsigned)));
1390 this->writeExpression(*p.fOperand);
1391 this->write(ByteCodeInstruction::kNotB);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001392 break;
1393 }
1394 default:
1395 SkASSERT(false);
1396 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001397 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001398}
1399
Brian Osmanb08cc022020-04-02 11:38:40 -04001400bool ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p, bool discard) {
1401 switch (p.fOperator) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001402 case Token::Kind::TK_PLUSPLUS: // fall through
1403 case Token::Kind::TK_MINUSMINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001404 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1405 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
1406 lvalue->load();
1407 // If we're not supposed to discard the result, then make a copy *before* the +/-
1408 if (!discard) {
1409 this->write(ByteCodeInstruction::kDup);
Brian Osmanb08cc022020-04-02 11:38:40 -04001410 }
1411 this->write(ByteCodeInstruction::kPushImmediate);
1412 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001413 if (p.fOperator == Token::Kind::TK_PLUSPLUS) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001414 this->writeTypedInstruction(p.fType,
1415 ByteCodeInstruction::kAddI,
1416 ByteCodeInstruction::kAddI,
1417 ByteCodeInstruction::kAddF,
1418 1);
1419 } else {
1420 this->writeTypedInstruction(p.fType,
1421 ByteCodeInstruction::kSubtractI,
1422 ByteCodeInstruction::kSubtractI,
1423 ByteCodeInstruction::kSubtractF,
1424 1);
1425 }
1426 // Always consume the result as part of the store
1427 lvalue->store(true);
1428 discard = false;
1429 break;
1430 }
1431 default:
1432 SkASSERT(false);
1433 }
1434 return discard;
1435}
1436
1437void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001438 if (swizzle_is_simple(s)) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001439 this->writeVariableExpression(s);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001440 return;
1441 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001442
Brian Osman3711c662020-06-18 14:42:21 -04001443 this->writeExpression(*s.fBase);
1444 this->write(ByteCodeInstruction::kSwizzle, s.fComponents.size() - s.fBase->fType.columns());
1445 this->write8(s.fBase->fType.columns());
1446 this->write8(s.fComponents.size());
1447 for (int c : s.fComponents) {
1448 this->write8(c);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001449 }
1450}
1451
Brian Osmanb08cc022020-04-02 11:38:40 -04001452void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001453 int count = SlotCount(t.fType);
1454 SkASSERT(count == SlotCount(t.fIfTrue->fType));
1455 SkASSERT(count == SlotCount(t.fIfFalse->fType));
1456
Brian Osmanb08cc022020-04-02 11:38:40 -04001457 this->writeExpression(*t.fTest);
1458 this->write(ByteCodeInstruction::kMaskPush);
1459 this->writeExpression(*t.fIfTrue);
1460 this->write(ByteCodeInstruction::kMaskNegate);
1461 this->writeExpression(*t.fIfFalse);
1462 this->write(ByteCodeInstruction::kMaskBlend, count);
1463 this->write8(count);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001464}
1465
Brian Osmanb08cc022020-04-02 11:38:40 -04001466void ByteCodeGenerator::writeExpression(const Expression& e, bool discard) {
1467 switch (e.fKind) {
1468 case Expression::kBinary_Kind:
1469 discard = this->writeBinaryExpression((BinaryExpression&) e, discard);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001470 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001471 case Expression::kBoolLiteral_Kind:
1472 this->writeBoolLiteral((BoolLiteral&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001473 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001474 case Expression::kConstructor_Kind:
1475 this->writeConstructor((Constructor&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001476 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001477 case Expression::kExternalFunctionCall_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001478 this->writeExternalFunctionCall((ExternalFunctionCall&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001479 break;
1480 case Expression::kExternalValue_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001481 this->writeExternalValue((ExternalValueReference&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001482 break;
1483 case Expression::kFieldAccess_Kind:
1484 case Expression::kIndex_Kind:
1485 case Expression::kVariableReference_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001486 this->writeVariableExpression(e);
1487 break;
1488 case Expression::kFloatLiteral_Kind:
1489 this->writeFloatLiteral((FloatLiteral&) e);
1490 break;
1491 case Expression::kFunctionCall_Kind:
1492 this->writeFunctionCall((FunctionCall&) e);
1493 break;
1494 case Expression::kIntLiteral_Kind:
1495 this->writeIntLiteral((IntLiteral&) e);
1496 break;
1497 case Expression::kNullLiteral_Kind:
1498 this->writeNullLiteral((NullLiteral&) e);
1499 break;
1500 case Expression::kPrefix_Kind:
1501 discard = this->writePrefixExpression((PrefixExpression&) e, discard);
1502 break;
1503 case Expression::kPostfix_Kind:
1504 discard = this->writePostfixExpression((PostfixExpression&) e, discard);
1505 break;
1506 case Expression::kSwizzle_Kind:
1507 this->writeSwizzle((Swizzle&) e);
1508 break;
1509 case Expression::kTernary_Kind:
1510 this->writeTernaryExpression((TernaryExpression&) e);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001511 break;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001512 default:
1513#ifdef SK_DEBUG
Brian Osmanb08cc022020-04-02 11:38:40 -04001514 printf("unsupported expression %s\n", e.description().c_str());
Ben Wagner470e0ac2020-01-22 16:59:21 -05001515#endif
Brian Osmanb08cc022020-04-02 11:38:40 -04001516 SkASSERT(false);
1517 }
1518 if (discard) {
1519 int count = SlotCount(e.fType);
1520 if (count > 4) {
1521 this->write(ByteCodeInstruction::kPopN, count);
1522 this->write8(count);
1523 } else if (count != 0) {
1524 this->write(vector_instruction(ByteCodeInstruction::kPop, count));
1525 }
1526 discard = false;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001527 }
Ethan Nicholas7deb1c22020-01-22 10:31:55 -05001528}
1529
Brian Osmanb08cc022020-04-02 11:38:40 -04001530class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
1531public:
1532 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, ExternalValue& value, int index)
1533 : INHERITED(*generator)
1534 , fCount(ByteCodeGenerator::SlotCount(value.type()))
1535 , fIndex(index) {}
1536
1537 void load() override {
1538 fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001539 fGenerator.write8(fIndex);
1540 }
1541
1542 void store(bool discard) override {
1543 if (!discard) {
1544 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001545 }
1546 fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
Brian Osmanb08cc022020-04-02 11:38:40 -04001547 fGenerator.write8(fIndex);
1548 }
1549
1550private:
1551 typedef LValue INHERITED;
1552
1553 int fCount;
1554
1555 int fIndex;
1556};
1557
1558class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
1559public:
1560 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
1561 : INHERITED(*generator)
1562 , fSwizzle(swizzle) {}
1563
1564 void load() override {
1565 fGenerator.writeSwizzle(fSwizzle);
1566 }
1567
1568 void store(bool discard) override {
1569 int count = fSwizzle.fComponents.size();
1570 if (!discard) {
1571 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001572 }
Brian Osman304dfa32020-06-18 15:53:51 -04001573 // We already have the correct number of values on the stack, thanks to type checking.
1574 // The algorithm: Walk down the values on the stack, doing 'count' single-element stores.
1575 // For each value, use the corresponding swizzle component to offset the store location.
1576 //
1577 // Static locations: We (wastefully) call getLocation every time, but get good byte code.
1578 // Note that we could (but don't) store adjacent/sequential values with fewer instructions.
1579 //
1580 // Dynamic locations: ... are bad. We have to recompute the base address on each iteration,
1581 // because the stack doesn't let us retain that address between stores. Dynamic locations
1582 // are rare though, and swizzled writes to those are even rarer, so we just live with this.
1583 for (int i = count; i-- > 0;) {
1584 ByteCodeGenerator::Location location = fGenerator.getLocation(*fSwizzle.fBase);
1585 if (!location.isOnStack()) {
1586 fGenerator.write(location.selectStore(ByteCodeInstruction::kStore,
1587 ByteCodeInstruction::kStoreGlobal));
1588 fGenerator.write8(location.fSlot + fSwizzle.fComponents[i]);
1589 } else {
1590 fGenerator.write(ByteCodeInstruction::kPushImmediate);
1591 fGenerator.write32(fSwizzle.fComponents[i]);
1592 fGenerator.write(ByteCodeInstruction::kAddI);
1593 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreExtended,
1594 ByteCodeInstruction::kStoreExtendedGlobal),
1595 1);
1596 fGenerator.write8(1);
1597 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001598 }
1599 }
1600
1601private:
1602 const Swizzle& fSwizzle;
1603
1604 typedef LValue INHERITED;
1605};
1606
1607class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
1608public:
1609 ByteCodeExpressionLValue(ByteCodeGenerator* generator, const Expression& expr)
1610 : INHERITED(*generator)
1611 , fExpression(expr) {}
1612
1613 void load() override {
1614 fGenerator.writeVariableExpression(fExpression);
1615 }
1616
1617 void store(bool discard) override {
1618 int count = ByteCodeGenerator::SlotCount(fExpression.fType);
1619 if (!discard) {
1620 if (count > 4) {
1621 fGenerator.write(ByteCodeInstruction::kDupN, count);
1622 fGenerator.write8(count);
1623 } else {
1624 fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
Brian Osmanb08cc022020-04-02 11:38:40 -04001625 }
1626 }
1627 ByteCodeGenerator::Location location = fGenerator.getLocation(fExpression);
1628 if (location.isOnStack() || count > 4) {
1629 if (!location.isOnStack()) {
1630 fGenerator.write(ByteCodeInstruction::kPushImmediate);
1631 fGenerator.write32(location.fSlot);
1632 }
1633 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreExtended,
1634 ByteCodeInstruction::kStoreExtendedGlobal),
1635 count);
1636 fGenerator.write8(count);
1637 } else {
1638 fGenerator.write(
1639 vector_instruction(location.selectStore(ByteCodeInstruction::kStore,
1640 ByteCodeInstruction::kStoreGlobal),
1641 count));
1642 fGenerator.write8(location.fSlot);
1643 }
1644 }
1645
1646private:
1647 typedef LValue INHERITED;
1648
1649 const Expression& fExpression;
1650};
1651
1652std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
1653 switch (e.fKind) {
1654 case Expression::kExternalValue_Kind: {
1655 ExternalValue* value = ((ExternalValueReference&) e).fValue;
1656 int index = fOutput->fExternalValues.size();
1657 fOutput->fExternalValues.push_back(value);
1658 SkASSERT(index <= 255);
1659 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
1660 }
1661 case Expression::kFieldAccess_Kind:
1662 case Expression::kIndex_Kind:
1663 case Expression::kVariableReference_Kind:
1664 return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
1665 case Expression::kSwizzle_Kind: {
1666 const Swizzle& s = (const Swizzle&) e;
1667 return swizzle_is_simple(s)
1668 ? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e))
1669 : std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s));
1670 }
1671 case Expression::kTernary_Kind:
1672 default:
1673#ifdef SK_DEBUG
1674 ABORT("unsupported lvalue %s\n", e.description().c_str());
1675#endif
1676 return nullptr;
1677 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001678}
1679
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001680void ByteCodeGenerator::writeBlock(const Block& b) {
1681 for (const auto& s : b.fStatements) {
1682 this->writeStatement(*s);
1683 }
1684}
1685
Brian Osmanb08cc022020-04-02 11:38:40 -04001686void ByteCodeGenerator::setBreakTargets() {
1687 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
1688 for (DeferredLocation& b : breaks) {
1689 b.set();
1690 }
1691 fBreakTargets.pop();
1692}
1693
1694void ByteCodeGenerator::setContinueTargets() {
1695 std::vector<DeferredLocation>& continues = fContinueTargets.top();
1696 for (DeferredLocation& c : continues) {
1697 c.set();
1698 }
1699 fContinueTargets.pop();
1700}
1701
1702void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
1703 // TODO: Include BranchIfAllFalse to top-most LoopNext
1704 this->write(ByteCodeInstruction::kLoopBreak);
1705}
1706
1707void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
1708 // TODO: Include BranchIfAllFalse to top-most LoopNext
1709 this->write(ByteCodeInstruction::kLoopContinue);
1710}
1711
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001712void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001713 this->write(ByteCodeInstruction::kLoopBegin);
1714 size_t start = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001715 this->writeStatement(*d.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001716 this->write(ByteCodeInstruction::kLoopNext);
1717 this->writeExpression(*d.fTest);
1718 this->write(ByteCodeInstruction::kLoopMask);
1719 // TODO: Could shorten this with kBranchIfAnyTrue
1720 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001721 DeferredLocation endLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -04001722 this->write(ByteCodeInstruction::kBranch);
1723 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001724 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001725 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001726}
1727
1728void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001729 fContinueTargets.emplace();
1730 fBreakTargets.emplace();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001731 if (f.fInitializer) {
1732 this->writeStatement(*f.fInitializer);
1733 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001734 this->write(ByteCodeInstruction::kLoopBegin);
1735 size_t start = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001736 if (f.fTest) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001737 this->writeExpression(*f.fTest);
1738 this->write(ByteCodeInstruction::kLoopMask);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001739 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001740 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001741 DeferredLocation endLocation(this);
1742 this->writeStatement(*f.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001743 this->write(ByteCodeInstruction::kLoopNext);
Brian Osman569f12f2019-06-13 11:23:57 -04001744 if (f.fNext) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001745 this->writeExpression(*f.fNext, true);
Brian Osman569f12f2019-06-13 11:23:57 -04001746 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001747 this->write(ByteCodeInstruction::kBranch);
1748 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001749 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001750 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001751}
1752
1753void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001754 this->writeExpression(*i.fTest);
1755 this->write(ByteCodeInstruction::kMaskPush);
1756 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001757 DeferredLocation falseLocation(this);
1758 this->writeStatement(*i.fIfTrue);
1759 falseLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001760 if (i.fIfFalse) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001761 this->write(ByteCodeInstruction::kMaskNegate);
1762 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001763 DeferredLocation endLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001764 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -05001765 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001766 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001767 this->write(ByteCodeInstruction::kMaskPop);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001768}
1769
Brian Osmanb08cc022020-04-02 11:38:40 -04001770void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
1771 if (fLoopCount || fConditionCount) {
Brian Osman4a47da72019-07-12 11:30:32 -04001772 fErrors.error(r.fOffset, "return not allowed inside conditional or loop");
1773 return;
1774 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001775 int count = SlotCount(r.fExpression->fType);
1776 this->writeExpression(*r.fExpression);
1777
1778 // Technically, the kReturn also pops fOutput->fLocalCount values from the stack, too, but we
1779 // haven't counted pushing those (they're outside the scope of our stack tracking). Instead,
1780 // we account for those in writeFunction().
1781
1782 // This is all fine because we don't allow conditional returns, so we only return once anyway.
1783 this->write(ByteCodeInstruction::kReturn, -count);
1784 this->write8(count);
1785}
1786
1787void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
1788 // not yet implemented
1789 abort();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001790}
1791
1792void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1793 for (const auto& declStatement : v.fVars) {
1794 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
Brian Osmanb08cc022020-04-02 11:38:40 -04001795 // we need to grab the location even if we don't use it, to ensure it has been allocated
1796 Location location = this->getLocation(*decl.fVar);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001797 if (decl.fValue) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001798 this->writeExpression(*decl.fValue);
1799 int count = SlotCount(decl.fValue->fType);
1800 if (count > 4) {
1801 this->write(ByteCodeInstruction::kPushImmediate);
1802 this->write32(location.fSlot);
1803 this->write(ByteCodeInstruction::kStoreExtended, count);
1804 this->write8(count);
1805 } else {
1806 this->write(vector_instruction(ByteCodeInstruction::kStore, count));
1807 this->write8(location.fSlot);
1808 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001809 }
1810 }
1811}
1812
1813void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001814 this->write(ByteCodeInstruction::kLoopBegin);
1815 size_t cond = fCode->size();
1816 this->writeExpression(*w.fTest);
1817 this->write(ByteCodeInstruction::kLoopMask);
1818 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001819 DeferredLocation endLocation(this);
1820 this->writeStatement(*w.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001821 this->write(ByteCodeInstruction::kLoopNext);
1822 this->write(ByteCodeInstruction::kBranch);
1823 this->write16(cond);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001824 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001825 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001826}
1827
1828void ByteCodeGenerator::writeStatement(const Statement& s) {
1829 switch (s.fKind) {
1830 case Statement::kBlock_Kind:
1831 this->writeBlock((Block&) s);
1832 break;
1833 case Statement::kBreak_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001834 this->writeBreakStatement((BreakStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001835 break;
1836 case Statement::kContinue_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001837 this->writeContinueStatement((ContinueStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001838 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001839 case Statement::kDiscard_Kind:
1840 // not yet implemented
1841 abort();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001842 case Statement::kDo_Kind:
1843 this->writeDoStatement((DoStatement&) s);
1844 break;
Brian Osman3e29f1d2019-05-28 09:35:05 -04001845 case Statement::kExpression_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001846 this->writeExpression(*((ExpressionStatement&) s).fExpression, true);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001847 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001848 case Statement::kFor_Kind:
1849 this->writeForStatement((ForStatement&) s);
1850 break;
1851 case Statement::kIf_Kind:
1852 this->writeIfStatement((IfStatement&) s);
1853 break;
1854 case Statement::kNop_Kind:
1855 break;
1856 case Statement::kReturn_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001857 this->writeReturnStatement((ReturnStatement&) s);
1858 break;
1859 case Statement::kSwitch_Kind:
1860 this->writeSwitchStatement((SwitchStatement&) s);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001861 break;
1862 case Statement::kVarDeclarations_Kind:
1863 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
1864 break;
1865 case Statement::kWhile_Kind:
1866 this->writeWhileStatement((WhileStatement&) s);
1867 break;
1868 default:
Brian Osmanb08cc022020-04-02 11:38:40 -04001869 SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001870 }
1871}
1872
Brian Osmanb08cc022020-04-02 11:38:40 -04001873ByteCodeFunction::ByteCodeFunction(const FunctionDeclaration* declaration)
1874 : fName(declaration->fName) {
Brian Osman80164412019-06-07 13:00:23 -04001875 fParameterCount = 0;
Brian Osmanb08cc022020-04-02 11:38:40 -04001876 for (const auto& p : declaration->fParameters) {
1877 int slots = ByteCodeGenerator::SlotCount(p->fType);
1878 fParameters.push_back({ slots, (bool)(p->fModifiers.fFlags & Modifiers::kOut_Flag) });
1879 fParameterCount += slots;
Brian Osman80164412019-06-07 13:00:23 -04001880 }
1881}
1882
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001883}