blob: 293a4cd21c9cfdf56877dae15772acdcc4cbb038 [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
Ethan Nicholasdfcad062019-05-07 12:53:34 -040033Interpreter::Interpreter(std::unique_ptr<Program> program, std::unique_ptr<ByteCode> byteCode,
34 Interpreter::Value inputs[])
35 : fProgram(std::move(program))
36 , fByteCode(std::move(byteCode)) {
37 for (int i = 0; i < fByteCode->fGlobalCount; ++i) {
38 fGlobals.push_back(Value((int) UNINITIALIZED));
39 }
Brian Osmand369a5e2019-05-09 13:13:25 -040040 this->setInputs(inputs);
41}
42
43void Interpreter::setInputs(Interpreter::Value inputs[]) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -040044 for (int i = fByteCode->fInputSlots.size() - 1; i >= 0; --i) {
45 fGlobals[fByteCode->fInputSlots[i]] = inputs[i];
46 }
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 }
Brian Osman226668a2019-05-14 16:47:30 -040061 run(f, stack, args, outReturn);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040062 int offset = 0;
63 for (const auto& p : f.fDeclaration.fParameters) {
64 if (p->fModifiers.fFlags & Modifiers::kOut_Flag) {
65 for (int i = p->fType.columns() * p->fType.rows() - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -040066 args[offset] = stack[offset];
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040067 ++offset;
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040068 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040069 } else {
70 offset += p->fType.columns() * p->fType.rows();
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040071 }
72 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040073}
74
Mike Kleinb11ab572018-10-24 06:42:14 -040075struct CallbackCtx : public SkRasterPipeline_CallbackCtx {
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040076 Interpreter* fInterpreter;
77 const FunctionDefinition* fFunction;
78};
79
Ethan Nicholasdfcad062019-05-07 12:53:34 -040080#define STACK_SIZE() (int) (sp - stack + 1)
81
Ethan Nicholas91164d12019-05-15 15:29:54 -040082#define TOP() (SkASSERT(sp >= stack), *sp)
Ethan Nicholasdfcad062019-05-07 12:53:34 -040083
Ethan Nicholas91164d12019-05-15 15:29:54 -040084#define POP() (SkASSERT(sp >= stack), *(sp--))
Ethan Nicholasdfcad062019-05-07 12:53:34 -040085
Ethan Nicholas91164d12019-05-15 15:29:54 -040086#define PUSH(v) (SkASSERT(sp + 1 >= stack), *(++sp) = v)
Ethan Nicholasdfcad062019-05-07 12:53:34 -040087
88#define READ8() (*(ip++))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040089
Mike Kleinb1e4a4e2019-05-17 19:21:46 +000090#define READ16() \
91 (SkASSERT((intptr_t) ip % 2 == 0), \
92 ip += 2, \
93 *(uint16_t*) (ip - 2))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040094
Mike Kleinb1e4a4e2019-05-17 19:21:46 +000095#define READ32() \
96 (SkASSERT((intptr_t) ip % 4 == 0), \
97 ip += 4, \
98 *(uint32_t*) (ip - 4))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040099
100static String value_string(uint32_t v) {
101 union { uint32_t u; float f; } pun = { v };
102 return to_string(v) + "(" + to_string(pun.f) + ")";
103}
104
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400105#define VECTOR_DISASSEMBLE(op, text) \
106 case ByteCodeInstruction::op: printf(text); break; \
107 case ByteCodeInstruction::op##2: printf(text "2"); break; \
108 case ByteCodeInstruction::op##3: printf(text "3"); break; \
109 case ByteCodeInstruction::op##4: printf(text "4"); break;
110
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400111void Interpreter::disassemble(const ByteCodeFunction& f) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400112 const uint8_t* ip = f.fCode.data();
113 while (ip < f.fCode.data() + f.fCode.size()) {
114 printf("%d: ", (int) (ip - f.fCode.data()));
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400115 switch ((ByteCodeInstruction) READ8()) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400116 VECTOR_DISASSEMBLE(kAddF, "addf")
117 VECTOR_DISASSEMBLE(kAddI, "addi")
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400118 case ByteCodeInstruction::kAndB: printf("andb"); break;
119 case ByteCodeInstruction::kAndI: printf("andi"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400120 case ByteCodeInstruction::kBranch: printf("branch %d", READ16()); break;
Brian Osman226668a2019-05-14 16:47:30 -0400121 case ByteCodeInstruction::kCall: printf("call %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400122 VECTOR_DISASSEMBLE(kCompareIEQ, "compareieq")
123 VECTOR_DISASSEMBLE(kCompareINEQ, "compareineq")
124 VECTOR_DISASSEMBLE(kCompareFEQ, "comparefeq")
125 VECTOR_DISASSEMBLE(kCompareFNEQ, "comparefneq")
126 VECTOR_DISASSEMBLE(kCompareFGT, "comparefgt")
127 VECTOR_DISASSEMBLE(kCompareFGTEQ, "comparefgteq")
128 VECTOR_DISASSEMBLE(kCompareFLT, "compareflt")
129 VECTOR_DISASSEMBLE(kCompareFLTEQ, "compareflteq")
130 VECTOR_DISASSEMBLE(kCompareSGT, "comparesgt")
131 VECTOR_DISASSEMBLE(kCompareSGTEQ, "comparesgteq")
132 VECTOR_DISASSEMBLE(kCompareSLT, "compareslt")
133 VECTOR_DISASSEMBLE(kCompareSLTEQ, "compareslteq")
134 VECTOR_DISASSEMBLE(kCompareUGT, "compareugt")
135 VECTOR_DISASSEMBLE(kCompareUGTEQ, "compareugteq")
136 VECTOR_DISASSEMBLE(kCompareULT, "compareult")
137 VECTOR_DISASSEMBLE(kCompareULTEQ, "compareulteq")
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400138 case ByteCodeInstruction::kConditionalBranch:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400139 printf("conditionalbranch %d", READ16());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400140 break;
141 case ByteCodeInstruction::kDebugPrint: printf("debugprint"); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400142 VECTOR_DISASSEMBLE(kDivideF, "dividef")
143 VECTOR_DISASSEMBLE(kDivideS, "divideS")
144 VECTOR_DISASSEMBLE(kDivideU, "divideu")
145 VECTOR_DISASSEMBLE(kDup, "dup")
146 VECTOR_DISASSEMBLE(kFloatToInt, "floattoint")
Brian Osman1091f022019-05-16 09:42:16 -0400147 case ByteCodeInstruction::kLoad: printf("load %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400148 case ByteCodeInstruction::kLoad2: printf("load2 %d", READ8()); break;
149 case ByteCodeInstruction::kLoad3: printf("load3 %d", READ8()); break;
150 case ByteCodeInstruction::kLoad4: printf("load4 %d", READ8()); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400151 case ByteCodeInstruction::kLoadGlobal: printf("loadglobal %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400152 case ByteCodeInstruction::kLoadGlobal2: printf("loadglobal2 %d", READ8()); break;
153 case ByteCodeInstruction::kLoadGlobal3: printf("loadglobal3 %d", READ8()); break;
154 case ByteCodeInstruction::kLoadGlobal4: printf("loadglobal4 %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400155 case ByteCodeInstruction::kLoadSwizzle: {
Brian Osman1091f022019-05-16 09:42:16 -0400156 int target = READ8();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400157 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400158 printf("loadswizzle %d %d", target, count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400159 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400160 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400161 }
162 break;
163 }
Brian Osmanb7451292019-05-15 13:02:13 -0400164 case ByteCodeInstruction::kLoadSwizzleGlobal: {
Brian Osman1091f022019-05-16 09:42:16 -0400165 int target = READ8();
Brian Osmanb7451292019-05-15 13:02:13 -0400166 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400167 printf("loadswizzleglobal %d %d", target, count);
Brian Osmanb7451292019-05-15 13:02:13 -0400168 for (int i = 0; i < count; ++i) {
169 printf(", %d", READ8());
170 }
171 break;
172 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400173 VECTOR_DISASSEMBLE(kMultiplyF, "multiplyf")
174 VECTOR_DISASSEMBLE(kMultiplyI, "multiplyi")
175 VECTOR_DISASSEMBLE(kNegateF, "negatef")
176 VECTOR_DISASSEMBLE(kNegateS, "negates")
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000177 case ByteCodeInstruction::kNop1: printf("nop1"); break;
178 case ByteCodeInstruction::kNop2: printf("nop2"); break;
179 case ByteCodeInstruction::kNop3: printf("nop3"); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400180 VECTOR_DISASSEMBLE(kNot, "not")
181 VECTOR_DISASSEMBLE(kOrB, "orb")
182 VECTOR_DISASSEMBLE(kOrI, "ori")
183 VECTOR_DISASSEMBLE(kPop, "pop")
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400184 case ByteCodeInstruction::kPushImmediate:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400185 printf("pushimmediate %s", value_string(READ32()).c_str());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400186 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400187 case ByteCodeInstruction::kReadExternal: printf("readexternal %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400188 case ByteCodeInstruction::kReadExternal2: printf("readexternal2 %d", READ8()); break;
189 case ByteCodeInstruction::kReadExternal3: printf("readexternal3 %d", READ8()); break;
190 case ByteCodeInstruction::kReadExternal4: printf("readexternal4 %d", READ8()); break;
191 VECTOR_DISASSEMBLE(kRemainderF, "remainderf")
192 VECTOR_DISASSEMBLE(kRemainderS, "remainders")
193 VECTOR_DISASSEMBLE(kRemainderU, "remainderu")
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400194 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400195 VECTOR_DISASSEMBLE(kSignedToFloat, "signedtofloat")
Brian Osman1091f022019-05-16 09:42:16 -0400196 case ByteCodeInstruction::kStore: printf("store %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400197 case ByteCodeInstruction::kStore2: printf("store2 %d", READ8()); break;
198 case ByteCodeInstruction::kStore3: printf("store3 %d", READ8()); break;
199 case ByteCodeInstruction::kStore4: printf("store4 %d", READ8()); break;
Brian Osman1091f022019-05-16 09:42:16 -0400200 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400201 case ByteCodeInstruction::kStoreGlobal2: printf("storeglobal2 %d", READ8()); break;
202 case ByteCodeInstruction::kStoreGlobal3: printf("storeglobal3 %d", READ8()); break;
203 case ByteCodeInstruction::kStoreGlobal4: printf("storeglobal4 %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400204 case ByteCodeInstruction::kStoreSwizzle: {
Brian Osman1091f022019-05-16 09:42:16 -0400205 int target = READ8();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400206 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400207 printf("storeswizzle %d %d", target, count);
208 for (int i = 0; i < count; ++i) {
209 printf(", %d", READ8());
210 }
211 break;
212 }
213 case ByteCodeInstruction::kStoreSwizzleGlobal: {
214 int target = READ8();
215 int count = READ8();
216 printf("storeswizzleglobal %d %d", target, count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400217 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400218 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400219 }
220 break;
221 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400222 VECTOR_DISASSEMBLE(kSubtractF, "subtractf")
223 VECTOR_DISASSEMBLE(kSubtractI, "subtracti")
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400224 case ByteCodeInstruction::kSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400225 printf("swizzle %d, ", READ8());
226 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400227 printf("%d", count);
228 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400229 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400230 }
231 break;
232 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400233 VECTOR_DISASSEMBLE(kUnsignedToFloat, "unsignedtofloat")
Ethan Nicholas91164d12019-05-15 15:29:54 -0400234 case ByteCodeInstruction::kWriteExternal: printf("writeexternal %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400235 case ByteCodeInstruction::kWriteExternal2: printf("writeexternal2 %d", READ8()); break;
236 case ByteCodeInstruction::kWriteExternal3: printf("writeexternal3 %d", READ8()); break;
237 case ByteCodeInstruction::kWriteExternal4: printf("writeexternal4 %d", READ8()); break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400238 default: printf("unknown(%d)\n", *(ip - 1)); SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400239 }
240 printf("\n");
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400241 }
242}
243
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400244#define VECTOR_BINARY_OP(inst, type, srcField, targetField, op) \
245 case ByteCodeInstruction::inst: \
246 tmp[0] = POP(); \
247 sp->targetField = sp->srcField op tmp[0].srcField; \
248 break; \
249 case ByteCodeInstruction::inst ## 2: \
250 tmp[1] = POP(); \
251 tmp[0] = POP(); \
252 sp[ 0].targetField = sp[ 0].srcField op tmp[1].srcField; \
253 sp[-1].targetField = sp[-1].srcField op tmp[0].srcField; \
254 break; \
255 case ByteCodeInstruction::inst ## 3: \
256 tmp[2] = POP(); \
257 tmp[1] = POP(); \
258 tmp[0] = POP(); \
259 sp[ 0].targetField = sp[ 0].srcField op tmp[2].srcField; \
260 sp[-1].targetField = sp[-1].srcField op tmp[1].srcField; \
261 sp[-2].targetField = sp[-2].srcField op tmp[0].srcField; \
262 break; \
263 case ByteCodeInstruction::inst ## 4: \
264 tmp[3] = POP(); \
265 tmp[2] = POP(); \
266 tmp[1] = POP(); \
267 tmp[0] = POP(); \
268 sp[ 0].targetField = sp[ 0].srcField op tmp[3].srcField; \
269 sp[-1].targetField = sp[-1].srcField op tmp[2].srcField; \
270 sp[-2].targetField = sp[-2].srcField op tmp[1].srcField; \
271 sp[-3].targetField = sp[-3].srcField op tmp[0].srcField; \
272 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400273
Brian Osman226668a2019-05-14 16:47:30 -0400274struct StackFrame {
275 const uint8_t* fCode;
276 const uint8_t* fIP;
277 Interpreter::Value* fStack;
278};
279
280void Interpreter::run(const ByteCodeFunction& f, Value* stack, Value args[], Value* outReturn) {
281 const uint8_t* code = f.fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400282 const uint8_t* ip = code;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400283 Value tmp[4];
284 int src;
285 int target;
286 int count;
Ethan Nicholasf9ef1b82019-05-15 16:50:20 -0400287 if (f.fParameterCount) {
288 memcpy(stack, args, f.fParameterCount * sizeof(Value));
289 }
Brian Osman226668a2019-05-14 16:47:30 -0400290 Value* sp = stack + f.fParameterCount + f.fLocalCount - 1;
291 std::vector<StackFrame> frames;
292
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400293 for (;;) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400294 ByteCodeInstruction inst = (ByteCodeInstruction) READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400295#ifdef TRACE
Ethan Nicholas91164d12019-05-15 15:29:54 -0400296 printf("at %d\n", (int) (ip - code - 1));
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400297#endif
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400298 switch (inst) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400299 VECTOR_BINARY_OP(kAddI, int32_t, fSigned, fSigned, +)
300 VECTOR_BINARY_OP(kAddF, float, fFloat, fFloat, +)
301 case ByteCodeInstruction::kBranch:
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400302 ip = code + READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400303 break;
Brian Osman226668a2019-05-14 16:47:30 -0400304 case ByteCodeInstruction::kCall: {
305 // Precursor code has pushed all parameters to the stack. Update our bottom of
306 // stack to point at the first parameter, and our sp to point past those parameters
307 // (plus space for locals).
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400308 target = READ8();
Brian Osman226668a2019-05-14 16:47:30 -0400309 const ByteCodeFunction* fun = fByteCode->fFunctions[target].get();
310 frames.push_back({ code, ip, stack });
311 ip = code = fun->fCode.data();
312 stack = sp - fun->fParameterCount + 1;
313 sp = stack + fun->fParameterCount + fun->fLocalCount - 1;
314 break;
315 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400316 VECTOR_BINARY_OP(kCompareIEQ, int32_t, fSigned, fBool, ==)
317 VECTOR_BINARY_OP(kCompareFEQ, float, fFloat, fBool, ==)
318 VECTOR_BINARY_OP(kCompareINEQ, int32_t, fSigned, fBool, !=)
319 VECTOR_BINARY_OP(kCompareFNEQ, float, fFloat, fBool, !=)
320 VECTOR_BINARY_OP(kCompareSGT, int32_t, fSigned, fBool, >)
321 VECTOR_BINARY_OP(kCompareUGT, uint32_t, fUnsigned, fBool, >)
322 VECTOR_BINARY_OP(kCompareFGT, float, fFloat, fBool, >)
323 VECTOR_BINARY_OP(kCompareSGTEQ, int32_t, fSigned, fBool, >=)
324 VECTOR_BINARY_OP(kCompareUGTEQ, uint32_t, fUnsigned, fBool, >=)
325 VECTOR_BINARY_OP(kCompareFGTEQ, float, fFloat, fBool, >=)
326 VECTOR_BINARY_OP(kCompareSLT, int32_t, fSigned, fBool, <)
327 VECTOR_BINARY_OP(kCompareULT, uint32_t, fUnsigned, fBool, <)
328 VECTOR_BINARY_OP(kCompareFLT, float, fFloat, fBool, <)
329 VECTOR_BINARY_OP(kCompareSLTEQ, int32_t, fSigned, fBool, <=)
330 VECTOR_BINARY_OP(kCompareULTEQ, uint32_t, fUnsigned, fBool, <=)
331 VECTOR_BINARY_OP(kCompareFLTEQ, float, fFloat, fBool, <=)
332 case ByteCodeInstruction::kConditionalBranch:
333 tmp[0].fSigned = READ16(); // target
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400334 if (POP().fBool) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400335 ip = code + tmp[0].fSigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400336 }
337 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400338 case ByteCodeInstruction::kDebugPrint:
339 tmp[0] = POP();
340 printf("Debug: %d(int), %d(uint), %f(float)\n", tmp[0].fSigned, tmp[0].fUnsigned,
341 tmp[0].fFloat);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400342 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400343 VECTOR_BINARY_OP(kDivideS, int32_t, fSigned, fSigned, /)
344 VECTOR_BINARY_OP(kDivideU, uint32_t, fUnsigned, fUnsigned, /)
345 VECTOR_BINARY_OP(kDivideF, float, fFloat, fFloat, /)
346 case ByteCodeInstruction::kDup: // fall through
347 case ByteCodeInstruction::kDup2: // fall through
348 case ByteCodeInstruction::kDup3: // fall through
349 case ByteCodeInstruction::kDup4:
350 count = (int) inst - (int) ByteCodeInstruction::kDup + 1;
351 memcpy(sp + 1, sp - count + 1, count * sizeof(Value));
352 sp += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400353 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400354 case ByteCodeInstruction::kFloatToInt4:
355 sp[-3].fSigned = (int) sp[-3].fFloat;
356 // fall through
357 case ByteCodeInstruction::kFloatToInt3:
358 sp[-2].fSigned = (int) sp[-2].fFloat;
359 // fall through
360 case ByteCodeInstruction::kFloatToInt2:
361 sp[-1].fSigned = (int) sp[-1].fFloat;
362 // fall through
363 case ByteCodeInstruction::kFloatToInt:
364 sp[0].fSigned = (int) sp[0].fFloat;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400365 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400366 case ByteCodeInstruction::kSignedToFloat4:
367 sp[-3].fFloat = (int) sp[-3].fSigned;
368 // fall through
369 case ByteCodeInstruction::kSignedToFloat3:
370 sp[-2].fFloat = (int) sp[-2].fSigned;
371 // fall through
372 case ByteCodeInstruction::kSignedToFloat2:
373 sp[-1].fFloat = (int) sp[-1].fSigned;
374 // fall through
375 case ByteCodeInstruction::kSignedToFloat:
376 sp[0].fFloat = (int) sp[0].fSigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400377 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400378 case ByteCodeInstruction::kUnsignedToFloat4:
379 sp[-3].fFloat = (int) sp[-3].fUnsigned;
380 // fall through
381 case ByteCodeInstruction::kUnsignedToFloat3:
382 sp[-2].fFloat = (int) sp[-2].fUnsigned;
383 // fall through
384 case ByteCodeInstruction::kUnsignedToFloat2:
385 sp[-1].fFloat = (int) sp[-1].fUnsigned;
386 // fall through
387 case ByteCodeInstruction::kUnsignedToFloat:
388 sp[0].fFloat = (int) sp[0].fUnsigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400389 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400390 case ByteCodeInstruction::kLoad: // fall through
391 case ByteCodeInstruction::kLoad2: // fall through
392 case ByteCodeInstruction::kLoad3: // fall through
393 case ByteCodeInstruction::kLoad4:
394 count = (int) inst - (int) ByteCodeInstruction::kLoad + 1;
395 src = READ8();
396 memcpy(sp + 1, &stack[src], count * sizeof(Value));
397 sp += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400398 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400399 case ByteCodeInstruction::kLoadGlobal: // fall through
400 case ByteCodeInstruction::kLoadGlobal2: // fall through
401 case ByteCodeInstruction::kLoadGlobal3: // fall through
402 case ByteCodeInstruction::kLoadGlobal4:
403 count = (int) inst - (int) ByteCodeInstruction::kLoadGlobal + 1;
404 src = READ8();
405 SkASSERT(src + count <= (int) fGlobals.size());
406 memcpy(sp + 1, &fGlobals[src], count * sizeof(Value));
407 sp += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400408 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400409 case ByteCodeInstruction::kLoadSwizzle:
410 src = READ8();
411 count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400412 for (int i = 0; i < count; ++i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400413 PUSH(stack[src + *(ip + i)]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400414 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400415 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400416 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400417 case ByteCodeInstruction::kLoadSwizzleGlobal:
418 src = READ8();
419 SkASSERT(src < (int) fGlobals.size());
420 count = READ8();
Brian Osmanb7451292019-05-15 13:02:13 -0400421 for (int i = 0; i < count; ++i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400422 PUSH(fGlobals[src + *(ip + i)]);
Brian Osmanb7451292019-05-15 13:02:13 -0400423 }
424 ip += count;
425 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400426 VECTOR_BINARY_OP(kMultiplyI, int32_t, fSigned, fSigned, *)
427 VECTOR_BINARY_OP(kMultiplyF, float, fFloat, fFloat, *)
428 case ByteCodeInstruction::kNot:
429 TOP().fBool = !TOP().fBool;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400430 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400431 case ByteCodeInstruction::kNegateF4:
432 sp[-3].fFloat = -sp[-3].fFloat;
433 // fall through
434 case ByteCodeInstruction::kNegateF3:
435 sp[-2].fFloat = -sp[-2].fFloat;
436 // fall through
437 case ByteCodeInstruction::kNegateF2:
438 sp[-1].fFloat = -sp[-1].fFloat;
439 // fall through
440 case ByteCodeInstruction::kNegateF:
441 sp[0].fFloat = -sp[0].fFloat;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400442 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400443 case ByteCodeInstruction::kNegateS4:
444 sp[-3].fSigned = -sp[-3].fSigned;
445 // fall through
446 case ByteCodeInstruction::kNegateS3:
447 sp[-2].fSigned = -sp[-2].fSigned;
448 // fall through
449 case ByteCodeInstruction::kNegateS2:
450 sp[-1].fSigned = -sp[-1].fSigned;
451 // fall through
452 case ByteCodeInstruction::kNegateS:
453 sp[0].fSigned = -sp[0].fSigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400454 break;
Mike Kleinb1e4a4e2019-05-17 19:21:46 +0000455 case ByteCodeInstruction::kNop1:
456 continue;
457 case ByteCodeInstruction::kNop2:
458 ++ip;
459 continue;
460 case ByteCodeInstruction::kNop3:
461 ip += 2;
462 continue;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400463 case ByteCodeInstruction::kPop:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400464 POP();
465 break;
466 case ByteCodeInstruction::kPop2:
467 sp -= 2;
468 break;
469 case ByteCodeInstruction::kPop3:
470 sp -= 3;
471 break;
472 case ByteCodeInstruction::kPop4:
473 sp -= 4;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400474 break;
475 case ByteCodeInstruction::kPushImmediate:
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400476 PUSH(Value((int) READ32()));
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400477 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400478 case ByteCodeInstruction::kReadExternal: // fall through
479 case ByteCodeInstruction::kReadExternal2: // fall through
480 case ByteCodeInstruction::kReadExternal3: // fall through
481 case ByteCodeInstruction::kReadExternal4:
482 count = (int) inst - (int) ByteCodeInstruction::kReadExternal + 1;
483 src = READ8();
484 fByteCode->fExternalValues[src]->read(sp + 1);
485 sp += count;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400486 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400487 case ByteCodeInstruction::kRemainderF:
488 tmp[0] = POP();
489 TOP().fFloat = fmodf(TOP().fFloat, tmp[0].fFloat);
Brian Osman3b41baf2019-05-08 09:24:46 -0400490 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400491 case ByteCodeInstruction::kRemainderF2:
492 tmp[1] = POP();
493 tmp[0] = POP();
494 sp[ 0].fFloat = fmodf(sp[ 0].fFloat, tmp[1].fFloat);
495 sp[-1].fFloat = fmodf(sp[-1].fFloat, tmp[0].fFloat);
496 break;
497 case ByteCodeInstruction::kRemainderF3:
498 tmp[2] = POP();
499 tmp[1] = POP();
500 tmp[0] = POP();
501 sp[ 0].fFloat = fmodf(sp[ 0].fFloat, tmp[2].fFloat);
502 sp[-1].fFloat = fmodf(sp[-1].fFloat, tmp[1].fFloat);
503 sp[-2].fFloat = fmodf(sp[-2].fFloat, tmp[0].fFloat);
504 break;
505 case ByteCodeInstruction::kRemainderF4:
506 tmp[3] = POP();
507 tmp[2] = POP();
508 tmp[1] = POP();
509 tmp[0] = POP();
510 sp[ 0].fFloat = fmodf(sp[ 0].fFloat, tmp[3].fFloat);
511 sp[-1].fFloat = fmodf(sp[-1].fFloat, tmp[2].fFloat);
512 sp[-2].fFloat = fmodf(sp[-2].fFloat, tmp[1].fFloat);
513 sp[-3].fFloat = fmodf(sp[-3].fFloat, tmp[0].fFloat);
514 break;
515 VECTOR_BINARY_OP(kRemainderS, int32_t, fSigned, fSigned, %)
516 VECTOR_BINARY_OP(kRemainderU, uint32_t, fUnsigned, fUnsigned, %)
517 case ByteCodeInstruction::kReturn:
518 count = READ8();
Brian Osman226668a2019-05-14 16:47:30 -0400519 if (frames.empty()) {
520 if (outReturn) {
521 memcpy(outReturn, sp - count + 1, count * sizeof(Value));
522 }
523 return;
524 } else {
525 // When we were called, 'stack' was positioned at the old top-of-stack (where
526 // our parameters were placed). So copy our return values to that same spot.
527 memmove(stack, sp - count + 1, count * sizeof(Value));
528
529 // Now move the stack pointer to the end of the just-pushed return values,
530 // and restore everything else.
531 const StackFrame& frame(frames.back());
532 sp = stack + count - 1;
533 stack = frame.fStack;
534 code = frame.fCode;
535 ip = frame.fIP;
536 frames.pop_back();
537 break;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400538 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400539 case ByteCodeInstruction::kStore: // fall through
540 case ByteCodeInstruction::kStore2: // fall through
541 case ByteCodeInstruction::kStore3: // fall through
542 case ByteCodeInstruction::kStore4:
543 count = (int) inst - (int) ByteCodeInstruction::kStore + 1;
544 target = READ8();
545 SkASSERT(target + count <= STACK_SIZE());
546 memcpy(&stack[target], sp - count + 1, count * sizeof(Value));
547 sp -= count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400548 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400549 case ByteCodeInstruction::kStoreGlobal: // fall through
550 case ByteCodeInstruction::kStoreGlobal2: // fall through
551 case ByteCodeInstruction::kStoreGlobal3: // fall through
552 case ByteCodeInstruction::kStoreGlobal4:
553 count = (int) inst - (int) ByteCodeInstruction::kStoreGlobal + 1;
554 target = READ8();
555 SkASSERT(target + count <= (int) fGlobals.size());
556 memcpy(&fGlobals[target], sp - count + 1, count * sizeof(Value));
557 sp -= count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400558 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400559 case ByteCodeInstruction::kStoreSwizzle:
560 target = READ8();
561 count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400562 for (int i = count - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400563 stack[target + *(ip + i)] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400564 }
Brian Osman1091f022019-05-16 09:42:16 -0400565 ip += count;
566 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400567 case ByteCodeInstruction::kStoreSwizzleGlobal:
568 target = READ8();
569 count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400570 for (int i = count - 1; i >= 0; --i) {
571 fGlobals[target + *(ip + i)] = POP();
572 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400573 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400574 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400575 VECTOR_BINARY_OP(kSubtractI, int32_t, fSigned, fSigned, -)
576 VECTOR_BINARY_OP(kSubtractF, float, fFloat, fFloat, -)
577 case ByteCodeInstruction::kSwizzle:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400578 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400579 tmp[i] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400580 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400581 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400582 PUSH(tmp[READ8()]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400583 }
584 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400585 case ByteCodeInstruction::kWriteExternal: // fall through
586 case ByteCodeInstruction::kWriteExternal2: // fall through
587 case ByteCodeInstruction::kWriteExternal3: // fall through
588 case ByteCodeInstruction::kWriteExternal4:
589 count = (int) inst - (int) ByteCodeInstruction::kWriteExternal + 1;
590 target = READ8();
591 fByteCode->fExternalValues[target]->write(sp - count + 1);
592 sp -= count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400593 break;
594 default:
595 printf("unsupported instruction %d\n", (int) inst);
596 SkASSERT(false);
597 }
598#ifdef TRACE
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400599 printf("STACK(%d):", STACK_SIZE());
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400600 for (int i = 0; i < STACK_SIZE(); ++i) {
601 printf(" %d(%f)", stack[i].fSigned, stack[i].fFloat);
602 }
603 printf("\n");
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400604#endif
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400605 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400606}
607
608} // namespace
609
610#endif