blob: 9e284450d893f3a6a2511b2cb246d99283792b86 [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"
Ethan Nicholas91164d12019-05-15 15:29:54 -040011#include "src/sksl/SkSLExternalValue.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "src/sksl/SkSLInterpreter.h"
13#include "src/sksl/ir/SkSLBinaryExpression.h"
14#include "src/sksl/ir/SkSLExpressionStatement.h"
15#include "src/sksl/ir/SkSLForStatement.h"
16#include "src/sksl/ir/SkSLFunctionCall.h"
17#include "src/sksl/ir/SkSLFunctionReference.h"
18#include "src/sksl/ir/SkSLIfStatement.h"
19#include "src/sksl/ir/SkSLIndexExpression.h"
20#include "src/sksl/ir/SkSLPostfixExpression.h"
21#include "src/sksl/ir/SkSLPrefixExpression.h"
22#include "src/sksl/ir/SkSLProgram.h"
23#include "src/sksl/ir/SkSLStatement.h"
24#include "src/sksl/ir/SkSLTernaryExpression.h"
25#include "src/sksl/ir/SkSLVarDeclarations.h"
26#include "src/sksl/ir/SkSLVarDeclarationsStatement.h"
27#include "src/sksl/ir/SkSLVariableReference.h"
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040028
29namespace SkSL {
30
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040031static constexpr int UNINITIALIZED = 0xDEADBEEF;
32
Mike Kleine7007382019-05-21 08:36:32 -050033Interpreter::Interpreter(std::unique_ptr<Program> program,
34 std::unique_ptr<ByteCode> byteCode,
Ethan Nicholasdfcad062019-05-07 12:53:34 -040035 Interpreter::Value inputs[])
36 : fProgram(std::move(program))
Mike Kleine7007382019-05-21 08:36:32 -050037 , fByteCode(std::move(byteCode))
38 , fGlobals(fByteCode->fGlobalCount, UNINITIALIZED) {
Brian Osmand369a5e2019-05-09 13:13:25 -040039 this->setInputs(inputs);
40}
41
42void Interpreter::setInputs(Interpreter::Value inputs[]) {
Mike Kleine7007382019-05-21 08:36:32 -050043 for (uint8_t slot : fByteCode->fInputSlots) {
44 fGlobals[slot] = *inputs++;
Ethan Nicholasdfcad062019-05-07 12:53:34 -040045 }
46}
47
48void Interpreter::run(const ByteCodeFunction& f, Interpreter::Value args[],
49 Interpreter::Value* outReturn) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040050#ifdef TRACE
51 this->disassemble(f);
52#endif
Ethan Nicholasdfcad062019-05-07 12:53:34 -040053 Value smallStack[128];
54 std::unique_ptr<Value[]> largeStack;
55 Value* stack = smallStack;
Brian Osman226668a2019-05-14 16:47:30 -040056 if ((int) SK_ARRAY_COUNT(smallStack) < f.fStackCount) {
57 largeStack.reset(new Value[f.fStackCount]);
Ethan Nicholasdfcad062019-05-07 12:53:34 -040058 stack = largeStack.get();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040059 }
Mike Kleine7007382019-05-21 08:36:32 -050060
61 if (f.fParameterCount) {
62 memcpy(stack, args, f.fParameterCount * sizeof(Value));
63 }
64 this->innerRun(f, stack, outReturn);
65
66 for (const Variable* p : f.fDeclaration.fParameters) {
67 const int nvalues = p->fType.columns()
68 * p->fType.rows();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040069 if (p->fModifiers.fFlags & Modifiers::kOut_Flag) {
Mike Kleine7007382019-05-21 08:36:32 -050070 memcpy(args, stack, nvalues * sizeof(Value));
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040071 }
Mike Kleine7007382019-05-21 08:36:32 -050072 args += nvalues;
73 stack += nvalues;
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040074 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040075}
76
Mike Klein76346ac2019-05-17 11:57:10 -050077template <typename T>
78static T unaligned_load(const void* ptr) {
79 T val;
80 memcpy(&val, ptr, sizeof(val));
81 return val;
82}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040083
Mike Kleine7007382019-05-21 08:36:32 -050084#define READ8() (*(ip++))
Mike Klein76346ac2019-05-17 11:57:10 -050085#define READ16() (ip += 2, unaligned_load<uint16_t>(ip - 2))
86#define READ32() (ip += 4, unaligned_load<uint32_t>(ip - 4))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040087
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040088#define VECTOR_DISASSEMBLE(op, text) \
89 case ByteCodeInstruction::op: printf(text); break; \
90 case ByteCodeInstruction::op##2: printf(text "2"); break; \
91 case ByteCodeInstruction::op##3: printf(text "3"); break; \
92 case ByteCodeInstruction::op##4: printf(text "4"); break;
93
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040094void Interpreter::disassemble(const ByteCodeFunction& f) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -040095 const uint8_t* ip = f.fCode.data();
96 while (ip < f.fCode.data() + f.fCode.size()) {
97 printf("%d: ", (int) (ip - f.fCode.data()));
Mike Klein108e9352019-05-21 11:05:17 -050098 switch ((ByteCodeInstruction) READ16()) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040099 VECTOR_DISASSEMBLE(kAddF, "addf")
100 VECTOR_DISASSEMBLE(kAddI, "addi")
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400101 case ByteCodeInstruction::kAndB: printf("andb"); break;
102 case ByteCodeInstruction::kAndI: printf("andi"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400103 case ByteCodeInstruction::kBranch: printf("branch %d", READ16()); break;
Brian Osman226668a2019-05-14 16:47:30 -0400104 case ByteCodeInstruction::kCall: printf("call %d", READ8()); break;
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400105 case ByteCodeInstruction::kCallExternal: {
106 int argumentCount = READ8();
107 int returnCount = READ8();
108 int externalValue = READ8();
109 printf("callexternal %d, %d, %d", argumentCount, returnCount, externalValue);
110 break;
111 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400112 VECTOR_DISASSEMBLE(kCompareIEQ, "compareieq")
113 VECTOR_DISASSEMBLE(kCompareINEQ, "compareineq")
114 VECTOR_DISASSEMBLE(kCompareFEQ, "comparefeq")
115 VECTOR_DISASSEMBLE(kCompareFNEQ, "comparefneq")
116 VECTOR_DISASSEMBLE(kCompareFGT, "comparefgt")
117 VECTOR_DISASSEMBLE(kCompareFGTEQ, "comparefgteq")
118 VECTOR_DISASSEMBLE(kCompareFLT, "compareflt")
119 VECTOR_DISASSEMBLE(kCompareFLTEQ, "compareflteq")
120 VECTOR_DISASSEMBLE(kCompareSGT, "comparesgt")
121 VECTOR_DISASSEMBLE(kCompareSGTEQ, "comparesgteq")
122 VECTOR_DISASSEMBLE(kCompareSLT, "compareslt")
123 VECTOR_DISASSEMBLE(kCompareSLTEQ, "compareslteq")
124 VECTOR_DISASSEMBLE(kCompareUGT, "compareugt")
125 VECTOR_DISASSEMBLE(kCompareUGTEQ, "compareugteq")
126 VECTOR_DISASSEMBLE(kCompareULT, "compareult")
127 VECTOR_DISASSEMBLE(kCompareULTEQ, "compareulteq")
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400128 case ByteCodeInstruction::kConditionalBranch:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400129 printf("conditionalbranch %d", READ16());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400130 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400131 VECTOR_DISASSEMBLE(kConvertFtoI, "convertftoi")
132 VECTOR_DISASSEMBLE(kConvertStoF, "convertstof")
133 VECTOR_DISASSEMBLE(kConvertUtoF, "convertutof")
134 VECTOR_DISASSEMBLE(kCos, "cos")
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400135 case ByteCodeInstruction::kDebugPrint: printf("debugprint"); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400136 VECTOR_DISASSEMBLE(kDivideF, "dividef")
137 VECTOR_DISASSEMBLE(kDivideS, "divideS")
138 VECTOR_DISASSEMBLE(kDivideU, "divideu")
139 VECTOR_DISASSEMBLE(kDup, "dup")
Brian Osman1091f022019-05-16 09:42:16 -0400140 case ByteCodeInstruction::kLoad: printf("load %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400141 case ByteCodeInstruction::kLoad2: printf("load2 %d", READ8()); break;
142 case ByteCodeInstruction::kLoad3: printf("load3 %d", READ8()); break;
143 case ByteCodeInstruction::kLoad4: printf("load4 %d", READ8()); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400144 case ByteCodeInstruction::kLoadGlobal: printf("loadglobal %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400145 case ByteCodeInstruction::kLoadGlobal2: printf("loadglobal2 %d", READ8()); break;
146 case ByteCodeInstruction::kLoadGlobal3: printf("loadglobal3 %d", READ8()); break;
147 case ByteCodeInstruction::kLoadGlobal4: printf("loadglobal4 %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400148 case ByteCodeInstruction::kLoadSwizzle: {
Brian Osman1091f022019-05-16 09:42:16 -0400149 int target = READ8();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400150 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400151 printf("loadswizzle %d %d", target, count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400152 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400153 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400154 }
155 break;
156 }
Brian Osmanb7451292019-05-15 13:02:13 -0400157 case ByteCodeInstruction::kLoadSwizzleGlobal: {
Brian Osman1091f022019-05-16 09:42:16 -0400158 int target = READ8();
Brian Osmanb7451292019-05-15 13:02:13 -0400159 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400160 printf("loadswizzleglobal %d %d", target, count);
Brian Osmanb7451292019-05-15 13:02:13 -0400161 for (int i = 0; i < count; ++i) {
162 printf(", %d", READ8());
163 }
164 break;
165 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400166 VECTOR_DISASSEMBLE(kMultiplyF, "multiplyf")
167 VECTOR_DISASSEMBLE(kMultiplyI, "multiplyi")
168 VECTOR_DISASSEMBLE(kNegateF, "negatef")
Mike Klein12710912019-05-21 11:04:59 -0500169 VECTOR_DISASSEMBLE(kNegateI, "negatei")
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400170 VECTOR_DISASSEMBLE(kNot, "not")
171 VECTOR_DISASSEMBLE(kOrB, "orb")
172 VECTOR_DISASSEMBLE(kOrI, "ori")
173 VECTOR_DISASSEMBLE(kPop, "pop")
Mike Kleine7007382019-05-21 08:36:32 -0500174 case ByteCodeInstruction::kPushImmediate: {
175 uint32_t v = READ32();
176 union { uint32_t u; float f; } pun = { v };
177 printf("pushimmediate %s", (to_string(v) + "(" + to_string(pun.f) + ")").c_str());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400178 break;
Mike Kleine7007382019-05-21 08:36:32 -0500179 }
Ethan Nicholas91164d12019-05-15 15:29:54 -0400180 case ByteCodeInstruction::kReadExternal: printf("readexternal %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400181 case ByteCodeInstruction::kReadExternal2: printf("readexternal2 %d", READ8()); break;
182 case ByteCodeInstruction::kReadExternal3: printf("readexternal3 %d", READ8()); break;
183 case ByteCodeInstruction::kReadExternal4: printf("readexternal4 %d", READ8()); break;
184 VECTOR_DISASSEMBLE(kRemainderF, "remainderf")
185 VECTOR_DISASSEMBLE(kRemainderS, "remainders")
186 VECTOR_DISASSEMBLE(kRemainderU, "remainderu")
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400187 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400188 VECTOR_DISASSEMBLE(kSin, "sin")
189 VECTOR_DISASSEMBLE(kSqrt, "sqrt")
Brian Osman1091f022019-05-16 09:42:16 -0400190 case ByteCodeInstruction::kStore: printf("store %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400191 case ByteCodeInstruction::kStore2: printf("store2 %d", READ8()); break;
192 case ByteCodeInstruction::kStore3: printf("store3 %d", READ8()); break;
193 case ByteCodeInstruction::kStore4: printf("store4 %d", READ8()); break;
Brian Osman1091f022019-05-16 09:42:16 -0400194 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400195 case ByteCodeInstruction::kStoreGlobal2: printf("storeglobal2 %d", READ8()); break;
196 case ByteCodeInstruction::kStoreGlobal3: printf("storeglobal3 %d", READ8()); break;
197 case ByteCodeInstruction::kStoreGlobal4: printf("storeglobal4 %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400198 case ByteCodeInstruction::kStoreSwizzle: {
Brian Osman1091f022019-05-16 09:42:16 -0400199 int target = READ8();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400200 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400201 printf("storeswizzle %d %d", target, count);
202 for (int i = 0; i < count; ++i) {
203 printf(", %d", READ8());
204 }
205 break;
206 }
207 case ByteCodeInstruction::kStoreSwizzleGlobal: {
208 int target = READ8();
209 int count = READ8();
210 printf("storeswizzleglobal %d %d", target, count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400211 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400212 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400213 }
214 break;
215 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400216 VECTOR_DISASSEMBLE(kSubtractF, "subtractf")
217 VECTOR_DISASSEMBLE(kSubtractI, "subtracti")
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400218 case ByteCodeInstruction::kSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400219 printf("swizzle %d, ", READ8());
220 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400221 printf("%d", count);
222 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400223 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400224 }
225 break;
226 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400227 VECTOR_DISASSEMBLE(kTan, "tan")
Ethan Nicholas91164d12019-05-15 15:29:54 -0400228 case ByteCodeInstruction::kWriteExternal: printf("writeexternal %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400229 case ByteCodeInstruction::kWriteExternal2: printf("writeexternal2 %d", READ8()); break;
230 case ByteCodeInstruction::kWriteExternal3: printf("writeexternal3 %d", READ8()); break;
231 case ByteCodeInstruction::kWriteExternal4: printf("writeexternal4 %d", READ8()); break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400232 default: printf("unknown(%d)\n", *(ip - 1)); SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400233 }
234 printf("\n");
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400235 }
236}
237
Mike Klein459aed12019-05-21 15:46:36 -0500238#define VECTOR_BINARY_OP(base, field, op) \
Mike Kleine7007382019-05-21 08:36:32 -0500239 case ByteCodeInstruction::base ## 4: \
Mike Klein459aed12019-05-21 15:46:36 -0500240 sp[-4] = sp[-4].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500241 POP(); \
242 /* fall through */ \
243 case ByteCodeInstruction::base ## 3: { \
244 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500245 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500246 POP(); \
247 } /* fall through */ \
248 case ByteCodeInstruction::base ## 2: { \
249 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500250 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500251 POP(); \
252 } /* fall through */ \
253 case ByteCodeInstruction::base: { \
254 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500255 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500256 POP(); \
257 break; \
258 }
Ethan Nicholasaeb71ce2019-05-20 09:55:44 -0400259
Mike Klein459aed12019-05-21 15:46:36 -0500260#define VECTOR_BINARY_FN(base, field, fn) \
Mike Kleine7007382019-05-21 08:36:32 -0500261 case ByteCodeInstruction::base ## 4: \
Mike Klein459aed12019-05-21 15:46:36 -0500262 sp[-4] = fn(sp[-4].field, sp[0].field); \
Mike Kleine7007382019-05-21 08:36:32 -0500263 POP(); \
264 /* fall through */ \
265 case ByteCodeInstruction::base ## 3: { \
266 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500267 sp[count] = fn(sp[count].field, sp[0].field); \
Mike Kleine7007382019-05-21 08:36:32 -0500268 POP(); \
269 } /* fall through */ \
270 case ByteCodeInstruction::base ## 2: { \
271 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500272 sp[count] = fn(sp[count].field, sp[0].field); \
Mike Kleine7007382019-05-21 08:36:32 -0500273 POP(); \
274 } /* fall through */ \
275 case ByteCodeInstruction::base: { \
276 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500277 sp[count] = fn(sp[count].field, sp[0].field); \
Mike Kleine7007382019-05-21 08:36:32 -0500278 POP(); \
279 break; \
280 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400281
Mike Klein459aed12019-05-21 15:46:36 -0500282#define VECTOR_UNARY_FN(base, fn, field) \
283 case ByteCodeInstruction::base ## 4: sp[-3] = fn(sp[-3].field); \
284 case ByteCodeInstruction::base ## 3: sp[-2] = fn(sp[-2].field); \
285 case ByteCodeInstruction::base ## 2: sp[-1] = fn(sp[-1].field); \
286 case ByteCodeInstruction::base: sp[ 0] = fn(sp[ 0].field); \
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400287 break;
288
Brian Osman226668a2019-05-14 16:47:30 -0400289struct StackFrame {
290 const uint8_t* fCode;
291 const uint8_t* fIP;
292 Interpreter::Value* fStack;
293};
294
Mike Kleine7007382019-05-21 08:36:32 -0500295void Interpreter::innerRun(const ByteCodeFunction& f, Value* stack, Value* outReturn) {
296 Value* sp = stack + f.fParameterCount + f.fLocalCount - 1;
297
298 auto POP = [&] { SkASSERT(sp >= stack); return *(sp--); };
299 auto PUSH = [&](Value v) { SkASSERT(sp + 1 >= stack); *(++sp) = v; };
300
Brian Osman226668a2019-05-14 16:47:30 -0400301 const uint8_t* code = f.fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400302 const uint8_t* ip = code;
Brian Osman226668a2019-05-14 16:47:30 -0400303 std::vector<StackFrame> frames;
304
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400305 for (;;) {
Mike Klein108e9352019-05-21 11:05:17 -0500306 ByteCodeInstruction inst = (ByteCodeInstruction) READ16();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400307#ifdef TRACE
Ethan Nicholas91164d12019-05-15 15:29:54 -0400308 printf("at %d\n", (int) (ip - code - 1));
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400309#endif
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400310 switch (inst) {
Mike Kleinc1999982019-05-21 13:03:49 -0500311 VECTOR_BINARY_OP(kAddI, fSigned, +)
312 VECTOR_BINARY_OP(kAddF, fFloat, +)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400313
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400314 case ByteCodeInstruction::kBranch:
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400315 ip = code + READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400316 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400317
Brian Osman226668a2019-05-14 16:47:30 -0400318 case ByteCodeInstruction::kCall: {
319 // Precursor code has pushed all parameters to the stack. Update our bottom of
320 // stack to point at the first parameter, and our sp to point past those parameters
321 // (plus space for locals).
Mike Kleine7007382019-05-21 08:36:32 -0500322 int target = READ8();
Brian Osman226668a2019-05-14 16:47:30 -0400323 const ByteCodeFunction* fun = fByteCode->fFunctions[target].get();
324 frames.push_back({ code, ip, stack });
325 ip = code = fun->fCode.data();
326 stack = sp - fun->fParameterCount + 1;
327 sp = stack + fun->fParameterCount + fun->fLocalCount - 1;
328 break;
329 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400330
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400331 case ByteCodeInstruction::kCallExternal: {
332 int argumentCount = READ8();
333 int returnCount = READ8();
Mike Kleine7007382019-05-21 08:36:32 -0500334 int target = READ8();
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400335 ExternalValue* v = fByteCode->fExternalValues[target];
336 sp -= argumentCount - 1;
Mike Kleine7007382019-05-21 08:36:32 -0500337
338 Value tmp[4];
339 SkASSERT(returnCount <= (int)SK_ARRAY_COUNT(tmp));
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400340 v->call(sp, tmp);
341 memcpy(sp, tmp, returnCount * sizeof(Value));
342 sp += returnCount - 1;
343 break;
344 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400345
Mike Kleinc1999982019-05-21 13:03:49 -0500346 VECTOR_BINARY_OP(kCompareIEQ, fSigned, ==)
347 VECTOR_BINARY_OP(kCompareFEQ, fFloat, ==)
348 VECTOR_BINARY_OP(kCompareINEQ, fSigned, !=)
349 VECTOR_BINARY_OP(kCompareFNEQ, fFloat, !=)
350 VECTOR_BINARY_OP(kCompareSGT, fSigned, >)
351 VECTOR_BINARY_OP(kCompareUGT, fUnsigned, >)
352 VECTOR_BINARY_OP(kCompareFGT, fFloat, >)
353 VECTOR_BINARY_OP(kCompareSGTEQ, fSigned, >=)
354 VECTOR_BINARY_OP(kCompareUGTEQ, fUnsigned, >=)
355 VECTOR_BINARY_OP(kCompareFGTEQ, fFloat, >=)
356 VECTOR_BINARY_OP(kCompareSLT, fSigned, <)
357 VECTOR_BINARY_OP(kCompareULT, fUnsigned, <)
358 VECTOR_BINARY_OP(kCompareFLT, fFloat, <)
359 VECTOR_BINARY_OP(kCompareSLTEQ, fSigned, <=)
360 VECTOR_BINARY_OP(kCompareULTEQ, fUnsigned, <=)
361 VECTOR_BINARY_OP(kCompareFLTEQ, fFloat, <=)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400362
Mike Kleine7007382019-05-21 08:36:32 -0500363 case ByteCodeInstruction::kConditionalBranch: {
364 int target = READ16();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400365 if (POP().fBool) {
Mike Kleine7007382019-05-21 08:36:32 -0500366 ip = code + target;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400367 }
368 break;
Mike Kleine7007382019-05-21 08:36:32 -0500369 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400370
371 case ByteCodeInstruction::kConvertFtoI4: sp[-3].fSigned = (int)sp[-3].fFloat;
372 case ByteCodeInstruction::kConvertFtoI3: sp[-2].fSigned = (int)sp[-2].fFloat;
373 case ByteCodeInstruction::kConvertFtoI2: sp[-1].fSigned = (int)sp[-1].fFloat;
374 case ByteCodeInstruction::kConvertFtoI: sp[ 0].fSigned = (int)sp[ 0].fFloat;
375 break;
376
377 case ByteCodeInstruction::kConvertStoF4: sp[-3].fFloat = sp[-3].fSigned;
378 case ByteCodeInstruction::kConvertStoF3: sp[-2].fFloat = sp[-2].fSigned;
379 case ByteCodeInstruction::kConvertStoF2: sp[-1].fFloat = sp[-1].fSigned;
380 case ByteCodeInstruction::kConvertStoF : sp[ 0].fFloat = sp[ 0].fSigned;
381 break;
382
383 case ByteCodeInstruction::kConvertUtoF4: sp[-3].fFloat = sp[-3].fUnsigned;
384 case ByteCodeInstruction::kConvertUtoF3: sp[-2].fFloat = sp[-2].fUnsigned;
385 case ByteCodeInstruction::kConvertUtoF2: sp[-1].fFloat = sp[-1].fUnsigned;
386 case ByteCodeInstruction::kConvertUtoF : sp[ 0].fFloat = sp[ 0].fUnsigned;
387 break;
388
Mike Klein459aed12019-05-21 15:46:36 -0500389 VECTOR_UNARY_FN(kCos, cosf, fFloat)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400390
Mike Kleine7007382019-05-21 08:36:32 -0500391 case ByteCodeInstruction::kDebugPrint: {
392 Value v = POP();
393 printf("Debug: %d(int), %d(uint), %f(float)\n", v.fSigned, v.fUnsigned, v.fFloat);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400394 break;
Mike Kleine7007382019-05-21 08:36:32 -0500395 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400396
Mike Kleinc1999982019-05-21 13:03:49 -0500397 VECTOR_BINARY_OP(kDivideS, fSigned, /)
398 VECTOR_BINARY_OP(kDivideU, fUnsigned, /)
399 VECTOR_BINARY_OP(kDivideF, fFloat, /)
Mike Kleine7007382019-05-21 08:36:32 -0500400
401 case ByteCodeInstruction::kDup4: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
402 case ByteCodeInstruction::kDup3: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
403 case ByteCodeInstruction::kDup2: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
404 case ByteCodeInstruction::kDup : PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
405 break;
406
Mike Kleine7007382019-05-21 08:36:32 -0500407 case ByteCodeInstruction::kLoad4: sp[4] = stack[*ip + 3];
408 case ByteCodeInstruction::kLoad3: sp[3] = stack[*ip + 2];
409 case ByteCodeInstruction::kLoad2: sp[2] = stack[*ip + 1];
410 case ByteCodeInstruction::kLoad : sp[1] = stack[*ip + 0];
411 ++ip;
412 sp += (int)inst - (int)ByteCodeInstruction::kLoad + 1;
413 break;
414
415 case ByteCodeInstruction::kLoadGlobal4: sp[4] = fGlobals[*ip + 3];
416 case ByteCodeInstruction::kLoadGlobal3: sp[3] = fGlobals[*ip + 2];
417 case ByteCodeInstruction::kLoadGlobal2: sp[2] = fGlobals[*ip + 1];
418 case ByteCodeInstruction::kLoadGlobal : sp[1] = fGlobals[*ip + 0];
419 ++ip;
420 sp += (int)inst - (int)ByteCodeInstruction::kLoadGlobal + 1;
421 break;
422
423 case ByteCodeInstruction::kLoadSwizzle: {
424 int src = READ8();
425 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400426 for (int i = 0; i < count; ++i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400427 PUSH(stack[src + *(ip + i)]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400428 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400429 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400430 break;
Mike Kleine7007382019-05-21 08:36:32 -0500431 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400432
Mike Kleine7007382019-05-21 08:36:32 -0500433 case ByteCodeInstruction::kLoadSwizzleGlobal: {
434 int src = READ8();
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400435 SkASSERT(src < (int) fGlobals.size());
Mike Kleine7007382019-05-21 08:36:32 -0500436 int count = READ8();
Brian Osmanb7451292019-05-15 13:02:13 -0400437 for (int i = 0; i < count; ++i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400438 PUSH(fGlobals[src + *(ip + i)]);
Brian Osmanb7451292019-05-15 13:02:13 -0400439 }
440 ip += count;
441 break;
Mike Kleine7007382019-05-21 08:36:32 -0500442 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400443
Mike Kleinc1999982019-05-21 13:03:49 -0500444 VECTOR_BINARY_OP(kMultiplyI, fSigned, *)
445 VECTOR_BINARY_OP(kMultiplyF, fFloat, *)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400446
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400447 case ByteCodeInstruction::kNot:
Mike Kleine7007382019-05-21 08:36:32 -0500448 sp[0].fBool = !sp[0].fBool;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400449 break;
Mike Kleine7007382019-05-21 08:36:32 -0500450
Mike Kleinc1999982019-05-21 13:03:49 -0500451 case ByteCodeInstruction::kNegateF4: sp[-3] = -sp[-3].fFloat;
452 case ByteCodeInstruction::kNegateF3: sp[-2] = -sp[-2].fFloat;
453 case ByteCodeInstruction::kNegateF2: sp[-1] = -sp[-1].fFloat;
454 case ByteCodeInstruction::kNegateF : sp[ 0] = -sp[ 0].fFloat;
Mike Kleine7007382019-05-21 08:36:32 -0500455 break;
456
Mike Kleinc1999982019-05-21 13:03:49 -0500457 case ByteCodeInstruction::kNegateI4: sp[-3] = -sp[-3].fSigned;
458 case ByteCodeInstruction::kNegateI3: sp[-2] = -sp[-2].fSigned;
459 case ByteCodeInstruction::kNegateI2: sp[-1] = -sp[-1].fSigned;
460 case ByteCodeInstruction::kNegateI : sp[ 0] = -sp [0].fSigned;
Mike Kleine7007382019-05-21 08:36:32 -0500461 break;
462
463 case ByteCodeInstruction::kPop4: POP();
464 case ByteCodeInstruction::kPop3: POP();
465 case ByteCodeInstruction::kPop2: POP();
466 case ByteCodeInstruction::kPop : POP();
467 break;
468
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400469 case ByteCodeInstruction::kPushImmediate:
Mike Kleine7007382019-05-21 08:36:32 -0500470 PUSH(READ32());
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400471 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400472
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400473 case ByteCodeInstruction::kReadExternal: // fall through
474 case ByteCodeInstruction::kReadExternal2: // fall through
475 case ByteCodeInstruction::kReadExternal3: // fall through
Mike Kleine7007382019-05-21 08:36:32 -0500476 case ByteCodeInstruction::kReadExternal4: {
477 int src = READ8();
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400478 fByteCode->fExternalValues[src]->read(sp + 1);
Mike Kleine7007382019-05-21 08:36:32 -0500479 sp += (int) inst - (int) ByteCodeInstruction::kReadExternal + 1;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400480 break;
Mike Kleine7007382019-05-21 08:36:32 -0500481 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400482
Mike Kleinc1999982019-05-21 13:03:49 -0500483 VECTOR_BINARY_FN(kRemainderF, fFloat, fmodf)
484 VECTOR_BINARY_OP(kRemainderS, fSigned, %)
485 VECTOR_BINARY_OP(kRemainderU, fUnsigned, %)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400486
Mike Kleine7007382019-05-21 08:36:32 -0500487 case ByteCodeInstruction::kReturn: {
488 int count = READ8();
Brian Osman226668a2019-05-14 16:47:30 -0400489 if (frames.empty()) {
490 if (outReturn) {
491 memcpy(outReturn, sp - count + 1, count * sizeof(Value));
492 }
493 return;
494 } else {
495 // When we were called, 'stack' was positioned at the old top-of-stack (where
496 // our parameters were placed). So copy our return values to that same spot.
497 memmove(stack, sp - count + 1, count * sizeof(Value));
498
499 // Now move the stack pointer to the end of the just-pushed return values,
500 // and restore everything else.
501 const StackFrame& frame(frames.back());
502 sp = stack + count - 1;
503 stack = frame.fStack;
504 code = frame.fCode;
505 ip = frame.fIP;
506 frames.pop_back();
507 break;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400508 }
Mike Kleine7007382019-05-21 08:36:32 -0500509 }
510
Mike Klein459aed12019-05-21 15:46:36 -0500511 VECTOR_UNARY_FN(kSin, sinf, fFloat)
512 VECTOR_UNARY_FN(kSqrt, sqrtf, fFloat)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400513
Mike Kleine7007382019-05-21 08:36:32 -0500514 case ByteCodeInstruction::kStore4: stack[*ip + 3] = POP();
515 case ByteCodeInstruction::kStore3: stack[*ip + 2] = POP();
516 case ByteCodeInstruction::kStore2: stack[*ip + 1] = POP();
517 case ByteCodeInstruction::kStore : stack[*ip + 0] = POP();
518 ++ip;
519 break;
520
521 case ByteCodeInstruction::kStoreGlobal4: fGlobals[*ip + 3] = POP();
522 case ByteCodeInstruction::kStoreGlobal3: fGlobals[*ip + 2] = POP();
523 case ByteCodeInstruction::kStoreGlobal2: fGlobals[*ip + 1] = POP();
524 case ByteCodeInstruction::kStoreGlobal : fGlobals[*ip + 0] = POP();
525 ++ip;
526 break;
527
528 case ByteCodeInstruction::kStoreSwizzle: {
529 int target = READ8();
530 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400531 for (int i = count - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400532 stack[target + *(ip + i)] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400533 }
Brian Osman1091f022019-05-16 09:42:16 -0400534 ip += count;
535 break;
Mike Kleine7007382019-05-21 08:36:32 -0500536 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400537
Mike Kleine7007382019-05-21 08:36:32 -0500538 case ByteCodeInstruction::kStoreSwizzleGlobal: {
539 int target = READ8();
540 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400541 for (int i = count - 1; i >= 0; --i) {
542 fGlobals[target + *(ip + i)] = POP();
543 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400544 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400545 break;
Mike Kleine7007382019-05-21 08:36:32 -0500546 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400547
Mike Kleinc1999982019-05-21 13:03:49 -0500548 VECTOR_BINARY_OP(kSubtractI, fSigned, -)
549 VECTOR_BINARY_OP(kSubtractF, fFloat, -)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400550
Mike Kleine7007382019-05-21 08:36:32 -0500551 case ByteCodeInstruction::kSwizzle: {
552 Value tmp[4];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400553 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400554 tmp[i] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400555 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400556 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400557 PUSH(tmp[READ8()]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400558 }
559 break;
Mike Kleine7007382019-05-21 08:36:32 -0500560 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400561
Mike Klein459aed12019-05-21 15:46:36 -0500562 VECTOR_UNARY_FN(kTan, tanf, fFloat)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400563
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400564 case ByteCodeInstruction::kWriteExternal: // fall through
565 case ByteCodeInstruction::kWriteExternal2: // fall through
566 case ByteCodeInstruction::kWriteExternal3: // fall through
Mike Kleine7007382019-05-21 08:36:32 -0500567 case ByteCodeInstruction::kWriteExternal4: {
568 int count = (int) inst - (int) ByteCodeInstruction::kWriteExternal + 1;
569 int target = READ8();
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400570 fByteCode->fExternalValues[target]->write(sp - count + 1);
571 sp -= count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400572 break;
Mike Kleine7007382019-05-21 08:36:32 -0500573 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400574
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400575 default:
Mike Kleine7007382019-05-21 08:36:32 -0500576 SkDEBUGFAILF("unsupported instruction %d\n", (int) inst);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400577 }
578#ifdef TRACE
Mike Kleine7007382019-05-21 08:36:32 -0500579 int stackSize = (int) (sp - stack + 1);
580 printf("STACK(%d):", stackSize);
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400581 for (int i = 0; i < stackSize; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400582 printf(" %d(%f)", stack[i].fSigned, stack[i].fFloat);
583 }
584 printf("\n");
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400585#endif
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400586 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400587}
588
589} // namespace
590
591#endif