blob: 593cb4bdc64606cc8e7cc4f514311d34d8c704ee [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
Ethan Nicholas7e603db2019-05-03 12:57:47 -040090#define READ16() \
Ethan Nicholasdfcad062019-05-07 12:53:34 -040091 (SkASSERT((intptr_t) ip % 2 == 0), \
Ethan Nicholas7e603db2019-05-03 12:57:47 -040092 ip += 2, \
Ethan Nicholasdfcad062019-05-07 12:53:34 -040093 *(uint16_t*) (ip - 2))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040094
Ethan Nicholas7e603db2019-05-03 12:57:47 -040095#define READ32() \
Ethan Nicholasdfcad062019-05-07 12:53:34 -040096 (SkASSERT((intptr_t) ip % 4 == 0), \
Ethan Nicholas7e603db2019-05-03 12:57:47 -040097 ip += 4, \
Ethan Nicholasdfcad062019-05-07 12:53:34 -040098 *(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
105void Interpreter::disassemble(const ByteCodeFunction& f) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400106 const uint8_t* ip = f.fCode.data();
107 while (ip < f.fCode.data() + f.fCode.size()) {
108 printf("%d: ", (int) (ip - f.fCode.data()));
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400109 switch ((ByteCodeInstruction) READ8()) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400110 case ByteCodeInstruction::kAddF: printf("addf"); break;
111 case ByteCodeInstruction::kAddI: printf("addi"); break;
112 case ByteCodeInstruction::kAndB: printf("andb"); break;
113 case ByteCodeInstruction::kAndI: printf("andi"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400114 case ByteCodeInstruction::kBranch: printf("branch %d", READ16()); break;
Brian Osman226668a2019-05-14 16:47:30 -0400115 case ByteCodeInstruction::kCall: printf("call %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400116 case ByteCodeInstruction::kCompareIEQ: printf("comparei eq"); break;
117 case ByteCodeInstruction::kCompareINEQ: printf("comparei neq"); break;
118 case ByteCodeInstruction::kCompareFEQ: printf("comparef eq"); break;
119 case ByteCodeInstruction::kCompareFGT: printf("comparef gt"); break;
120 case ByteCodeInstruction::kCompareFGTEQ: printf("comparef gteq"); break;
121 case ByteCodeInstruction::kCompareFLT: printf("comparef lt"); break;
122 case ByteCodeInstruction::kCompareFLTEQ: printf("comparef lteq"); break;
123 case ByteCodeInstruction::kCompareFNEQ: printf("comparef neq"); break;
124 case ByteCodeInstruction::kCompareSGT: printf("compares sgt"); break;
125 case ByteCodeInstruction::kCompareSGTEQ: printf("compares sgteq"); break;
126 case ByteCodeInstruction::kCompareSLT: printf("compares lt"); break;
127 case ByteCodeInstruction::kCompareSLTEQ: printf("compares lteq"); break;
128 case ByteCodeInstruction::kCompareUGT: printf("compareu gt"); break;
129 case ByteCodeInstruction::kCompareUGTEQ: printf("compareu gteq"); break;
130 case ByteCodeInstruction::kCompareULT: printf("compareu lt"); break;
131 case ByteCodeInstruction::kCompareULTEQ: printf("compareu lteq"); break;
132 case ByteCodeInstruction::kConditionalBranch:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400133 printf("conditionalbranch %d", READ16());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400134 break;
135 case ByteCodeInstruction::kDebugPrint: printf("debugprint"); break;
136 case ByteCodeInstruction::kDivideF: printf("dividef"); break;
137 case ByteCodeInstruction::kDivideS: printf("divides"); break;
138 case ByteCodeInstruction::kDivideU: printf("divideu"); break;
139 case ByteCodeInstruction::kDup: printf("dup"); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400140 case ByteCodeInstruction::kFloatToInt: printf("floattoint"); break;
Brian Osman1091f022019-05-16 09:42:16 -0400141 case ByteCodeInstruction::kLoad: printf("load %d", READ8()); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400142 case ByteCodeInstruction::kLoadGlobal: printf("loadglobal %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400143 case ByteCodeInstruction::kLoadSwizzle: {
Brian Osman1091f022019-05-16 09:42:16 -0400144 int target = READ8();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400145 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400146 printf("loadswizzle %d %d", target, count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400147 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400148 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400149 }
150 break;
151 }
Brian Osmanb7451292019-05-15 13:02:13 -0400152 case ByteCodeInstruction::kLoadSwizzleGlobal: {
Brian Osman1091f022019-05-16 09:42:16 -0400153 int target = READ8();
Brian Osmanb7451292019-05-15 13:02:13 -0400154 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400155 printf("loadswizzleglobal %d %d", target, count);
Brian Osmanb7451292019-05-15 13:02:13 -0400156 for (int i = 0; i < count; ++i) {
157 printf(", %d", READ8());
158 }
159 break;
160 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400161 case ByteCodeInstruction::kMultiplyF: printf("multiplyf"); break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400162 case ByteCodeInstruction::kMultiplyI: printf("multiplyi"); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400163 case ByteCodeInstruction::kNegateF: printf("negatef"); break;
164 case ByteCodeInstruction::kNegateS: printf("negates"); break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400165 case ByteCodeInstruction::kNop1: printf("nop1"); break;
166 case ByteCodeInstruction::kNop2: printf("nop2"); break;
167 case ByteCodeInstruction::kNop3: printf("nop3"); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400168 case ByteCodeInstruction::kNot: printf("not"); break;
169 case ByteCodeInstruction::kOrB: printf("orb"); break;
170 case ByteCodeInstruction::kOrI: printf("ori"); break;
171 case ByteCodeInstruction::kParameter: printf("parameter"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400172 case ByteCodeInstruction::kPop: printf("pop %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400173 case ByteCodeInstruction::kPushImmediate:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400174 printf("pushimmediate %s", value_string(READ32()).c_str());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400175 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400176 case ByteCodeInstruction::kReadExternal: printf("readexternal %d", READ8()); break;
Brian Osman3b41baf2019-05-08 09:24:46 -0400177 case ByteCodeInstruction::kRemainderF: printf("remainderf"); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400178 case ByteCodeInstruction::kRemainderS: printf("remainders"); break;
179 case ByteCodeInstruction::kRemainderU: printf("remainderu"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400180 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400181 case ByteCodeInstruction::kSignedToFloat: printf("signedtofloat"); break;
Brian Osman1091f022019-05-16 09:42:16 -0400182 case ByteCodeInstruction::kStore: printf("store %d", READ8()); break;
183 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400184 case ByteCodeInstruction::kStoreSwizzle: {
Brian Osman1091f022019-05-16 09:42:16 -0400185 int target = READ8();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400186 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400187 printf("storeswizzle %d %d", target, count);
188 for (int i = 0; i < count; ++i) {
189 printf(", %d", READ8());
190 }
191 break;
192 }
193 case ByteCodeInstruction::kStoreSwizzleGlobal: {
194 int target = READ8();
195 int count = READ8();
196 printf("storeswizzleglobal %d %d", target, count);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400197 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400198 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400199 }
200 break;
201 }
202 case ByteCodeInstruction::kSubtractF: printf("subtractf"); break;
203 case ByteCodeInstruction::kSubtractI: printf("subtracti"); break;
204 case ByteCodeInstruction::kSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400205 printf("swizzle %d, ", READ8());
206 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400207 printf("%d", count);
208 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400209 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400210 }
211 break;
212 }
213 case ByteCodeInstruction::kUnsignedToFloat: printf("unsignedtofloat"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400214 case ByteCodeInstruction::kVector: printf("vector%d", READ8()); break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400215 case ByteCodeInstruction::kWriteExternal: printf("writeexternal %d", READ8()); break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400216 default: printf("unknown(%d)\n", *(ip - 1)); SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400217 }
218 printf("\n");
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400219 }
220}
221
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400222#define BINARY_OP(inst, type, field, op) \
223 case ByteCodeInstruction::inst: { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400224 type b = POP().field; \
225 Value* a = &TOP(); \
Ethan Nicholas95859472019-04-24 12:55:51 -0400226 *a = Value(a->field op b); \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400227 break; \
228 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400229
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400230static constexpr int VECTOR_MAX = 16;
231
232#define VECTOR_BINARY_OP(inst, type, field, op) \
233 case ByteCodeInstruction::inst: { \
234 Value result[VECTOR_MAX]; \
235 for (int i = count - 1; i >= 0; --i) { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400236 result[i] = POP(); \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400237 } \
238 for (int i = count - 1; i >= 0; --i) { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400239 result[i] = POP().field op result[i].field; \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400240 } \
241 for (int i = 0; i < count; ++i) { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400242 PUSH(result[i]); \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400243 } \
244 break; \
245 }
246
Brian Osman226668a2019-05-14 16:47:30 -0400247struct StackFrame {
248 const uint8_t* fCode;
249 const uint8_t* fIP;
250 Interpreter::Value* fStack;
251};
252
253void Interpreter::run(const ByteCodeFunction& f, Value* stack, Value args[], Value* outReturn) {
254 const uint8_t* code = f.fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400255 const uint8_t* ip = code;
Ethan Nicholasf9ef1b82019-05-15 16:50:20 -0400256 if (f.fParameterCount) {
257 memcpy(stack, args, f.fParameterCount * sizeof(Value));
258 }
Brian Osman226668a2019-05-14 16:47:30 -0400259 Value* sp = stack + f.fParameterCount + f.fLocalCount - 1;
260 std::vector<StackFrame> frames;
261
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400262 for (;;) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400263 ByteCodeInstruction inst = (ByteCodeInstruction) READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400264#ifdef TRACE
Ethan Nicholas91164d12019-05-15 15:29:54 -0400265 printf("at %d\n", (int) (ip - code - 1));
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400266#endif
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400267 switch (inst) {
268 BINARY_OP(kAddI, int32_t, fSigned, +)
269 BINARY_OP(kAddF, float, fFloat, +)
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400270 case ByteCodeInstruction::kBranch: {
271 ip = code + READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400272 break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400273 }
Brian Osman226668a2019-05-14 16:47:30 -0400274 case ByteCodeInstruction::kCall: {
275 // Precursor code has pushed all parameters to the stack. Update our bottom of
276 // stack to point at the first parameter, and our sp to point past those parameters
277 // (plus space for locals).
278 int target = READ8();
279 const ByteCodeFunction* fun = fByteCode->fFunctions[target].get();
280 frames.push_back({ code, ip, stack });
281 ip = code = fun->fCode.data();
282 stack = sp - fun->fParameterCount + 1;
283 sp = stack + fun->fParameterCount + fun->fLocalCount - 1;
284 break;
285 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400286 BINARY_OP(kCompareIEQ, int32_t, fSigned, ==)
287 BINARY_OP(kCompareFEQ, float, fFloat, ==)
288 BINARY_OP(kCompareINEQ, int32_t, fSigned, !=)
289 BINARY_OP(kCompareFNEQ, float, fFloat, !=)
290 BINARY_OP(kCompareSGT, int32_t, fSigned, >)
291 BINARY_OP(kCompareUGT, uint32_t, fUnsigned, >)
292 BINARY_OP(kCompareFGT, float, fFloat, >)
293 BINARY_OP(kCompareSGTEQ, int32_t, fSigned, >=)
294 BINARY_OP(kCompareUGTEQ, uint32_t, fUnsigned, >=)
295 BINARY_OP(kCompareFGTEQ, float, fFloat, >=)
296 BINARY_OP(kCompareSLT, int32_t, fSigned, <)
297 BINARY_OP(kCompareULT, uint32_t, fUnsigned, <)
298 BINARY_OP(kCompareFLT, float, fFloat, <)
299 BINARY_OP(kCompareSLTEQ, int32_t, fSigned, <=)
300 BINARY_OP(kCompareULTEQ, uint32_t, fUnsigned, <=)
301 BINARY_OP(kCompareFLTEQ, float, fFloat, <=)
302 case ByteCodeInstruction::kConditionalBranch: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400303 int target = READ16();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400304 if (POP().fBool) {
305 ip = code + target;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400306 }
307 break;
308 }
309 case ByteCodeInstruction::kDebugPrint: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400310 Value v = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400311 printf("Debug: %d(int), %d(uint), %f(float)\n", v.fSigned, v.fUnsigned, v.fFloat);
312 break;
313 }
314 BINARY_OP(kDivideS, int32_t, fSigned, /)
315 BINARY_OP(kDivideU, uint32_t, fUnsigned, /)
316 BINARY_OP(kDivideF, float, fFloat, /)
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400317 case ByteCodeInstruction::kDup: {
318 Value& top = TOP();
319 PUSH(top);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400320 break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400321 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400322 case ByteCodeInstruction::kFloatToInt: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400323 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400324 top.fSigned = (int) top.fFloat;
325 break;
326 }
327 case ByteCodeInstruction::kSignedToFloat: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400328 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400329 top.fFloat = (float) top.fSigned;
330 break;
331 }
332 case ByteCodeInstruction::kUnsignedToFloat: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400333 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400334 top.fFloat = (float) top.fUnsigned;
335 break;
336 }
337 case ByteCodeInstruction::kLoad: {
Brian Osman1091f022019-05-16 09:42:16 -0400338 int target = READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400339 SkASSERT(target < STACK_SIZE());
340 PUSH(stack[target]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400341 break;
342 }
343 case ByteCodeInstruction::kLoadGlobal: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400344 int target = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400345 SkASSERT(target < (int) fGlobals.size());
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400346 PUSH(fGlobals[target]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400347 break;
348 }
349 case ByteCodeInstruction::kLoadSwizzle: {
Brian Osman1091f022019-05-16 09:42:16 -0400350 int target = READ8();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400351 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400352 for (int i = 0; i < count; ++i) {
Brian Osman1091f022019-05-16 09:42:16 -0400353 PUSH(stack[target + *(ip + i)]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400354 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400355 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400356 break;
357 }
Brian Osmanb7451292019-05-15 13:02:13 -0400358 case ByteCodeInstruction::kLoadSwizzleGlobal: {
359 int target = READ8();
360 SkASSERT(target < (int) fGlobals.size());
361 int count = READ8();
362 for (int i = 0; i < count; ++i) {
363 PUSH(fGlobals[target + *(ip + i)]);
364 }
365 ip += count;
366 break;
367 }
Ethan Nicholas91164d12019-05-15 15:29:54 -0400368 BINARY_OP(kMultiplyI, int32_t, fSigned, *)
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400369 BINARY_OP(kMultiplyF, float, fFloat, *)
370 case ByteCodeInstruction::kNot: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400371 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400372 top.fBool = !top.fBool;
373 break;
374 }
375 case ByteCodeInstruction::kNegateF: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400376 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400377 top.fFloat = -top.fFloat;
378 break;
379 }
380 case ByteCodeInstruction::kNegateS: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400381 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400382 top.fSigned = -top.fSigned;
383 break;
384 }
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400385 case ByteCodeInstruction::kNop1:
386 continue;
387 case ByteCodeInstruction::kNop2:
388 ++ip;
389 continue;
390 case ByteCodeInstruction::kNop3:
391 ip += 2;
392 continue;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400393 case ByteCodeInstruction::kPop:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400394 for (int i = READ8(); i > 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400395 POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400396 }
397 break;
398 case ByteCodeInstruction::kPushImmediate:
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400399 PUSH(Value((int) READ32()));
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400400 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400401 case ByteCodeInstruction::kReadExternal: {
402 int target = READ8();
403 ++sp;
404 fByteCode->fExternalValues[target]->read(sp);
405 break;
406 }
Brian Osman3b41baf2019-05-08 09:24:46 -0400407 case ByteCodeInstruction::kRemainderF: {
408 float b = POP().fFloat;
409 Value* a = &TOP();
410 *a = Value(fmodf(a->fFloat, b));
411 break;
412 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400413 BINARY_OP(kRemainderS, int32_t, fSigned, %)
414 BINARY_OP(kRemainderU, uint32_t, fUnsigned, %)
415 case ByteCodeInstruction::kReturn: {
Brian Osman226668a2019-05-14 16:47:30 -0400416 int count = READ8();
417 if (frames.empty()) {
418 if (outReturn) {
419 memcpy(outReturn, sp - count + 1, count * sizeof(Value));
420 }
421 return;
422 } else {
423 // When we were called, 'stack' was positioned at the old top-of-stack (where
424 // our parameters were placed). So copy our return values to that same spot.
425 memmove(stack, sp - count + 1, count * sizeof(Value));
426
427 // Now move the stack pointer to the end of the just-pushed return values,
428 // and restore everything else.
429 const StackFrame& frame(frames.back());
430 sp = stack + count - 1;
431 stack = frame.fStack;
432 code = frame.fCode;
433 ip = frame.fIP;
434 frames.pop_back();
435 break;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400436 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400437 }
438 case ByteCodeInstruction::kStore: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400439 Value value = POP();
Brian Osman1091f022019-05-16 09:42:16 -0400440 int target = READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400441 SkASSERT(target < STACK_SIZE());
442 stack[target] = value;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400443 break;
444 }
445 case ByteCodeInstruction::kStoreGlobal: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400446 Value value = POP();
Brian Osman1091f022019-05-16 09:42:16 -0400447 int target = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400448 SkASSERT(target < (int) fGlobals.size());
449 fGlobals[target] = value;
450 break;
451 }
452 case ByteCodeInstruction::kStoreSwizzle: {
Brian Osman1091f022019-05-16 09:42:16 -0400453 int target = READ8();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400454 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400455 for (int i = count - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400456 stack[target + *(ip + i)] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400457 }
Brian Osman1091f022019-05-16 09:42:16 -0400458 ip += count;
459 break;
460 }
461 case ByteCodeInstruction::kStoreSwizzleGlobal: {
462 int target = READ8();
463 int count = READ8();
464 for (int i = count - 1; i >= 0; --i) {
465 fGlobals[target + *(ip + i)] = POP();
466 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400467 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400468 break;
469 }
470 BINARY_OP(kSubtractI, int32_t, fSigned, -)
471 BINARY_OP(kSubtractF, float, fFloat, -)
472 case ByteCodeInstruction::kSwizzle: {
473 Value vec[4];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400474 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400475 vec[i] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400476 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400477 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400478 PUSH(vec[READ8()]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400479 }
480 break;
481 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400482 case ByteCodeInstruction::kVector: {
483 uint8_t count = READ8();
484 ByteCodeInstruction inst = (ByteCodeInstruction) READ8();
485 switch (inst) {
486 VECTOR_BINARY_OP(kAddI, int32_t, fSigned, +)
487 VECTOR_BINARY_OP(kAddF, float, fFloat, +)
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400488 VECTOR_BINARY_OP(kCompareIEQ, int32_t, fSigned, ==)
489 VECTOR_BINARY_OP(kCompareFEQ, float, fFloat, ==)
490 VECTOR_BINARY_OP(kCompareINEQ, int32_t, fSigned, !=)
491 VECTOR_BINARY_OP(kCompareFNEQ, float, fFloat, !=)
492 VECTOR_BINARY_OP(kCompareSGT, int32_t, fSigned, >)
493 VECTOR_BINARY_OP(kCompareUGT, uint32_t, fUnsigned, >)
494 VECTOR_BINARY_OP(kCompareFGT, float, fFloat, >)
495 VECTOR_BINARY_OP(kCompareSGTEQ, int32_t, fSigned, >=)
496 VECTOR_BINARY_OP(kCompareUGTEQ, uint32_t, fUnsigned, >=)
497 VECTOR_BINARY_OP(kCompareFGTEQ, float, fFloat, >=)
498 VECTOR_BINARY_OP(kCompareSLT, int32_t, fSigned, <)
499 VECTOR_BINARY_OP(kCompareULT, uint32_t, fUnsigned, <)
500 VECTOR_BINARY_OP(kCompareFLT, float, fFloat, <)
501 VECTOR_BINARY_OP(kCompareSLTEQ, int32_t, fSigned, <=)
502 VECTOR_BINARY_OP(kCompareULTEQ, uint32_t, fUnsigned, <=)
503 VECTOR_BINARY_OP(kCompareFLTEQ, float, fFloat, <=)
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400504 VECTOR_BINARY_OP(kDivideS, int32_t, fSigned, /)
505 VECTOR_BINARY_OP(kDivideU, uint32_t, fUnsigned, /)
506 VECTOR_BINARY_OP(kDivideF, float, fFloat, /)
Ethan Nicholas91164d12019-05-15 15:29:54 -0400507 case ByteCodeInstruction::kDup: {
508 SkASSERT(sp - count + 1 >= stack);
509 memcpy(sp + 1, sp - count + 1, count * sizeof(Value));
510 sp += count;
511 break;
512 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400513 case ByteCodeInstruction::kFloatToInt: {
514 for (int i = 0; i < count; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400515 Value& v = sp[-i];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400516 v.fSigned = (int) v.fFloat;
517 }
518 break;
519 }
520 case ByteCodeInstruction::kSignedToFloat: {
521 for (int i = 0; i < count; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400522 Value& v = sp[-i];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400523 v.fFloat = (float) v.fSigned;
524 }
525 break;
526 }
527 case ByteCodeInstruction::kUnsignedToFloat: {
528 for (int i = 0; i < count; ++i) {
Brian Osman41672152019-05-14 13:37:30 -0400529 Value& v = sp[-i];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400530 v.fFloat = (float) v.fUnsigned;
531 }
532 break;
533 }
534 case ByteCodeInstruction::kLoad: {
Brian Osman1091f022019-05-16 09:42:16 -0400535 int target = READ8();
536 SkASSERT(target + count <= STACK_SIZE());
537 memcpy(sp + 1, &stack[target], count * sizeof(Value));
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400538 sp += count;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400539 break;
540 }
541 case ByteCodeInstruction::kLoadGlobal: {
542 int target = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400543 SkASSERT(target + count <= (int) fGlobals.size());
Brian Osmanb7451292019-05-15 13:02:13 -0400544 memcpy(sp + 1, &fGlobals[target], count * sizeof(Value));
545 sp += count;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400546 break;
547 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400548 case ByteCodeInstruction::kNegateS: {
549 for (int i = 0; i < count; ++i) {
550 Value& v = sp[-i];
551 v.fSigned = -v.fSigned;
552 }
553 break;
554 }
555 case ByteCodeInstruction::kNegateF: {
556 for (int i = 0; i < count; ++i) {
557 Value& v = sp[-i];
558 v.fFloat = -v.fFloat;
559 }
560 break;
561 }
Ethan Nicholas91164d12019-05-15 15:29:54 -0400562 VECTOR_BINARY_OP(kMultiplyI, int32_t, fSigned, *)
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400563 VECTOR_BINARY_OP(kMultiplyF, float, fFloat, *)
Brian Osman3b41baf2019-05-08 09:24:46 -0400564 case ByteCodeInstruction::kRemainderF: {
565 Value result[VECTOR_MAX];
566 for (int i = count - 1; i >= 0; --i) {
567 result[i] = POP();
568 }
569 for (int i = count - 1; i >= 0; --i) {
570 result[i] = fmodf(POP().fFloat, result[i].fFloat);
571 }
572 for (int i = 0; i < count; ++i) {
573 PUSH(result[i]);
574 }
575 break;
576 }
Ethan Nicholas91164d12019-05-15 15:29:54 -0400577 case ByteCodeInstruction::kReadExternal: {
578 int target = READ8();
579 // We read all the values in a single read() call, because the external
580 // value should know how many bytes to transfer. The vector op prefix just
581 // tells the interpreter how many stack slots to allocate.
582 fByteCode->fExternalValues[target]->read(sp + 1);
583 sp += count;
584 break;
585 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400586 VECTOR_BINARY_OP(kRemainderS, int32_t, fSigned, %)
587 VECTOR_BINARY_OP(kRemainderU, uint32_t, fUnsigned, %)
588 case ByteCodeInstruction::kStore: {
Brian Osman1091f022019-05-16 09:42:16 -0400589 int target = READ8();
590 SkASSERT(target + count <= STACK_SIZE());
591 memcpy(&stack[target], sp - count + 1, count * sizeof(Value));
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400592 sp -= count;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400593 break;
594 }
Brian Osmanb7451292019-05-15 13:02:13 -0400595 case ByteCodeInstruction::kStoreGlobal: {
Brian Osman1091f022019-05-16 09:42:16 -0400596 int target = READ8();
597 SkASSERT(target + count <= (int)fGlobals.size());
Brian Osmanb7451292019-05-15 13:02:13 -0400598 memcpy(&fGlobals[target], sp - count + 1, count * sizeof(Value));
599 sp -= count;
600 break;
601 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400602 VECTOR_BINARY_OP(kSubtractI, int32_t, fSigned, -)
603 VECTOR_BINARY_OP(kSubtractF, float, fFloat, -)
Ethan Nicholas91164d12019-05-15 15:29:54 -0400604 case ByteCodeInstruction::kWriteExternal: {
605 int target = READ8();
606 // We write all the values in a single write() call, because the external
607 // value should know how many bytes to transfer. The vector op prefix just
608 // tells the interpreter how many stack slots to deallocate.
609 fByteCode->fExternalValues[target]->write(sp - count + 1);
610 sp -= count;
611 break;
612 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400613 default:
614 printf("unsupported instruction %d\n", (int) inst);
615 SkASSERT(false);
616 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400617 break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400618 }
Ethan Nicholas91164d12019-05-15 15:29:54 -0400619 case ByteCodeInstruction::kWriteExternal: {
620 int target = READ8();
621 fByteCode->fExternalValues[target]->write(sp);
622 POP();
623 break;
624 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400625 default:
626 printf("unsupported instruction %d\n", (int) inst);
627 SkASSERT(false);
628 }
629#ifdef TRACE
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400630 printf("STACK:");
631 for (int i = 0; i < STACK_SIZE(); ++i) {
632 printf(" %d(%f)", stack[i].fSigned, stack[i].fFloat);
633 }
634 printf("\n");
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400635#endif
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400636 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400637}
638
639} // namespace
640
641#endif