blob: 805c65a3005925f1bec9f23c12147fab8a594b33 [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"
Brian Osman07c117b2019-05-23 12:51:06 -070011#include "src/sksl/SkSLByteCodeGenerator.h"
Ethan Nicholas91164d12019-05-15 15:29:54 -040012#include "src/sksl/SkSLExternalValue.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "src/sksl/SkSLInterpreter.h"
14#include "src/sksl/ir/SkSLBinaryExpression.h"
15#include "src/sksl/ir/SkSLExpressionStatement.h"
16#include "src/sksl/ir/SkSLForStatement.h"
17#include "src/sksl/ir/SkSLFunctionCall.h"
18#include "src/sksl/ir/SkSLFunctionReference.h"
19#include "src/sksl/ir/SkSLIfStatement.h"
20#include "src/sksl/ir/SkSLIndexExpression.h"
21#include "src/sksl/ir/SkSLPostfixExpression.h"
22#include "src/sksl/ir/SkSLPrefixExpression.h"
23#include "src/sksl/ir/SkSLProgram.h"
24#include "src/sksl/ir/SkSLStatement.h"
25#include "src/sksl/ir/SkSLTernaryExpression.h"
26#include "src/sksl/ir/SkSLVarDeclarations.h"
27#include "src/sksl/ir/SkSLVarDeclarationsStatement.h"
28#include "src/sksl/ir/SkSLVariableReference.h"
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040029
30namespace SkSL {
31
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040032static constexpr int UNINITIALIZED = 0xDEADBEEF;
33
Mike Kleine7007382019-05-21 08:36:32 -050034Interpreter::Interpreter(std::unique_ptr<Program> program,
35 std::unique_ptr<ByteCode> byteCode,
Ethan Nicholasdfcad062019-05-07 12:53:34 -040036 Interpreter::Value inputs[])
37 : fProgram(std::move(program))
Mike Kleine7007382019-05-21 08:36:32 -050038 , fByteCode(std::move(byteCode))
39 , fGlobals(fByteCode->fGlobalCount, UNINITIALIZED) {
Brian Osmand369a5e2019-05-09 13:13:25 -040040 this->setInputs(inputs);
41}
42
43void Interpreter::setInputs(Interpreter::Value inputs[]) {
Mike Kleine7007382019-05-21 08:36:32 -050044 for (uint8_t slot : fByteCode->fInputSlots) {
45 fGlobals[slot] = *inputs++;
Ethan Nicholasdfcad062019-05-07 12:53:34 -040046 }
47}
48
49void Interpreter::run(const ByteCodeFunction& f, Interpreter::Value args[],
50 Interpreter::Value* outReturn) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040051#ifdef TRACE
52 this->disassemble(f);
53#endif
Ethan Nicholasdfcad062019-05-07 12:53:34 -040054 Value smallStack[128];
55 std::unique_ptr<Value[]> largeStack;
56 Value* stack = smallStack;
Brian Osman226668a2019-05-14 16:47:30 -040057 if ((int) SK_ARRAY_COUNT(smallStack) < f.fStackCount) {
58 largeStack.reset(new Value[f.fStackCount]);
Ethan Nicholasdfcad062019-05-07 12:53:34 -040059 stack = largeStack.get();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040060 }
Mike Kleine7007382019-05-21 08:36:32 -050061
62 if (f.fParameterCount) {
63 memcpy(stack, args, f.fParameterCount * sizeof(Value));
64 }
65 this->innerRun(f, stack, outReturn);
66
67 for (const Variable* p : f.fDeclaration.fParameters) {
Brian Osman07c117b2019-05-23 12:51:06 -070068 const int nvalues = ByteCodeGenerator::SlotCount(p->fType);
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 Osman07c117b2019-05-23 12:51:06 -0700140 case ByteCodeInstruction::kDupN: printf("dupN %d", READ8()); break;
Brian Osman1091f022019-05-16 09:42:16 -0400141 case ByteCodeInstruction::kLoad: printf("load %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400142 case ByteCodeInstruction::kLoad2: printf("load2 %d", READ8()); break;
143 case ByteCodeInstruction::kLoad3: printf("load3 %d", READ8()); break;
144 case ByteCodeInstruction::kLoad4: printf("load4 %d", READ8()); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400145 case ByteCodeInstruction::kLoadGlobal: printf("loadglobal %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400146 case ByteCodeInstruction::kLoadGlobal2: printf("loadglobal2 %d", READ8()); break;
147 case ByteCodeInstruction::kLoadGlobal3: printf("loadglobal3 %d", READ8()); break;
148 case ByteCodeInstruction::kLoadGlobal4: printf("loadglobal4 %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400149 case ByteCodeInstruction::kLoadSwizzle: {
Brian Osman1091f022019-05-16 09:42:16 -0400150 int target = READ8();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400151 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400152 printf("loadswizzle %d %d", target, count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400153 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400154 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400155 }
156 break;
157 }
Brian Osmanb7451292019-05-15 13:02:13 -0400158 case ByteCodeInstruction::kLoadSwizzleGlobal: {
Brian Osman1091f022019-05-16 09:42:16 -0400159 int target = READ8();
Brian Osmanb7451292019-05-15 13:02:13 -0400160 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400161 printf("loadswizzleglobal %d %d", target, count);
Brian Osmanb7451292019-05-15 13:02:13 -0400162 for (int i = 0; i < count; ++i) {
163 printf(", %d", READ8());
164 }
165 break;
166 }
Brian Osman07c117b2019-05-23 12:51:06 -0700167 case ByteCodeInstruction::kLoadExtended: printf("loadextended %d", READ8()); break;
168 case ByteCodeInstruction::kLoadExtendedGlobal: printf("loadextendedglobal %d", READ8());
169 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400170 VECTOR_DISASSEMBLE(kMultiplyF, "multiplyf")
171 VECTOR_DISASSEMBLE(kMultiplyI, "multiplyi")
172 VECTOR_DISASSEMBLE(kNegateF, "negatef")
Mike Klein12710912019-05-21 11:04:59 -0500173 VECTOR_DISASSEMBLE(kNegateI, "negatei")
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400174 VECTOR_DISASSEMBLE(kNot, "not")
175 VECTOR_DISASSEMBLE(kOrB, "orb")
176 VECTOR_DISASSEMBLE(kOrI, "ori")
177 VECTOR_DISASSEMBLE(kPop, "pop")
Brian Osman07c117b2019-05-23 12:51:06 -0700178 case ByteCodeInstruction::kPopN: printf("popN %d", READ8()); break;
Mike Kleine7007382019-05-21 08:36:32 -0500179 case ByteCodeInstruction::kPushImmediate: {
180 uint32_t v = READ32();
181 union { uint32_t u; float f; } pun = { v };
182 printf("pushimmediate %s", (to_string(v) + "(" + to_string(pun.f) + ")").c_str());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400183 break;
Mike Kleine7007382019-05-21 08:36:32 -0500184 }
Ethan Nicholas91164d12019-05-15 15:29:54 -0400185 case ByteCodeInstruction::kReadExternal: printf("readexternal %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400186 case ByteCodeInstruction::kReadExternal2: printf("readexternal2 %d", READ8()); break;
187 case ByteCodeInstruction::kReadExternal3: printf("readexternal3 %d", READ8()); break;
188 case ByteCodeInstruction::kReadExternal4: printf("readexternal4 %d", READ8()); break;
189 VECTOR_DISASSEMBLE(kRemainderF, "remainderf")
190 VECTOR_DISASSEMBLE(kRemainderS, "remainders")
191 VECTOR_DISASSEMBLE(kRemainderU, "remainderu")
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400192 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400193 VECTOR_DISASSEMBLE(kSin, "sin")
194 VECTOR_DISASSEMBLE(kSqrt, "sqrt")
Brian Osman1091f022019-05-16 09:42:16 -0400195 case ByteCodeInstruction::kStore: printf("store %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400196 case ByteCodeInstruction::kStore2: printf("store2 %d", READ8()); break;
197 case ByteCodeInstruction::kStore3: printf("store3 %d", READ8()); break;
198 case ByteCodeInstruction::kStore4: printf("store4 %d", READ8()); break;
Brian Osman1091f022019-05-16 09:42:16 -0400199 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400200 case ByteCodeInstruction::kStoreGlobal2: printf("storeglobal2 %d", READ8()); break;
201 case ByteCodeInstruction::kStoreGlobal3: printf("storeglobal3 %d", READ8()); break;
202 case ByteCodeInstruction::kStoreGlobal4: printf("storeglobal4 %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400203 case ByteCodeInstruction::kStoreSwizzle: {
Brian Osman1091f022019-05-16 09:42:16 -0400204 int target = READ8();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400205 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400206 printf("storeswizzle %d %d", target, count);
207 for (int i = 0; i < count; ++i) {
208 printf(", %d", READ8());
209 }
210 break;
211 }
212 case ByteCodeInstruction::kStoreSwizzleGlobal: {
213 int target = READ8();
214 int count = READ8();
215 printf("storeswizzleglobal %d %d", target, count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400216 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400217 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400218 }
219 break;
220 }
Brian Osman07c117b2019-05-23 12:51:06 -0700221 case ByteCodeInstruction::kStoreSwizzleIndirect: {
222 int count = READ8();
223 printf("storeswizzleindirect %d", count);
224 for (int i = 0; i < count; ++i) {
225 printf(", %d", READ8());
226 }
227 break;
228 }
229 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
230 int count = READ8();
231 printf("storeswizzleindirectglobal %d", count);
232 for (int i = 0; i < count; ++i) {
233 printf(", %d", READ8());
234 }
235 break;
236 }
237 case ByteCodeInstruction::kStoreExtended: printf("storeextended %d", READ8()); break;
238 case ByteCodeInstruction::kStoreExtendedGlobal:
239 printf("storeextendedglobal %d", READ8());
240 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400241 VECTOR_DISASSEMBLE(kSubtractF, "subtractf")
242 VECTOR_DISASSEMBLE(kSubtractI, "subtracti")
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400243 case ByteCodeInstruction::kSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400244 printf("swizzle %d, ", READ8());
245 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400246 printf("%d", count);
247 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400248 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400249 }
250 break;
251 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400252 VECTOR_DISASSEMBLE(kTan, "tan")
Ethan Nicholas91164d12019-05-15 15:29:54 -0400253 case ByteCodeInstruction::kWriteExternal: printf("writeexternal %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400254 case ByteCodeInstruction::kWriteExternal2: printf("writeexternal2 %d", READ8()); break;
255 case ByteCodeInstruction::kWriteExternal3: printf("writeexternal3 %d", READ8()); break;
256 case ByteCodeInstruction::kWriteExternal4: printf("writeexternal4 %d", READ8()); break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400257 default: printf("unknown(%d)\n", *(ip - 1)); SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400258 }
259 printf("\n");
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400260 }
261}
262
Mike Klein459aed12019-05-21 15:46:36 -0500263#define VECTOR_BINARY_OP(base, field, op) \
Mike Kleine7007382019-05-21 08:36:32 -0500264 case ByteCodeInstruction::base ## 4: \
Mike Klein459aed12019-05-21 15:46:36 -0500265 sp[-4] = sp[-4].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500266 POP(); \
267 /* fall through */ \
268 case ByteCodeInstruction::base ## 3: { \
269 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500270 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500271 POP(); \
272 } /* fall through */ \
273 case ByteCodeInstruction::base ## 2: { \
274 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500275 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500276 POP(); \
277 } /* fall through */ \
278 case ByteCodeInstruction::base: { \
279 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500280 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500281 POP(); \
282 break; \
283 }
Ethan Nicholasaeb71ce2019-05-20 09:55:44 -0400284
Mike Klein459aed12019-05-21 15:46:36 -0500285#define VECTOR_BINARY_FN(base, field, fn) \
Mike Kleine7007382019-05-21 08:36:32 -0500286 case ByteCodeInstruction::base ## 4: \
Mike Klein459aed12019-05-21 15:46:36 -0500287 sp[-4] = fn(sp[-4].field, sp[0].field); \
Mike Kleine7007382019-05-21 08:36:32 -0500288 POP(); \
289 /* fall through */ \
290 case ByteCodeInstruction::base ## 3: { \
291 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500292 sp[count] = fn(sp[count].field, sp[0].field); \
Mike Kleine7007382019-05-21 08:36:32 -0500293 POP(); \
294 } /* fall through */ \
295 case ByteCodeInstruction::base ## 2: { \
296 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500297 sp[count] = fn(sp[count].field, sp[0].field); \
Mike Kleine7007382019-05-21 08:36:32 -0500298 POP(); \
299 } /* fall through */ \
300 case ByteCodeInstruction::base: { \
301 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500302 sp[count] = fn(sp[count].field, sp[0].field); \
Mike Kleine7007382019-05-21 08:36:32 -0500303 POP(); \
304 break; \
305 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400306
Mike Klein459aed12019-05-21 15:46:36 -0500307#define VECTOR_UNARY_FN(base, fn, field) \
308 case ByteCodeInstruction::base ## 4: sp[-3] = fn(sp[-3].field); \
309 case ByteCodeInstruction::base ## 3: sp[-2] = fn(sp[-2].field); \
310 case ByteCodeInstruction::base ## 2: sp[-1] = fn(sp[-1].field); \
311 case ByteCodeInstruction::base: sp[ 0] = fn(sp[ 0].field); \
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400312 break;
313
Brian Osman226668a2019-05-14 16:47:30 -0400314struct StackFrame {
315 const uint8_t* fCode;
316 const uint8_t* fIP;
317 Interpreter::Value* fStack;
318};
319
Mike Kleine7007382019-05-21 08:36:32 -0500320void Interpreter::innerRun(const ByteCodeFunction& f, Value* stack, Value* outReturn) {
321 Value* sp = stack + f.fParameterCount + f.fLocalCount - 1;
322
323 auto POP = [&] { SkASSERT(sp >= stack); return *(sp--); };
324 auto PUSH = [&](Value v) { SkASSERT(sp + 1 >= stack); *(++sp) = v; };
325
Brian Osman226668a2019-05-14 16:47:30 -0400326 const uint8_t* code = f.fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400327 const uint8_t* ip = code;
Brian Osman226668a2019-05-14 16:47:30 -0400328 std::vector<StackFrame> frames;
329
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400330 for (;;) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400331#ifdef TRACE
Brian Osmane85b6a52019-05-22 14:50:59 -0700332 printf("at %d\n", (int) (ip - code));
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400333#endif
Brian Osmane85b6a52019-05-22 14:50:59 -0700334 ByteCodeInstruction inst = (ByteCodeInstruction) READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400335 switch (inst) {
Mike Kleinc1999982019-05-21 13:03:49 -0500336 VECTOR_BINARY_OP(kAddI, fSigned, +)
337 VECTOR_BINARY_OP(kAddF, fFloat, +)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400338
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400339 case ByteCodeInstruction::kBranch:
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400340 ip = code + READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400341 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400342
Brian Osman226668a2019-05-14 16:47:30 -0400343 case ByteCodeInstruction::kCall: {
344 // Precursor code has pushed all parameters to the stack. Update our bottom of
345 // stack to point at the first parameter, and our sp to point past those parameters
346 // (plus space for locals).
Mike Kleine7007382019-05-21 08:36:32 -0500347 int target = READ8();
Brian Osman226668a2019-05-14 16:47:30 -0400348 const ByteCodeFunction* fun = fByteCode->fFunctions[target].get();
349 frames.push_back({ code, ip, stack });
350 ip = code = fun->fCode.data();
351 stack = sp - fun->fParameterCount + 1;
352 sp = stack + fun->fParameterCount + fun->fLocalCount - 1;
353 break;
354 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400355
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400356 case ByteCodeInstruction::kCallExternal: {
357 int argumentCount = READ8();
358 int returnCount = READ8();
Mike Kleine7007382019-05-21 08:36:32 -0500359 int target = READ8();
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400360 ExternalValue* v = fByteCode->fExternalValues[target];
361 sp -= argumentCount - 1;
Mike Kleine7007382019-05-21 08:36:32 -0500362
363 Value tmp[4];
364 SkASSERT(returnCount <= (int)SK_ARRAY_COUNT(tmp));
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400365 v->call(sp, tmp);
366 memcpy(sp, tmp, returnCount * sizeof(Value));
367 sp += returnCount - 1;
368 break;
369 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400370
Mike Kleinc1999982019-05-21 13:03:49 -0500371 VECTOR_BINARY_OP(kCompareIEQ, fSigned, ==)
372 VECTOR_BINARY_OP(kCompareFEQ, fFloat, ==)
373 VECTOR_BINARY_OP(kCompareINEQ, fSigned, !=)
374 VECTOR_BINARY_OP(kCompareFNEQ, fFloat, !=)
375 VECTOR_BINARY_OP(kCompareSGT, fSigned, >)
376 VECTOR_BINARY_OP(kCompareUGT, fUnsigned, >)
377 VECTOR_BINARY_OP(kCompareFGT, fFloat, >)
378 VECTOR_BINARY_OP(kCompareSGTEQ, fSigned, >=)
379 VECTOR_BINARY_OP(kCompareUGTEQ, fUnsigned, >=)
380 VECTOR_BINARY_OP(kCompareFGTEQ, fFloat, >=)
381 VECTOR_BINARY_OP(kCompareSLT, fSigned, <)
382 VECTOR_BINARY_OP(kCompareULT, fUnsigned, <)
383 VECTOR_BINARY_OP(kCompareFLT, fFloat, <)
384 VECTOR_BINARY_OP(kCompareSLTEQ, fSigned, <=)
385 VECTOR_BINARY_OP(kCompareULTEQ, fUnsigned, <=)
386 VECTOR_BINARY_OP(kCompareFLTEQ, fFloat, <=)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400387
Mike Kleine7007382019-05-21 08:36:32 -0500388 case ByteCodeInstruction::kConditionalBranch: {
389 int target = READ16();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400390 if (POP().fBool) {
Mike Kleine7007382019-05-21 08:36:32 -0500391 ip = code + target;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400392 }
393 break;
Mike Kleine7007382019-05-21 08:36:32 -0500394 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400395
396 case ByteCodeInstruction::kConvertFtoI4: sp[-3].fSigned = (int)sp[-3].fFloat;
397 case ByteCodeInstruction::kConvertFtoI3: sp[-2].fSigned = (int)sp[-2].fFloat;
398 case ByteCodeInstruction::kConvertFtoI2: sp[-1].fSigned = (int)sp[-1].fFloat;
399 case ByteCodeInstruction::kConvertFtoI: sp[ 0].fSigned = (int)sp[ 0].fFloat;
400 break;
401
402 case ByteCodeInstruction::kConvertStoF4: sp[-3].fFloat = sp[-3].fSigned;
403 case ByteCodeInstruction::kConvertStoF3: sp[-2].fFloat = sp[-2].fSigned;
404 case ByteCodeInstruction::kConvertStoF2: sp[-1].fFloat = sp[-1].fSigned;
405 case ByteCodeInstruction::kConvertStoF : sp[ 0].fFloat = sp[ 0].fSigned;
406 break;
407
408 case ByteCodeInstruction::kConvertUtoF4: sp[-3].fFloat = sp[-3].fUnsigned;
409 case ByteCodeInstruction::kConvertUtoF3: sp[-2].fFloat = sp[-2].fUnsigned;
410 case ByteCodeInstruction::kConvertUtoF2: sp[-1].fFloat = sp[-1].fUnsigned;
411 case ByteCodeInstruction::kConvertUtoF : sp[ 0].fFloat = sp[ 0].fUnsigned;
412 break;
413
Mike Klein459aed12019-05-21 15:46:36 -0500414 VECTOR_UNARY_FN(kCos, cosf, fFloat)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400415
Mike Kleine7007382019-05-21 08:36:32 -0500416 case ByteCodeInstruction::kDebugPrint: {
417 Value v = POP();
418 printf("Debug: %d(int), %d(uint), %f(float)\n", v.fSigned, v.fUnsigned, v.fFloat);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400419 break;
Mike Kleine7007382019-05-21 08:36:32 -0500420 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400421
Mike Kleinc1999982019-05-21 13:03:49 -0500422 VECTOR_BINARY_OP(kDivideS, fSigned, /)
423 VECTOR_BINARY_OP(kDivideU, fUnsigned, /)
424 VECTOR_BINARY_OP(kDivideF, fFloat, /)
Mike Kleine7007382019-05-21 08:36:32 -0500425
426 case ByteCodeInstruction::kDup4: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
427 case ByteCodeInstruction::kDup3: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
428 case ByteCodeInstruction::kDup2: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
429 case ByteCodeInstruction::kDup : PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
430 break;
431
Brian Osman07c117b2019-05-23 12:51:06 -0700432 case ByteCodeInstruction::kDupN: {
433 int count = READ8();
434 memcpy(sp + 1, sp - count + 1, count * sizeof(Value));
435 sp += count;
436 break;
437 }
438
Mike Kleine7007382019-05-21 08:36:32 -0500439 case ByteCodeInstruction::kLoad4: sp[4] = stack[*ip + 3];
440 case ByteCodeInstruction::kLoad3: sp[3] = stack[*ip + 2];
441 case ByteCodeInstruction::kLoad2: sp[2] = stack[*ip + 1];
442 case ByteCodeInstruction::kLoad : sp[1] = stack[*ip + 0];
443 ++ip;
444 sp += (int)inst - (int)ByteCodeInstruction::kLoad + 1;
445 break;
446
447 case ByteCodeInstruction::kLoadGlobal4: sp[4] = fGlobals[*ip + 3];
448 case ByteCodeInstruction::kLoadGlobal3: sp[3] = fGlobals[*ip + 2];
449 case ByteCodeInstruction::kLoadGlobal2: sp[2] = fGlobals[*ip + 1];
450 case ByteCodeInstruction::kLoadGlobal : sp[1] = fGlobals[*ip + 0];
451 ++ip;
Brian Osman07c117b2019-05-23 12:51:06 -0700452 sp += (int)inst -
453 (int)ByteCodeInstruction::kLoadGlobal + 1;
Mike Kleine7007382019-05-21 08:36:32 -0500454 break;
455
Brian Osman07c117b2019-05-23 12:51:06 -0700456 case ByteCodeInstruction::kLoadExtended: {
457 int count = READ8();
458 int src = POP().fSigned;
459 memcpy(sp + 1, &stack[src], count * sizeof(Value));
460 sp += count;
461 break;
462 }
463
464 case ByteCodeInstruction::kLoadExtendedGlobal: {
465 int count = READ8();
466 int src = POP().fSigned;
467 SkASSERT(src + count <= (int) fGlobals.size());
468 memcpy(sp + 1, &fGlobals[src], count * sizeof(Value));
469 sp += count;
470 break;
471 }
472
Mike Kleine7007382019-05-21 08:36:32 -0500473 case ByteCodeInstruction::kLoadSwizzle: {
474 int src = READ8();
475 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400476 for (int i = 0; i < count; ++i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400477 PUSH(stack[src + *(ip + i)]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400478 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400479 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400480 break;
Mike Kleine7007382019-05-21 08:36:32 -0500481 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400482
Mike Kleine7007382019-05-21 08:36:32 -0500483 case ByteCodeInstruction::kLoadSwizzleGlobal: {
484 int src = READ8();
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400485 SkASSERT(src < (int) fGlobals.size());
Mike Kleine7007382019-05-21 08:36:32 -0500486 int count = READ8();
Brian Osmanb7451292019-05-15 13:02:13 -0400487 for (int i = 0; i < count; ++i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400488 PUSH(fGlobals[src + *(ip + i)]);
Brian Osmanb7451292019-05-15 13:02:13 -0400489 }
490 ip += count;
491 break;
Mike Kleine7007382019-05-21 08:36:32 -0500492 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400493
Mike Kleinc1999982019-05-21 13:03:49 -0500494 VECTOR_BINARY_OP(kMultiplyI, fSigned, *)
495 VECTOR_BINARY_OP(kMultiplyF, fFloat, *)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400496
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400497 case ByteCodeInstruction::kNot:
Mike Kleine7007382019-05-21 08:36:32 -0500498 sp[0].fBool = !sp[0].fBool;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400499 break;
Mike Kleine7007382019-05-21 08:36:32 -0500500
Mike Kleinc1999982019-05-21 13:03:49 -0500501 case ByteCodeInstruction::kNegateF4: sp[-3] = -sp[-3].fFloat;
502 case ByteCodeInstruction::kNegateF3: sp[-2] = -sp[-2].fFloat;
503 case ByteCodeInstruction::kNegateF2: sp[-1] = -sp[-1].fFloat;
504 case ByteCodeInstruction::kNegateF : sp[ 0] = -sp[ 0].fFloat;
Mike Kleine7007382019-05-21 08:36:32 -0500505 break;
506
Mike Kleinc1999982019-05-21 13:03:49 -0500507 case ByteCodeInstruction::kNegateI4: sp[-3] = -sp[-3].fSigned;
508 case ByteCodeInstruction::kNegateI3: sp[-2] = -sp[-2].fSigned;
509 case ByteCodeInstruction::kNegateI2: sp[-1] = -sp[-1].fSigned;
510 case ByteCodeInstruction::kNegateI : sp[ 0] = -sp [0].fSigned;
Mike Kleine7007382019-05-21 08:36:32 -0500511 break;
512
513 case ByteCodeInstruction::kPop4: POP();
514 case ByteCodeInstruction::kPop3: POP();
515 case ByteCodeInstruction::kPop2: POP();
516 case ByteCodeInstruction::kPop : POP();
517 break;
518
Brian Osman07c117b2019-05-23 12:51:06 -0700519 case ByteCodeInstruction::kPopN:
520 sp -= READ8();
521 break;
522
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400523 case ByteCodeInstruction::kPushImmediate:
Mike Kleine7007382019-05-21 08:36:32 -0500524 PUSH(READ32());
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400525 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400526
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400527 case ByteCodeInstruction::kReadExternal: // fall through
528 case ByteCodeInstruction::kReadExternal2: // fall through
529 case ByteCodeInstruction::kReadExternal3: // fall through
Mike Kleine7007382019-05-21 08:36:32 -0500530 case ByteCodeInstruction::kReadExternal4: {
531 int src = READ8();
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400532 fByteCode->fExternalValues[src]->read(sp + 1);
Mike Kleine7007382019-05-21 08:36:32 -0500533 sp += (int) inst - (int) ByteCodeInstruction::kReadExternal + 1;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400534 break;
Mike Kleine7007382019-05-21 08:36:32 -0500535 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400536
Mike Kleinc1999982019-05-21 13:03:49 -0500537 VECTOR_BINARY_FN(kRemainderF, fFloat, fmodf)
538 VECTOR_BINARY_OP(kRemainderS, fSigned, %)
539 VECTOR_BINARY_OP(kRemainderU, fUnsigned, %)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400540
Mike Kleine7007382019-05-21 08:36:32 -0500541 case ByteCodeInstruction::kReturn: {
542 int count = READ8();
Brian Osman226668a2019-05-14 16:47:30 -0400543 if (frames.empty()) {
544 if (outReturn) {
545 memcpy(outReturn, sp - count + 1, count * sizeof(Value));
546 }
547 return;
548 } else {
549 // When we were called, 'stack' was positioned at the old top-of-stack (where
550 // our parameters were placed). So copy our return values to that same spot.
551 memmove(stack, sp - count + 1, count * sizeof(Value));
552
553 // Now move the stack pointer to the end of the just-pushed return values,
554 // and restore everything else.
555 const StackFrame& frame(frames.back());
556 sp = stack + count - 1;
557 stack = frame.fStack;
558 code = frame.fCode;
559 ip = frame.fIP;
560 frames.pop_back();
561 break;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400562 }
Mike Kleine7007382019-05-21 08:36:32 -0500563 }
564
Mike Klein459aed12019-05-21 15:46:36 -0500565 VECTOR_UNARY_FN(kSin, sinf, fFloat)
566 VECTOR_UNARY_FN(kSqrt, sqrtf, fFloat)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400567
Mike Kleine7007382019-05-21 08:36:32 -0500568 case ByteCodeInstruction::kStore4: stack[*ip + 3] = POP();
569 case ByteCodeInstruction::kStore3: stack[*ip + 2] = POP();
570 case ByteCodeInstruction::kStore2: stack[*ip + 1] = POP();
571 case ByteCodeInstruction::kStore : stack[*ip + 0] = POP();
572 ++ip;
573 break;
574
575 case ByteCodeInstruction::kStoreGlobal4: fGlobals[*ip + 3] = POP();
576 case ByteCodeInstruction::kStoreGlobal3: fGlobals[*ip + 2] = POP();
577 case ByteCodeInstruction::kStoreGlobal2: fGlobals[*ip + 1] = POP();
578 case ByteCodeInstruction::kStoreGlobal : fGlobals[*ip + 0] = POP();
579 ++ip;
580 break;
581
Brian Osman07c117b2019-05-23 12:51:06 -0700582 case ByteCodeInstruction::kStoreExtended: {
583 int count = READ8();
584 int target = POP().fSigned;
585 memcpy(&stack[target], sp - count + 1, count * sizeof(Value));
586 sp -= count;
587 break;
588 }
589 case ByteCodeInstruction::kStoreExtendedGlobal: {
590 int count = READ8();
591 int target = POP().fSigned;
592 SkASSERT(target + count <= (int) fGlobals.size());
593 memcpy(&fGlobals[target], sp - count + 1, count * sizeof(Value));
594 sp -= count;
595 break;
596 }
597
Mike Kleine7007382019-05-21 08:36:32 -0500598 case ByteCodeInstruction::kStoreSwizzle: {
599 int target = READ8();
600 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400601 for (int i = count - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400602 stack[target + *(ip + i)] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400603 }
Brian Osman1091f022019-05-16 09:42:16 -0400604 ip += count;
605 break;
Mike Kleine7007382019-05-21 08:36:32 -0500606 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400607
Mike Kleine7007382019-05-21 08:36:32 -0500608 case ByteCodeInstruction::kStoreSwizzleGlobal: {
609 int target = READ8();
610 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400611 for (int i = count - 1; i >= 0; --i) {
612 fGlobals[target + *(ip + i)] = POP();
613 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400614 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400615 break;
Mike Kleine7007382019-05-21 08:36:32 -0500616 }
Brian Osman07c117b2019-05-23 12:51:06 -0700617 case ByteCodeInstruction::kStoreSwizzleIndirect: {
618 int target = POP().fSigned;
619 int count = READ8();
620 for (int i = count - 1; i >= 0; --i) {
621 stack[target + *(ip + i)] = POP();
622 }
623 ip += count;
624 break;
625 }
626 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
627 int target = POP().fSigned;
628 int count = READ8();
629 for (int i = count - 1; i >= 0; --i) {
630 fGlobals[target + *(ip + i)] = POP();
631 }
632 ip += count;
633 break;
634 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400635
Mike Kleinc1999982019-05-21 13:03:49 -0500636 VECTOR_BINARY_OP(kSubtractI, fSigned, -)
637 VECTOR_BINARY_OP(kSubtractF, fFloat, -)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400638
Mike Kleine7007382019-05-21 08:36:32 -0500639 case ByteCodeInstruction::kSwizzle: {
640 Value tmp[4];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400641 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400642 tmp[i] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400643 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400644 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400645 PUSH(tmp[READ8()]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400646 }
647 break;
Mike Kleine7007382019-05-21 08:36:32 -0500648 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400649
Mike Klein459aed12019-05-21 15:46:36 -0500650 VECTOR_UNARY_FN(kTan, tanf, fFloat)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400651
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400652 case ByteCodeInstruction::kWriteExternal: // fall through
653 case ByteCodeInstruction::kWriteExternal2: // fall through
654 case ByteCodeInstruction::kWriteExternal3: // fall through
Mike Kleine7007382019-05-21 08:36:32 -0500655 case ByteCodeInstruction::kWriteExternal4: {
656 int count = (int) inst - (int) ByteCodeInstruction::kWriteExternal + 1;
657 int target = READ8();
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400658 fByteCode->fExternalValues[target]->write(sp - count + 1);
659 sp -= count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400660 break;
Mike Kleine7007382019-05-21 08:36:32 -0500661 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400662
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400663 default:
Mike Kleine7007382019-05-21 08:36:32 -0500664 SkDEBUGFAILF("unsupported instruction %d\n", (int) inst);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400665 }
666#ifdef TRACE
Mike Kleine7007382019-05-21 08:36:32 -0500667 int stackSize = (int) (sp - stack + 1);
668 printf("STACK(%d):", stackSize);
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400669 for (int i = 0; i < stackSize; ++i) {
Brian Osmane85b6a52019-05-22 14:50:59 -0700670 printf(" %d(%g)", stack[i].fSigned, stack[i].fFloat);
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400671 }
672 printf("\n");
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400673#endif
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400674 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400675}
676
677} // namespace
678
679#endif