blob: fc79e9704597650f34b5d884ccbedbe1cfdeeffa [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 Klein76346ac2019-05-17 11:57:10 -050090template <typename T>
91static T unaligned_load(const void* ptr) {
92 T val;
93 memcpy(&val, ptr, sizeof(val));
94 return val;
95}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040096
Mike Klein76346ac2019-05-17 11:57:10 -050097#define READ16() (ip += 2, unaligned_load<uint16_t>(ip - 2))
98#define READ32() (ip += 4, unaligned_load<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")
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400177 VECTOR_DISASSEMBLE(kNot, "not")
178 VECTOR_DISASSEMBLE(kOrB, "orb")
179 VECTOR_DISASSEMBLE(kOrI, "ori")
180 VECTOR_DISASSEMBLE(kPop, "pop")
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400181 case ByteCodeInstruction::kPushImmediate:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400182 printf("pushimmediate %s", value_string(READ32()).c_str());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400183 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400184 case ByteCodeInstruction::kReadExternal: printf("readexternal %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400185 case ByteCodeInstruction::kReadExternal2: printf("readexternal2 %d", READ8()); break;
186 case ByteCodeInstruction::kReadExternal3: printf("readexternal3 %d", READ8()); break;
187 case ByteCodeInstruction::kReadExternal4: printf("readexternal4 %d", READ8()); break;
188 VECTOR_DISASSEMBLE(kRemainderF, "remainderf")
189 VECTOR_DISASSEMBLE(kRemainderS, "remainders")
190 VECTOR_DISASSEMBLE(kRemainderU, "remainderu")
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400191 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400192 VECTOR_DISASSEMBLE(kSignedToFloat, "signedtofloat")
Brian Osman1091f022019-05-16 09:42:16 -0400193 case ByteCodeInstruction::kStore: printf("store %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400194 case ByteCodeInstruction::kStore2: printf("store2 %d", READ8()); break;
195 case ByteCodeInstruction::kStore3: printf("store3 %d", READ8()); break;
196 case ByteCodeInstruction::kStore4: printf("store4 %d", READ8()); break;
Brian Osman1091f022019-05-16 09:42:16 -0400197 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400198 case ByteCodeInstruction::kStoreGlobal2: printf("storeglobal2 %d", READ8()); break;
199 case ByteCodeInstruction::kStoreGlobal3: printf("storeglobal3 %d", READ8()); break;
200 case ByteCodeInstruction::kStoreGlobal4: printf("storeglobal4 %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400201 case ByteCodeInstruction::kStoreSwizzle: {
Brian Osman1091f022019-05-16 09:42:16 -0400202 int target = READ8();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400203 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400204 printf("storeswizzle %d %d", target, count);
205 for (int i = 0; i < count; ++i) {
206 printf(", %d", READ8());
207 }
208 break;
209 }
210 case ByteCodeInstruction::kStoreSwizzleGlobal: {
211 int target = READ8();
212 int count = READ8();
213 printf("storeswizzleglobal %d %d", target, count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400214 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400215 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400216 }
217 break;
218 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400219 VECTOR_DISASSEMBLE(kSubtractF, "subtractf")
220 VECTOR_DISASSEMBLE(kSubtractI, "subtracti")
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400221 case ByteCodeInstruction::kSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400222 printf("swizzle %d, ", READ8());
223 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400224 printf("%d", count);
225 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400226 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400227 }
228 break;
229 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400230 VECTOR_DISASSEMBLE(kUnsignedToFloat, "unsignedtofloat")
Ethan Nicholas91164d12019-05-15 15:29:54 -0400231 case ByteCodeInstruction::kWriteExternal: printf("writeexternal %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400232 case ByteCodeInstruction::kWriteExternal2: printf("writeexternal2 %d", READ8()); break;
233 case ByteCodeInstruction::kWriteExternal3: printf("writeexternal3 %d", READ8()); break;
234 case ByteCodeInstruction::kWriteExternal4: printf("writeexternal4 %d", READ8()); break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400235 default: printf("unknown(%d)\n", *(ip - 1)); SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400236 }
237 printf("\n");
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400238 }
239}
240
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400241#define VECTOR_BINARY_OP(inst, type, srcField, targetField, op) \
242 case ByteCodeInstruction::inst: \
243 tmp[0] = POP(); \
244 sp->targetField = sp->srcField op tmp[0].srcField; \
245 break; \
246 case ByteCodeInstruction::inst ## 2: \
247 tmp[1] = POP(); \
248 tmp[0] = POP(); \
249 sp[ 0].targetField = sp[ 0].srcField op tmp[1].srcField; \
250 sp[-1].targetField = sp[-1].srcField op tmp[0].srcField; \
251 break; \
252 case ByteCodeInstruction::inst ## 3: \
253 tmp[2] = POP(); \
254 tmp[1] = POP(); \
255 tmp[0] = POP(); \
256 sp[ 0].targetField = sp[ 0].srcField op tmp[2].srcField; \
257 sp[-1].targetField = sp[-1].srcField op tmp[1].srcField; \
258 sp[-2].targetField = sp[-2].srcField op tmp[0].srcField; \
259 break; \
260 case ByteCodeInstruction::inst ## 4: \
261 tmp[3] = POP(); \
262 tmp[2] = POP(); \
263 tmp[1] = POP(); \
264 tmp[0] = POP(); \
265 sp[ 0].targetField = sp[ 0].srcField op tmp[3].srcField; \
266 sp[-1].targetField = sp[-1].srcField op tmp[2].srcField; \
267 sp[-2].targetField = sp[-2].srcField op tmp[1].srcField; \
268 sp[-3].targetField = sp[-3].srcField op tmp[0].srcField; \
269 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400270
Brian Osman226668a2019-05-14 16:47:30 -0400271struct StackFrame {
272 const uint8_t* fCode;
273 const uint8_t* fIP;
274 Interpreter::Value* fStack;
275};
276
277void Interpreter::run(const ByteCodeFunction& f, Value* stack, Value args[], Value* outReturn) {
278 const uint8_t* code = f.fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400279 const uint8_t* ip = code;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400280 Value tmp[4];
281 int src;
282 int target;
283 int count;
Ethan Nicholasf9ef1b82019-05-15 16:50:20 -0400284 if (f.fParameterCount) {
285 memcpy(stack, args, f.fParameterCount * sizeof(Value));
286 }
Brian Osman226668a2019-05-14 16:47:30 -0400287 Value* sp = stack + f.fParameterCount + f.fLocalCount - 1;
288 std::vector<StackFrame> frames;
289
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400290 for (;;) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400291 ByteCodeInstruction inst = (ByteCodeInstruction) READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400292#ifdef TRACE
Ethan Nicholas91164d12019-05-15 15:29:54 -0400293 printf("at %d\n", (int) (ip - code - 1));
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400294#endif
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400295 switch (inst) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400296 VECTOR_BINARY_OP(kAddI, int32_t, fSigned, fSigned, +)
297 VECTOR_BINARY_OP(kAddF, float, fFloat, fFloat, +)
298 case ByteCodeInstruction::kBranch:
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400299 ip = code + READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400300 break;
Brian Osman226668a2019-05-14 16:47:30 -0400301 case ByteCodeInstruction::kCall: {
302 // Precursor code has pushed all parameters to the stack. Update our bottom of
303 // stack to point at the first parameter, and our sp to point past those parameters
304 // (plus space for locals).
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400305 target = READ8();
Brian Osman226668a2019-05-14 16:47:30 -0400306 const ByteCodeFunction* fun = fByteCode->fFunctions[target].get();
307 frames.push_back({ code, ip, stack });
308 ip = code = fun->fCode.data();
309 stack = sp - fun->fParameterCount + 1;
310 sp = stack + fun->fParameterCount + fun->fLocalCount - 1;
311 break;
312 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400313 VECTOR_BINARY_OP(kCompareIEQ, int32_t, fSigned, fBool, ==)
314 VECTOR_BINARY_OP(kCompareFEQ, float, fFloat, fBool, ==)
315 VECTOR_BINARY_OP(kCompareINEQ, int32_t, fSigned, fBool, !=)
316 VECTOR_BINARY_OP(kCompareFNEQ, float, fFloat, fBool, !=)
317 VECTOR_BINARY_OP(kCompareSGT, int32_t, fSigned, fBool, >)
318 VECTOR_BINARY_OP(kCompareUGT, uint32_t, fUnsigned, fBool, >)
319 VECTOR_BINARY_OP(kCompareFGT, float, fFloat, fBool, >)
320 VECTOR_BINARY_OP(kCompareSGTEQ, int32_t, fSigned, fBool, >=)
321 VECTOR_BINARY_OP(kCompareUGTEQ, uint32_t, fUnsigned, fBool, >=)
322 VECTOR_BINARY_OP(kCompareFGTEQ, float, fFloat, fBool, >=)
323 VECTOR_BINARY_OP(kCompareSLT, int32_t, fSigned, fBool, <)
324 VECTOR_BINARY_OP(kCompareULT, uint32_t, fUnsigned, fBool, <)
325 VECTOR_BINARY_OP(kCompareFLT, float, fFloat, fBool, <)
326 VECTOR_BINARY_OP(kCompareSLTEQ, int32_t, fSigned, fBool, <=)
327 VECTOR_BINARY_OP(kCompareULTEQ, uint32_t, fUnsigned, fBool, <=)
328 VECTOR_BINARY_OP(kCompareFLTEQ, float, fFloat, fBool, <=)
329 case ByteCodeInstruction::kConditionalBranch:
330 tmp[0].fSigned = READ16(); // target
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400331 if (POP().fBool) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400332 ip = code + tmp[0].fSigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400333 }
334 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400335 case ByteCodeInstruction::kDebugPrint:
336 tmp[0] = POP();
337 printf("Debug: %d(int), %d(uint), %f(float)\n", tmp[0].fSigned, tmp[0].fUnsigned,
338 tmp[0].fFloat);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400339 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400340 VECTOR_BINARY_OP(kDivideS, int32_t, fSigned, fSigned, /)
341 VECTOR_BINARY_OP(kDivideU, uint32_t, fUnsigned, fUnsigned, /)
342 VECTOR_BINARY_OP(kDivideF, float, fFloat, fFloat, /)
343 case ByteCodeInstruction::kDup: // fall through
344 case ByteCodeInstruction::kDup2: // fall through
345 case ByteCodeInstruction::kDup3: // fall through
346 case ByteCodeInstruction::kDup4:
347 count = (int) inst - (int) ByteCodeInstruction::kDup + 1;
348 memcpy(sp + 1, sp - count + 1, count * sizeof(Value));
349 sp += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400350 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400351 case ByteCodeInstruction::kFloatToInt4:
352 sp[-3].fSigned = (int) sp[-3].fFloat;
353 // fall through
354 case ByteCodeInstruction::kFloatToInt3:
355 sp[-2].fSigned = (int) sp[-2].fFloat;
356 // fall through
357 case ByteCodeInstruction::kFloatToInt2:
358 sp[-1].fSigned = (int) sp[-1].fFloat;
359 // fall through
360 case ByteCodeInstruction::kFloatToInt:
361 sp[0].fSigned = (int) sp[0].fFloat;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400362 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400363 case ByteCodeInstruction::kSignedToFloat4:
364 sp[-3].fFloat = (int) sp[-3].fSigned;
365 // fall through
366 case ByteCodeInstruction::kSignedToFloat3:
367 sp[-2].fFloat = (int) sp[-2].fSigned;
368 // fall through
369 case ByteCodeInstruction::kSignedToFloat2:
370 sp[-1].fFloat = (int) sp[-1].fSigned;
371 // fall through
372 case ByteCodeInstruction::kSignedToFloat:
373 sp[0].fFloat = (int) sp[0].fSigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400374 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400375 case ByteCodeInstruction::kUnsignedToFloat4:
376 sp[-3].fFloat = (int) sp[-3].fUnsigned;
377 // fall through
378 case ByteCodeInstruction::kUnsignedToFloat3:
379 sp[-2].fFloat = (int) sp[-2].fUnsigned;
380 // fall through
381 case ByteCodeInstruction::kUnsignedToFloat2:
382 sp[-1].fFloat = (int) sp[-1].fUnsigned;
383 // fall through
384 case ByteCodeInstruction::kUnsignedToFloat:
385 sp[0].fFloat = (int) sp[0].fUnsigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400386 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400387 case ByteCodeInstruction::kLoad: // fall through
388 case ByteCodeInstruction::kLoad2: // fall through
389 case ByteCodeInstruction::kLoad3: // fall through
390 case ByteCodeInstruction::kLoad4:
391 count = (int) inst - (int) ByteCodeInstruction::kLoad + 1;
392 src = READ8();
393 memcpy(sp + 1, &stack[src], count * sizeof(Value));
394 sp += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400395 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400396 case ByteCodeInstruction::kLoadGlobal: // fall through
397 case ByteCodeInstruction::kLoadGlobal2: // fall through
398 case ByteCodeInstruction::kLoadGlobal3: // fall through
399 case ByteCodeInstruction::kLoadGlobal4:
400 count = (int) inst - (int) ByteCodeInstruction::kLoadGlobal + 1;
401 src = READ8();
402 SkASSERT(src + count <= (int) fGlobals.size());
403 memcpy(sp + 1, &fGlobals[src], count * sizeof(Value));
404 sp += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400405 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400406 case ByteCodeInstruction::kLoadSwizzle:
407 src = READ8();
408 count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400409 for (int i = 0; i < count; ++i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400410 PUSH(stack[src + *(ip + i)]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400411 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400412 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400413 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400414 case ByteCodeInstruction::kLoadSwizzleGlobal:
415 src = READ8();
416 SkASSERT(src < (int) fGlobals.size());
417 count = READ8();
Brian Osmanb7451292019-05-15 13:02:13 -0400418 for (int i = 0; i < count; ++i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400419 PUSH(fGlobals[src + *(ip + i)]);
Brian Osmanb7451292019-05-15 13:02:13 -0400420 }
421 ip += count;
422 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400423 VECTOR_BINARY_OP(kMultiplyI, int32_t, fSigned, fSigned, *)
424 VECTOR_BINARY_OP(kMultiplyF, float, fFloat, fFloat, *)
425 case ByteCodeInstruction::kNot:
426 TOP().fBool = !TOP().fBool;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400427 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400428 case ByteCodeInstruction::kNegateF4:
429 sp[-3].fFloat = -sp[-3].fFloat;
430 // fall through
431 case ByteCodeInstruction::kNegateF3:
432 sp[-2].fFloat = -sp[-2].fFloat;
433 // fall through
434 case ByteCodeInstruction::kNegateF2:
435 sp[-1].fFloat = -sp[-1].fFloat;
436 // fall through
437 case ByteCodeInstruction::kNegateF:
438 sp[0].fFloat = -sp[0].fFloat;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400439 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400440 case ByteCodeInstruction::kNegateS4:
441 sp[-3].fSigned = -sp[-3].fSigned;
442 // fall through
443 case ByteCodeInstruction::kNegateS3:
444 sp[-2].fSigned = -sp[-2].fSigned;
445 // fall through
446 case ByteCodeInstruction::kNegateS2:
447 sp[-1].fSigned = -sp[-1].fSigned;
448 // fall through
449 case ByteCodeInstruction::kNegateS:
450 sp[0].fSigned = -sp[0].fSigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400451 break;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400452 case ByteCodeInstruction::kPop:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400453 POP();
454 break;
455 case ByteCodeInstruction::kPop2:
456 sp -= 2;
457 break;
458 case ByteCodeInstruction::kPop3:
459 sp -= 3;
460 break;
461 case ByteCodeInstruction::kPop4:
462 sp -= 4;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400463 break;
464 case ByteCodeInstruction::kPushImmediate:
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400465 PUSH(Value((int) READ32()));
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400466 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400467 case ByteCodeInstruction::kReadExternal: // fall through
468 case ByteCodeInstruction::kReadExternal2: // fall through
469 case ByteCodeInstruction::kReadExternal3: // fall through
470 case ByteCodeInstruction::kReadExternal4:
471 count = (int) inst - (int) ByteCodeInstruction::kReadExternal + 1;
472 src = READ8();
473 fByteCode->fExternalValues[src]->read(sp + 1);
474 sp += count;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400475 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400476 case ByteCodeInstruction::kRemainderF:
477 tmp[0] = POP();
478 TOP().fFloat = fmodf(TOP().fFloat, tmp[0].fFloat);
Brian Osman3b41baf2019-05-08 09:24:46 -0400479 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400480 case ByteCodeInstruction::kRemainderF2:
481 tmp[1] = POP();
482 tmp[0] = POP();
483 sp[ 0].fFloat = fmodf(sp[ 0].fFloat, tmp[1].fFloat);
484 sp[-1].fFloat = fmodf(sp[-1].fFloat, tmp[0].fFloat);
485 break;
486 case ByteCodeInstruction::kRemainderF3:
487 tmp[2] = POP();
488 tmp[1] = POP();
489 tmp[0] = POP();
490 sp[ 0].fFloat = fmodf(sp[ 0].fFloat, tmp[2].fFloat);
491 sp[-1].fFloat = fmodf(sp[-1].fFloat, tmp[1].fFloat);
492 sp[-2].fFloat = fmodf(sp[-2].fFloat, tmp[0].fFloat);
493 break;
494 case ByteCodeInstruction::kRemainderF4:
495 tmp[3] = POP();
496 tmp[2] = POP();
497 tmp[1] = POP();
498 tmp[0] = POP();
499 sp[ 0].fFloat = fmodf(sp[ 0].fFloat, tmp[3].fFloat);
500 sp[-1].fFloat = fmodf(sp[-1].fFloat, tmp[2].fFloat);
501 sp[-2].fFloat = fmodf(sp[-2].fFloat, tmp[1].fFloat);
502 sp[-3].fFloat = fmodf(sp[-3].fFloat, tmp[0].fFloat);
503 break;
504 VECTOR_BINARY_OP(kRemainderS, int32_t, fSigned, fSigned, %)
505 VECTOR_BINARY_OP(kRemainderU, uint32_t, fUnsigned, fUnsigned, %)
506 case ByteCodeInstruction::kReturn:
507 count = READ8();
Brian Osman226668a2019-05-14 16:47:30 -0400508 if (frames.empty()) {
509 if (outReturn) {
510 memcpy(outReturn, sp - count + 1, count * sizeof(Value));
511 }
512 return;
513 } else {
514 // When we were called, 'stack' was positioned at the old top-of-stack (where
515 // our parameters were placed). So copy our return values to that same spot.
516 memmove(stack, sp - count + 1, count * sizeof(Value));
517
518 // Now move the stack pointer to the end of the just-pushed return values,
519 // and restore everything else.
520 const StackFrame& frame(frames.back());
521 sp = stack + count - 1;
522 stack = frame.fStack;
523 code = frame.fCode;
524 ip = frame.fIP;
525 frames.pop_back();
526 break;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400527 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400528 case ByteCodeInstruction::kStore: // fall through
529 case ByteCodeInstruction::kStore2: // fall through
530 case ByteCodeInstruction::kStore3: // fall through
531 case ByteCodeInstruction::kStore4:
532 count = (int) inst - (int) ByteCodeInstruction::kStore + 1;
533 target = READ8();
534 SkASSERT(target + count <= STACK_SIZE());
535 memcpy(&stack[target], sp - count + 1, count * sizeof(Value));
536 sp -= count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400537 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400538 case ByteCodeInstruction::kStoreGlobal: // fall through
539 case ByteCodeInstruction::kStoreGlobal2: // fall through
540 case ByteCodeInstruction::kStoreGlobal3: // fall through
541 case ByteCodeInstruction::kStoreGlobal4:
542 count = (int) inst - (int) ByteCodeInstruction::kStoreGlobal + 1;
543 target = READ8();
544 SkASSERT(target + count <= (int) fGlobals.size());
545 memcpy(&fGlobals[target], sp - count + 1, count * sizeof(Value));
546 sp -= count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400547 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400548 case ByteCodeInstruction::kStoreSwizzle:
549 target = READ8();
550 count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400551 for (int i = count - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400552 stack[target + *(ip + i)] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400553 }
Brian Osman1091f022019-05-16 09:42:16 -0400554 ip += count;
555 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400556 case ByteCodeInstruction::kStoreSwizzleGlobal:
557 target = READ8();
558 count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400559 for (int i = count - 1; i >= 0; --i) {
560 fGlobals[target + *(ip + i)] = POP();
561 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400562 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400563 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400564 VECTOR_BINARY_OP(kSubtractI, int32_t, fSigned, fSigned, -)
565 VECTOR_BINARY_OP(kSubtractF, float, fFloat, fFloat, -)
566 case ByteCodeInstruction::kSwizzle:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400567 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400568 tmp[i] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400569 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400570 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400571 PUSH(tmp[READ8()]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400572 }
573 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400574 case ByteCodeInstruction::kWriteExternal: // fall through
575 case ByteCodeInstruction::kWriteExternal2: // fall through
576 case ByteCodeInstruction::kWriteExternal3: // fall through
577 case ByteCodeInstruction::kWriteExternal4:
578 count = (int) inst - (int) ByteCodeInstruction::kWriteExternal + 1;
579 target = READ8();
580 fByteCode->fExternalValues[target]->write(sp - count + 1);
581 sp -= count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400582 break;
583 default:
584 printf("unsupported instruction %d\n", (int) inst);
585 SkASSERT(false);
586 }
587#ifdef TRACE
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400588 printf("STACK(%d):", STACK_SIZE());
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400589 for (int i = 0; i < STACK_SIZE(); ++i) {
590 printf(" %d(%f)", stack[i].fSigned, stack[i].fFloat);
591 }
592 printf("\n");
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400593#endif
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400594 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400595}
596
597} // namespace
598
599#endif