blob: d4575b369561d15ccf199d8a5bde392ceb8049e6 [file] [log] [blame]
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001/*
2 * Copyright 2018 Google Inc.
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
8#ifndef SKSL_STANDALONE
9
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "src/core/SkRasterPipeline.h"
11#include "src/sksl/SkSLInterpreter.h"
12#include "src/sksl/ir/SkSLBinaryExpression.h"
13#include "src/sksl/ir/SkSLExpressionStatement.h"
14#include "src/sksl/ir/SkSLForStatement.h"
15#include "src/sksl/ir/SkSLFunctionCall.h"
16#include "src/sksl/ir/SkSLFunctionReference.h"
17#include "src/sksl/ir/SkSLIfStatement.h"
18#include "src/sksl/ir/SkSLIndexExpression.h"
19#include "src/sksl/ir/SkSLPostfixExpression.h"
20#include "src/sksl/ir/SkSLPrefixExpression.h"
21#include "src/sksl/ir/SkSLProgram.h"
22#include "src/sksl/ir/SkSLStatement.h"
23#include "src/sksl/ir/SkSLTernaryExpression.h"
24#include "src/sksl/ir/SkSLVarDeclarations.h"
25#include "src/sksl/ir/SkSLVarDeclarationsStatement.h"
26#include "src/sksl/ir/SkSLVariableReference.h"
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040027
28namespace SkSL {
29
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040030static constexpr int UNINITIALIZED = 0xDEADBEEF;
31
Ethan Nicholas746035a2019-04-23 13:31:09 -040032Interpreter::Value* Interpreter::run(const ByteCodeFunction& f, Interpreter::Value args[],
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040033 Interpreter::Value inputs[]) {
34 fIP = 0;
35 fCurrentFunction = &f;
36 fStack.clear();
37 fGlobals.clear();
38#ifdef TRACE
39 this->disassemble(f);
40#endif
41 for (int i = 0; i < f.fParameterCount; ++i) {
42 this->push(args[i]);
43 }
44 for (int i = 0; i < f.fLocalCount; ++i) {
45 this->push(Value((int) UNINITIALIZED));
46 }
47 for (int i = 0; i < f.fOwner.fGlobalCount; ++i) {
48 fGlobals.push_back(Value((int) UNINITIALIZED));
49 }
50 for (int i = f.fOwner.fInputSlots.size() - 1; i >= 0; --i) {
51 fGlobals[f.fOwner.fInputSlots[i]] = inputs[i];
52 }
53 run();
54 int offset = 0;
55 for (const auto& p : f.fDeclaration.fParameters) {
56 if (p->fModifiers.fFlags & Modifiers::kOut_Flag) {
57 for (int i = p->fType.columns() * p->fType.rows() - 1; i >= 0; --i) {
58 args[offset] = fStack[offset];
59 ++offset;
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040060 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040061 } else {
62 offset += p->fType.columns() * p->fType.rows();
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040063 }
64 }
Ethan Nicholas746035a2019-04-23 13:31:09 -040065 return fStack.data();
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040066}
67
Mike Kleinb11ab572018-10-24 06:42:14 -040068struct CallbackCtx : public SkRasterPipeline_CallbackCtx {
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040069 Interpreter* fInterpreter;
70 const FunctionDefinition* fFunction;
71};
72
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040073uint8_t Interpreter::read8() {
74 return fCurrentFunction->fCode[fIP++];
75}
76
77uint16_t Interpreter::read16() {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -040078 SkASSERT(fIP % 2 == 0);
79 uint16_t result = *(uint16_t*) &fCurrentFunction->fCode[fIP];
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040080 fIP += 2;
81 return result;
82}
83
84uint32_t Interpreter::read32() {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -040085 SkASSERT(fIP % 4 == 0);
86 uint32_t result = *(uint32_t*) &fCurrentFunction->fCode[fIP];
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040087 fIP += 4;
88 return result;
89}
90
91void Interpreter::push(Value v) {
92 fStack.push_back(v);
93}
94
95Interpreter::Value Interpreter::pop() {
96 Value v = fStack.back();
97 fStack.pop_back();
98 return v;
99}
100
101static String value_string(uint32_t v) {
102 union { uint32_t u; float f; } pun = { v };
103 return to_string(v) + "(" + to_string(pun.f) + ")";
104}
105
106void Interpreter::disassemble(const ByteCodeFunction& f) {
107 SkASSERT(fIP == 0);
108 while (fIP < (int) f.fCode.size()) {
109 printf("%d: ", fIP);
110 switch ((ByteCodeInstruction) this->read8()) {
111 case ByteCodeInstruction::kAddF: printf("addf"); break;
112 case ByteCodeInstruction::kAddI: printf("addi"); break;
113 case ByteCodeInstruction::kAndB: printf("andb"); break;
114 case ByteCodeInstruction::kAndI: printf("andi"); break;
115 case ByteCodeInstruction::kBranch: printf("branch %d", this->read16()); break;
116 case ByteCodeInstruction::kCompareIEQ: printf("comparei eq"); break;
117 case ByteCodeInstruction::kCompareINEQ: printf("comparei neq"); break;
118 case ByteCodeInstruction::kCompareFEQ: printf("comparef eq"); break;
119 case ByteCodeInstruction::kCompareFGT: printf("comparef gt"); break;
120 case ByteCodeInstruction::kCompareFGTEQ: printf("comparef gteq"); break;
121 case ByteCodeInstruction::kCompareFLT: printf("comparef lt"); break;
122 case ByteCodeInstruction::kCompareFLTEQ: printf("comparef lteq"); break;
123 case ByteCodeInstruction::kCompareFNEQ: printf("comparef neq"); break;
124 case ByteCodeInstruction::kCompareSGT: printf("compares sgt"); break;
125 case ByteCodeInstruction::kCompareSGTEQ: printf("compares sgteq"); break;
126 case ByteCodeInstruction::kCompareSLT: printf("compares lt"); break;
127 case ByteCodeInstruction::kCompareSLTEQ: printf("compares lteq"); break;
128 case ByteCodeInstruction::kCompareUGT: printf("compareu gt"); break;
129 case ByteCodeInstruction::kCompareUGTEQ: printf("compareu gteq"); break;
130 case ByteCodeInstruction::kCompareULT: printf("compareu lt"); break;
131 case ByteCodeInstruction::kCompareULTEQ: printf("compareu lteq"); break;
132 case ByteCodeInstruction::kConditionalBranch:
133 printf("conditionalbranch %d", this->read16());
134 break;
135 case ByteCodeInstruction::kDebugPrint: printf("debugprint"); break;
136 case ByteCodeInstruction::kDivideF: printf("dividef"); break;
137 case ByteCodeInstruction::kDivideS: printf("divides"); break;
138 case ByteCodeInstruction::kDivideU: printf("divideu"); break;
139 case ByteCodeInstruction::kDup: printf("dup"); break;
140 case ByteCodeInstruction::kDupDown: printf("dupdown %d", this->read8()); break;
141 case ByteCodeInstruction::kFloatToInt: printf("floattoint"); break;
142 case ByteCodeInstruction::kLoad: printf("load"); break;
Ethan Nicholas746035a2019-04-23 13:31:09 -0400143 case ByteCodeInstruction::kLoadGlobal: printf("loadglobal %d", this->read8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400144 case ByteCodeInstruction::kLoadSwizzle: {
145 int count = this->read8();
146 printf("loadswizzle %d", count);
147 for (int i = 0; i < count; ++i) {
148 printf(", %d", this->read8());
149 }
150 break;
151 }
152 case ByteCodeInstruction::kMultiplyF: printf("multiplyf"); break;
153 case ByteCodeInstruction::kMultiplyS: printf("multiplys"); break;
154 case ByteCodeInstruction::kMultiplyU: printf("multiplyu"); break;
155 case ByteCodeInstruction::kNegateF: printf("negatef"); break;
156 case ByteCodeInstruction::kNegateS: printf("negates"); break;
157 case ByteCodeInstruction::kNot: printf("not"); break;
158 case ByteCodeInstruction::kOrB: printf("orb"); break;
159 case ByteCodeInstruction::kOrI: printf("ori"); break;
160 case ByteCodeInstruction::kParameter: printf("parameter"); break;
161 case ByteCodeInstruction::kPop: printf("pop %d", this->read8()); break;
162 case ByteCodeInstruction::kPushImmediate:
163 printf("pushimmediate %s", value_string(this->read32()).c_str());
164 break;
165 case ByteCodeInstruction::kRemainderS: printf("remainders"); break;
166 case ByteCodeInstruction::kRemainderU: printf("remainderu"); break;
Ethan Nicholas746035a2019-04-23 13:31:09 -0400167 case ByteCodeInstruction::kReturn: printf("return %d", this->read8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400168 case ByteCodeInstruction::kSignedToFloat: printf("signedtofloat"); break;
169 case ByteCodeInstruction::kStore: printf("store"); break;
Ethan Nicholas746035a2019-04-23 13:31:09 -0400170 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal"); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400171 case ByteCodeInstruction::kStoreSwizzle: {
172 int count = this->read8();
173 printf("storeswizzle %d", count);
174 for (int i = 0; i < count; ++i) {
175 printf(", %d", this->read8());
176 }
177 break;
178 }
179 case ByteCodeInstruction::kSubtractF: printf("subtractf"); break;
180 case ByteCodeInstruction::kSubtractI: printf("subtracti"); break;
181 case ByteCodeInstruction::kSwizzle: {
182 printf("swizzle %d, ", this->read8());
183 int count = this->read8();
184 printf("%d", count);
185 for (int i = 0; i < count; ++i) {
186 printf(", %d", this->read8());
187 }
188 break;
189 }
190 case ByteCodeInstruction::kUnsignedToFloat: printf("unsignedtofloat"); break;
191 case ByteCodeInstruction::kVector: printf("vector%d", this->read8()); break;
Ethan Nicholas746035a2019-04-23 13:31:09 -0400192 default: printf("%d\n", fCurrentFunction->fCode[fIP - 1]);
193 SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400194 }
195 printf("\n");
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400196 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400197 fIP = 0;
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400198}
199
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400200void Interpreter::dumpStack() {
201 printf("STACK:");
202 for (size_t i = 0; i < fStack.size(); ++i) {
203 printf(" %d(%f)", fStack[i].fSigned, fStack[i].fFloat);
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400204 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400205 printf("\n");
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400206}
207
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400208#define BINARY_OP(inst, type, field, op) \
209 case ByteCodeInstruction::inst: { \
210 type b = this->pop().field; \
Ethan Nicholas95859472019-04-24 12:55:51 -0400211 Value* a = &fStack.back(); \
212 *a = Value(a->field op b); \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400213 break; \
214 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400215
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400216static constexpr int VECTOR_MAX = 16;
217
218#define VECTOR_BINARY_OP(inst, type, field, op) \
219 case ByteCodeInstruction::inst: { \
220 Value result[VECTOR_MAX]; \
221 for (int i = count - 1; i >= 0; --i) { \
222 result[i] = this->pop(); \
223 } \
224 for (int i = count - 1; i >= 0; --i) { \
225 result[i] = this->pop().field op result[i].field; \
226 } \
227 for (int i = 0; i < count; ++i) { \
228 this->push(result[i]); \
229 } \
230 break; \
231 }
232
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400233void Interpreter::vectorOp(int count) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400234 ByteCodeInstruction inst = (ByteCodeInstruction) this->read8();
235 switch (inst) {
236 VECTOR_BINARY_OP(kAddI, int32_t, fSigned, +)
237 VECTOR_BINARY_OP(kAddF, float, fFloat, +)
238 case ByteCodeInstruction::kBranch:
239 fIP = this->read16();
240 break;
241 VECTOR_BINARY_OP(kCompareIEQ, int32_t, fSigned, ==)
242 VECTOR_BINARY_OP(kCompareFEQ, float, fFloat, ==)
243 VECTOR_BINARY_OP(kCompareINEQ, int32_t, fSigned, !=)
244 VECTOR_BINARY_OP(kCompareFNEQ, float, fFloat, !=)
245 VECTOR_BINARY_OP(kCompareSGT, int32_t, fSigned, >)
246 VECTOR_BINARY_OP(kCompareUGT, uint32_t, fUnsigned, >)
247 VECTOR_BINARY_OP(kCompareFGT, float, fFloat, >)
248 VECTOR_BINARY_OP(kCompareSGTEQ, int32_t, fSigned, >=)
249 VECTOR_BINARY_OP(kCompareUGTEQ, uint32_t, fUnsigned, >=)
250 VECTOR_BINARY_OP(kCompareFGTEQ, float, fFloat, >=)
251 VECTOR_BINARY_OP(kCompareSLT, int32_t, fSigned, <)
252 VECTOR_BINARY_OP(kCompareULT, uint32_t, fUnsigned, <)
253 VECTOR_BINARY_OP(kCompareFLT, float, fFloat, <)
254 VECTOR_BINARY_OP(kCompareSLTEQ, int32_t, fSigned, <=)
255 VECTOR_BINARY_OP(kCompareULTEQ, uint32_t, fUnsigned, <=)
256 VECTOR_BINARY_OP(kCompareFLTEQ, float, fFloat, <=)
257 case ByteCodeInstruction::kConditionalBranch: {
258 int target = this->read16();
259 if (this->pop().fBool) {
260 fIP = target;
261 }
262 break;
263 }
264 VECTOR_BINARY_OP(kDivideS, int32_t, fSigned, /)
265 VECTOR_BINARY_OP(kDivideU, uint32_t, fUnsigned, /)
266 VECTOR_BINARY_OP(kDivideF, float, fFloat, /)
267 case ByteCodeInstruction::kFloatToInt: {
268 for (int i = 0; i < count; ++i) {
269 Value& v = fStack[fStack.size() - i - 1];
270 v.fSigned = (int) v.fFloat;
271 }
272 break;
273 }
274 case ByteCodeInstruction::kSignedToFloat: {
275 for (int i = 0; i < count; ++i) {
276 Value& v = fStack[fStack.size() - i - 1];
277 v.fFloat = (float) v.fSigned;
278 }
279 break;
280 }
281 case ByteCodeInstruction::kUnsignedToFloat: {
282 for (int i = 0; i < count; ++i) {
283 Value& v = fStack[fStack.size() - i - 1];
284 v.fFloat = (float) v.fUnsigned;
285 }
286 break;
287 }
288 case ByteCodeInstruction::kLoad: {
289 int target = this->pop().fSigned;
290 for (int i = 0; i < count; ++i) {
291 SkASSERT(target < (int) fStack.size());
292 this->push(fStack[target++]);
293 }
294 break;
295 }
296 case ByteCodeInstruction::kLoadGlobal: {
297 int target = this->read8();
298 SkASSERT(target < (int) fGlobals.size());
299 this->push(fGlobals[target]);
300 break;
301 }
302 VECTOR_BINARY_OP(kMultiplyS, int32_t, fSigned, *)
303 VECTOR_BINARY_OP(kMultiplyU, uint32_t, fUnsigned, *)
304 VECTOR_BINARY_OP(kMultiplyF, float, fFloat, *)
305 VECTOR_BINARY_OP(kRemainderS, int32_t, fSigned, %)
306 VECTOR_BINARY_OP(kRemainderU, uint32_t, fUnsigned, %)
307 case ByteCodeInstruction::kStore: {
308 int target = fStack[fStack.size() - count - 1].fSigned + count;
309 for (int i = count - 1; i >= 0; --i) {
310 SkASSERT(target < (int) fStack.size());
311 fStack[--target] = this->pop();
312 }
313 break;
314 }
315 VECTOR_BINARY_OP(kSubtractI, int32_t, fSigned, -)
316 VECTOR_BINARY_OP(kSubtractF, float, fFloat, -)
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400317 default:
318 printf("unsupported instruction %d\n", (int) inst);
319 SkASSERT(false);
320 }
321}
322
323void Interpreter::run() {
324 while (fIP < (int) fCurrentFunction->fCode.size()) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400325#ifdef TRACE
326 printf("at %d\n", fIP);
327#endif
328 ByteCodeInstruction inst = (ByteCodeInstruction) this->read8();
329 switch (inst) {
330 BINARY_OP(kAddI, int32_t, fSigned, +)
331 BINARY_OP(kAddF, float, fFloat, +)
332 case ByteCodeInstruction::kBranch:
333 fIP = this->read16();
334 break;
335 BINARY_OP(kCompareIEQ, int32_t, fSigned, ==)
336 BINARY_OP(kCompareFEQ, float, fFloat, ==)
337 BINARY_OP(kCompareINEQ, int32_t, fSigned, !=)
338 BINARY_OP(kCompareFNEQ, float, fFloat, !=)
339 BINARY_OP(kCompareSGT, int32_t, fSigned, >)
340 BINARY_OP(kCompareUGT, uint32_t, fUnsigned, >)
341 BINARY_OP(kCompareFGT, float, fFloat, >)
342 BINARY_OP(kCompareSGTEQ, int32_t, fSigned, >=)
343 BINARY_OP(kCompareUGTEQ, uint32_t, fUnsigned, >=)
344 BINARY_OP(kCompareFGTEQ, float, fFloat, >=)
345 BINARY_OP(kCompareSLT, int32_t, fSigned, <)
346 BINARY_OP(kCompareULT, uint32_t, fUnsigned, <)
347 BINARY_OP(kCompareFLT, float, fFloat, <)
348 BINARY_OP(kCompareSLTEQ, int32_t, fSigned, <=)
349 BINARY_OP(kCompareULTEQ, uint32_t, fUnsigned, <=)
350 BINARY_OP(kCompareFLTEQ, float, fFloat, <=)
351 case ByteCodeInstruction::kConditionalBranch: {
352 int target = this->read16();
353 if (this->pop().fBool) {
354 fIP = target;
355 }
356 break;
357 }
358 case ByteCodeInstruction::kDebugPrint: {
359 Value v = this->pop();
360 printf("Debug: %d(int), %d(uint), %f(float)\n", v.fSigned, v.fUnsigned, v.fFloat);
361 break;
362 }
363 BINARY_OP(kDivideS, int32_t, fSigned, /)
364 BINARY_OP(kDivideU, uint32_t, fUnsigned, /)
365 BINARY_OP(kDivideF, float, fFloat, /)
366 case ByteCodeInstruction::kDup:
367 this->push(fStack.back());
368 break;
369 case ByteCodeInstruction::kDupDown: {
370 int count = this->read8();
371 for (int i = 0; i < count; ++i) {
372 fStack.insert(fStack.end() - i - count - 1, fStack[fStack.size() - i - 1]);
373 }
374 break;
375 }
376 case ByteCodeInstruction::kFloatToInt: {
377 Value& top = fStack.back();
378 top.fSigned = (int) top.fFloat;
379 break;
380 }
381 case ByteCodeInstruction::kSignedToFloat: {
382 Value& top = fStack.back();
383 top.fFloat = (float) top.fSigned;
384 break;
385 }
386 case ByteCodeInstruction::kUnsignedToFloat: {
387 Value& top = fStack.back();
388 top.fFloat = (float) top.fUnsigned;
389 break;
390 }
391 case ByteCodeInstruction::kLoad: {
392 int target = this->pop().fSigned;
393 SkASSERT(target < (int) fStack.size());
394 this->push(fStack[target]);
395 break;
396 }
397 case ByteCodeInstruction::kLoadGlobal: {
398 int target = this->read8();
399 SkASSERT(target < (int) fGlobals.size());
400 this->push(fGlobals[target]);
401 break;
402 }
403 case ByteCodeInstruction::kLoadSwizzle: {
404 Value target = this->pop();
405 int count = read8();
406 for (int i = 0; i < count; ++i) {
407 SkASSERT(target.fSigned + fCurrentFunction->fCode[fIP + i] < (int) fStack.size());
408 this->push(fStack[target.fSigned + fCurrentFunction->fCode[fIP + i]]);
409 }
410 fIP += count;
411 break;
412 }
413 BINARY_OP(kMultiplyS, int32_t, fSigned, *)
414 BINARY_OP(kMultiplyU, uint32_t, fUnsigned, *)
415 BINARY_OP(kMultiplyF, float, fFloat, *)
416 case ByteCodeInstruction::kNot: {
417 Value& top = fStack.back();
418 top.fBool = !top.fBool;
419 break;
420 }
421 case ByteCodeInstruction::kNegateF: {
422 Value& top = fStack.back();
423 top.fFloat = -top.fFloat;
424 break;
425 }
426 case ByteCodeInstruction::kNegateS: {
427 Value& top = fStack.back();
428 top.fSigned = -top.fSigned;
429 break;
430 }
431 case ByteCodeInstruction::kNop:
432 break;
433 case ByteCodeInstruction::kPop:
434 for (int i = read8(); i > 0; --i) {
435 this->pop();
436 }
437 break;
438 case ByteCodeInstruction::kPushImmediate:
439 this->push(Value((int) read32()));
440 break;
441 BINARY_OP(kRemainderS, int32_t, fSigned, %)
442 BINARY_OP(kRemainderU, uint32_t, fUnsigned, %)
443 case ByteCodeInstruction::kReturn: {
444 int count = this->read8();
445 for (int i = 0; i < count; ++i) {
446 fStack[i] = fStack[fStack.size() - count + i];
447 }
448 fIP = (int) fCurrentFunction->fCode.size();
449 break;
450 }
451 case ByteCodeInstruction::kStore: {
452 Value value = this->pop();
453 int target = this->pop().fSigned;
454 SkASSERT(target < (int) fStack.size());
455 fStack[target] = value;
456 break;
457 }
458 case ByteCodeInstruction::kStoreGlobal: {
459 Value value = this->pop();
460 int target = this->pop().fSigned;
461 SkASSERT(target < (int) fGlobals.size());
462 fGlobals[target] = value;
463 break;
464 }
465 case ByteCodeInstruction::kStoreSwizzle: {
466 int count = read8();
467 int target = fStack[fStack.size() - count - 1].fSigned;
468 for (int i = count - 1; i >= 0; --i) {
469 SkASSERT(target + fCurrentFunction->fCode[fIP + i] < (int) fStack.size());
470 fStack[target + fCurrentFunction->fCode[fIP + i]] = this->pop();
471 }
472 this->pop();
473 fIP += count;
474 break;
475 }
476 BINARY_OP(kSubtractI, int32_t, fSigned, -)
477 BINARY_OP(kSubtractF, float, fFloat, -)
478 case ByteCodeInstruction::kSwizzle: {
479 Value vec[4];
480 for (int i = this->read8() - 1; i >= 0; --i) {
481 vec[i] = this->pop();
482 }
483 for (int i = this->read8() - 1; i >= 0; --i) {
484 this->push(vec[this->read8()]);
485 }
486 break;
487 }
488 case ByteCodeInstruction::kVector:
489 this->vectorOp(this->read8());
490 break;
491 default:
492 printf("unsupported instruction %d\n", (int) inst);
493 SkASSERT(false);
494 }
495#ifdef TRACE
496 this->dumpStack();
497#endif
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400498 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400499}
500
501} // namespace
502
503#endif