blob: 86c874ebe83264948ba9a8bbdea1a53705c6508b [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: {
John Stiles3dc0da62020-08-19 17:48:31 -0400145 std::unique_ptr<ByteCodeFunction> f =
146 this->writeFunction(e.as<FunctionDefinition>());
Brian Osmanb08cc022020-04-02 11:38:40 -0400147 if (!f) {
148 return false;
149 }
150 fOutput->fFunctions.push_back(std::move(f));
John Stiles3dc0da62020-08-19 17:48:31 -0400151 fFunctions.push_back(&e.as<FunctionDefinition>());
Brian Osmanb08cc022020-04-02 11:38:40 -0400152 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500153 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400154 case ProgramElement::kVar_Kind: {
John Stiles3dc0da62020-08-19 17:48:31 -0400155 const VarDeclarations& decl = e.as<VarDeclarations>();
Brian Osmanb08cc022020-04-02 11:38:40 -0400156 for (const auto& v : decl.fVars) {
John Stiles3dc0da62020-08-19 17:48:31 -0400157 const Variable* declVar = v->as<VarDeclaration>().fVar;
Brian Osmana43d8202020-06-17 16:50:39 -0400158 if (declVar->fType == *fContext.fFragmentProcessor_Type) {
159 fOutput->fChildFPCount++;
160 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400161 if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
162 continue;
163 }
164 if (is_uniform(*declVar)) {
165 this->gatherUniforms(declVar->fType, declVar->fName);
166 } else {
167 fOutput->fGlobalSlotCount += SlotCount(declVar->fType);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400168 }
169 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400170 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400171 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400172 default:
173 ; // ignore
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400174 }
175 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400176 return 0 == fErrors.errorCount();
177}
178
179std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
180 fFunction = &f;
181 std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
182 fParameterCount = result->fParameterCount;
183 fLoopCount = fMaxLoopCount = 0;
184 fConditionCount = fMaxConditionCount = 0;
185 fStackCount = fMaxStackCount = 0;
186 fCode = &result->fCode;
187
188 this->writeStatement(*f.fBody);
189 if (0 == fErrors.errorCount()) {
190 SkASSERT(fLoopCount == 0);
191 SkASSERT(fConditionCount == 0);
192 SkASSERT(fStackCount == 0);
193 }
194 this->write(ByteCodeInstruction::kReturn, 0);
Brian Osmanb08cc022020-04-02 11:38:40 -0400195
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 Osman5aaaeea2020-06-22 14:26:03 -0400210// If the expression is a reference to a builtin global variable, return the builtin ID.
211// Otherwise, return -1.
212static int expression_as_builtin(const Expression& e) {
213 if (e.fKind == Expression::kVariableReference_Kind) {
214 const Variable& var(((VariableReference&)e).fVariable);
215 if (var.fStorage == Variable::kGlobal_Storage) {
216 return var.fModifiers.fLayout.fBuiltin;
217 }
218 }
219 return -1;
220}
221
Brian Osman0785db02019-05-24 14:19:11 -0400222// A "simple" Swizzle is based on a variable (or a compound variable like a struct or array), and
223// that references consecutive values, such that it can be implemented using normal load/store ops
224// with an offset. Note that all single-component swizzles (of suitable base types) are simple.
225static bool swizzle_is_simple(const Swizzle& s) {
Brian Osman5aaaeea2020-06-22 14:26:03 -0400226 // Builtin variables use dedicated instructions that don't allow subset loads
227 if (expression_as_builtin(*s.fBase) >= 0) {
228 return false;
229 }
230
Brian Osman0785db02019-05-24 14:19:11 -0400231 switch (s.fBase->fKind) {
232 case Expression::kFieldAccess_Kind:
233 case Expression::kIndex_Kind:
234 case Expression::kVariableReference_Kind:
235 break;
236 default:
237 return false;
238 }
239
240 for (size_t i = 1; i < s.fComponents.size(); ++i) {
241 if (s.fComponents[i] != s.fComponents[i - 1] + 1) {
242 return false;
243 }
244 }
245 return true;
246}
247
Brian Osmanb08cc022020-04-02 11:38:40 -0400248int ByteCodeGenerator::StackUsage(ByteCodeInstruction inst, int count_) {
249 // Ensures that we use count iff we're passed a non-default value. Most instructions have an
250 // implicit count, so the caller shouldn't need to worry about it (or count makes no sense).
251 // The asserts avoids callers thinking they're supplying useful information in that scenario,
252 // or failing to supply necessary information for the ops that need a count.
253 struct CountValue {
254 operator int() {
255 SkASSERT(val != ByteCodeGenerator::kUnusedStackCount);
256 SkDEBUGCODE(used = true);
257 return val;
258 }
259 ~CountValue() {
260 SkASSERT(used || val == ByteCodeGenerator::kUnusedStackCount);
261 }
262 int val;
263 SkDEBUGCODE(bool used = false;)
264 } count = { count_ };
265
266 switch (inst) {
267 // Unary functions/operators that don't change stack depth at all:
Brian Osmanb08cc022020-04-02 11:38:40 -0400268
Brian Osman49b30f42020-06-26 17:22:27 -0400269#define VEC_UNARY(inst) case ByteCodeInstruction::inst: return count - count;
Brian Osmanb08cc022020-04-02 11:38:40 -0400270
Brian Osman49b30f42020-06-26 17:22:27 -0400271 VEC_UNARY(kConvertFtoI)
272 VEC_UNARY(kConvertStoF)
273 VEC_UNARY(kConvertUtoF)
Brian Osmanb08cc022020-04-02 11:38:40 -0400274
Brian Osman49b30f42020-06-26 17:22:27 -0400275 VEC_UNARY(kATan)
276 VEC_UNARY(kCeil)
277 VEC_UNARY(kCos)
278 VEC_UNARY(kFloor)
279 VEC_UNARY(kFract)
280 VEC_UNARY(kSin)
281 VEC_UNARY(kSqrt)
282 VEC_UNARY(kTan)
283
284 VEC_UNARY(kNegateF)
285 VEC_UNARY(kNegateI)
286 VEC_UNARY(kNotB)
287
288#undef VEC_UNARY
Brian Osmanb08cc022020-04-02 11:38:40 -0400289
290 case ByteCodeInstruction::kInverse2x2:
291 case ByteCodeInstruction::kInverse3x3:
292 case ByteCodeInstruction::kInverse4x4: return 0;
293
Brian Osman49b30f42020-06-26 17:22:27 -0400294 case ByteCodeInstruction::kClampIndex: return 0;
295 case ByteCodeInstruction::kShiftLeft: return 0;
Brian Osmanb08cc022020-04-02 11:38:40 -0400296 case ByteCodeInstruction::kShiftRightS: return 0;
297 case ByteCodeInstruction::kShiftRightU: return 0;
298
Brian Osman49b30f42020-06-26 17:22:27 -0400299 // Binary functions/operators that do a 2 -> 1 reduction, N times
300 case ByteCodeInstruction::kAndB: return -count;
301 case ByteCodeInstruction::kOrB: return -count;
302 case ByteCodeInstruction::kXorB: return -count;
Brian Osmanb08cc022020-04-02 11:38:40 -0400303
Brian Osman49b30f42020-06-26 17:22:27 -0400304 case ByteCodeInstruction::kAddI: return -count;
305 case ByteCodeInstruction::kAddF: return -count;
Brian Osmanb08cc022020-04-02 11:38:40 -0400306
Brian Osman49b30f42020-06-26 17:22:27 -0400307 case ByteCodeInstruction::kCompareIEQ: return -count;
308 case ByteCodeInstruction::kCompareFEQ: return -count;
309 case ByteCodeInstruction::kCompareINEQ: return -count;
310 case ByteCodeInstruction::kCompareFNEQ: return -count;
311 case ByteCodeInstruction::kCompareSGT: return -count;
312 case ByteCodeInstruction::kCompareUGT: return -count;
313 case ByteCodeInstruction::kCompareFGT: return -count;
314 case ByteCodeInstruction::kCompareSGTEQ: return -count;
315 case ByteCodeInstruction::kCompareUGTEQ: return -count;
316 case ByteCodeInstruction::kCompareFGTEQ: return -count;
317 case ByteCodeInstruction::kCompareSLT: return -count;
318 case ByteCodeInstruction::kCompareULT: return -count;
319 case ByteCodeInstruction::kCompareFLT: return -count;
320 case ByteCodeInstruction::kCompareSLTEQ: return -count;
321 case ByteCodeInstruction::kCompareULTEQ: return -count;
322 case ByteCodeInstruction::kCompareFLTEQ: return -count;
Brian Osmanb08cc022020-04-02 11:38:40 -0400323
Brian Osman49b30f42020-06-26 17:22:27 -0400324 case ByteCodeInstruction::kDivideS: return -count;
325 case ByteCodeInstruction::kDivideU: return -count;
326 case ByteCodeInstruction::kDivideF: return -count;
327 case ByteCodeInstruction::kMaxF: return -count;
328 case ByteCodeInstruction::kMaxS: return -count;
329 case ByteCodeInstruction::kMinF: return -count;
330 case ByteCodeInstruction::kMinS: return -count;
331 case ByteCodeInstruction::kMultiplyI: return -count;
332 case ByteCodeInstruction::kMultiplyF: return -count;
333 case ByteCodeInstruction::kPow: return -count;
334 case ByteCodeInstruction::kRemainderF: return -count;
335 case ByteCodeInstruction::kRemainderS: return -count;
336 case ByteCodeInstruction::kRemainderU: return -count;
337 case ByteCodeInstruction::kSubtractI: return -count;
338 case ByteCodeInstruction::kSubtractF: return -count;
Brian Osmanb08cc022020-04-02 11:38:40 -0400339
340 // Ops that push or load data to grow the stack:
Brian Osman49b30f42020-06-26 17:22:27 -0400341 case ByteCodeInstruction::kPushImmediate:
342 return 1;
343 case ByteCodeInstruction::kLoadFragCoord:
344 return 4;
345
Brian Osmanb08cc022020-04-02 11:38:40 -0400346 case ByteCodeInstruction::kDup:
347 case ByteCodeInstruction::kLoad:
348 case ByteCodeInstruction::kLoadGlobal:
349 case ByteCodeInstruction::kLoadUniform:
350 case ByteCodeInstruction::kReadExternal:
Brian Osman49b30f42020-06-26 17:22:27 -0400351 case ByteCodeInstruction::kReserve:
Brian Osmanb08cc022020-04-02 11:38:40 -0400352 return count;
353
354 // Pushes 'count' values, minus one for the 'address' that's consumed first
355 case ByteCodeInstruction::kLoadExtended:
356 case ByteCodeInstruction::kLoadExtendedGlobal:
357 case ByteCodeInstruction::kLoadExtendedUniform:
358 return count - 1;
359
360 // Ops that pop or store data to shrink the stack:
361 case ByteCodeInstruction::kPop:
Brian Osman49b30f42020-06-26 17:22:27 -0400362 case ByteCodeInstruction::kReturn:
Brian Osmanb08cc022020-04-02 11:38:40 -0400363 case ByteCodeInstruction::kStore:
364 case ByteCodeInstruction::kStoreGlobal:
365 case ByteCodeInstruction::kWriteExternal:
Brian Osmanb08cc022020-04-02 11:38:40 -0400366 return -count;
367
368 // Consumes 'count' values, plus one for the 'address'
369 case ByteCodeInstruction::kStoreExtended:
370 case ByteCodeInstruction::kStoreExtendedGlobal:
Brian Osmanb08cc022020-04-02 11:38:40 -0400371 return -count - 1;
372
373 // Strange ops where the caller computes the delta for us:
374 case ByteCodeInstruction::kCallExternal:
375 case ByteCodeInstruction::kMatrixToMatrix:
376 case ByteCodeInstruction::kMatrixMultiply:
Brian Osmanb08cc022020-04-02 11:38:40 -0400377 case ByteCodeInstruction::kScalarToMatrix:
378 case ByteCodeInstruction::kSwizzle:
379 return count;
380
381 // Miscellaneous
382
Brian Osman795efd22020-07-01 13:18:36 -0400383 // () -> (R, G, B, A)
384 case ByteCodeInstruction::kSample: return 4;
Brian Osmana43d8202020-06-17 16:50:39 -0400385 // (X, Y) -> (R, G, B, A)
386 case ByteCodeInstruction::kSampleExplicit: return 4 - 2;
387 // (float3x3) -> (R, G, B, A)
388 case ByteCodeInstruction::kSampleMatrix: return 4 - 9;
389
Brian Osman8842b372020-05-01 15:07:49 -0400390 // kMix does a 3 -> 1 reduction (A, B, M -> A -or- B) for each component
Brian Osman49b30f42020-06-26 17:22:27 -0400391 case ByteCodeInstruction::kMix: return -(2 * count);
Brian Osman8842b372020-05-01 15:07:49 -0400392
393 // kLerp works the same way (producing lerp(A, B, T) for each component)
Brian Osman49b30f42020-06-26 17:22:27 -0400394 case ByteCodeInstruction::kLerp: return -(2 * count);
Brian Osman8842b372020-05-01 15:07:49 -0400395
Brian Osmanb08cc022020-04-02 11:38:40 -0400396 // kCall is net-zero. Max stack depth is adjusted in writeFunctionCall.
397 case ByteCodeInstruction::kCall: return 0;
398 case ByteCodeInstruction::kBranch: return 0;
399 case ByteCodeInstruction::kBranchIfAllFalse: return 0;
400
401 case ByteCodeInstruction::kMaskPush: return -1;
402 case ByteCodeInstruction::kMaskPop: return 0;
403 case ByteCodeInstruction::kMaskNegate: return 0;
404 case ByteCodeInstruction::kMaskBlend: return -count;
405
406 case ByteCodeInstruction::kLoopBegin: return 0;
407 case ByteCodeInstruction::kLoopNext: return 0;
408 case ByteCodeInstruction::kLoopMask: return -1;
409 case ByteCodeInstruction::kLoopEnd: return 0;
410 case ByteCodeInstruction::kLoopBreak: return 0;
411 case ByteCodeInstruction::kLoopContinue: return 0;
Brian Osmanb08cc022020-04-02 11:38:40 -0400412 }
Brian Osmand5f937b2020-05-04 12:07:29 -0400413
414 SkUNREACHABLE;
Brian Osmanb08cc022020-04-02 11:38:40 -0400415}
416
417ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var) {
418 // given that we seldom have more than a couple of variables, linear search is probably the most
419 // efficient way to handle lookups
420 switch (var.fStorage) {
421 case Variable::kLocal_Storage: {
422 for (int i = fLocals.size() - 1; i >= 0; --i) {
423 if (fLocals[i] == &var) {
424 SkASSERT(fParameterCount + i <= 255);
425 return { fParameterCount + i, Storage::kLocal };
426 }
427 }
428 int result = fParameterCount + fLocals.size();
429 fLocals.push_back(&var);
430 for (int i = 0; i < SlotCount(var.fType) - 1; ++i) {
431 fLocals.push_back(nullptr);
432 }
433 SkASSERT(result <= 255);
434 return { result, Storage::kLocal };
435 }
436 case Variable::kParameter_Storage: {
437 int offset = 0;
438 for (const auto& p : fFunction->fDeclaration.fParameters) {
439 if (p == &var) {
440 SkASSERT(offset <= 255);
441 return { offset, Storage::kLocal };
442 }
443 offset += SlotCount(p->fType);
444 }
445 SkASSERT(false);
446 return Location::MakeInvalid();
447 }
448 case Variable::kGlobal_Storage: {
Brian Osmana43d8202020-06-17 16:50:39 -0400449 if (var.fType == *fContext.fFragmentProcessor_Type) {
450 int offset = 0;
451 for (const auto& e : fProgram) {
452 if (e.fKind == ProgramElement::kVar_Kind) {
453 VarDeclarations& decl = (VarDeclarations&) e;
454 for (const auto& v : decl.fVars) {
455 const Variable* declVar = ((VarDeclaration&) *v).fVar;
456 if (declVar->fType != *fContext.fFragmentProcessor_Type) {
457 continue;
458 }
459 if (declVar == &var) {
460 SkASSERT(offset <= 255);
461 return { offset, Storage::kChildFP };
462 }
463 offset++;
464 }
465 }
466 }
467 SkASSERT(false);
468 return Location::MakeInvalid();
469 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400470 if (is_in(var)) {
471 // If you see this error, it means the program is using raw 'in' variables. You
472 // should either specialize the program (Compiler::specialize) to bake in the final
473 // values of the 'in' variables, or not use 'in' variables (maybe you meant to use
474 // 'uniform' instead?).
475 fErrors.error(var.fOffset,
476 "'in' variable is not specialized or has unsupported type");
477 return Location::MakeInvalid();
478 }
479 int offset = 0;
480 bool isUniform = is_uniform(var);
481 for (const auto& e : fProgram) {
482 if (e.fKind == ProgramElement::kVar_Kind) {
483 VarDeclarations& decl = (VarDeclarations&) e;
484 for (const auto& v : decl.fVars) {
485 const Variable* declVar = ((VarDeclaration&) *v).fVar;
486 if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
487 continue;
488 }
489 if (isUniform != is_uniform(*declVar)) {
490 continue;
491 }
492 if (declVar == &var) {
493 SkASSERT(offset <= 255);
494 return { offset, isUniform ? Storage::kUniform : Storage::kGlobal };
495 }
496 offset += SlotCount(declVar->fType);
497 }
498 }
499 }
500 SkASSERT(false);
501 return Location::MakeInvalid();
502 }
503 default:
504 SkASSERT(false);
505 return Location::MakeInvalid();
506 }
507}
508
Brian Osman1c110a02019-10-01 14:53:32 -0400509ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Expression& expr) {
Brian Osman07c117b2019-05-23 12:51:06 -0700510 switch (expr.fKind) {
511 case Expression::kFieldAccess_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400512 const FieldAccess& f = (const FieldAccess&)expr;
513 Location baseLoc = this->getLocation(*f.fBase);
Brian Osman07c117b2019-05-23 12:51:06 -0700514 int offset = 0;
515 for (int i = 0; i < f.fFieldIndex; ++i) {
516 offset += SlotCount(*f.fBase->fType.fields()[i].fType);
517 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400518 if (baseLoc.isOnStack()) {
519 if (offset != 0) {
520 this->write(ByteCodeInstruction::kPushImmediate);
521 this->write32(offset);
Brian Osman49b30f42020-06-26 17:22:27 -0400522 this->write(ByteCodeInstruction::kAddI, 1);
Ben Wagner470e0ac2020-01-22 16:59:21 -0500523 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400524 return baseLoc;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500525 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400526 return baseLoc + offset;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500527 }
Ben Wagner470e0ac2020-01-22 16:59:21 -0500528 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400529 case Expression::kIndex_Kind: {
530 const IndexExpression& i = (const IndexExpression&)expr;
531 int stride = SlotCount(i.fType);
532 int length = i.fBase->fType.columns();
533 SkASSERT(length <= 255);
534 int offset = -1;
Brian Osmanb6b95732020-06-30 11:44:27 -0400535 if (i.fIndex->isCompileTimeConstant()) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400536 int64_t index = i.fIndex->getConstantInt();
537 if (index < 0 || index >= length) {
538 fErrors.error(i.fIndex->fOffset, "Array index out of bounds.");
539 return Location::MakeInvalid();
540 }
541 offset = index * stride;
542 } else {
543 if (i.fIndex->hasSideEffects()) {
544 // Having a side-effect in an indexer is technically safe for an rvalue,
545 // but with lvalues we have to evaluate the indexer twice, so make it an error.
546 fErrors.error(i.fIndex->fOffset,
547 "Index expressions with side-effects not supported in byte code.");
548 return Location::MakeInvalid();
549 }
550 this->writeExpression(*i.fIndex);
551 this->write(ByteCodeInstruction::kClampIndex);
552 this->write8(length);
553 if (stride != 1) {
554 this->write(ByteCodeInstruction::kPushImmediate);
555 this->write32(stride);
Brian Osman49b30f42020-06-26 17:22:27 -0400556 this->write(ByteCodeInstruction::kMultiplyI, 1);
Brian Osmanb08cc022020-04-02 11:38:40 -0400557 }
558 }
559 Location baseLoc = this->getLocation(*i.fBase);
560
561 // Are both components known statically?
562 if (!baseLoc.isOnStack() && offset >= 0) {
563 return baseLoc + offset;
564 }
565
566 // At least one component is dynamic (and on the stack).
567
568 // If the other component is zero, we're done
569 if (baseLoc.fSlot == 0 || offset == 0) {
570 return baseLoc.makeOnStack();
571 }
572
573 // Push the non-dynamic component (if any) to the stack, then add the two
574 if (!baseLoc.isOnStack()) {
575 this->write(ByteCodeInstruction::kPushImmediate);
576 this->write32(baseLoc.fSlot);
577 }
578 if (offset >= 0) {
579 this->write(ByteCodeInstruction::kPushImmediate);
580 this->write32(offset);
581 }
Brian Osman49b30f42020-06-26 17:22:27 -0400582 this->write(ByteCodeInstruction::kAddI, 1);
Brian Osmanb08cc022020-04-02 11:38:40 -0400583 return baseLoc.makeOnStack();
584 }
Brian Osman0785db02019-05-24 14:19:11 -0400585 case Expression::kSwizzle_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400586 const Swizzle& s = (const Swizzle&)expr;
Brian Osman0785db02019-05-24 14:19:11 -0400587 SkASSERT(swizzle_is_simple(s));
Brian Osmanb08cc022020-04-02 11:38:40 -0400588 Location baseLoc = this->getLocation(*s.fBase);
589 int offset = s.fComponents[0];
590 if (baseLoc.isOnStack()) {
591 if (offset != 0) {
592 this->write(ByteCodeInstruction::kPushImmediate);
593 this->write32(offset);
Brian Osman49b30f42020-06-26 17:22:27 -0400594 this->write(ByteCodeInstruction::kAddI, 1);
Brian Osmanb08cc022020-04-02 11:38:40 -0400595 }
596 return baseLoc;
597 } else {
598 return baseLoc + offset;
599 }
Brian Osman0785db02019-05-24 14:19:11 -0400600 }
Brian Osman07c117b2019-05-23 12:51:06 -0700601 case Expression::kVariableReference_Kind: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400602 const Variable& var = ((const VariableReference&)expr).fVariable;
Brian Osman07c117b2019-05-23 12:51:06 -0700603 return this->getLocation(var);
604 }
605 default:
606 SkASSERT(false);
Brian Osmanb08cc022020-04-02 11:38:40 -0400607 return Location::MakeInvalid();
Brian Osman07c117b2019-05-23 12:51:06 -0700608 }
609}
610
Brian Osmanb08cc022020-04-02 11:38:40 -0400611void ByteCodeGenerator::write8(uint8_t b) {
612 fCode->push_back(b);
Ethan Nicholas2cde3a12020-01-21 09:23:13 -0500613}
614
Brian Osmanb08cc022020-04-02 11:38:40 -0400615void ByteCodeGenerator::write16(uint16_t i) {
616 size_t n = fCode->size();
617 fCode->resize(n+2);
618 memcpy(fCode->data() + n, &i, 2);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500619}
Ben Wagner470e0ac2020-01-22 16:59:21 -0500620
Brian Osmanb08cc022020-04-02 11:38:40 -0400621void ByteCodeGenerator::write32(uint32_t i) {
622 size_t n = fCode->size();
623 fCode->resize(n+4);
624 memcpy(fCode->data() + n, &i, 4);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500625}
626
Brian Osmanb08cc022020-04-02 11:38:40 -0400627void ByteCodeGenerator::write(ByteCodeInstruction i, int count) {
628 switch (i) {
629 case ByteCodeInstruction::kLoopBegin: this->enterLoop(); break;
630 case ByteCodeInstruction::kLoopEnd: this->exitLoop(); break;
Ethan Nicholas2329da02020-01-24 15:49:33 -0500631
Brian Osmanb08cc022020-04-02 11:38:40 -0400632 case ByteCodeInstruction::kMaskPush: this->enterCondition(); break;
633 case ByteCodeInstruction::kMaskPop:
634 case ByteCodeInstruction::kMaskBlend: this->exitCondition(); break;
635 default: /* Do nothing */ break;
Ben Wagner470e0ac2020-01-22 16:59:21 -0500636 }
Mike Klein01d01612020-08-14 10:52:11 -0500637 this->write8((uint8_t)i);
Brian Osmanb08cc022020-04-02 11:38:40 -0400638 fStackCount += StackUsage(i, count);
639 fMaxStackCount = std::max(fMaxStackCount, fStackCount);
Brian Osman49b30f42020-06-26 17:22:27 -0400640
641 // Most ops have an explicit count byte after them (passed here as 'count')
642 // Ops that don't have a count byte pass the default (kUnusedStackCount)
643 // There are a handful of strange ops that pass in a computed stack delta as count, but where
644 // that value should *not* be written as a count byte (it may even be negative!)
645 if (count != kUnusedStackCount) {
646 switch (i) {
647 // Odd instructions that have a non-default count, but we shouldn't write it
648 case ByteCodeInstruction::kCallExternal:
649 case ByteCodeInstruction::kMatrixToMatrix:
650 case ByteCodeInstruction::kMatrixMultiply:
651 case ByteCodeInstruction::kScalarToMatrix:
652 case ByteCodeInstruction::kSwizzle:
653 break;
654 default:
655 this->write8(count);
656 break;
657 }
658 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500659}
660
Brian Osman49b30f42020-06-26 17:22:27 -0400661void ByteCodeGenerator::writeTypedInstruction(const Type& type,
662 ByteCodeInstruction s,
663 ByteCodeInstruction u,
664 ByteCodeInstruction f,
Brian Osmanab8f3842020-04-07 09:30:44 -0400665 int count) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500666 switch (type_category(type)) {
Brian Osman8842b372020-05-01 15:07:49 -0400667 case TypeCategory::kBool:
Brian Osman49b30f42020-06-26 17:22:27 -0400668 case TypeCategory::kSigned: this->write(s, count); break;
669 case TypeCategory::kUnsigned: this->write(u, count); break;
670 case TypeCategory::kFloat: this->write(f, count); break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500671 default:
672 SkASSERT(false);
673 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500674}
675
Brian Osmanb08cc022020-04-02 11:38:40 -0400676bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool discard) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400677 if (b.fOperator == Token::Kind::TK_EQ) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500678 std::unique_ptr<LValue> lvalue = this->getLValue(*b.fLeft);
Brian Osmanb08cc022020-04-02 11:38:40 -0400679 this->writeExpression(*b.fRight);
680 lvalue->store(discard);
681 discard = false;
682 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500683 }
684 const Type& lType = b.fLeft->fType;
685 const Type& rType = b.fRight->fType;
686 bool lVecOrMtx = (lType.kind() == Type::kVector_Kind || lType.kind() == Type::kMatrix_Kind);
687 bool rVecOrMtx = (rType.kind() == Type::kVector_Kind || rType.kind() == Type::kMatrix_Kind);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500688 Token::Kind op;
689 std::unique_ptr<LValue> lvalue;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500690 if (is_assignment(b.fOperator)) {
691 lvalue = this->getLValue(*b.fLeft);
Brian Osmanb08cc022020-04-02 11:38:40 -0400692 lvalue->load();
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500693 op = remove_assignment(b.fOperator);
694 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400695 this->writeExpression(*b.fLeft);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500696 op = b.fOperator;
697 if (!lVecOrMtx && rVecOrMtx) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400698 for (int i = SlotCount(rType); i > 1; --i) {
Brian Osman49b30f42020-06-26 17:22:27 -0400699 this->write(ByteCodeInstruction::kDup, 1);
Brian Osmanb08cc022020-04-02 11:38:40 -0400700 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500701 }
702 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500703 int count = std::max(SlotCount(lType), SlotCount(rType));
Brian Osmanb08cc022020-04-02 11:38:40 -0400704 SkDEBUGCODE(TypeCategory tc = type_category(lType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500705 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400706 case Token::Kind::TK_LOGICALAND: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400707 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
Brian Osman49b30f42020-06-26 17:22:27 -0400708 this->write(ByteCodeInstruction::kDup, 1);
Brian Osmanb08cc022020-04-02 11:38:40 -0400709 this->write(ByteCodeInstruction::kMaskPush);
710 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500711 DeferredLocation falseLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -0400712 this->writeExpression(*b.fRight);
Brian Osman49b30f42020-06-26 17:22:27 -0400713 this->write(ByteCodeInstruction::kAndB, 1);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500714 falseLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -0400715 this->write(ByteCodeInstruction::kMaskPop);
716 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500717 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400718 case Token::Kind::TK_LOGICALOR: {
Brian Osmanb08cc022020-04-02 11:38:40 -0400719 SkASSERT(tc == SkSL::TypeCategory::kBool && count == 1);
Brian Osman49b30f42020-06-26 17:22:27 -0400720 this->write(ByteCodeInstruction::kDup, 1);
721 this->write(ByteCodeInstruction::kNotB, 1);
Brian Osmanb08cc022020-04-02 11:38:40 -0400722 this->write(ByteCodeInstruction::kMaskPush);
723 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500724 DeferredLocation falseLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -0400725 this->writeExpression(*b.fRight);
Brian Osman49b30f42020-06-26 17:22:27 -0400726 this->write(ByteCodeInstruction::kOrB, 1);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500727 falseLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -0400728 this->write(ByteCodeInstruction::kMaskPop);
729 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500730 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400731 case Token::Kind::TK_SHL:
732 case Token::Kind::TK_SHR: {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500733 SkASSERT(count == 1 && (tc == SkSL::TypeCategory::kSigned ||
734 tc == SkSL::TypeCategory::kUnsigned));
Brian Osmanb6b95732020-06-30 11:44:27 -0400735 if (!b.fRight->isCompileTimeConstant()) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500736 fErrors.error(b.fRight->fOffset, "Shift amounts must be constant");
Brian Osmanb08cc022020-04-02 11:38:40 -0400737 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500738 }
739 int64_t shift = b.fRight->getConstantInt();
740 if (shift < 0 || shift > 31) {
741 fErrors.error(b.fRight->fOffset, "Shift amount out of range");
Brian Osmanb08cc022020-04-02 11:38:40 -0400742 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500743 }
744
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400745 if (op == Token::Kind::TK_SHL) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400746 this->write(ByteCodeInstruction::kShiftLeft);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500747 } else {
748 this->write(type_category(lType) == TypeCategory::kSigned
Brian Osmanb08cc022020-04-02 11:38:40 -0400749 ? ByteCodeInstruction::kShiftRightS
750 : ByteCodeInstruction::kShiftRightU);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500751 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400752 this->write8(shift);
753 return false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500754 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500755
756 default:
757 break;
758 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400759 this->writeExpression(*b.fRight);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500760 if (lVecOrMtx && !rVecOrMtx) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400761 for (int i = SlotCount(lType); i > 1; --i) {
Brian Osman49b30f42020-06-26 17:22:27 -0400762 this->write(ByteCodeInstruction::kDup, 1);
Brian Osmanb08cc022020-04-02 11:38:40 -0400763 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500764 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400765 // Special case for M*V, V*M, M*M (but not V*V!)
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400766 if (op == Token::Kind::TK_STAR && lVecOrMtx && rVecOrMtx &&
Brian Osmanb08cc022020-04-02 11:38:40 -0400767 !(lType.kind() == Type::kVector_Kind && rType.kind() == Type::kVector_Kind)) {
768 this->write(ByteCodeInstruction::kMatrixMultiply,
769 SlotCount(b.fType) - (SlotCount(lType) + SlotCount(rType)));
770 int rCols = rType.columns(),
771 rRows = rType.rows(),
772 lCols = lType.columns(),
773 lRows = lType.rows();
774 // M*V treats the vector as a column
775 if (rType.kind() == Type::kVector_Kind) {
776 std::swap(rCols, rRows);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500777 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400778 SkASSERT(lCols == rRows);
779 SkASSERT(SlotCount(b.fType) == lRows * rCols);
780 this->write8(lCols);
781 this->write8(lRows);
782 this->write8(rCols);
783 } else {
784 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400785 case Token::Kind::TK_EQEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400786 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareIEQ,
787 ByteCodeInstruction::kCompareIEQ,
788 ByteCodeInstruction::kCompareFEQ,
789 count);
790 // Collapse to a single bool
791 for (int i = count; i > 1; --i) {
Brian Osman49b30f42020-06-26 17:22:27 -0400792 this->write(ByteCodeInstruction::kAndB, 1);
Brian Osmanb08cc022020-04-02 11:38:40 -0400793 }
794 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400795 case Token::Kind::TK_GT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400796 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGT,
797 ByteCodeInstruction::kCompareUGT,
798 ByteCodeInstruction::kCompareFGT,
799 count);
800 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400801 case Token::Kind::TK_GTEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400802 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSGTEQ,
803 ByteCodeInstruction::kCompareUGTEQ,
804 ByteCodeInstruction::kCompareFGTEQ,
805 count);
806 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400807 case Token::Kind::TK_LT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400808 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLT,
809 ByteCodeInstruction::kCompareULT,
810 ByteCodeInstruction::kCompareFLT,
811 count);
812 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400813 case Token::Kind::TK_LTEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400814 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareSLTEQ,
815 ByteCodeInstruction::kCompareULTEQ,
816 ByteCodeInstruction::kCompareFLTEQ,
817 count);
818 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400819 case Token::Kind::TK_MINUS:
Brian Osmanb08cc022020-04-02 11:38:40 -0400820 this->writeTypedInstruction(lType, ByteCodeInstruction::kSubtractI,
821 ByteCodeInstruction::kSubtractI,
822 ByteCodeInstruction::kSubtractF,
823 count);
824 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400825 case Token::Kind::TK_NEQ:
Brian Osmanb08cc022020-04-02 11:38:40 -0400826 this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareINEQ,
827 ByteCodeInstruction::kCompareINEQ,
828 ByteCodeInstruction::kCompareFNEQ,
829 count);
830 // Collapse to a single bool
831 for (int i = count; i > 1; --i) {
Brian Osman49b30f42020-06-26 17:22:27 -0400832 this->write(ByteCodeInstruction::kOrB, 1);
Brian Osmanb08cc022020-04-02 11:38:40 -0400833 }
834 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400835 case Token::Kind::TK_PERCENT:
Brian Osmanb08cc022020-04-02 11:38:40 -0400836 this->writeTypedInstruction(lType, ByteCodeInstruction::kRemainderS,
837 ByteCodeInstruction::kRemainderU,
838 ByteCodeInstruction::kRemainderF,
839 count);
840 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400841 case Token::Kind::TK_PLUS:
Brian Osmanb08cc022020-04-02 11:38:40 -0400842 this->writeTypedInstruction(lType, ByteCodeInstruction::kAddI,
843 ByteCodeInstruction::kAddI,
844 ByteCodeInstruction::kAddF,
845 count);
846 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400847 case Token::Kind::TK_SLASH:
Brian Osmanb08cc022020-04-02 11:38:40 -0400848 this->writeTypedInstruction(lType, ByteCodeInstruction::kDivideS,
849 ByteCodeInstruction::kDivideU,
850 ByteCodeInstruction::kDivideF,
851 count);
852 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400853 case Token::Kind::TK_STAR:
Brian Osmanb08cc022020-04-02 11:38:40 -0400854 this->writeTypedInstruction(lType, ByteCodeInstruction::kMultiplyI,
855 ByteCodeInstruction::kMultiplyI,
856 ByteCodeInstruction::kMultiplyF,
857 count);
858 break;
859
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400860 case Token::Kind::TK_LOGICALXOR:
Brian Osman49b30f42020-06-26 17:22:27 -0400861 SkASSERT(tc == SkSL::TypeCategory::kBool);
862 this->write(ByteCodeInstruction::kXorB, count);
Brian Osmanb08cc022020-04-02 11:38:40 -0400863 break;
864
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400865 case Token::Kind::TK_BITWISEAND:
Brian Osman49b30f42020-06-26 17:22:27 -0400866 SkASSERT(tc == SkSL::TypeCategory::kSigned || tc == SkSL::TypeCategory::kUnsigned);
867 this->write(ByteCodeInstruction::kAndB, count);
Brian Osmanb08cc022020-04-02 11:38:40 -0400868 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400869 case Token::Kind::TK_BITWISEOR:
Brian Osman49b30f42020-06-26 17:22:27 -0400870 SkASSERT(tc == SkSL::TypeCategory::kSigned || tc == SkSL::TypeCategory::kUnsigned);
871 this->write(ByteCodeInstruction::kOrB, count);
Brian Osmanb08cc022020-04-02 11:38:40 -0400872 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400873 case Token::Kind::TK_BITWISEXOR:
Brian Osman49b30f42020-06-26 17:22:27 -0400874 SkASSERT(tc == SkSL::TypeCategory::kSigned || tc == SkSL::TypeCategory::kUnsigned);
875 this->write(ByteCodeInstruction::kXorB, count);
Brian Osmanb08cc022020-04-02 11:38:40 -0400876 break;
877
878 default:
879 fErrors.error(b.fOffset, SkSL::String::printf("Unsupported binary operator '%s'",
880 Compiler::OperatorName(op)));
881 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500882 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500883 }
884 if (lvalue) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400885 lvalue->store(discard);
886 discard = false;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500887 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400888 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500889}
890
Brian Osmanb08cc022020-04-02 11:38:40 -0400891void ByteCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
892 this->write(ByteCodeInstruction::kPushImmediate);
893 this->write32(b.fValue ? ~0 : 0);
894}
895
896void ByteCodeGenerator::writeConstructor(const Constructor& c) {
897 for (const auto& arg : c.fArguments) {
898 this->writeExpression(*arg);
899 }
900 if (c.fArguments.size() == 1) {
901 const Type& inType = c.fArguments[0]->fType;
902 const Type& outType = c.fType;
903 TypeCategory inCategory = type_category(inType);
904 TypeCategory outCategory = type_category(outType);
905 int inCount = SlotCount(inType);
906 int outCount = SlotCount(outType);
907 if (inCategory != outCategory) {
908 SkASSERT(inCount == outCount);
909 if (inCategory == TypeCategory::kFloat) {
910 SkASSERT(outCategory == TypeCategory::kSigned ||
911 outCategory == TypeCategory::kUnsigned);
Brian Osman49b30f42020-06-26 17:22:27 -0400912 this->write(ByteCodeInstruction::kConvertFtoI, outCount);
Brian Osmanb08cc022020-04-02 11:38:40 -0400913 } else if (outCategory == TypeCategory::kFloat) {
914 if (inCategory == TypeCategory::kSigned) {
Brian Osman49b30f42020-06-26 17:22:27 -0400915 this->write(ByteCodeInstruction::kConvertStoF, outCount);
Brian Osmanb08cc022020-04-02 11:38:40 -0400916 } else {
917 SkASSERT(inCategory == TypeCategory::kUnsigned);
Brian Osman49b30f42020-06-26 17:22:27 -0400918 this->write(ByteCodeInstruction::kConvertUtoF, outCount);
Brian Osmanb08cc022020-04-02 11:38:40 -0400919 }
920 } else {
921 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500922 }
923 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400924 if (inType.kind() == Type::kMatrix_Kind && outType.kind() == Type::kMatrix_Kind) {
925 this->write(ByteCodeInstruction::kMatrixToMatrix,
926 SlotCount(outType) - SlotCount(inType));
927 this->write8(inType.columns());
928 this->write8(inType.rows());
929 this->write8(outType.columns());
930 this->write8(outType.rows());
931 } else if (inCount != outCount) {
932 SkASSERT(inCount == 1);
933 if (outType.kind() == Type::kMatrix_Kind) {
934 this->write(ByteCodeInstruction::kScalarToMatrix, SlotCount(outType) - 1);
935 this->write8(outType.columns());
936 this->write8(outType.rows());
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500937 } else {
Brian Osmanb08cc022020-04-02 11:38:40 -0400938 SkASSERT(outType.kind() == Type::kVector_Kind);
939 for (; inCount != outCount; ++inCount) {
Brian Osman49b30f42020-06-26 17:22:27 -0400940 this->write(ByteCodeInstruction::kDup, 1);
Brian Osmanb08cc022020-04-02 11:38:40 -0400941 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500942 }
943 }
944 }
945}
946
Brian Osmanb08cc022020-04-02 11:38:40 -0400947void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500948 int argumentCount = 0;
949 for (const auto& arg : f.fArguments) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400950 this->writeExpression(*arg);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500951 argumentCount += SlotCount(arg->fType);
952 }
Brian Osmanb08cc022020-04-02 11:38:40 -0400953 this->write(ByteCodeInstruction::kCallExternal, SlotCount(f.fType) - argumentCount);
954 SkASSERT(argumentCount <= 255);
955 this->write8(argumentCount);
956 this->write8(SlotCount(f.fType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500957 int index = fOutput->fExternalValues.size();
958 fOutput->fExternalValues.push_back(f.fFunction);
959 SkASSERT(index <= 255);
Brian Osmanb08cc022020-04-02 11:38:40 -0400960 this->write8(index);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500961}
962
Brian Osmanb08cc022020-04-02 11:38:40 -0400963void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
964 int count = SlotCount(e.fValue->type());
Brian Osman49b30f42020-06-26 17:22:27 -0400965 this->write(ByteCodeInstruction::kReadExternal, count);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500966 int index = fOutput->fExternalValues.size();
967 fOutput->fExternalValues.push_back(e.fValue);
968 SkASSERT(index <= 255);
Brian Osmanb08cc022020-04-02 11:38:40 -0400969 this->write8(index);
Ethan Nicholasb962eff2020-01-23 16:49:41 -0500970}
971
Brian Osmanb08cc022020-04-02 11:38:40 -0400972void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
Brian Osman5aaaeea2020-06-22 14:26:03 -0400973 if (int builtin = expression_as_builtin(expr); builtin >= 0) {
974 switch (builtin) {
975 case SK_FRAGCOORD_BUILTIN:
976 this->write(ByteCodeInstruction::kLoadFragCoord);
977 fOutput->fUsesFragCoord = true;
978 break;
979 default:
980 fErrors.error(expr.fOffset, "Unsupported builtin");
981 break;
982 }
983 return;
984 }
985
Brian Osmanb08cc022020-04-02 11:38:40 -0400986 Location location = this->getLocation(expr);
987 int count = SlotCount(expr.fType);
Brian Osmanefb08402020-04-13 16:30:44 -0400988 if (count == 0) {
989 return;
990 }
Brian Osman02f8b072020-06-19 14:04:48 -0400991 if (location.isOnStack()) {
Brian Osmanb08cc022020-04-02 11:38:40 -0400992 this->write(location.selectLoad(ByteCodeInstruction::kLoadExtended,
993 ByteCodeInstruction::kLoadExtendedGlobal,
994 ByteCodeInstruction::kLoadExtendedUniform),
995 count);
Brian Osmanb08cc022020-04-02 11:38:40 -0400996 } else {
Brian Osman49b30f42020-06-26 17:22:27 -0400997 this->write(location.selectLoad(ByteCodeInstruction::kLoad,
998 ByteCodeInstruction::kLoadGlobal,
999 ByteCodeInstruction::kLoadUniform),
1000 count);
1001 this->write8(location.fSlot);
Brian Osmanb08cc022020-04-02 11:38:40 -04001002 }
1003}
1004
1005static inline uint32_t float_to_bits(float x) {
1006 uint32_t u;
1007 memcpy(&u, &x, sizeof(uint32_t));
1008 return u;
1009}
1010
1011void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
1012 this->write(ByteCodeInstruction::kPushImmediate);
1013 this->write32(float_to_bits(f.fValue));
1014}
1015
Brian Osman8842b372020-05-01 15:07:49 -04001016static bool is_generic_type(const Type* type, const Type* generic) {
1017 const std::vector<const Type*>& concrete(generic->coercibleTypes());
1018 return std::find(concrete.begin(), concrete.end(), type) != concrete.end();
1019}
1020
Brian Osmanb08cc022020-04-02 11:38:40 -04001021void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
1022 auto found = fIntrinsics.find(c.fFunction.fName);
1023 if (found == fIntrinsics.end()) {
1024 fErrors.error(c.fOffset, String::printf("Unsupported intrinsic: '%s'",
1025 String(c.fFunction.fName).c_str()));
1026 return;
1027 }
Mike Klein45be0772020-05-01 09:13:18 -05001028 Intrinsic intrin = found->second;
Brian Osman795efd22020-07-01 13:18:36 -04001029
1030 const auto& args = c.fArguments;
1031 const size_t nargs = args.size();
1032 SkASSERT(nargs >= 1);
1033
1034 int count = SlotCount(args[0]->fType);
Brian Osmand5f937b2020-05-04 12:07:29 -04001035
1036 // Several intrinsics have variants where one argument is either scalar, or the same size as
1037 // the first argument. Call dupSmallerType(SlotCount(argType)) to ensure equal component count.
1038 auto dupSmallerType = [count, this](int smallCount) {
1039 SkASSERT(smallCount == 1 || smallCount == count);
1040 for (int i = smallCount; i < count; ++i) {
Brian Osman49b30f42020-06-26 17:22:27 -04001041 this->write(ByteCodeInstruction::kDup, 1);
Brian Osmand5f937b2020-05-04 12:07:29 -04001042 }
1043 };
1044
Brian Osmana43d8202020-06-17 16:50:39 -04001045 if (intrin.is_special && intrin.special == SpecialIntrinsic::kSample) {
Brian Osman795efd22020-07-01 13:18:36 -04001046 // Sample is very special, the first argument is an FP, which can't be pushed to the stack.
1047 if (nargs > 2 || args[0]->fType != *fContext.fFragmentProcessor_Type ||
1048 (nargs == 2 && (args[1]->fType != *fContext.fFloat2_Type &&
1049 args[1]->fType != *fContext.fFloat3x3_Type))) {
Brian Osmana43d8202020-06-17 16:50:39 -04001050 fErrors.error(c.fOffset, "Unsupported form of sample");
1051 return;
1052 }
1053
Brian Osman795efd22020-07-01 13:18:36 -04001054 if (nargs == 2) {
1055 // Write our coords or matrix
1056 this->writeExpression(*args[1]);
1057 this->write(args[1]->fType == *fContext.fFloat3x3_Type
1058 ? ByteCodeInstruction::kSampleMatrix
1059 : ByteCodeInstruction::kSampleExplicit);
1060 } else {
1061 this->write(ByteCodeInstruction::kSample);
1062 }
Brian Osmana43d8202020-06-17 16:50:39 -04001063
Brian Osman795efd22020-07-01 13:18:36 -04001064 Location childLoc = this->getLocation(*args[0]);
Brian Osmana43d8202020-06-17 16:50:39 -04001065 SkASSERT(childLoc.fStorage == Storage::kChildFP);
1066 this->write8(childLoc.fSlot);
1067 return;
1068 }
1069
Brian Osmand5f937b2020-05-04 12:07:29 -04001070 if (intrin.is_special && (intrin.special == SpecialIntrinsic::kClamp ||
1071 intrin.special == SpecialIntrinsic::kSaturate)) {
1072 // These intrinsics are extra-special, we need instructions interleaved with arguments
1073 bool saturate = (intrin.special == SpecialIntrinsic::kSaturate);
Brian Osman795efd22020-07-01 13:18:36 -04001074 SkASSERT(nargs == (saturate ? 1 : 3));
1075 int limitCount = saturate ? 1 : SlotCount(args[1]->fType);
Brian Osmand5f937b2020-05-04 12:07:29 -04001076
1077 // 'x'
Brian Osman795efd22020-07-01 13:18:36 -04001078 this->writeExpression(*args[0]);
Brian Osmand5f937b2020-05-04 12:07:29 -04001079
1080 // 'minVal'
1081 if (saturate) {
1082 this->write(ByteCodeInstruction::kPushImmediate);
1083 this->write32(float_to_bits(0.0f));
1084 } else {
Brian Osman795efd22020-07-01 13:18:36 -04001085 this->writeExpression(*args[1]);
Brian Osmand5f937b2020-05-04 12:07:29 -04001086 }
1087 dupSmallerType(limitCount);
Brian Osman795efd22020-07-01 13:18:36 -04001088 this->writeTypedInstruction(args[0]->fType,
Brian Osmand5f937b2020-05-04 12:07:29 -04001089 ByteCodeInstruction::kMaxS,
1090 ByteCodeInstruction::kMaxS,
1091 ByteCodeInstruction::kMaxF,
1092 count);
1093
1094 // 'maxVal'
1095 if (saturate) {
1096 this->write(ByteCodeInstruction::kPushImmediate);
1097 this->write32(float_to_bits(1.0f));
1098 } else {
Brian Osman795efd22020-07-01 13:18:36 -04001099 SkASSERT(limitCount == SlotCount(args[2]->fType));
1100 this->writeExpression(*args[2]);
Brian Osmand5f937b2020-05-04 12:07:29 -04001101 }
1102 dupSmallerType(limitCount);
Brian Osman795efd22020-07-01 13:18:36 -04001103 this->writeTypedInstruction(args[0]->fType,
Brian Osmand5f937b2020-05-04 12:07:29 -04001104 ByteCodeInstruction::kMinS,
1105 ByteCodeInstruction::kMinS,
1106 ByteCodeInstruction::kMinF,
1107 count);
1108 return;
1109 }
1110
1111 // All other intrinsics can handle their arguments being on the stack in order
Brian Osman795efd22020-07-01 13:18:36 -04001112 for (const auto& arg : args) {
Brian Osmand5f937b2020-05-04 12:07:29 -04001113 this->writeExpression(*arg);
1114 }
1115
Mike Klein45be0772020-05-01 09:13:18 -05001116 if (intrin.is_special) {
1117 switch (intrin.special) {
Brian Osman8842b372020-05-01 15:07:49 -04001118 case SpecialIntrinsic::kAll: {
1119 for (int i = count-1; i --> 0;) {
Brian Osman49b30f42020-06-26 17:22:27 -04001120 this->write(ByteCodeInstruction::kAndB, 1);
Brian Osman8842b372020-05-01 15:07:49 -04001121 }
1122 } break;
1123
1124 case SpecialIntrinsic::kAny: {
1125 for (int i = count-1; i --> 0;) {
Brian Osman49b30f42020-06-26 17:22:27 -04001126 this->write(ByteCodeInstruction::kOrB, 1);
Brian Osman8842b372020-05-01 15:07:49 -04001127 }
1128 } break;
1129
Brian Osman15c98cb2020-02-27 18:36:57 +00001130 case SpecialIntrinsic::kDot: {
Brian Osman795efd22020-07-01 13:18:36 -04001131 SkASSERT(nargs == 2);
1132 SkASSERT(count == SlotCount(args[1]->fType));
Brian Osman49b30f42020-06-26 17:22:27 -04001133 this->write(ByteCodeInstruction::kMultiplyF, count);
Mike Klein45be0772020-05-01 09:13:18 -05001134 for (int i = count-1; i --> 0;) {
Brian Osman49b30f42020-06-26 17:22:27 -04001135 this->write(ByteCodeInstruction::kAddF, 1);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001136 }
Mike Klein45be0772020-05-01 09:13:18 -05001137 } break;
1138
1139 case SpecialIntrinsic::kLength: {
Brian Osman795efd22020-07-01 13:18:36 -04001140 SkASSERT(nargs == 1);
Brian Osman49b30f42020-06-26 17:22:27 -04001141 this->write(ByteCodeInstruction::kDup, count);
1142 this->write(ByteCodeInstruction::kMultiplyF, count);
Mike Klein45be0772020-05-01 09:13:18 -05001143 for (int i = count-1; i --> 0;) {
Brian Osman49b30f42020-06-26 17:22:27 -04001144 this->write(ByteCodeInstruction::kAddF, 1);
Mike Klein45be0772020-05-01 09:13:18 -05001145 }
Brian Osman49b30f42020-06-26 17:22:27 -04001146 this->write(ByteCodeInstruction::kSqrt, 1);
Mike Klein45be0772020-05-01 09:13:18 -05001147 } break;
1148
Brian Osmand5f937b2020-05-04 12:07:29 -04001149 case SpecialIntrinsic::kMax:
1150 case SpecialIntrinsic::kMin: {
Brian Osman795efd22020-07-01 13:18:36 -04001151 SkASSERT(nargs == 2);
Brian Osmand5f937b2020-05-04 12:07:29 -04001152 // There are variants where the second argument is scalar
Brian Osman795efd22020-07-01 13:18:36 -04001153 dupSmallerType(SlotCount(args[1]->fType));
Brian Osmand5f937b2020-05-04 12:07:29 -04001154 if (intrin.special == SpecialIntrinsic::kMax) {
Brian Osman795efd22020-07-01 13:18:36 -04001155 this->writeTypedInstruction(args[0]->fType,
Brian Osmand5f937b2020-05-04 12:07:29 -04001156 ByteCodeInstruction::kMaxS,
1157 ByteCodeInstruction::kMaxS,
1158 ByteCodeInstruction::kMaxF,
1159 count);
1160 } else {
Brian Osman795efd22020-07-01 13:18:36 -04001161 this->writeTypedInstruction(args[0]->fType,
Brian Osmand5f937b2020-05-04 12:07:29 -04001162 ByteCodeInstruction::kMinS,
1163 ByteCodeInstruction::kMinS,
1164 ByteCodeInstruction::kMinF,
1165 count);
1166 }
1167 } break;
1168
Brian Osman8842b372020-05-01 15:07:49 -04001169 case SpecialIntrinsic::kMix: {
1170 // Two main variants of mix to handle
Brian Osman795efd22020-07-01 13:18:36 -04001171 SkASSERT(nargs == 3);
1172 SkASSERT(count == SlotCount(args[1]->fType));
1173 int selectorCount = SlotCount(args[2]->fType);
Brian Osman8842b372020-05-01 15:07:49 -04001174
Brian Osman795efd22020-07-01 13:18:36 -04001175 if (is_generic_type(&args[2]->fType, fContext.fGenBType_Type.get())) {
Brian Osman8842b372020-05-01 15:07:49 -04001176 // mix(genType, genType, genBoolType)
1177 SkASSERT(selectorCount == count);
Brian Osman49b30f42020-06-26 17:22:27 -04001178 this->write(ByteCodeInstruction::kMix, count);
Brian Osman8842b372020-05-01 15:07:49 -04001179 } else {
1180 // mix(genType, genType, genType) or mix(genType, genType, float)
Brian Osmand5f937b2020-05-04 12:07:29 -04001181 dupSmallerType(selectorCount);
Brian Osman49b30f42020-06-26 17:22:27 -04001182 this->write(ByteCodeInstruction::kLerp, count);
Brian Osman8842b372020-05-01 15:07:49 -04001183 }
1184 } break;
1185
Brian Osman2a4871b2020-06-19 11:29:58 -04001186 case SpecialIntrinsic::kNormalize: {
Brian Osman795efd22020-07-01 13:18:36 -04001187 SkASSERT(nargs == 1);
Brian Osman49b30f42020-06-26 17:22:27 -04001188 this->write(ByteCodeInstruction::kDup, count);
1189 this->write(ByteCodeInstruction::kDup, count);
1190 this->write(ByteCodeInstruction::kMultiplyF, count);
Brian Osman2a4871b2020-06-19 11:29:58 -04001191 for (int i = count-1; i --> 0;) {
Brian Osman49b30f42020-06-26 17:22:27 -04001192 this->write(ByteCodeInstruction::kAddF, 1);
Brian Osman2a4871b2020-06-19 11:29:58 -04001193 }
Brian Osman49b30f42020-06-26 17:22:27 -04001194 this->write(ByteCodeInstruction::kSqrt, 1);
Brian Osman2a4871b2020-06-19 11:29:58 -04001195 dupSmallerType(1);
Brian Osman49b30f42020-06-26 17:22:27 -04001196 this->write(ByteCodeInstruction::kDivideF, count);
Brian Osman2a4871b2020-06-19 11:29:58 -04001197 } break;
1198
Brian Osmanb08cc022020-04-02 11:38:40 -04001199 default:
1200 SkASSERT(false);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001201 }
1202 } else {
Brian Osman8842b372020-05-01 15:07:49 -04001203 switch (intrin.inst_f) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001204 case ByteCodeInstruction::kInverse2x2: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001205 auto op = ByteCodeInstruction::kInverse2x2;
1206 switch (count) {
1207 case 4: break; // float2x2
1208 case 9: op = ByteCodeInstruction::kInverse3x3; break;
1209 case 16: op = ByteCodeInstruction::kInverse4x4; break;
1210 default: SkASSERT(false);
1211 }
1212 this->write(op);
1213 break;
Brian Osman15c98cb2020-02-27 18:36:57 +00001214 }
Mike Klein45be0772020-05-01 09:13:18 -05001215
Brian Osmanb08cc022020-04-02 11:38:40 -04001216 default:
Brian Osman795efd22020-07-01 13:18:36 -04001217 this->writeTypedInstruction(args[0]->fType,
Brian Osman49b30f42020-06-26 17:22:27 -04001218 intrin.inst_s,
1219 intrin.inst_u,
1220 intrin.inst_f,
1221 count);
Brian Osman8842b372020-05-01 15:07:49 -04001222 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001223 }
1224 }
1225}
1226
Brian Osmanb08cc022020-04-02 11:38:40 -04001227void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001228 // Find the index of the function we're calling. We explicitly do not allow calls to functions
1229 // before they're defined. This is an easy-to-understand rule that prevents recursion.
Brian Osmanb08cc022020-04-02 11:38:40 -04001230 int idx = -1;
1231 for (size_t i = 0; i < fFunctions.size(); ++i) {
1232 if (f.fFunction.matches(fFunctions[i]->fDeclaration)) {
1233 idx = i;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001234 break;
1235 }
1236 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001237 if (idx == -1) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001238 this->writeIntrinsicCall(f);
1239 return;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001240 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001241
1242
1243 if (idx > 255) {
1244 fErrors.error(f.fOffset, "Function count limit exceeded");
1245 return;
1246 } else if (idx >= (int) fFunctions.size()) {
1247 fErrors.error(f.fOffset, "Call to undefined function");
1248 return;
1249 }
1250
1251 // We may need to deal with out parameters, so the sequence is tricky
1252 if (int returnCount = SlotCount(f.fType)) {
1253 this->write(ByteCodeInstruction::kReserve, returnCount);
Brian Osmanb08cc022020-04-02 11:38:40 -04001254 }
1255
1256 int argCount = f.fArguments.size();
1257 std::vector<std::unique_ptr<LValue>> lvalues;
1258 for (int i = 0; i < argCount; ++i) {
1259 const auto& param = f.fFunction.fParameters[i];
1260 const auto& arg = f.fArguments[i];
1261 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1262 lvalues.emplace_back(this->getLValue(*arg));
1263 lvalues.back()->load();
1264 } else {
1265 this->writeExpression(*arg);
1266 }
1267 }
1268
1269 // The space used by the call is based on the callee, but it also unwinds all of that before
1270 // we continue execution. We adjust our max stack depths below.
1271 this->write(ByteCodeInstruction::kCall);
1272 this->write8(idx);
1273
1274 const ByteCodeFunction* callee = fOutput->fFunctions[idx].get();
1275 fMaxLoopCount = std::max(fMaxLoopCount, fLoopCount + callee->fLoopCount);
1276 fMaxConditionCount = std::max(fMaxConditionCount, fConditionCount + callee->fConditionCount);
1277 fMaxStackCount = std::max(fMaxStackCount, fStackCount + callee->fLocalCount
1278 + callee->fStackCount);
1279
1280 // After the called function returns, the stack will still contain our arguments. We have to
1281 // pop them (storing any out parameters back to their lvalues as we go). We glob together slot
1282 // counts for all parameters that aren't out-params, so we can pop them in one big chunk.
1283 int popCount = 0;
1284 auto pop = [&]() {
Brian Osman49b30f42020-06-26 17:22:27 -04001285 if (popCount > 0) {
1286 this->write(ByteCodeInstruction::kPop, popCount);
Brian Osmanb08cc022020-04-02 11:38:40 -04001287 }
1288 popCount = 0;
1289 };
1290
1291 for (int i = argCount - 1; i >= 0; --i) {
1292 const auto& param = f.fFunction.fParameters[i];
1293 const auto& arg = f.fArguments[i];
1294 if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
1295 pop();
1296 lvalues.back()->store(true);
1297 lvalues.pop_back();
1298 } else {
1299 popCount += SlotCount(arg->fType);
1300 }
1301 }
1302 pop();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001303}
1304
Brian Osmanb08cc022020-04-02 11:38:40 -04001305void ByteCodeGenerator::writeIntLiteral(const IntLiteral& i) {
1306 this->write(ByteCodeInstruction::kPushImmediate);
1307 this->write32(i.fValue);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001308}
1309
Brian Osmanb08cc022020-04-02 11:38:40 -04001310void ByteCodeGenerator::writeNullLiteral(const NullLiteral& n) {
1311 // not yet implemented
1312 abort();
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001313}
1314
Brian Osmanb08cc022020-04-02 11:38:40 -04001315bool ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p, bool discard) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001316 switch (p.fOperator) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001317 case Token::Kind::TK_PLUSPLUS: // fall through
1318 case Token::Kind::TK_MINUSMINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001319 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1320 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
1321 lvalue->load();
1322 this->write(ByteCodeInstruction::kPushImmediate);
1323 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001324 if (p.fOperator == Token::Kind::TK_PLUSPLUS) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001325 this->writeTypedInstruction(p.fType,
1326 ByteCodeInstruction::kAddI,
1327 ByteCodeInstruction::kAddI,
1328 ByteCodeInstruction::kAddF,
1329 1);
1330 } else {
1331 this->writeTypedInstruction(p.fType,
1332 ByteCodeInstruction::kSubtractI,
1333 ByteCodeInstruction::kSubtractI,
1334 ByteCodeInstruction::kSubtractF,
1335 1);
1336 }
1337 lvalue->store(discard);
1338 discard = false;
1339 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001340 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001341 case Token::Kind::TK_MINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001342 this->writeExpression(*p.fOperand);
1343 this->writeTypedInstruction(p.fType,
1344 ByteCodeInstruction::kNegateI,
1345 ByteCodeInstruction::kNegateI,
1346 ByteCodeInstruction::kNegateF,
Brian Osmanab8f3842020-04-07 09:30:44 -04001347 SlotCount(p.fOperand->fType));
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001348 break;
1349 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001350 case Token::Kind::TK_LOGICALNOT:
1351 case Token::Kind::TK_BITWISENOT: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001352 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1353 SkDEBUGCODE(TypeCategory tc = type_category(p.fOperand->fType));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001354 SkASSERT((p.fOperator == Token::Kind::TK_LOGICALNOT && tc == TypeCategory::kBool) ||
1355 (p.fOperator == Token::Kind::TK_BITWISENOT && (tc == TypeCategory::kSigned ||
Brian Osmanb08cc022020-04-02 11:38:40 -04001356 tc == TypeCategory::kUnsigned)));
1357 this->writeExpression(*p.fOperand);
Brian Osman49b30f42020-06-26 17:22:27 -04001358 this->write(ByteCodeInstruction::kNotB, 1);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001359 break;
1360 }
1361 default:
1362 SkASSERT(false);
1363 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001364 return discard;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001365}
1366
Brian Osmanb08cc022020-04-02 11:38:40 -04001367bool ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p, bool discard) {
1368 switch (p.fOperator) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001369 case Token::Kind::TK_PLUSPLUS: // fall through
1370 case Token::Kind::TK_MINUSMINUS: {
Brian Osmanb08cc022020-04-02 11:38:40 -04001371 SkASSERT(SlotCount(p.fOperand->fType) == 1);
1372 std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
1373 lvalue->load();
1374 // If we're not supposed to discard the result, then make a copy *before* the +/-
1375 if (!discard) {
Brian Osman49b30f42020-06-26 17:22:27 -04001376 this->write(ByteCodeInstruction::kDup, 1);
Brian Osmanb08cc022020-04-02 11:38:40 -04001377 }
1378 this->write(ByteCodeInstruction::kPushImmediate);
1379 this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001380 if (p.fOperator == Token::Kind::TK_PLUSPLUS) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001381 this->writeTypedInstruction(p.fType,
1382 ByteCodeInstruction::kAddI,
1383 ByteCodeInstruction::kAddI,
1384 ByteCodeInstruction::kAddF,
1385 1);
1386 } else {
1387 this->writeTypedInstruction(p.fType,
1388 ByteCodeInstruction::kSubtractI,
1389 ByteCodeInstruction::kSubtractI,
1390 ByteCodeInstruction::kSubtractF,
1391 1);
1392 }
1393 // Always consume the result as part of the store
1394 lvalue->store(true);
1395 discard = false;
1396 break;
1397 }
1398 default:
1399 SkASSERT(false);
1400 }
1401 return discard;
1402}
1403
1404void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001405 if (swizzle_is_simple(s)) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001406 this->writeVariableExpression(s);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001407 return;
1408 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001409
Brian Osman3711c662020-06-18 14:42:21 -04001410 this->writeExpression(*s.fBase);
1411 this->write(ByteCodeInstruction::kSwizzle, s.fComponents.size() - s.fBase->fType.columns());
1412 this->write8(s.fBase->fType.columns());
1413 this->write8(s.fComponents.size());
1414 for (int c : s.fComponents) {
1415 this->write8(c);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001416 }
1417}
1418
Brian Osmanb08cc022020-04-02 11:38:40 -04001419void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001420 int count = SlotCount(t.fType);
1421 SkASSERT(count == SlotCount(t.fIfTrue->fType));
1422 SkASSERT(count == SlotCount(t.fIfFalse->fType));
1423
Brian Osmanb08cc022020-04-02 11:38:40 -04001424 this->writeExpression(*t.fTest);
1425 this->write(ByteCodeInstruction::kMaskPush);
1426 this->writeExpression(*t.fIfTrue);
1427 this->write(ByteCodeInstruction::kMaskNegate);
1428 this->writeExpression(*t.fIfFalse);
1429 this->write(ByteCodeInstruction::kMaskBlend, count);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001430}
1431
Brian Osmanb08cc022020-04-02 11:38:40 -04001432void ByteCodeGenerator::writeExpression(const Expression& e, bool discard) {
1433 switch (e.fKind) {
1434 case Expression::kBinary_Kind:
John Stiles81365af2020-08-18 09:24:00 -04001435 discard = this->writeBinaryExpression(e.as<BinaryExpression>(), discard);
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001436 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001437 case Expression::kBoolLiteral_Kind:
John Stiles81365af2020-08-18 09:24:00 -04001438 this->writeBoolLiteral(e.as<BoolLiteral>());
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001439 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001440 case Expression::kConstructor_Kind:
John Stiles81365af2020-08-18 09:24:00 -04001441 this->writeConstructor(e.as<Constructor>());
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001442 break;
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001443 case Expression::kExternalFunctionCall_Kind:
John Stiles81365af2020-08-18 09:24:00 -04001444 this->writeExternalFunctionCall(e.as<ExternalFunctionCall>());
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001445 break;
1446 case Expression::kExternalValue_Kind:
John Stiles81365af2020-08-18 09:24:00 -04001447 this->writeExternalValue(e.as<ExternalValueReference>());
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001448 break;
1449 case Expression::kFieldAccess_Kind:
1450 case Expression::kIndex_Kind:
1451 case Expression::kVariableReference_Kind:
Brian Osmanb08cc022020-04-02 11:38:40 -04001452 this->writeVariableExpression(e);
1453 break;
1454 case Expression::kFloatLiteral_Kind:
John Stiles81365af2020-08-18 09:24:00 -04001455 this->writeFloatLiteral(e.as<FloatLiteral>());
Brian Osmanb08cc022020-04-02 11:38:40 -04001456 break;
1457 case Expression::kFunctionCall_Kind:
John Stiles81365af2020-08-18 09:24:00 -04001458 this->writeFunctionCall(e.as<FunctionCall>());
Brian Osmanb08cc022020-04-02 11:38:40 -04001459 break;
1460 case Expression::kIntLiteral_Kind:
John Stiles81365af2020-08-18 09:24:00 -04001461 this->writeIntLiteral(e.as<IntLiteral>());
Brian Osmanb08cc022020-04-02 11:38:40 -04001462 break;
1463 case Expression::kNullLiteral_Kind:
John Stiles81365af2020-08-18 09:24:00 -04001464 this->writeNullLiteral(e.as<NullLiteral>());
Brian Osmanb08cc022020-04-02 11:38:40 -04001465 break;
1466 case Expression::kPrefix_Kind:
John Stiles81365af2020-08-18 09:24:00 -04001467 discard = this->writePrefixExpression(e.as<PrefixExpression>(), discard);
Brian Osmanb08cc022020-04-02 11:38:40 -04001468 break;
1469 case Expression::kPostfix_Kind:
John Stiles81365af2020-08-18 09:24:00 -04001470 discard = this->writePostfixExpression(e.as<PostfixExpression>(), discard);
Brian Osmanb08cc022020-04-02 11:38:40 -04001471 break;
1472 case Expression::kSwizzle_Kind:
John Stiles81365af2020-08-18 09:24:00 -04001473 this->writeSwizzle(e.as<Swizzle>());
Brian Osmanb08cc022020-04-02 11:38:40 -04001474 break;
1475 case Expression::kTernary_Kind:
John Stiles81365af2020-08-18 09:24:00 -04001476 this->writeTernaryExpression(e.as<TernaryExpression>());
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001477 break;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001478 default:
1479#ifdef SK_DEBUG
Brian Osmanb08cc022020-04-02 11:38:40 -04001480 printf("unsupported expression %s\n", e.description().c_str());
Ben Wagner470e0ac2020-01-22 16:59:21 -05001481#endif
Brian Osmanb08cc022020-04-02 11:38:40 -04001482 SkASSERT(false);
1483 }
1484 if (discard) {
1485 int count = SlotCount(e.fType);
Brian Osman49b30f42020-06-26 17:22:27 -04001486 if (count > 0) {
1487 this->write(ByteCodeInstruction::kPop, count);
Brian Osmanb08cc022020-04-02 11:38:40 -04001488 }
1489 discard = false;
Ben Wagner470e0ac2020-01-22 16:59:21 -05001490 }
Ethan Nicholas7deb1c22020-01-22 10:31:55 -05001491}
1492
Brian Osmanb08cc022020-04-02 11:38:40 -04001493class ByteCodeExternalValueLValue : public ByteCodeGenerator::LValue {
1494public:
John Stiles534d7992020-08-18 00:06:01 -04001495 ByteCodeExternalValueLValue(ByteCodeGenerator* generator, const ExternalValue& value, int index)
Brian Osmanb08cc022020-04-02 11:38:40 -04001496 : INHERITED(*generator)
1497 , fCount(ByteCodeGenerator::SlotCount(value.type()))
1498 , fIndex(index) {}
1499
1500 void load() override {
Brian Osman49b30f42020-06-26 17:22:27 -04001501 fGenerator.write(ByteCodeInstruction::kReadExternal, fCount);
Brian Osmanb08cc022020-04-02 11:38:40 -04001502 fGenerator.write8(fIndex);
1503 }
1504
1505 void store(bool discard) override {
1506 if (!discard) {
Brian Osman49b30f42020-06-26 17:22:27 -04001507 fGenerator.write(ByteCodeInstruction::kDup, fCount);
Brian Osmanb08cc022020-04-02 11:38:40 -04001508 }
Brian Osman49b30f42020-06-26 17:22:27 -04001509 fGenerator.write(ByteCodeInstruction::kWriteExternal, fCount);
Brian Osmanb08cc022020-04-02 11:38:40 -04001510 fGenerator.write8(fIndex);
1511 }
1512
1513private:
1514 typedef LValue INHERITED;
1515
1516 int fCount;
Brian Osmanb08cc022020-04-02 11:38:40 -04001517 int fIndex;
1518};
1519
1520class ByteCodeSwizzleLValue : public ByteCodeGenerator::LValue {
1521public:
1522 ByteCodeSwizzleLValue(ByteCodeGenerator* generator, const Swizzle& swizzle)
1523 : INHERITED(*generator)
1524 , fSwizzle(swizzle) {}
1525
1526 void load() override {
1527 fGenerator.writeSwizzle(fSwizzle);
1528 }
1529
1530 void store(bool discard) override {
1531 int count = fSwizzle.fComponents.size();
1532 if (!discard) {
Brian Osman49b30f42020-06-26 17:22:27 -04001533 fGenerator.write(ByteCodeInstruction::kDup, count);
Brian Osmanb08cc022020-04-02 11:38:40 -04001534 }
Brian Osman304dfa32020-06-18 15:53:51 -04001535 // We already have the correct number of values on the stack, thanks to type checking.
1536 // The algorithm: Walk down the values on the stack, doing 'count' single-element stores.
1537 // For each value, use the corresponding swizzle component to offset the store location.
1538 //
1539 // Static locations: We (wastefully) call getLocation every time, but get good byte code.
1540 // Note that we could (but don't) store adjacent/sequential values with fewer instructions.
1541 //
1542 // Dynamic locations: ... are bad. We have to recompute the base address on each iteration,
1543 // because the stack doesn't let us retain that address between stores. Dynamic locations
1544 // are rare though, and swizzled writes to those are even rarer, so we just live with this.
1545 for (int i = count; i-- > 0;) {
1546 ByteCodeGenerator::Location location = fGenerator.getLocation(*fSwizzle.fBase);
1547 if (!location.isOnStack()) {
1548 fGenerator.write(location.selectStore(ByteCodeInstruction::kStore,
Brian Osman49b30f42020-06-26 17:22:27 -04001549 ByteCodeInstruction::kStoreGlobal),
1550 1);
Brian Osman304dfa32020-06-18 15:53:51 -04001551 fGenerator.write8(location.fSlot + fSwizzle.fComponents[i]);
1552 } else {
1553 fGenerator.write(ByteCodeInstruction::kPushImmediate);
1554 fGenerator.write32(fSwizzle.fComponents[i]);
Brian Osman49b30f42020-06-26 17:22:27 -04001555 fGenerator.write(ByteCodeInstruction::kAddI, 1);
Brian Osman304dfa32020-06-18 15:53:51 -04001556 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreExtended,
1557 ByteCodeInstruction::kStoreExtendedGlobal),
1558 1);
Brian Osman304dfa32020-06-18 15:53:51 -04001559 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001560 }
1561 }
1562
1563private:
1564 const Swizzle& fSwizzle;
1565
1566 typedef LValue INHERITED;
1567};
1568
1569class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
1570public:
1571 ByteCodeExpressionLValue(ByteCodeGenerator* generator, const Expression& expr)
1572 : INHERITED(*generator)
1573 , fExpression(expr) {}
1574
1575 void load() override {
1576 fGenerator.writeVariableExpression(fExpression);
1577 }
1578
1579 void store(bool discard) override {
1580 int count = ByteCodeGenerator::SlotCount(fExpression.fType);
1581 if (!discard) {
Brian Osman49b30f42020-06-26 17:22:27 -04001582 fGenerator.write(ByteCodeInstruction::kDup, count);
Brian Osmanb08cc022020-04-02 11:38:40 -04001583 }
1584 ByteCodeGenerator::Location location = fGenerator.getLocation(fExpression);
Brian Osman49b30f42020-06-26 17:22:27 -04001585 if (location.isOnStack()) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001586 fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreExtended,
1587 ByteCodeInstruction::kStoreExtendedGlobal),
1588 count);
Brian Osmanb08cc022020-04-02 11:38:40 -04001589 } else {
Brian Osman49b30f42020-06-26 17:22:27 -04001590 fGenerator.write(location.selectStore(ByteCodeInstruction::kStore,
1591 ByteCodeInstruction::kStoreGlobal),
1592 count);
Brian Osmanb08cc022020-04-02 11:38:40 -04001593 fGenerator.write8(location.fSlot);
1594 }
1595 }
1596
1597private:
1598 typedef LValue INHERITED;
1599
1600 const Expression& fExpression;
1601};
1602
1603std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
1604 switch (e.fKind) {
1605 case Expression::kExternalValue_Kind: {
John Stiles17c5b702020-08-18 10:40:03 -04001606 const ExternalValue* value = e.as<ExternalValueReference>().fValue;
Brian Osmanb08cc022020-04-02 11:38:40 -04001607 int index = fOutput->fExternalValues.size();
1608 fOutput->fExternalValues.push_back(value);
1609 SkASSERT(index <= 255);
1610 return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
1611 }
1612 case Expression::kFieldAccess_Kind:
1613 case Expression::kIndex_Kind:
1614 case Expression::kVariableReference_Kind:
1615 return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
1616 case Expression::kSwizzle_Kind: {
John Stiles17c5b702020-08-18 10:40:03 -04001617 const Swizzle& s = e.as<Swizzle>();
Brian Osmanb08cc022020-04-02 11:38:40 -04001618 return swizzle_is_simple(s)
1619 ? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e))
1620 : std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s));
1621 }
1622 case Expression::kTernary_Kind:
1623 default:
1624#ifdef SK_DEBUG
1625 ABORT("unsupported lvalue %s\n", e.description().c_str());
1626#endif
1627 return nullptr;
1628 }
Ethan Nicholasb962eff2020-01-23 16:49:41 -05001629}
1630
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001631void ByteCodeGenerator::writeBlock(const Block& b) {
1632 for (const auto& s : b.fStatements) {
1633 this->writeStatement(*s);
1634 }
1635}
1636
Brian Osmanb08cc022020-04-02 11:38:40 -04001637void ByteCodeGenerator::setBreakTargets() {
1638 std::vector<DeferredLocation>& breaks = fBreakTargets.top();
1639 for (DeferredLocation& b : breaks) {
1640 b.set();
1641 }
1642 fBreakTargets.pop();
1643}
1644
1645void ByteCodeGenerator::setContinueTargets() {
1646 std::vector<DeferredLocation>& continues = fContinueTargets.top();
1647 for (DeferredLocation& c : continues) {
1648 c.set();
1649 }
1650 fContinueTargets.pop();
1651}
1652
1653void ByteCodeGenerator::writeBreakStatement(const BreakStatement& b) {
1654 // TODO: Include BranchIfAllFalse to top-most LoopNext
1655 this->write(ByteCodeInstruction::kLoopBreak);
1656}
1657
1658void ByteCodeGenerator::writeContinueStatement(const ContinueStatement& c) {
1659 // TODO: Include BranchIfAllFalse to top-most LoopNext
1660 this->write(ByteCodeInstruction::kLoopContinue);
1661}
1662
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001663void ByteCodeGenerator::writeDoStatement(const DoStatement& d) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001664 this->write(ByteCodeInstruction::kLoopBegin);
1665 size_t start = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001666 this->writeStatement(*d.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001667 this->write(ByteCodeInstruction::kLoopNext);
1668 this->writeExpression(*d.fTest);
1669 this->write(ByteCodeInstruction::kLoopMask);
1670 // TODO: Could shorten this with kBranchIfAnyTrue
1671 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001672 DeferredLocation endLocation(this);
Brian Osmanb08cc022020-04-02 11:38:40 -04001673 this->write(ByteCodeInstruction::kBranch);
1674 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001675 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001676 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001677}
1678
1679void ByteCodeGenerator::writeForStatement(const ForStatement& f) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001680 fContinueTargets.emplace();
1681 fBreakTargets.emplace();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001682 if (f.fInitializer) {
1683 this->writeStatement(*f.fInitializer);
1684 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001685 this->write(ByteCodeInstruction::kLoopBegin);
1686 size_t start = fCode->size();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001687 if (f.fTest) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001688 this->writeExpression(*f.fTest);
1689 this->write(ByteCodeInstruction::kLoopMask);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001690 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001691 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001692 DeferredLocation endLocation(this);
1693 this->writeStatement(*f.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001694 this->write(ByteCodeInstruction::kLoopNext);
Brian Osman569f12f2019-06-13 11:23:57 -04001695 if (f.fNext) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001696 this->writeExpression(*f.fNext, true);
Brian Osman569f12f2019-06-13 11:23:57 -04001697 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001698 this->write(ByteCodeInstruction::kBranch);
1699 this->write16(start);
Brian Osman569f12f2019-06-13 11:23:57 -04001700 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001701 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001702}
1703
1704void ByteCodeGenerator::writeIfStatement(const IfStatement& i) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001705 this->writeExpression(*i.fTest);
1706 this->write(ByteCodeInstruction::kMaskPush);
1707 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001708 DeferredLocation falseLocation(this);
1709 this->writeStatement(*i.fIfTrue);
1710 falseLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001711 if (i.fIfFalse) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001712 this->write(ByteCodeInstruction::kMaskNegate);
1713 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Brian Osman569f12f2019-06-13 11:23:57 -04001714 DeferredLocation endLocation(this);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001715 this->writeStatement(*i.fIfFalse);
Mike Kleinb45ee832019-05-17 11:11:11 -05001716 endLocation.set();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001717 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001718 this->write(ByteCodeInstruction::kMaskPop);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001719}
1720
Brian Osmanb08cc022020-04-02 11:38:40 -04001721void ByteCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
1722 if (fLoopCount || fConditionCount) {
Brian Osman4a47da72019-07-12 11:30:32 -04001723 fErrors.error(r.fOffset, "return not allowed inside conditional or loop");
1724 return;
1725 }
Brian Osmanb08cc022020-04-02 11:38:40 -04001726 int count = SlotCount(r.fExpression->fType);
1727 this->writeExpression(*r.fExpression);
1728
1729 // Technically, the kReturn also pops fOutput->fLocalCount values from the stack, too, but we
1730 // haven't counted pushing those (they're outside the scope of our stack tracking). Instead,
1731 // we account for those in writeFunction().
1732
1733 // This is all fine because we don't allow conditional returns, so we only return once anyway.
Brian Osman49b30f42020-06-26 17:22:27 -04001734 this->write(ByteCodeInstruction::kReturn, count);
Brian Osmanb08cc022020-04-02 11:38:40 -04001735}
1736
1737void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) {
1738 // not yet implemented
1739 abort();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001740}
1741
1742void ByteCodeGenerator::writeVarDeclarations(const VarDeclarations& v) {
1743 for (const auto& declStatement : v.fVars) {
1744 const VarDeclaration& decl = (VarDeclaration&) *declStatement;
Brian Osmanb08cc022020-04-02 11:38:40 -04001745 // we need to grab the location even if we don't use it, to ensure it has been allocated
1746 Location location = this->getLocation(*decl.fVar);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001747 if (decl.fValue) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001748 this->writeExpression(*decl.fValue);
1749 int count = SlotCount(decl.fValue->fType);
Brian Osman49b30f42020-06-26 17:22:27 -04001750 this->write(ByteCodeInstruction::kStore, count);
1751 this->write8(location.fSlot);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001752 }
1753 }
1754}
1755
1756void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
Brian Osmanb08cc022020-04-02 11:38:40 -04001757 this->write(ByteCodeInstruction::kLoopBegin);
1758 size_t cond = fCode->size();
1759 this->writeExpression(*w.fTest);
1760 this->write(ByteCodeInstruction::kLoopMask);
1761 this->write(ByteCodeInstruction::kBranchIfAllFalse);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001762 DeferredLocation endLocation(this);
1763 this->writeStatement(*w.fStatement);
Brian Osmanb08cc022020-04-02 11:38:40 -04001764 this->write(ByteCodeInstruction::kLoopNext);
1765 this->write(ByteCodeInstruction::kBranch);
1766 this->write16(cond);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001767 endLocation.set();
Brian Osmanb08cc022020-04-02 11:38:40 -04001768 this->write(ByteCodeInstruction::kLoopEnd);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001769}
1770
1771void ByteCodeGenerator::writeStatement(const Statement& s) {
1772 switch (s.fKind) {
1773 case Statement::kBlock_Kind:
John Stiles26f98502020-08-18 09:30:51 -04001774 this->writeBlock(s.as<Block>());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001775 break;
1776 case Statement::kBreak_Kind:
John Stiles26f98502020-08-18 09:30:51 -04001777 this->writeBreakStatement(s.as<BreakStatement>());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001778 break;
1779 case Statement::kContinue_Kind:
John Stiles26f98502020-08-18 09:30:51 -04001780 this->writeContinueStatement(s.as<ContinueStatement>());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001781 break;
Brian Osmanb08cc022020-04-02 11:38:40 -04001782 case Statement::kDiscard_Kind:
1783 // not yet implemented
1784 abort();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001785 case Statement::kDo_Kind:
John Stiles26f98502020-08-18 09:30:51 -04001786 this->writeDoStatement(s.as<DoStatement>());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001787 break;
Brian Osman3e29f1d2019-05-28 09:35:05 -04001788 case Statement::kExpression_Kind:
John Stiles26f98502020-08-18 09:30:51 -04001789 this->writeExpression(*s.as<ExpressionStatement>().fExpression, true);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001790 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001791 case Statement::kFor_Kind:
John Stiles26f98502020-08-18 09:30:51 -04001792 this->writeForStatement(s.as<ForStatement>());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001793 break;
1794 case Statement::kIf_Kind:
John Stiles26f98502020-08-18 09:30:51 -04001795 this->writeIfStatement(s.as<IfStatement>());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001796 break;
1797 case Statement::kNop_Kind:
1798 break;
1799 case Statement::kReturn_Kind:
John Stiles26f98502020-08-18 09:30:51 -04001800 this->writeReturnStatement(s.as<ReturnStatement>());
Brian Osmanb08cc022020-04-02 11:38:40 -04001801 break;
1802 case Statement::kSwitch_Kind:
John Stiles26f98502020-08-18 09:30:51 -04001803 this->writeSwitchStatement(s.as<SwitchStatement>());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001804 break;
1805 case Statement::kVarDeclarations_Kind:
John Stiles26f98502020-08-18 09:30:51 -04001806 this->writeVarDeclarations(*s.as<VarDeclarationsStatement>().fDeclaration);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001807 break;
1808 case Statement::kWhile_Kind:
John Stiles26f98502020-08-18 09:30:51 -04001809 this->writeWhileStatement(s.as<WhileStatement>());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001810 break;
1811 default:
Brian Osmanb08cc022020-04-02 11:38:40 -04001812 SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001813 }
1814}
1815
Brian Osmanb08cc022020-04-02 11:38:40 -04001816ByteCodeFunction::ByteCodeFunction(const FunctionDeclaration* declaration)
1817 : fName(declaration->fName) {
Brian Osman80164412019-06-07 13:00:23 -04001818 fParameterCount = 0;
Brian Osmanb08cc022020-04-02 11:38:40 -04001819 for (const auto& p : declaration->fParameters) {
1820 int slots = ByteCodeGenerator::SlotCount(p->fType);
1821 fParameters.push_back({ slots, (bool)(p->fModifiers.fFlags & Modifiers::kOut_Flag) });
1822 fParameterCount += slots;
Brian Osman80164412019-06-07 13:00:23 -04001823 }
1824}
1825
John Stilesa6841be2020-08-06 14:11:56 -04001826} // namespace SkSL