blob: b05d7d9eb68b5248bdc2903c8c07d67221fda576 [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"
11#include "src/sksl/SkSLInterpreter.h"
12#include "src/sksl/ir/SkSLBinaryExpression.h"
13#include "src/sksl/ir/SkSLExpressionStatement.h"
14#include "src/sksl/ir/SkSLForStatement.h"
15#include "src/sksl/ir/SkSLFunctionCall.h"
16#include "src/sksl/ir/SkSLFunctionReference.h"
17#include "src/sksl/ir/SkSLIfStatement.h"
18#include "src/sksl/ir/SkSLIndexExpression.h"
19#include "src/sksl/ir/SkSLPostfixExpression.h"
20#include "src/sksl/ir/SkSLPrefixExpression.h"
21#include "src/sksl/ir/SkSLProgram.h"
22#include "src/sksl/ir/SkSLStatement.h"
23#include "src/sksl/ir/SkSLTernaryExpression.h"
24#include "src/sksl/ir/SkSLVarDeclarations.h"
25#include "src/sksl/ir/SkSLVarDeclarationsStatement.h"
26#include "src/sksl/ir/SkSLVariableReference.h"
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040027
28namespace SkSL {
29
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040030static constexpr int UNINITIALIZED = 0xDEADBEEF;
31
Ethan Nicholasdfcad062019-05-07 12:53:34 -040032Interpreter::Interpreter(std::unique_ptr<Program> program, std::unique_ptr<ByteCode> byteCode,
33 Interpreter::Value inputs[])
34 : fProgram(std::move(program))
35 , fByteCode(std::move(byteCode)) {
36 for (int i = 0; i < fByteCode->fGlobalCount; ++i) {
37 fGlobals.push_back(Value((int) UNINITIALIZED));
38 }
Brian Osmand369a5e2019-05-09 13:13:25 -040039 this->setInputs(inputs);
40}
41
42void Interpreter::setInputs(Interpreter::Value inputs[]) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -040043 for (int i = fByteCode->fInputSlots.size() - 1; i >= 0; --i) {
44 fGlobals[fByteCode->fInputSlots[i]] = inputs[i];
45 }
46}
47
48void Interpreter::run(const ByteCodeFunction& f, Interpreter::Value args[],
49 Interpreter::Value* outReturn) {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040050 fCurrentFunction = &f;
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;
57 if ((int) SK_ARRAY_COUNT(smallStack) < fCurrentFunction->fStackCount) {
58 largeStack.reset(new Value[fCurrentFunction->fStackCount]);
59 stack = largeStack.get();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040060 }
Ethan Nicholasdfcad062019-05-07 12:53:34 -040061 run(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
82#define TOP() (*sp)
83
84#define POP() (*(sp--))
85
86#define PUSH(v) (*(++sp) = v)
87
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;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400115 case ByteCodeInstruction::kCompareIEQ: printf("comparei eq"); break;
116 case ByteCodeInstruction::kCompareINEQ: printf("comparei neq"); break;
117 case ByteCodeInstruction::kCompareFEQ: printf("comparef eq"); break;
118 case ByteCodeInstruction::kCompareFGT: printf("comparef gt"); break;
119 case ByteCodeInstruction::kCompareFGTEQ: printf("comparef gteq"); break;
120 case ByteCodeInstruction::kCompareFLT: printf("comparef lt"); break;
121 case ByteCodeInstruction::kCompareFLTEQ: printf("comparef lteq"); break;
122 case ByteCodeInstruction::kCompareFNEQ: printf("comparef neq"); break;
123 case ByteCodeInstruction::kCompareSGT: printf("compares sgt"); break;
124 case ByteCodeInstruction::kCompareSGTEQ: printf("compares sgteq"); break;
125 case ByteCodeInstruction::kCompareSLT: printf("compares lt"); break;
126 case ByteCodeInstruction::kCompareSLTEQ: printf("compares lteq"); break;
127 case ByteCodeInstruction::kCompareUGT: printf("compareu gt"); break;
128 case ByteCodeInstruction::kCompareUGTEQ: printf("compareu gteq"); break;
129 case ByteCodeInstruction::kCompareULT: printf("compareu lt"); break;
130 case ByteCodeInstruction::kCompareULTEQ: printf("compareu lteq"); break;
131 case ByteCodeInstruction::kConditionalBranch:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400132 printf("conditionalbranch %d", READ16());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400133 break;
134 case ByteCodeInstruction::kDebugPrint: printf("debugprint"); break;
135 case ByteCodeInstruction::kDivideF: printf("dividef"); break;
136 case ByteCodeInstruction::kDivideS: printf("divides"); break;
137 case ByteCodeInstruction::kDivideU: printf("divideu"); break;
138 case ByteCodeInstruction::kDup: printf("dup"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400139 case ByteCodeInstruction::kDupDown: printf("dupdown %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400140 case ByteCodeInstruction::kFloatToInt: printf("floattoint"); break;
141 case ByteCodeInstruction::kLoad: printf("load"); 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: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400144 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400145 printf("loadswizzle %d", count);
146 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400147 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400148 }
149 break;
150 }
151 case ByteCodeInstruction::kMultiplyF: printf("multiplyf"); break;
152 case ByteCodeInstruction::kMultiplyS: printf("multiplys"); break;
153 case ByteCodeInstruction::kMultiplyU: printf("multiplyu"); break;
154 case ByteCodeInstruction::kNegateF: printf("negatef"); break;
155 case ByteCodeInstruction::kNegateS: printf("negates"); break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400156 case ByteCodeInstruction::kNop1: printf("nop1"); break;
157 case ByteCodeInstruction::kNop2: printf("nop2"); break;
158 case ByteCodeInstruction::kNop3: printf("nop3"); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400159 case ByteCodeInstruction::kNot: printf("not"); break;
160 case ByteCodeInstruction::kOrB: printf("orb"); break;
161 case ByteCodeInstruction::kOrI: printf("ori"); break;
162 case ByteCodeInstruction::kParameter: printf("parameter"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400163 case ByteCodeInstruction::kPop: printf("pop %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400164 case ByteCodeInstruction::kPushImmediate:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400165 printf("pushimmediate %s", value_string(READ32()).c_str());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400166 break;
Brian Osman3b41baf2019-05-08 09:24:46 -0400167 case ByteCodeInstruction::kRemainderF: printf("remainderf"); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400168 case ByteCodeInstruction::kRemainderS: printf("remainders"); break;
169 case ByteCodeInstruction::kRemainderU: printf("remainderu"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400170 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400171 case ByteCodeInstruction::kSignedToFloat: printf("signedtofloat"); break;
172 case ByteCodeInstruction::kStore: printf("store"); break;
Ethan Nicholas746035a2019-04-23 13:31:09 -0400173 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal"); break;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400174 case ByteCodeInstruction::kStoreSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400175 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400176 printf("storeswizzle %d", count);
177 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400178 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400179 }
180 break;
181 }
182 case ByteCodeInstruction::kSubtractF: printf("subtractf"); break;
183 case ByteCodeInstruction::kSubtractI: printf("subtracti"); break;
184 case ByteCodeInstruction::kSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400185 printf("swizzle %d, ", READ8());
186 int count = READ8();
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400187 printf("%d", count);
188 for (int i = 0; i < count; ++i) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400189 printf(", %d", READ8());
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400190 }
191 break;
192 }
193 case ByteCodeInstruction::kUnsignedToFloat: printf("unsignedtofloat"); break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400194 case ByteCodeInstruction::kVector: printf("vector%d", READ8()); break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400195 default: printf("unknown(%d)\n", *(ip - 1)); SkASSERT(false);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400196 }
197 printf("\n");
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400198 }
199}
200
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400201#define BINARY_OP(inst, type, field, op) \
202 case ByteCodeInstruction::inst: { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400203 type b = POP().field; \
204 Value* a = &TOP(); \
Ethan Nicholas95859472019-04-24 12:55:51 -0400205 *a = Value(a->field op b); \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400206 break; \
207 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400208
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400209static constexpr int VECTOR_MAX = 16;
210
211#define VECTOR_BINARY_OP(inst, type, field, op) \
212 case ByteCodeInstruction::inst: { \
213 Value result[VECTOR_MAX]; \
214 for (int i = count - 1; i >= 0; --i) { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400215 result[i] = POP(); \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400216 } \
217 for (int i = count - 1; i >= 0; --i) { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400218 result[i] = POP().field op result[i].field; \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400219 } \
220 for (int i = 0; i < count; ++i) { \
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400221 PUSH(result[i]); \
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400222 } \
223 break; \
224 }
225
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400226void Interpreter::run(Value* stack, Value args[], Value* outReturn) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400227 const uint8_t* code = fCurrentFunction->fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400228 const uint8_t* ip = code;
229 memcpy(stack, args, fCurrentFunction->fParameterCount * sizeof(Value));
230 Value* sp = stack + fCurrentFunction->fParameterCount + fCurrentFunction->fLocalCount - 1;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400231 for (;;) {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400232 ByteCodeInstruction inst = (ByteCodeInstruction) READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400233#ifdef TRACE
234 printf("at %d\n", (int) (ip - fCurrentFunction->fCode.data() - 1));
235#endif
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400236 switch (inst) {
237 BINARY_OP(kAddI, int32_t, fSigned, +)
238 BINARY_OP(kAddF, float, fFloat, +)
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400239 case ByteCodeInstruction::kBranch: {
240 ip = code + READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400241 break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400242 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400243 BINARY_OP(kCompareIEQ, int32_t, fSigned, ==)
244 BINARY_OP(kCompareFEQ, float, fFloat, ==)
245 BINARY_OP(kCompareINEQ, int32_t, fSigned, !=)
246 BINARY_OP(kCompareFNEQ, float, fFloat, !=)
247 BINARY_OP(kCompareSGT, int32_t, fSigned, >)
248 BINARY_OP(kCompareUGT, uint32_t, fUnsigned, >)
249 BINARY_OP(kCompareFGT, float, fFloat, >)
250 BINARY_OP(kCompareSGTEQ, int32_t, fSigned, >=)
251 BINARY_OP(kCompareUGTEQ, uint32_t, fUnsigned, >=)
252 BINARY_OP(kCompareFGTEQ, float, fFloat, >=)
253 BINARY_OP(kCompareSLT, int32_t, fSigned, <)
254 BINARY_OP(kCompareULT, uint32_t, fUnsigned, <)
255 BINARY_OP(kCompareFLT, float, fFloat, <)
256 BINARY_OP(kCompareSLTEQ, int32_t, fSigned, <=)
257 BINARY_OP(kCompareULTEQ, uint32_t, fUnsigned, <=)
258 BINARY_OP(kCompareFLTEQ, float, fFloat, <=)
259 case ByteCodeInstruction::kConditionalBranch: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400260 int target = READ16();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400261 if (POP().fBool) {
262 ip = code + target;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400263 }
264 break;
265 }
266 case ByteCodeInstruction::kDebugPrint: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400267 Value v = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400268 printf("Debug: %d(int), %d(uint), %f(float)\n", v.fSigned, v.fUnsigned, v.fFloat);
269 break;
270 }
271 BINARY_OP(kDivideS, int32_t, fSigned, /)
272 BINARY_OP(kDivideU, uint32_t, fUnsigned, /)
273 BINARY_OP(kDivideF, float, fFloat, /)
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400274 case ByteCodeInstruction::kDup: {
275 Value& top = TOP();
276 PUSH(top);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400277 break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400278 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400279 case ByteCodeInstruction::kDupDown: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400280 int count = READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400281 // before dupdown 4: X A B C D
282 // after dupdown 4: A B C D X A B C D
283 memmove(sp, sp - count, sizeof(Value) * (count + 1));
284 sp += count;
285 memcpy(sp - count * 2, sp - count + 1, sizeof(Value) * count);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400286 break;
287 }
288 case ByteCodeInstruction::kFloatToInt: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400289 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400290 top.fSigned = (int) top.fFloat;
291 break;
292 }
293 case ByteCodeInstruction::kSignedToFloat: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400294 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400295 top.fFloat = (float) top.fSigned;
296 break;
297 }
298 case ByteCodeInstruction::kUnsignedToFloat: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400299 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400300 top.fFloat = (float) top.fUnsigned;
301 break;
302 }
303 case ByteCodeInstruction::kLoad: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400304 int target = POP().fSigned;
305 SkASSERT(target < STACK_SIZE());
306 PUSH(stack[target]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400307 break;
308 }
309 case ByteCodeInstruction::kLoadGlobal: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400310 int target = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400311 SkASSERT(target < (int) fGlobals.size());
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400312 PUSH(fGlobals[target]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400313 break;
314 }
315 case ByteCodeInstruction::kLoadSwizzle: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400316 Value target = POP();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400317 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400318 for (int i = 0; i < count; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400319 PUSH(stack[target.fSigned + *(ip + i)]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400320 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400321 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400322 break;
323 }
324 BINARY_OP(kMultiplyS, int32_t, fSigned, *)
325 BINARY_OP(kMultiplyU, uint32_t, fUnsigned, *)
326 BINARY_OP(kMultiplyF, float, fFloat, *)
327 case ByteCodeInstruction::kNot: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400328 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400329 top.fBool = !top.fBool;
330 break;
331 }
332 case ByteCodeInstruction::kNegateF: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400333 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400334 top.fFloat = -top.fFloat;
335 break;
336 }
337 case ByteCodeInstruction::kNegateS: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400338 Value& top = TOP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400339 top.fSigned = -top.fSigned;
340 break;
341 }
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400342 case ByteCodeInstruction::kNop1:
343 continue;
344 case ByteCodeInstruction::kNop2:
345 ++ip;
346 continue;
347 case ByteCodeInstruction::kNop3:
348 ip += 2;
349 continue;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400350 case ByteCodeInstruction::kPop:
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400351 for (int i = READ8(); i > 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400352 POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400353 }
354 break;
355 case ByteCodeInstruction::kPushImmediate:
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400356 PUSH(Value((int) READ32()));
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400357 break;
Brian Osman3b41baf2019-05-08 09:24:46 -0400358 case ByteCodeInstruction::kRemainderF: {
359 float b = POP().fFloat;
360 Value* a = &TOP();
361 *a = Value(fmodf(a->fFloat, b));
362 break;
363 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400364 BINARY_OP(kRemainderS, int32_t, fSigned, %)
365 BINARY_OP(kRemainderU, uint32_t, fUnsigned, %)
366 case ByteCodeInstruction::kReturn: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400367 if (outReturn) {
368 int count = READ8();
369 memcpy(outReturn, sp - count + 1, count * sizeof(Value));
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400370 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400371 return;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400372 }
373 case ByteCodeInstruction::kStore: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400374 Value value = POP();
375 int target = POP().fSigned;
376 SkASSERT(target < STACK_SIZE());
377 stack[target] = value;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400378 break;
379 }
380 case ByteCodeInstruction::kStoreGlobal: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400381 Value value = POP();
382 int target = POP().fSigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400383 SkASSERT(target < (int) fGlobals.size());
384 fGlobals[target] = value;
385 break;
386 }
387 case ByteCodeInstruction::kStoreSwizzle: {
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400388 int count = READ8();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400389 int target = (sp - count)->fSigned;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400390 for (int i = count - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400391 stack[target + *(ip + i)] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400392 }
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400393 POP();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400394 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400395 break;
396 }
397 BINARY_OP(kSubtractI, int32_t, fSigned, -)
398 BINARY_OP(kSubtractF, float, fFloat, -)
399 case ByteCodeInstruction::kSwizzle: {
400 Value vec[4];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400401 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400402 vec[i] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400403 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400404 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400405 PUSH(vec[READ8()]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400406 }
407 break;
408 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400409 case ByteCodeInstruction::kVector: {
410 uint8_t count = READ8();
411 ByteCodeInstruction inst = (ByteCodeInstruction) READ8();
412 switch (inst) {
413 VECTOR_BINARY_OP(kAddI, int32_t, fSigned, +)
414 VECTOR_BINARY_OP(kAddF, float, fFloat, +)
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400415 case ByteCodeInstruction::kBranch: {
416 ip = code + READ16();
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400417 break;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400418 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400419 VECTOR_BINARY_OP(kCompareIEQ, int32_t, fSigned, ==)
420 VECTOR_BINARY_OP(kCompareFEQ, float, fFloat, ==)
421 VECTOR_BINARY_OP(kCompareINEQ, int32_t, fSigned, !=)
422 VECTOR_BINARY_OP(kCompareFNEQ, float, fFloat, !=)
423 VECTOR_BINARY_OP(kCompareSGT, int32_t, fSigned, >)
424 VECTOR_BINARY_OP(kCompareUGT, uint32_t, fUnsigned, >)
425 VECTOR_BINARY_OP(kCompareFGT, float, fFloat, >)
426 VECTOR_BINARY_OP(kCompareSGTEQ, int32_t, fSigned, >=)
427 VECTOR_BINARY_OP(kCompareUGTEQ, uint32_t, fUnsigned, >=)
428 VECTOR_BINARY_OP(kCompareFGTEQ, float, fFloat, >=)
429 VECTOR_BINARY_OP(kCompareSLT, int32_t, fSigned, <)
430 VECTOR_BINARY_OP(kCompareULT, uint32_t, fUnsigned, <)
431 VECTOR_BINARY_OP(kCompareFLT, float, fFloat, <)
432 VECTOR_BINARY_OP(kCompareSLTEQ, int32_t, fSigned, <=)
433 VECTOR_BINARY_OP(kCompareULTEQ, uint32_t, fUnsigned, <=)
434 VECTOR_BINARY_OP(kCompareFLTEQ, float, fFloat, <=)
435 case ByteCodeInstruction::kConditionalBranch: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400436 uint16_t target = READ16();
437 if (POP().fBool) {
438 ip = code + target;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400439 }
440 break;
441 }
442 VECTOR_BINARY_OP(kDivideS, int32_t, fSigned, /)
443 VECTOR_BINARY_OP(kDivideU, uint32_t, fUnsigned, /)
444 VECTOR_BINARY_OP(kDivideF, float, fFloat, /)
445 case ByteCodeInstruction::kFloatToInt: {
446 for (int i = 0; i < count; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400447 Value& v = sp[-i];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400448 v.fSigned = (int) v.fFloat;
449 }
450 break;
451 }
452 case ByteCodeInstruction::kSignedToFloat: {
453 for (int i = 0; i < count; ++i) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400454 Value& v = sp[-i];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400455 v.fFloat = (float) v.fSigned;
456 }
457 break;
458 }
459 case ByteCodeInstruction::kUnsignedToFloat: {
460 for (int i = 0; i < count; ++i) {
Brian Osman41672152019-05-14 13:37:30 -0400461 Value& v = sp[-i];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400462 v.fFloat = (float) v.fUnsigned;
463 }
464 break;
465 }
466 case ByteCodeInstruction::kLoad: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400467 int src = POP().fSigned;
468 memcpy(sp + 1, &stack[src], count * sizeof(Value));
469 sp += count;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400470 break;
471 }
472 case ByteCodeInstruction::kLoadGlobal: {
473 int target = READ8();
474 SkASSERT(target < (int) fGlobals.size());
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400475 PUSH(fGlobals[target]);
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400476 break;
477 }
Ethan Nicholas354ecf32019-05-07 16:13:02 -0400478 case ByteCodeInstruction::kNegateS: {
479 for (int i = 0; i < count; ++i) {
480 Value& v = sp[-i];
481 v.fSigned = -v.fSigned;
482 }
483 break;
484 }
485 case ByteCodeInstruction::kNegateF: {
486 for (int i = 0; i < count; ++i) {
487 Value& v = sp[-i];
488 v.fFloat = -v.fFloat;
489 }
490 break;
491 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400492 VECTOR_BINARY_OP(kMultiplyS, int32_t, fSigned, *)
493 VECTOR_BINARY_OP(kMultiplyU, uint32_t, fUnsigned, *)
494 VECTOR_BINARY_OP(kMultiplyF, float, fFloat, *)
Brian Osman3b41baf2019-05-08 09:24:46 -0400495 case ByteCodeInstruction::kRemainderF: {
496 Value result[VECTOR_MAX];
497 for (int i = count - 1; i >= 0; --i) {
498 result[i] = POP();
499 }
500 for (int i = count - 1; i >= 0; --i) {
501 result[i] = fmodf(POP().fFloat, result[i].fFloat);
502 }
503 for (int i = 0; i < count; ++i) {
504 PUSH(result[i]);
505 }
506 break;
507 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400508 VECTOR_BINARY_OP(kRemainderS, int32_t, fSigned, %)
509 VECTOR_BINARY_OP(kRemainderU, uint32_t, fUnsigned, %)
510 case ByteCodeInstruction::kStore: {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400511 memcpy(&stack[(sp - count)->fSigned], sp - count + 1,
512 count * sizeof(Value));
513 sp -= count;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400514 break;
515 }
516 VECTOR_BINARY_OP(kSubtractI, int32_t, fSigned, -)
517 VECTOR_BINARY_OP(kSubtractF, float, fFloat, -)
518 default:
519 printf("unsupported instruction %d\n", (int) inst);
520 SkASSERT(false);
521 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400522 break;
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400523 }
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400524 default:
525 printf("unsupported instruction %d\n", (int) inst);
526 SkASSERT(false);
527 }
528#ifdef TRACE
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400529 printf("STACK:");
530 for (int i = 0; i < STACK_SIZE(); ++i) {
531 printf(" %d(%f)", stack[i].fSigned, stack[i].fFloat);
532 }
533 printf("\n");
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400534#endif
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400535 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400536}
537
538} // namespace
539
540#endif