blob: c929337329a04d485bc553e54ec6b21582560d5f [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 Nicholas7e603db2019-05-03 12:57:47 -0400140 case ByteCodeInstruction::kDupDown: printf("dupdown %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400141 case ByteCodeInstruction::kFloatToInt: printf("floattoint"); break;
142 case ByteCodeInstruction::kLoad: printf("load"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400143 case ByteCodeInstruction::kLoadGlobal: printf("loadglobal %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400144 case ByteCodeInstruction::kLoadSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400145 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400146 printf("loadswizzle %d", count);
147 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: {
153 int count = READ8();
154 printf("loadswizzleglobal %d", count);
155 for (int i = 0; i < count; ++i) {
156 printf(", %d", READ8());
157 }
158 break;
159 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400160 case ByteCodeInstruction::kMultiplyF: printf("multiplyf"); break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400161 case ByteCodeInstruction::kMultiplyI: printf("multiplyi"); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400162 case ByteCodeInstruction::kNegateF: printf("negatef"); break;
163 case ByteCodeInstruction::kNegateS: printf("negates"); break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400164 case ByteCodeInstruction::kNop1: printf("nop1"); break;
165 case ByteCodeInstruction::kNop2: printf("nop2"); break;
166 case ByteCodeInstruction::kNop3: printf("nop3"); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400167 case ByteCodeInstruction::kNot: printf("not"); break;
168 case ByteCodeInstruction::kOrB: printf("orb"); break;
169 case ByteCodeInstruction::kOrI: printf("ori"); break;
170 case ByteCodeInstruction::kParameter: printf("parameter"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400171 case ByteCodeInstruction::kPop: printf("pop %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400172 case ByteCodeInstruction::kPushImmediate:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400173 printf("pushimmediate %s", value_string(READ32()).c_str());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400174 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400175 case ByteCodeInstruction::kReadExternal: printf("readexternal %d", READ8()); break;
Brian Osman3b41baf2019-05-08 09:24:46 -0400176 case ByteCodeInstruction::kRemainderF: printf("remainderf"); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400177 case ByteCodeInstruction::kRemainderS: printf("remainders"); break;
178 case ByteCodeInstruction::kRemainderU: printf("remainderu"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400179 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400180 case ByteCodeInstruction::kSignedToFloat: printf("signedtofloat"); break;
181 case ByteCodeInstruction::kStore: printf("store"); break;
Ethan Nicholas746035a2019-04-23 13:31:09 -0400182 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal"); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400183 case ByteCodeInstruction::kStoreSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400184 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400185 printf("storeswizzle %d", count);
186 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400187 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400188 }
189 break;
190 }
191 case ByteCodeInstruction::kSubtractF: printf("subtractf"); break;
192 case ByteCodeInstruction::kSubtractI: printf("subtracti"); break;
193 case ByteCodeInstruction::kSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400194 printf("swizzle %d, ", READ8());
195 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400196 printf("%d", count);
197 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::kUnsignedToFloat: printf("unsignedtofloat"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400203 case ByteCodeInstruction::kVector: printf("vector%d", READ8()); break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400204 case ByteCodeInstruction::kWriteExternal: printf("writeexternal %d", READ8()); break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400205 default: printf("unknown(%d)\n", *(ip - 1)); SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400206 }
207 printf("\n");
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400208 }
209}
210
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400211#define BINARY_OP(inst, type, field, op) \
212 case ByteCodeInstruction::inst: { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400213 type b = POP().field; \
214 Value* a = &TOP(); \
Ethan Nicholas95859472019-04-24 12:55:51 -0400215 *a = Value(a->field op b); \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400216 break; \
217 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400218
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400219static constexpr int VECTOR_MAX = 16;
220
221#define VECTOR_BINARY_OP(inst, type, field, op) \
222 case ByteCodeInstruction::inst: { \
223 Value result[VECTOR_MAX]; \
224 for (int i = count - 1; i >= 0; --i) { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400225 result[i] = POP(); \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400226 } \
227 for (int i = count - 1; i >= 0; --i) { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400228 result[i] = POP().field op result[i].field; \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400229 } \
230 for (int i = 0; i < count; ++i) { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400231 PUSH(result[i]); \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400232 } \
233 break; \
234 }
235
Brian Osman226668a2019-05-14 16:47:30 -0400236struct StackFrame {
237 const uint8_t* fCode;
238 const uint8_t* fIP;
239 Interpreter::Value* fStack;
240};
241
242void Interpreter::run(const ByteCodeFunction& f, Value* stack, Value args[], Value* outReturn) {
243 const uint8_t* code = f.fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400244 const uint8_t* ip = code;
Brian Osman226668a2019-05-14 16:47:30 -0400245 memcpy(stack, args, f.fParameterCount * sizeof(Value));
246 Value* sp = stack + f.fParameterCount + f.fLocalCount - 1;
247 std::vector<StackFrame> frames;
248
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400249 for (;;) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400250 ByteCodeInstruction inst = (ByteCodeInstruction) READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400251#ifdef TRACE
Ethan Nicholas91164d12019-05-15 15:29:54 -0400252 printf("at %d\n", (int) (ip - code - 1));
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400253#endif
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400254 switch (inst) {
255 BINARY_OP(kAddI, int32_t, fSigned, +)
256 BINARY_OP(kAddF, float, fFloat, +)
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400257 case ByteCodeInstruction::kBranch: {
258 ip = code + READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400259 break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400260 }
Brian Osman226668a2019-05-14 16:47:30 -0400261 case ByteCodeInstruction::kCall: {
262 // Precursor code has pushed all parameters to the stack. Update our bottom of
263 // stack to point at the first parameter, and our sp to point past those parameters
264 // (plus space for locals).
265 int target = READ8();
266 const ByteCodeFunction* fun = fByteCode->fFunctions[target].get();
267 frames.push_back({ code, ip, stack });
268 ip = code = fun->fCode.data();
269 stack = sp - fun->fParameterCount + 1;
270 sp = stack + fun->fParameterCount + fun->fLocalCount - 1;
271 break;
272 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400273 BINARY_OP(kCompareIEQ, int32_t, fSigned, ==)
274 BINARY_OP(kCompareFEQ, float, fFloat, ==)
275 BINARY_OP(kCompareINEQ, int32_t, fSigned, !=)
276 BINARY_OP(kCompareFNEQ, float, fFloat, !=)
277 BINARY_OP(kCompareSGT, int32_t, fSigned, >)
278 BINARY_OP(kCompareUGT, uint32_t, fUnsigned, >)
279 BINARY_OP(kCompareFGT, float, fFloat, >)
280 BINARY_OP(kCompareSGTEQ, int32_t, fSigned, >=)
281 BINARY_OP(kCompareUGTEQ, uint32_t, fUnsigned, >=)
282 BINARY_OP(kCompareFGTEQ, float, fFloat, >=)
283 BINARY_OP(kCompareSLT, int32_t, fSigned, <)
284 BINARY_OP(kCompareULT, uint32_t, fUnsigned, <)
285 BINARY_OP(kCompareFLT, float, fFloat, <)
286 BINARY_OP(kCompareSLTEQ, int32_t, fSigned, <=)
287 BINARY_OP(kCompareULTEQ, uint32_t, fUnsigned, <=)
288 BINARY_OP(kCompareFLTEQ, float, fFloat, <=)
289 case ByteCodeInstruction::kConditionalBranch: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400290 int target = READ16();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400291 if (POP().fBool) {
292 ip = code + target;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400293 }
294 break;
295 }
296 case ByteCodeInstruction::kDebugPrint: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400297 Value v = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400298 printf("Debug: %d(int), %d(uint), %f(float)\n", v.fSigned, v.fUnsigned, v.fFloat);
299 break;
300 }
301 BINARY_OP(kDivideS, int32_t, fSigned, /)
302 BINARY_OP(kDivideU, uint32_t, fUnsigned, /)
303 BINARY_OP(kDivideF, float, fFloat, /)
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400304 case ByteCodeInstruction::kDup: {
305 Value& top = TOP();
306 PUSH(top);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400307 break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400308 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400309 case ByteCodeInstruction::kDupDown: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400310 int count = READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400311 // before dupdown 4: X A B C D
312 // after dupdown 4: A B C D X A B C D
Ethan Nicholas91164d12019-05-15 15:29:54 -0400313 SkASSERT(sp - count >= stack);
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400314 memmove(sp, sp - count, sizeof(Value) * (count + 1));
315 sp += count;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400316 SkASSERT(sp - count * 2 >= stack);
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400317 memcpy(sp - count * 2, sp - count + 1, sizeof(Value) * count);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400318 break;
319 }
320 case ByteCodeInstruction::kFloatToInt: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400321 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400322 top.fSigned = (int) top.fFloat;
323 break;
324 }
325 case ByteCodeInstruction::kSignedToFloat: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400326 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400327 top.fFloat = (float) top.fSigned;
328 break;
329 }
330 case ByteCodeInstruction::kUnsignedToFloat: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400331 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400332 top.fFloat = (float) top.fUnsigned;
333 break;
334 }
335 case ByteCodeInstruction::kLoad: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400336 int target = POP().fSigned;
337 SkASSERT(target < STACK_SIZE());
338 PUSH(stack[target]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400339 break;
340 }
341 case ByteCodeInstruction::kLoadGlobal: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400342 int target = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400343 SkASSERT(target < (int) fGlobals.size());
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400344 PUSH(fGlobals[target]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400345 break;
346 }
347 case ByteCodeInstruction::kLoadSwizzle: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400348 Value target = POP();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400349 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400350 for (int i = 0; i < count; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400351 PUSH(stack[target.fSigned + *(ip + i)]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400352 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400353 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400354 break;
355 }
Brian Osmanb7451292019-05-15 13:02:13 -0400356 case ByteCodeInstruction::kLoadSwizzleGlobal: {
357 int target = READ8();
358 SkASSERT(target < (int) fGlobals.size());
359 int count = READ8();
360 for (int i = 0; i < count; ++i) {
361 PUSH(fGlobals[target + *(ip + i)]);
362 }
363 ip += count;
364 break;
365 }
Ethan Nicholas91164d12019-05-15 15:29:54 -0400366 BINARY_OP(kMultiplyI, int32_t, fSigned, *)
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400367 BINARY_OP(kMultiplyF, float, fFloat, *)
368 case ByteCodeInstruction::kNot: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400369 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400370 top.fBool = !top.fBool;
371 break;
372 }
373 case ByteCodeInstruction::kNegateF: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400374 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400375 top.fFloat = -top.fFloat;
376 break;
377 }
378 case ByteCodeInstruction::kNegateS: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400379 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400380 top.fSigned = -top.fSigned;
381 break;
382 }
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400383 case ByteCodeInstruction::kNop1:
384 continue;
385 case ByteCodeInstruction::kNop2:
386 ++ip;
387 continue;
388 case ByteCodeInstruction::kNop3:
389 ip += 2;
390 continue;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400391 case ByteCodeInstruction::kPop:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400392 for (int i = READ8(); i > 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400393 POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400394 }
395 break;
396 case ByteCodeInstruction::kPushImmediate:
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400397 PUSH(Value((int) READ32()));
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400398 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400399 case ByteCodeInstruction::kReadExternal: {
400 int target = READ8();
401 ++sp;
402 fByteCode->fExternalValues[target]->read(sp);
403 break;
404 }
Brian Osman3b41baf2019-05-08 09:24:46 -0400405 case ByteCodeInstruction::kRemainderF: {
406 float b = POP().fFloat;
407 Value* a = &TOP();
408 *a = Value(fmodf(a->fFloat, b));
409 break;
410 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400411 BINARY_OP(kRemainderS, int32_t, fSigned, %)
412 BINARY_OP(kRemainderU, uint32_t, fUnsigned, %)
413 case ByteCodeInstruction::kReturn: {
Brian Osman226668a2019-05-14 16:47:30 -0400414 int count = READ8();
415 if (frames.empty()) {
416 if (outReturn) {
417 memcpy(outReturn, sp - count + 1, count * sizeof(Value));
418 }
419 return;
420 } else {
421 // When we were called, 'stack' was positioned at the old top-of-stack (where
422 // our parameters were placed). So copy our return values to that same spot.
423 memmove(stack, sp - count + 1, count * sizeof(Value));
424
425 // Now move the stack pointer to the end of the just-pushed return values,
426 // and restore everything else.
427 const StackFrame& frame(frames.back());
428 sp = stack + count - 1;
429 stack = frame.fStack;
430 code = frame.fCode;
431 ip = frame.fIP;
432 frames.pop_back();
433 break;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400434 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400435 }
436 case ByteCodeInstruction::kStore: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400437 Value value = POP();
438 int target = POP().fSigned;
439 SkASSERT(target < STACK_SIZE());
440 stack[target] = value;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400441 break;
442 }
443 case ByteCodeInstruction::kStoreGlobal: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400444 Value value = POP();
445 int target = POP().fSigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400446 SkASSERT(target < (int) fGlobals.size());
447 fGlobals[target] = value;
448 break;
449 }
450 case ByteCodeInstruction::kStoreSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400451 int count = READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400452 int target = (sp - count)->fSigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400453 for (int i = count - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400454 stack[target + *(ip + i)] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400455 }
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400456 POP();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400457 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400458 break;
459 }
460 BINARY_OP(kSubtractI, int32_t, fSigned, -)
461 BINARY_OP(kSubtractF, float, fFloat, -)
462 case ByteCodeInstruction::kSwizzle: {
463 Value vec[4];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400464 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400465 vec[i] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400466 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400467 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400468 PUSH(vec[READ8()]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400469 }
470 break;
471 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400472 case ByteCodeInstruction::kVector: {
473 uint8_t count = READ8();
474 ByteCodeInstruction inst = (ByteCodeInstruction) READ8();
475 switch (inst) {
476 VECTOR_BINARY_OP(kAddI, int32_t, fSigned, +)
477 VECTOR_BINARY_OP(kAddF, float, fFloat, +)
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400478 VECTOR_BINARY_OP(kCompareIEQ, int32_t, fSigned, ==)
479 VECTOR_BINARY_OP(kCompareFEQ, float, fFloat, ==)
480 VECTOR_BINARY_OP(kCompareINEQ, int32_t, fSigned, !=)
481 VECTOR_BINARY_OP(kCompareFNEQ, float, fFloat, !=)
482 VECTOR_BINARY_OP(kCompareSGT, int32_t, fSigned, >)
483 VECTOR_BINARY_OP(kCompareUGT, uint32_t, fUnsigned, >)
484 VECTOR_BINARY_OP(kCompareFGT, float, fFloat, >)
485 VECTOR_BINARY_OP(kCompareSGTEQ, int32_t, fSigned, >=)
486 VECTOR_BINARY_OP(kCompareUGTEQ, uint32_t, fUnsigned, >=)
487 VECTOR_BINARY_OP(kCompareFGTEQ, float, fFloat, >=)
488 VECTOR_BINARY_OP(kCompareSLT, int32_t, fSigned, <)
489 VECTOR_BINARY_OP(kCompareULT, uint32_t, fUnsigned, <)
490 VECTOR_BINARY_OP(kCompareFLT, float, fFloat, <)
491 VECTOR_BINARY_OP(kCompareSLTEQ, int32_t, fSigned, <=)
492 VECTOR_BINARY_OP(kCompareULTEQ, uint32_t, fUnsigned, <=)
493 VECTOR_BINARY_OP(kCompareFLTEQ, float, fFloat, <=)
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400494 VECTOR_BINARY_OP(kDivideS, int32_t, fSigned, /)
495 VECTOR_BINARY_OP(kDivideU, uint32_t, fUnsigned, /)
496 VECTOR_BINARY_OP(kDivideF, float, fFloat, /)
Ethan Nicholas91164d12019-05-15 15:29:54 -0400497 case ByteCodeInstruction::kDup: {
498 SkASSERT(sp - count + 1 >= stack);
499 memcpy(sp + 1, sp - count + 1, count * sizeof(Value));
500 sp += count;
501 break;
502 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400503 case ByteCodeInstruction::kFloatToInt: {
504 for (int i = 0; i < count; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400505 Value& v = sp[-i];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400506 v.fSigned = (int) v.fFloat;
507 }
508 break;
509 }
510 case ByteCodeInstruction::kSignedToFloat: {
511 for (int i = 0; i < count; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400512 Value& v = sp[-i];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400513 v.fFloat = (float) v.fSigned;
514 }
515 break;
516 }
517 case ByteCodeInstruction::kUnsignedToFloat: {
518 for (int i = 0; i < count; ++i) {
Brian Osman41672152019-05-14 13:37:30 -0400519 Value& v = sp[-i];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400520 v.fFloat = (float) v.fUnsigned;
521 }
522 break;
523 }
524 case ByteCodeInstruction::kLoad: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400525 int src = POP().fSigned;
526 memcpy(sp + 1, &stack[src], count * sizeof(Value));
527 sp += count;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400528 break;
529 }
530 case ByteCodeInstruction::kLoadGlobal: {
531 int target = READ8();
532 SkASSERT(target < (int) fGlobals.size());
Brian Osmanb7451292019-05-15 13:02:13 -0400533 memcpy(sp + 1, &fGlobals[target], count * sizeof(Value));
534 sp += count;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400535 break;
536 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400537 case ByteCodeInstruction::kNegateS: {
538 for (int i = 0; i < count; ++i) {
539 Value& v = sp[-i];
540 v.fSigned = -v.fSigned;
541 }
542 break;
543 }
544 case ByteCodeInstruction::kNegateF: {
545 for (int i = 0; i < count; ++i) {
546 Value& v = sp[-i];
547 v.fFloat = -v.fFloat;
548 }
549 break;
550 }
Ethan Nicholas91164d12019-05-15 15:29:54 -0400551 VECTOR_BINARY_OP(kMultiplyI, int32_t, fSigned, *)
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400552 VECTOR_BINARY_OP(kMultiplyF, float, fFloat, *)
Brian Osman3b41baf2019-05-08 09:24:46 -0400553 case ByteCodeInstruction::kRemainderF: {
554 Value result[VECTOR_MAX];
555 for (int i = count - 1; i >= 0; --i) {
556 result[i] = POP();
557 }
558 for (int i = count - 1; i >= 0; --i) {
559 result[i] = fmodf(POP().fFloat, result[i].fFloat);
560 }
561 for (int i = 0; i < count; ++i) {
562 PUSH(result[i]);
563 }
564 break;
565 }
Ethan Nicholas91164d12019-05-15 15:29:54 -0400566 case ByteCodeInstruction::kReadExternal: {
567 int target = READ8();
568 // We read all the values in a single read() call, because the external
569 // value should know how many bytes to transfer. The vector op prefix just
570 // tells the interpreter how many stack slots to allocate.
571 fByteCode->fExternalValues[target]->read(sp + 1);
572 sp += count;
573 break;
574 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400575 VECTOR_BINARY_OP(kRemainderS, int32_t, fSigned, %)
576 VECTOR_BINARY_OP(kRemainderU, uint32_t, fUnsigned, %)
577 case ByteCodeInstruction::kStore: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400578 memcpy(&stack[(sp - count)->fSigned], sp - count + 1,
579 count * sizeof(Value));
580 sp -= count;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400581 break;
582 }
Brian Osmanb7451292019-05-15 13:02:13 -0400583 case ByteCodeInstruction::kStoreGlobal: {
584 int target = (sp - count)->fSigned;
585 SkASSERT(target < (int)fGlobals.size());
586 memcpy(&fGlobals[target], sp - count + 1, count * sizeof(Value));
587 sp -= count;
588 break;
589 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400590 VECTOR_BINARY_OP(kSubtractI, int32_t, fSigned, -)
591 VECTOR_BINARY_OP(kSubtractF, float, fFloat, -)
Ethan Nicholas91164d12019-05-15 15:29:54 -0400592 case ByteCodeInstruction::kWriteExternal: {
593 int target = READ8();
594 // We write all the values in a single write() call, because the external
595 // value should know how many bytes to transfer. The vector op prefix just
596 // tells the interpreter how many stack slots to deallocate.
597 fByteCode->fExternalValues[target]->write(sp - count + 1);
598 sp -= count;
599 break;
600 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400601 default:
602 printf("unsupported instruction %d\n", (int) inst);
603 SkASSERT(false);
604 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400605 break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400606 }
Ethan Nicholas91164d12019-05-15 15:29:54 -0400607 case ByteCodeInstruction::kWriteExternal: {
608 int target = READ8();
609 fByteCode->fExternalValues[target]->write(sp);
610 POP();
611 break;
612 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400613 default:
614 printf("unsupported instruction %d\n", (int) inst);
615 SkASSERT(false);
616 }
617#ifdef TRACE
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400618 printf("STACK:");
619 for (int i = 0; i < STACK_SIZE(); ++i) {
620 printf(" %d(%f)", stack[i].fSigned, stack[i].fFloat);
621 }
622 printf("\n");
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400623#endif
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400624 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400625}
626
627} // namespace
628
629#endif