blob: 99e7eadafa9ed2930c73ea543475cef92cc87938 [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 Nicholas9e6a3932019-05-17 16:31:21 -0400122 case ByteCodeInstruction::kCallExternal: {
123 int argumentCount = READ8();
124 int returnCount = READ8();
125 int externalValue = READ8();
126 printf("callexternal %d, %d, %d", argumentCount, returnCount, externalValue);
127 break;
128 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400129 VECTOR_DISASSEMBLE(kCompareIEQ, "compareieq")
130 VECTOR_DISASSEMBLE(kCompareINEQ, "compareineq")
131 VECTOR_DISASSEMBLE(kCompareFEQ, "comparefeq")
132 VECTOR_DISASSEMBLE(kCompareFNEQ, "comparefneq")
133 VECTOR_DISASSEMBLE(kCompareFGT, "comparefgt")
134 VECTOR_DISASSEMBLE(kCompareFGTEQ, "comparefgteq")
135 VECTOR_DISASSEMBLE(kCompareFLT, "compareflt")
136 VECTOR_DISASSEMBLE(kCompareFLTEQ, "compareflteq")
137 VECTOR_DISASSEMBLE(kCompareSGT, "comparesgt")
138 VECTOR_DISASSEMBLE(kCompareSGTEQ, "comparesgteq")
139 VECTOR_DISASSEMBLE(kCompareSLT, "compareslt")
140 VECTOR_DISASSEMBLE(kCompareSLTEQ, "compareslteq")
141 VECTOR_DISASSEMBLE(kCompareUGT, "compareugt")
142 VECTOR_DISASSEMBLE(kCompareUGTEQ, "compareugteq")
143 VECTOR_DISASSEMBLE(kCompareULT, "compareult")
144 VECTOR_DISASSEMBLE(kCompareULTEQ, "compareulteq")
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400145 case ByteCodeInstruction::kConditionalBranch:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400146 printf("conditionalbranch %d", READ16());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400147 break;
148 case ByteCodeInstruction::kDebugPrint: printf("debugprint"); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400149 VECTOR_DISASSEMBLE(kDivideF, "dividef")
150 VECTOR_DISASSEMBLE(kDivideS, "divideS")
151 VECTOR_DISASSEMBLE(kDivideU, "divideu")
152 VECTOR_DISASSEMBLE(kDup, "dup")
153 VECTOR_DISASSEMBLE(kFloatToInt, "floattoint")
Brian Osman1091f022019-05-16 09:42:16 -0400154 case ByteCodeInstruction::kLoad: printf("load %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400155 case ByteCodeInstruction::kLoad2: printf("load2 %d", READ8()); break;
156 case ByteCodeInstruction::kLoad3: printf("load3 %d", READ8()); break;
157 case ByteCodeInstruction::kLoad4: printf("load4 %d", READ8()); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400158 case ByteCodeInstruction::kLoadGlobal: printf("loadglobal %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400159 case ByteCodeInstruction::kLoadGlobal2: printf("loadglobal2 %d", READ8()); break;
160 case ByteCodeInstruction::kLoadGlobal3: printf("loadglobal3 %d", READ8()); break;
161 case ByteCodeInstruction::kLoadGlobal4: printf("loadglobal4 %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400162 case ByteCodeInstruction::kLoadSwizzle: {
Brian Osman1091f022019-05-16 09:42:16 -0400163 int target = READ8();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400164 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400165 printf("loadswizzle %d %d", target, count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400166 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400167 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400168 }
169 break;
170 }
Brian Osmanb7451292019-05-15 13:02:13 -0400171 case ByteCodeInstruction::kLoadSwizzleGlobal: {
Brian Osman1091f022019-05-16 09:42:16 -0400172 int target = READ8();
Brian Osmanb7451292019-05-15 13:02:13 -0400173 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400174 printf("loadswizzleglobal %d %d", target, count);
Brian Osmanb7451292019-05-15 13:02:13 -0400175 for (int i = 0; i < count; ++i) {
176 printf(", %d", READ8());
177 }
178 break;
179 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400180 VECTOR_DISASSEMBLE(kMultiplyF, "multiplyf")
181 VECTOR_DISASSEMBLE(kMultiplyI, "multiplyi")
182 VECTOR_DISASSEMBLE(kNegateF, "negatef")
183 VECTOR_DISASSEMBLE(kNegateS, "negates")
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400184 VECTOR_DISASSEMBLE(kNot, "not")
185 VECTOR_DISASSEMBLE(kOrB, "orb")
186 VECTOR_DISASSEMBLE(kOrI, "ori")
187 VECTOR_DISASSEMBLE(kPop, "pop")
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400188 case ByteCodeInstruction::kPushImmediate:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400189 printf("pushimmediate %s", value_string(READ32()).c_str());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400190 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400191 case ByteCodeInstruction::kReadExternal: printf("readexternal %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400192 case ByteCodeInstruction::kReadExternal2: printf("readexternal2 %d", READ8()); break;
193 case ByteCodeInstruction::kReadExternal3: printf("readexternal3 %d", READ8()); break;
194 case ByteCodeInstruction::kReadExternal4: printf("readexternal4 %d", READ8()); break;
195 VECTOR_DISASSEMBLE(kRemainderF, "remainderf")
196 VECTOR_DISASSEMBLE(kRemainderS, "remainders")
197 VECTOR_DISASSEMBLE(kRemainderU, "remainderu")
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400198 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400199 VECTOR_DISASSEMBLE(kSignedToFloat, "signedtofloat")
Brian Osman1091f022019-05-16 09:42:16 -0400200 case ByteCodeInstruction::kStore: printf("store %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400201 case ByteCodeInstruction::kStore2: printf("store2 %d", READ8()); break;
202 case ByteCodeInstruction::kStore3: printf("store3 %d", READ8()); break;
203 case ByteCodeInstruction::kStore4: printf("store4 %d", READ8()); break;
Brian Osman1091f022019-05-16 09:42:16 -0400204 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400205 case ByteCodeInstruction::kStoreGlobal2: printf("storeglobal2 %d", READ8()); break;
206 case ByteCodeInstruction::kStoreGlobal3: printf("storeglobal3 %d", READ8()); break;
207 case ByteCodeInstruction::kStoreGlobal4: printf("storeglobal4 %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400208 case ByteCodeInstruction::kStoreSwizzle: {
Brian Osman1091f022019-05-16 09:42:16 -0400209 int target = READ8();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400210 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400211 printf("storeswizzle %d %d", target, count);
212 for (int i = 0; i < count; ++i) {
213 printf(", %d", READ8());
214 }
215 break;
216 }
217 case ByteCodeInstruction::kStoreSwizzleGlobal: {
218 int target = READ8();
219 int count = READ8();
220 printf("storeswizzleglobal %d %d", target, count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400221 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400222 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400223 }
224 break;
225 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400226 VECTOR_DISASSEMBLE(kSubtractF, "subtractf")
227 VECTOR_DISASSEMBLE(kSubtractI, "subtracti")
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400228 case ByteCodeInstruction::kSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400229 printf("swizzle %d, ", READ8());
230 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400231 printf("%d", count);
232 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400233 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400234 }
235 break;
236 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400237 VECTOR_DISASSEMBLE(kUnsignedToFloat, "unsignedtofloat")
Ethan Nicholas91164d12019-05-15 15:29:54 -0400238 case ByteCodeInstruction::kWriteExternal: printf("writeexternal %d", READ8()); break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400239 case ByteCodeInstruction::kWriteExternal2: printf("writeexternal2 %d", READ8()); break;
240 case ByteCodeInstruction::kWriteExternal3: printf("writeexternal3 %d", READ8()); break;
241 case ByteCodeInstruction::kWriteExternal4: printf("writeexternal4 %d", READ8()); break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400242 default: printf("unknown(%d)\n", *(ip - 1)); SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400243 }
244 printf("\n");
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400245 }
246}
247
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400248#define VECTOR_BINARY_OP(inst, type, srcField, targetField, op) \
249 case ByteCodeInstruction::inst: \
250 tmp[0] = POP(); \
251 sp->targetField = sp->srcField op tmp[0].srcField; \
252 break; \
253 case ByteCodeInstruction::inst ## 2: \
254 tmp[1] = POP(); \
255 tmp[0] = POP(); \
256 sp[ 0].targetField = sp[ 0].srcField op tmp[1].srcField; \
257 sp[-1].targetField = sp[-1].srcField op tmp[0].srcField; \
258 break; \
259 case ByteCodeInstruction::inst ## 3: \
260 tmp[2] = POP(); \
261 tmp[1] = POP(); \
262 tmp[0] = POP(); \
263 sp[ 0].targetField = sp[ 0].srcField op tmp[2].srcField; \
264 sp[-1].targetField = sp[-1].srcField op tmp[1].srcField; \
265 sp[-2].targetField = sp[-2].srcField op tmp[0].srcField; \
266 break; \
267 case ByteCodeInstruction::inst ## 4: \
268 tmp[3] = POP(); \
269 tmp[2] = POP(); \
270 tmp[1] = POP(); \
271 tmp[0] = POP(); \
272 sp[ 0].targetField = sp[ 0].srcField op tmp[3].srcField; \
273 sp[-1].targetField = sp[-1].srcField op tmp[2].srcField; \
274 sp[-2].targetField = sp[-2].srcField op tmp[1].srcField; \
275 sp[-3].targetField = sp[-3].srcField op tmp[0].srcField; \
276 break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400277
Brian Osman226668a2019-05-14 16:47:30 -0400278struct StackFrame {
279 const uint8_t* fCode;
280 const uint8_t* fIP;
281 Interpreter::Value* fStack;
282};
283
284void Interpreter::run(const ByteCodeFunction& f, Value* stack, Value args[], Value* outReturn) {
285 const uint8_t* code = f.fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400286 const uint8_t* ip = code;
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400287 static constexpr int TMP_SLOTS = 4;
288 Value tmp[TMP_SLOTS];
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400289 int src;
290 int target;
291 int count;
Ethan Nicholasf9ef1b82019-05-15 16:50:20 -0400292 if (f.fParameterCount) {
293 memcpy(stack, args, f.fParameterCount * sizeof(Value));
294 }
Brian Osman226668a2019-05-14 16:47:30 -0400295 Value* sp = stack + f.fParameterCount + f.fLocalCount - 1;
296 std::vector<StackFrame> frames;
297
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400298 for (;;) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400299 ByteCodeInstruction inst = (ByteCodeInstruction) READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400300#ifdef TRACE
Ethan Nicholas91164d12019-05-15 15:29:54 -0400301 printf("at %d\n", (int) (ip - code - 1));
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400302#endif
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400303 switch (inst) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400304 VECTOR_BINARY_OP(kAddI, int32_t, fSigned, fSigned, +)
305 VECTOR_BINARY_OP(kAddF, float, fFloat, fFloat, +)
306 case ByteCodeInstruction::kBranch:
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400307 ip = code + READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400308 break;
Brian Osman226668a2019-05-14 16:47:30 -0400309 case ByteCodeInstruction::kCall: {
310 // Precursor code has pushed all parameters to the stack. Update our bottom of
311 // stack to point at the first parameter, and our sp to point past those parameters
312 // (plus space for locals).
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400313 target = READ8();
Brian Osman226668a2019-05-14 16:47:30 -0400314 const ByteCodeFunction* fun = fByteCode->fFunctions[target].get();
315 frames.push_back({ code, ip, stack });
316 ip = code = fun->fCode.data();
317 stack = sp - fun->fParameterCount + 1;
318 sp = stack + fun->fParameterCount + fun->fLocalCount - 1;
319 break;
320 }
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400321 case ByteCodeInstruction::kCallExternal: {
322 int argumentCount = READ8();
323 int returnCount = READ8();
324 SkASSERT(returnCount <= TMP_SLOTS);
325 target = READ8();
326 ExternalValue* v = fByteCode->fExternalValues[target];
327 sp -= argumentCount - 1;
328 v->call(sp, tmp);
329 memcpy(sp, tmp, returnCount * sizeof(Value));
330 sp += returnCount - 1;
331 break;
332 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400333 VECTOR_BINARY_OP(kCompareIEQ, int32_t, fSigned, fBool, ==)
334 VECTOR_BINARY_OP(kCompareFEQ, float, fFloat, fBool, ==)
335 VECTOR_BINARY_OP(kCompareINEQ, int32_t, fSigned, fBool, !=)
336 VECTOR_BINARY_OP(kCompareFNEQ, float, fFloat, fBool, !=)
337 VECTOR_BINARY_OP(kCompareSGT, int32_t, fSigned, fBool, >)
338 VECTOR_BINARY_OP(kCompareUGT, uint32_t, fUnsigned, fBool, >)
339 VECTOR_BINARY_OP(kCompareFGT, float, fFloat, fBool, >)
340 VECTOR_BINARY_OP(kCompareSGTEQ, int32_t, fSigned, fBool, >=)
341 VECTOR_BINARY_OP(kCompareUGTEQ, uint32_t, fUnsigned, fBool, >=)
342 VECTOR_BINARY_OP(kCompareFGTEQ, float, fFloat, fBool, >=)
343 VECTOR_BINARY_OP(kCompareSLT, int32_t, fSigned, fBool, <)
344 VECTOR_BINARY_OP(kCompareULT, uint32_t, fUnsigned, fBool, <)
345 VECTOR_BINARY_OP(kCompareFLT, float, fFloat, fBool, <)
346 VECTOR_BINARY_OP(kCompareSLTEQ, int32_t, fSigned, fBool, <=)
347 VECTOR_BINARY_OP(kCompareULTEQ, uint32_t, fUnsigned, fBool, <=)
348 VECTOR_BINARY_OP(kCompareFLTEQ, float, fFloat, fBool, <=)
349 case ByteCodeInstruction::kConditionalBranch:
350 tmp[0].fSigned = READ16(); // target
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400351 if (POP().fBool) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400352 ip = code + tmp[0].fSigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400353 }
354 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400355 case ByteCodeInstruction::kDebugPrint:
356 tmp[0] = POP();
357 printf("Debug: %d(int), %d(uint), %f(float)\n", tmp[0].fSigned, tmp[0].fUnsigned,
358 tmp[0].fFloat);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400359 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400360 VECTOR_BINARY_OP(kDivideS, int32_t, fSigned, fSigned, /)
361 VECTOR_BINARY_OP(kDivideU, uint32_t, fUnsigned, fUnsigned, /)
362 VECTOR_BINARY_OP(kDivideF, float, fFloat, fFloat, /)
363 case ByteCodeInstruction::kDup: // fall through
364 case ByteCodeInstruction::kDup2: // fall through
365 case ByteCodeInstruction::kDup3: // fall through
366 case ByteCodeInstruction::kDup4:
367 count = (int) inst - (int) ByteCodeInstruction::kDup + 1;
368 memcpy(sp + 1, sp - count + 1, count * sizeof(Value));
369 sp += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400370 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400371 case ByteCodeInstruction::kFloatToInt4:
372 sp[-3].fSigned = (int) sp[-3].fFloat;
373 // fall through
374 case ByteCodeInstruction::kFloatToInt3:
375 sp[-2].fSigned = (int) sp[-2].fFloat;
376 // fall through
377 case ByteCodeInstruction::kFloatToInt2:
378 sp[-1].fSigned = (int) sp[-1].fFloat;
379 // fall through
380 case ByteCodeInstruction::kFloatToInt:
381 sp[0].fSigned = (int) sp[0].fFloat;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400382 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400383 case ByteCodeInstruction::kSignedToFloat4:
384 sp[-3].fFloat = (int) sp[-3].fSigned;
385 // fall through
386 case ByteCodeInstruction::kSignedToFloat3:
387 sp[-2].fFloat = (int) sp[-2].fSigned;
388 // fall through
389 case ByteCodeInstruction::kSignedToFloat2:
390 sp[-1].fFloat = (int) sp[-1].fSigned;
391 // fall through
392 case ByteCodeInstruction::kSignedToFloat:
393 sp[0].fFloat = (int) sp[0].fSigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400394 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400395 case ByteCodeInstruction::kUnsignedToFloat4:
396 sp[-3].fFloat = (int) sp[-3].fUnsigned;
397 // fall through
398 case ByteCodeInstruction::kUnsignedToFloat3:
399 sp[-2].fFloat = (int) sp[-2].fUnsigned;
400 // fall through
401 case ByteCodeInstruction::kUnsignedToFloat2:
402 sp[-1].fFloat = (int) sp[-1].fUnsigned;
403 // fall through
404 case ByteCodeInstruction::kUnsignedToFloat:
405 sp[0].fFloat = (int) sp[0].fUnsigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400406 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400407 case ByteCodeInstruction::kLoad: // fall through
408 case ByteCodeInstruction::kLoad2: // fall through
409 case ByteCodeInstruction::kLoad3: // fall through
410 case ByteCodeInstruction::kLoad4:
411 count = (int) inst - (int) ByteCodeInstruction::kLoad + 1;
412 src = READ8();
413 memcpy(sp + 1, &stack[src], count * sizeof(Value));
414 sp += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400415 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400416 case ByteCodeInstruction::kLoadGlobal: // fall through
417 case ByteCodeInstruction::kLoadGlobal2: // fall through
418 case ByteCodeInstruction::kLoadGlobal3: // fall through
419 case ByteCodeInstruction::kLoadGlobal4:
420 count = (int) inst - (int) ByteCodeInstruction::kLoadGlobal + 1;
421 src = READ8();
422 SkASSERT(src + count <= (int) fGlobals.size());
423 memcpy(sp + 1, &fGlobals[src], count * sizeof(Value));
424 sp += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400425 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400426 case ByteCodeInstruction::kLoadSwizzle:
427 src = READ8();
428 count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400429 for (int i = 0; i < count; ++i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400430 PUSH(stack[src + *(ip + i)]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400431 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400432 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400433 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400434 case ByteCodeInstruction::kLoadSwizzleGlobal:
435 src = READ8();
436 SkASSERT(src < (int) fGlobals.size());
437 count = READ8();
Brian Osmanb7451292019-05-15 13:02:13 -0400438 for (int i = 0; i < count; ++i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400439 PUSH(fGlobals[src + *(ip + i)]);
Brian Osmanb7451292019-05-15 13:02:13 -0400440 }
441 ip += count;
442 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400443 VECTOR_BINARY_OP(kMultiplyI, int32_t, fSigned, fSigned, *)
444 VECTOR_BINARY_OP(kMultiplyF, float, fFloat, fFloat, *)
445 case ByteCodeInstruction::kNot:
446 TOP().fBool = !TOP().fBool;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400447 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400448 case ByteCodeInstruction::kNegateF4:
449 sp[-3].fFloat = -sp[-3].fFloat;
450 // fall through
451 case ByteCodeInstruction::kNegateF3:
452 sp[-2].fFloat = -sp[-2].fFloat;
453 // fall through
454 case ByteCodeInstruction::kNegateF2:
455 sp[-1].fFloat = -sp[-1].fFloat;
456 // fall through
457 case ByteCodeInstruction::kNegateF:
458 sp[0].fFloat = -sp[0].fFloat;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400459 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400460 case ByteCodeInstruction::kNegateS4:
461 sp[-3].fSigned = -sp[-3].fSigned;
462 // fall through
463 case ByteCodeInstruction::kNegateS3:
464 sp[-2].fSigned = -sp[-2].fSigned;
465 // fall through
466 case ByteCodeInstruction::kNegateS2:
467 sp[-1].fSigned = -sp[-1].fSigned;
468 // fall through
469 case ByteCodeInstruction::kNegateS:
470 sp[0].fSigned = -sp[0].fSigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400471 break;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400472 case ByteCodeInstruction::kPop:
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400473 POP();
474 break;
475 case ByteCodeInstruction::kPop2:
476 sp -= 2;
477 break;
478 case ByteCodeInstruction::kPop3:
479 sp -= 3;
480 break;
481 case ByteCodeInstruction::kPop4:
482 sp -= 4;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400483 break;
484 case ByteCodeInstruction::kPushImmediate:
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400485 PUSH(Value((int) READ32()));
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400486 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400487 case ByteCodeInstruction::kReadExternal: // fall through
488 case ByteCodeInstruction::kReadExternal2: // fall through
489 case ByteCodeInstruction::kReadExternal3: // fall through
490 case ByteCodeInstruction::kReadExternal4:
491 count = (int) inst - (int) ByteCodeInstruction::kReadExternal + 1;
492 src = READ8();
493 fByteCode->fExternalValues[src]->read(sp + 1);
494 sp += count;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400495 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400496 case ByteCodeInstruction::kRemainderF:
497 tmp[0] = POP();
498 TOP().fFloat = fmodf(TOP().fFloat, tmp[0].fFloat);
Brian Osman3b41baf2019-05-08 09:24:46 -0400499 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400500 case ByteCodeInstruction::kRemainderF2:
501 tmp[1] = POP();
502 tmp[0] = POP();
503 sp[ 0].fFloat = fmodf(sp[ 0].fFloat, tmp[1].fFloat);
504 sp[-1].fFloat = fmodf(sp[-1].fFloat, tmp[0].fFloat);
505 break;
506 case ByteCodeInstruction::kRemainderF3:
507 tmp[2] = POP();
508 tmp[1] = POP();
509 tmp[0] = POP();
510 sp[ 0].fFloat = fmodf(sp[ 0].fFloat, tmp[2].fFloat);
511 sp[-1].fFloat = fmodf(sp[-1].fFloat, tmp[1].fFloat);
512 sp[-2].fFloat = fmodf(sp[-2].fFloat, tmp[0].fFloat);
513 break;
514 case ByteCodeInstruction::kRemainderF4:
515 tmp[3] = POP();
516 tmp[2] = POP();
517 tmp[1] = POP();
518 tmp[0] = POP();
519 sp[ 0].fFloat = fmodf(sp[ 0].fFloat, tmp[3].fFloat);
520 sp[-1].fFloat = fmodf(sp[-1].fFloat, tmp[2].fFloat);
521 sp[-2].fFloat = fmodf(sp[-2].fFloat, tmp[1].fFloat);
522 sp[-3].fFloat = fmodf(sp[-3].fFloat, tmp[0].fFloat);
523 break;
524 VECTOR_BINARY_OP(kRemainderS, int32_t, fSigned, fSigned, %)
525 VECTOR_BINARY_OP(kRemainderU, uint32_t, fUnsigned, fUnsigned, %)
526 case ByteCodeInstruction::kReturn:
527 count = READ8();
Brian Osman226668a2019-05-14 16:47:30 -0400528 if (frames.empty()) {
529 if (outReturn) {
530 memcpy(outReturn, sp - count + 1, count * sizeof(Value));
531 }
532 return;
533 } else {
534 // When we were called, 'stack' was positioned at the old top-of-stack (where
535 // our parameters were placed). So copy our return values to that same spot.
536 memmove(stack, sp - count + 1, count * sizeof(Value));
537
538 // Now move the stack pointer to the end of the just-pushed return values,
539 // and restore everything else.
540 const StackFrame& frame(frames.back());
541 sp = stack + count - 1;
542 stack = frame.fStack;
543 code = frame.fCode;
544 ip = frame.fIP;
545 frames.pop_back();
546 break;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400547 }
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400548 case ByteCodeInstruction::kStore: // fall through
549 case ByteCodeInstruction::kStore2: // fall through
550 case ByteCodeInstruction::kStore3: // fall through
551 case ByteCodeInstruction::kStore4:
552 count = (int) inst - (int) ByteCodeInstruction::kStore + 1;
553 target = READ8();
554 SkASSERT(target + count <= STACK_SIZE());
555 memcpy(&stack[target], sp - count + 1, count * sizeof(Value));
556 sp -= count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400557 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400558 case ByteCodeInstruction::kStoreGlobal: // fall through
559 case ByteCodeInstruction::kStoreGlobal2: // fall through
560 case ByteCodeInstruction::kStoreGlobal3: // fall through
561 case ByteCodeInstruction::kStoreGlobal4:
562 count = (int) inst - (int) ByteCodeInstruction::kStoreGlobal + 1;
563 target = READ8();
564 SkASSERT(target + count <= (int) fGlobals.size());
565 memcpy(&fGlobals[target], sp - count + 1, count * sizeof(Value));
566 sp -= count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400567 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400568 case ByteCodeInstruction::kStoreSwizzle:
569 target = READ8();
570 count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400571 for (int i = count - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400572 stack[target + *(ip + i)] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400573 }
Brian Osman1091f022019-05-16 09:42:16 -0400574 ip += count;
575 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400576 case ByteCodeInstruction::kStoreSwizzleGlobal:
577 target = READ8();
578 count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400579 for (int i = count - 1; i >= 0; --i) {
580 fGlobals[target + *(ip + i)] = POP();
581 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400582 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400583 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400584 VECTOR_BINARY_OP(kSubtractI, int32_t, fSigned, fSigned, -)
585 VECTOR_BINARY_OP(kSubtractF, float, fFloat, fFloat, -)
586 case ByteCodeInstruction::kSwizzle:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400587 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400588 tmp[i] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400589 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400590 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400591 PUSH(tmp[READ8()]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400592 }
593 break;
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400594 case ByteCodeInstruction::kWriteExternal: // fall through
595 case ByteCodeInstruction::kWriteExternal2: // fall through
596 case ByteCodeInstruction::kWriteExternal3: // fall through
597 case ByteCodeInstruction::kWriteExternal4:
598 count = (int) inst - (int) ByteCodeInstruction::kWriteExternal + 1;
599 target = READ8();
600 fByteCode->fExternalValues[target]->write(sp - count + 1);
601 sp -= count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400602 break;
603 default:
604 printf("unsupported instruction %d\n", (int) inst);
605 SkASSERT(false);
606 }
607#ifdef TRACE
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400608 printf("STACK(%d):", STACK_SIZE());
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400609 for (int i = 0; i < STACK_SIZE(); ++i) {
610 printf(" %d(%f)", stack[i].fSigned, stack[i].fFloat);
611 }
612 printf("\n");
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400613#endif
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400614 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400615}
616
617} // namespace
618
619#endif