Move interpreter disassemble to out-of-line member of ByteCode

Now it returns a string (rather than just calling printf).

Adds GUI view of particle effect byte code (for fun), and fixes the
unit tests that called ByteCodeFunction::disassemble, which wasn't
doing anything.

Change-Id: Ide3fd933cf14832feae7ff9e0fdc1ae8f24a28d4
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/273878
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
Brian Osman 2020-02-27 16:56:14 -05:00 committed by Skia Commit-Bot
parent 9d4b788807
commit 1b0124fec6
6 changed files with 364 additions and 331 deletions

View File

@ -8,6 +8,7 @@ _src = get_path_info("../src", "abspath")
skia_sksl_sources = [
"$_src/sksl/SkSLASTNode.cpp",
"$_src/sksl/SkSLByteCode.cpp",
"$_src/sksl/SkSLByteCodeGenerator.cpp",
"$_src/sksl/SkSLCFGGenerator.cpp",
"$_src/sksl/SkSLCompiler.cpp",

323
src/sksl/SkSLByteCode.cpp Normal file
View File

@ -0,0 +1,323 @@
/*
* Copyright 2020 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/core/SkUtils.h"
#include "src/sksl/SkSLByteCode.h"
#include "src/sksl/SkSLExternalValue.h"
namespace SkSL {
template <typename T>
static T read(const uint8_t** ip) {
*ip += sizeof(T);
return sk_unaligned_load<T>(*ip - sizeof(T));
}
#define DISASSEMBLE_0(inst, name) \
case Instruction::inst: \
return String(name);
#define DISASSEMBLE_1(inst, name) \
case Instruction::inst: \
return String::printf(name " $%d", read<Register>(ip).fIndex);
#define DISASSEMBLE_UNARY(inst, name) \
case Instruction::inst: { \
Register target = read<Register>(ip); \
Register src = read<Register>(ip); \
return String::printf(name " $%d -> $%d", src.fIndex, target.fIndex); \
}
#define DISASSEMBLE_VECTOR_UNARY(inst, name) \
case Instruction::inst: { \
Register target = read<Register>(ip); \
Register src = read<Register>(ip); \
return String::printf(name " $%d -> $%d", src.fIndex, target.fIndex); \
} \
case Instruction::inst##N: { \
uint8_t count = read<uint8_t>(ip); \
Register target = read<Register>(ip); \
Register src = read<Register>(ip); \
return String::printf(name "%d $%d -> $%d", count, src.fIndex, target.fIndex); \
}
#define DISASSEMBLE_BINARY(inst, name) \
case Instruction::inst: { \
Register target = read<Register>(ip); \
Register src1 = read<Register>(ip); \
Register src2 = read<Register>(ip); \
return String::printf(name " $%d, $%d -> $%d", src1.fIndex, src2.fIndex, target.fIndex); \
}
#define DISASSEMBLE_VECTOR_BINARY(inst, name) \
case Instruction::inst: { \
Register target = read<Register>(ip); \
Register src1 = read<Register>(ip); \
Register src2 = read<Register>(ip); \
return String::printf(name " $%d, $%d -> $%d", src1.fIndex, src2.fIndex, target.fIndex); \
} \
case Instruction::inst##N: { \
uint8_t count = read<uint8_t>(ip); \
Register target = read<Register>(ip); \
Register src1 = read<Register>(ip); \
Register src2 = read<Register>(ip); \
return String::printf(name "%d $%d, $%d -> $%d", count, src1.fIndex, src2.fIndex, \
target.fIndex); \
}
// $x = register
// @x = memory cell
// &x = parameter
String ByteCode::disassemble(const uint8_t** ip) const {
Instruction inst = read<Instruction>(ip);
switch (inst) {
DISASSEMBLE_VECTOR_BINARY(kAddF, "addF")
DISASSEMBLE_VECTOR_BINARY(kAddI, "addI")
DISASSEMBLE_BINARY(kAnd, "and")
DISASSEMBLE_BINARY(kCompareEQF, "compare eqF")
DISASSEMBLE_BINARY(kCompareEQI, "compare eqI")
DISASSEMBLE_BINARY(kCompareNEQF, "compare neqF")
DISASSEMBLE_BINARY(kCompareNEQI, "compare neqI")
DISASSEMBLE_BINARY(kCompareGTF, "compare gtF")
DISASSEMBLE_BINARY(kCompareGTS, "compare gtS")
DISASSEMBLE_BINARY(kCompareGTU, "compare gtU")
DISASSEMBLE_BINARY(kCompareGTEQF, "compare gteqF")
DISASSEMBLE_BINARY(kCompareGTEQS, "compare gteqS")
DISASSEMBLE_BINARY(kCompareGTEQU, "compare gteqU")
DISASSEMBLE_BINARY(kCompareLTF, "compare ltF")
DISASSEMBLE_BINARY(kCompareLTS, "compare ltS")
DISASSEMBLE_BINARY(kCompareLTU, "compare ltU")
DISASSEMBLE_BINARY(kCompareLTEQF, "compare lteqF")
DISASSEMBLE_BINARY(kCompareLTEQS, "compare lteqS")
DISASSEMBLE_BINARY(kCompareLTEQU, "compare lteqU")
DISASSEMBLE_VECTOR_BINARY(kSubtractF, "subF")
DISASSEMBLE_VECTOR_BINARY(kSubtractI, "subI")
DISASSEMBLE_VECTOR_BINARY(kDivideF, "divF")
DISASSEMBLE_VECTOR_BINARY(kDivideS, "divS")
DISASSEMBLE_VECTOR_BINARY(kDivideU, "divU")
DISASSEMBLE_VECTOR_BINARY(kRemainderS, "remS")
DISASSEMBLE_VECTOR_BINARY(kRemainderU, "remU")
DISASSEMBLE_VECTOR_BINARY(kRemainderF, "remF")
DISASSEMBLE_VECTOR_BINARY(kMultiplyF, "mulF")
DISASSEMBLE_VECTOR_BINARY(kMultiplyI, "mulI")
DISASSEMBLE_BINARY(kOr, "or")
DISASSEMBLE_BINARY(kXor, "xor")
DISASSEMBLE_0(kNop, "nop")
DISASSEMBLE_0(kAbort, "abort")
case Instruction::kBoundsCheck: {
Register r = read<Register>(ip);
int length = read<int>(ip);
return String::printf("boundsCheck 0 <= $%d < %d", r.fIndex, length);
}
case Instruction::kBranch:
return String::printf("branch %d", read<Pointer>(ip).fAddress);
case Instruction::kBranchIfAllFalse:
return String::printf("branchIfAllFalse %d", read<Pointer>(ip).fAddress);
DISASSEMBLE_0(kBreak, "break")
case Instruction::kCall: {
Register target = read<Register>(ip);
uint8_t idx = read<uint8_t>(ip);
Register args = read<Register>(ip);
ByteCodeFunction* f = fFunctions[idx].get();
return String::printf("call %s($%d...) -> $%d", f->fName.c_str(), args.fIndex,
target.fIndex);
}
case Instruction::kCallExternal: {
Register target = read<Register>(ip);
uint8_t idx = read<uint8_t>(ip);
uint8_t targetCount = read<uint8_t>(ip);
Register args = read<Register>(ip);
uint8_t argCount = read<uint8_t>(ip);
ExternalValue* ev = fExternalValues[idx];
return String::printf("callExternal %s($%d(%d)...) -> $%d(%d)",
String(ev->fName).c_str(), args.fIndex, argCount, target.fIndex,
targetCount);
}
DISASSEMBLE_0(kContinue, "continue")
DISASSEMBLE_UNARY(kCopy, "copy")
DISASSEMBLE_UNARY(kCos, "cos")
DISASSEMBLE_UNARY(kFloatToSigned, "FtoS")
DISASSEMBLE_UNARY(kFloatToUnsigned, "FtoU")
case Instruction::kImmediate: {
Register target = read<Register>(ip);
Immediate src = read<Immediate>(ip);
return String::printf("immediate (%d | %f) -> $%d", src.fInt, src.fFloat,
target.fIndex);
}
DISASSEMBLE_UNARY(kInverse2x2, "inverse2x2")
DISASSEMBLE_UNARY(kInverse3x3, "inverse3x3")
DISASSEMBLE_UNARY(kInverse4x4, "inverse4x4")
DISASSEMBLE_VECTOR_UNARY(kLoad, "load")
case Instruction::kLoadDirect: {
Register target = read<Register>(ip);
Pointer src = read<Pointer>(ip);
return String::printf("loadDirect @%d -> $%d", src.fAddress, target.fIndex);
}
case Instruction::kLoadDirectN: {
uint8_t count = read<uint8_t>(ip);
Register target = read<Register>(ip);
Pointer src = read<Pointer>(ip);
return String::printf("loadDirect%d @%d -> $%d", count, src.fAddress, target.fIndex);
}
DISASSEMBLE_VECTOR_UNARY(kLoadParameter, "loadParameter")
case Instruction::kLoadParameterDirect: {
Register target = read<Register>(ip);
Pointer src = read<Pointer>(ip);
return String::printf("loadParameterDirect &%d -> $%d", src.fAddress, target.fIndex);
}
case Instruction::kLoadParameterDirectN: {
uint8_t count = read<uint8_t>(ip);
Register target = read<Register>(ip);
Pointer src = read<Pointer>(ip);
return String::printf("loadParameterDirect%d &%d -> $%d", count, src.fAddress,
target.fIndex);
}
DISASSEMBLE_VECTOR_UNARY(kLoadStack, "loadStack")
case Instruction::kLoadStackDirect: {
Register target = read<Register>(ip);
Pointer src = read<Pointer>(ip);
return String::printf("loadStackDirect @%d -> $%d", src.fAddress, target.fIndex);
}
case Instruction::kLoadStackDirectN: {
uint8_t count = read<uint8_t>(ip);
Register target = read<Register>(ip);
Pointer src = read<Pointer>(ip);
return String::printf("loadStackDirect%d @%d -> $%d", count, src.fAddress,
target.fIndex);
}
DISASSEMBLE_0(kLoopBegin, "loopBegin")
DISASSEMBLE_0(kLoopEnd, "loopEnd")
DISASSEMBLE_1(kLoopMask, "loopMask")
DISASSEMBLE_0(kLoopNext, "loopNext")
DISASSEMBLE_0(kMaskNegate, "maskNegate")
DISASSEMBLE_0(kMaskPop, "maskPop")
DISASSEMBLE_1(kMaskPush, "maskPush")
case Instruction::kMatrixMultiply: {
Register target = read<Register>(ip);
Register left = read<Register>(ip);
Register right = read<Register>(ip);
uint8_t leftColsAndRightRows = read<uint8_t>(ip);
uint8_t leftRows = read<uint8_t>(ip);
uint8_t rightColumns = read<uint8_t>(ip);
return String::printf("matrixMultiply $%d, $%d, %d, %d, %d -> $%d", left.fIndex,
right.fIndex, leftColsAndRightRows, leftRows, rightColumns,
target.fIndex);
}
case Instruction::kMatrixToMatrix: {
Register target = read<Register>(ip);
Register src = read<Register>(ip);
uint8_t srcColumns = read<uint8_t>(ip);
uint8_t srcRows = read<uint8_t>(ip);
uint8_t dstColumns = read<uint8_t>(ip);
uint8_t dstRows = read<uint8_t>(ip);
return String::printf("matrixToMatrix $%d, %dx%d to %dx%d -> $%d", src.fIndex,
srcColumns, srcRows, dstColumns, dstRows, target.fIndex);
}
DISASSEMBLE_UNARY(kNegateF, "negateF")
DISASSEMBLE_UNARY(kNegateS, "negateS")
DISASSEMBLE_UNARY(kNot, "not")
case Instruction::kReadExternal: {
Register target = read<Register>(ip);
uint8_t count = read<uint8_t>(ip);
uint8_t index = read<uint8_t>(ip);
return String::printf("readExternal %d, %d -> $%d", count, index, target.fIndex);
}
DISASSEMBLE_1(kPrint, "print")
DISASSEMBLE_0(kReturn, "return")
DISASSEMBLE_1(kReturnValue, "returnValue")
case Instruction::kScalarToMatrix: {
Register target = read<Register>(ip);
Register src = read<Register>(ip);
uint8_t columns = read<uint8_t>(ip);
uint8_t rows = read<uint8_t>(ip);
return String::printf("scalarToMatrix $%d, %dx%d -> $%d", src.fIndex, columns, rows,
target.fIndex);
}
case Instruction::kSelect: {
Register target = read<Register>(ip);
Register test = read<Register>(ip);
Register src1 = read<Register>(ip);
Register src2 = read<Register>(ip);
return String::printf("select $%d, $%d, $%d -> %d", test.fIndex, src1.fIndex,
src2.fIndex, target.fIndex);
}
DISASSEMBLE_BINARY(kShiftLeft, "shiftLeft")
DISASSEMBLE_BINARY(kShiftRightS, "shiftRightS")
DISASSEMBLE_BINARY(kShiftRightU, "shiftRightU")
DISASSEMBLE_UNARY(kSignedToFloat, "signedToFloat")
DISASSEMBLE_UNARY(kSin, "sin")
case Instruction::kSplat: {
uint8_t count = read<uint8_t>(ip);
Pointer target = read<Pointer>(ip);
Register src = read<Register>(ip);
return String::printf("splat%d $%d -> @%d", count, src.fIndex, target.fAddress);
}
DISASSEMBLE_UNARY(kSqrt, "sqrt")
DISASSEMBLE_VECTOR_UNARY(kStore, "store")
case Instruction::kStoreDirect: {
Pointer target = read<Pointer>(ip);
Register src = read<Register>(ip);
return String::printf("store $%d -> @%d", src.fIndex, target.fAddress);
}
case Instruction::kStoreDirectN: {
uint8_t count = read<uint8_t>(ip);
Pointer target = read<Pointer>(ip);
Register src = read<Register>(ip);
return String::printf("store%d $%d -> @%d", count, src.fIndex, target.fAddress);
}
DISASSEMBLE_VECTOR_UNARY(kStoreParameter, "storeParameter")
case Instruction::kStoreParameterDirect: {
Pointer target = read<Pointer>(ip);
Register src = read<Register>(ip);
return String::printf("storeParameterDirect $%d -> &%d", src.fIndex, target.fAddress);
}
case Instruction::kStoreParameterDirectN: {
uint8_t count = read<uint8_t>(ip);
Pointer target = read<Pointer>(ip);
Register src = read<Register>(ip);
return String::printf("storeParameterDirect%d $%d -> &%d", count, src.fIndex,
target.fAddress);
}
DISASSEMBLE_VECTOR_UNARY(kStoreStack, "storeStack")
case Instruction::kStoreStackDirect: {
Pointer target = read<Pointer>(ip);
Register src = read<Register>(ip);
return String::printf("storeStackDirect $%d -> @%d", src.fIndex, target.fAddress);
}
case Instruction::kStoreStackDirectN: {
uint8_t count = read<uint8_t>(ip);
Pointer target = read<Pointer>(ip);
Register src = read<Register>(ip);
return String::printf("storeStackDirect%d $%d -> @%d", count, src.fIndex,
target.fAddress);
}
DISASSEMBLE_UNARY(kTan, "tan")
DISASSEMBLE_UNARY(kUnsignedToFloat, "unsignedToFloat")
case Instruction::kWriteExternal: {
uint8_t index = read<uint8_t>(ip);
uint8_t count = read<uint8_t>(ip);
Register src = read<Register>(ip);
return String::printf("writeExternal $%d, %d -> %d", src.fIndex, count, index);
}
default:
SkASSERT(false);
return String::printf("unsupported: %d", (int)inst);
}
}
String ByteCode::disassembleFunction(const ByteCodeFunction* f) const {
String result;
const uint8_t* ip = f->fCode.data();
const uint8_t* codeEnd = f->fCode.data() + f->fCode.size();
while (ip < codeEnd) {
result.append(this->disassemble(&ip));
result.append("\n");
}
return result;
}
} // namespace SkSL

View File

@ -33,14 +33,10 @@ public:
* Note that this is the actual number of parameters, not the number of parameter slots.
*/
int getParameterCount() const { return fParameters.size(); }
Parameter getParameter(int idx) const { return fParameters[idx]; }
int getParameterSlotCount() const { return fParameterSlotCount; }
int getReturnSlotCount() const { return fReturnSlotCount; }
void disassemble() const { }
const String& name() const { return fName; }
private:
ByteCodeFunction(const FunctionDeclaration* declaration)
@ -340,6 +336,8 @@ public:
static constexpr int kPointerMax = 65535;
static constexpr int kRegisterMax = 65535;
int getFunctionCount() const { return fFunctions.size(); }
const ByteCodeFunction* getFunction(int i) const { return fFunctions[i].get(); }
const ByteCodeFunction* getFunction(const char* name) const {
for (const auto& f : fFunctions) {
if (f->fName == name) {
@ -373,10 +371,14 @@ public:
}
const Uniform& getUniform(int i) const { return fUniforms[i]; }
String disassembleFunction(const ByteCodeFunction*) const;
private:
ByteCode(const ByteCode&) = delete;
ByteCode& operator=(const ByteCode&) = delete;
String disassemble(const uint8_t** ip) const;
std::vector<std::unique_ptr<ByteCodeFunction>> fFunctions;
std::vector<ExternalValue*> fExternalValues;

View File

@ -27,12 +27,12 @@ namespace SkSL {
using instruction = void*;
#define LABEL(name) name:
#ifdef TRACE
#define NEXT() \
{ \
const uint8_t* trace_ip = ip; \
printf("%d: ", (int) (trace_ip - code)); \
disassemble(&trace_ip); \
} \
#define NEXT() \
{ \
const uint8_t* trace_ip = ip; \
printf("%d: ", (int) (trace_ip - code)); \
printf("%s\n", fCode->disassemble(&trace_ip).c_str()); \
} \
goto *labels[(int) read<ByteCode::Instruction>(&ip)]
#else
#define NEXT() goto *labels[(int) read<ByteCode::Instruction>(&ip)]
@ -141,63 +141,6 @@ static T read(const uint8_t** ip) {
NEXT(); \
}
#define DISASSEMBLE_0(inst, name) \
case ByteCode::Instruction::inst: printf(name "\n"); break;
#define DISASSEMBLE_1(inst, name) \
case ByteCode::Instruction::inst: \
printf(name " $%d\n", read<ByteCode::Register>(ip).fIndex); \
break;
#define DISASSEMBLE_UNARY(inst, name) \
case ByteCode::Instruction::inst: { \
ByteCode::Register target = read<ByteCode::Register>(ip); \
ByteCode::Register src = read<ByteCode::Register>(ip); \
printf(name " $%d -> $%d\n", src.fIndex, target.fIndex); \
break; \
}
#define DISASSEMBLE_VECTOR_UNARY(inst, name) \
case ByteCode::Instruction::inst: { \
ByteCode::Register target = read<ByteCode::Register>(ip); \
ByteCode::Register src = read<ByteCode::Register>(ip); \
printf(name " $%d -> $%d\n", src.fIndex, target.fIndex); \
break; \
} \
case ByteCode::Instruction::inst ## N: { \
uint8_t count = read<uint8_t>(ip); \
ByteCode::Register target = read<ByteCode::Register>(ip); \
ByteCode::Register src = read<ByteCode::Register>(ip); \
printf(name "%d $%d -> $%d\n", count, src.fIndex, target.fIndex); \
break; \
}
#define DISASSEMBLE_BINARY(inst, name) \
case ByteCode::Instruction::inst: { \
ByteCode::Register target = read<ByteCode::Register>(ip); \
ByteCode::Register src1 = read<ByteCode::Register>(ip); \
ByteCode::Register src2 = read<ByteCode::Register>(ip); \
printf(name " $%d, $%d -> $%d\n", src1.fIndex, src2.fIndex, target.fIndex); \
break; \
}
#define DISASSEMBLE_VECTOR_BINARY(inst, name) \
case ByteCode::Instruction::inst: { \
ByteCode::Register target = read<ByteCode::Register>(ip); \
ByteCode::Register src1 = read<ByteCode::Register>(ip); \
ByteCode::Register src2 = read<ByteCode::Register>(ip); \
printf(name " $%d, $%d -> $%d\n", src1.fIndex, src2.fIndex, target.fIndex); \
break; \
} \
case ByteCode::Instruction::inst ## N: { \
uint8_t count = read<uint8_t>(ip); \
ByteCode::Register target = read<ByteCode::Register>(ip); \
ByteCode::Register src1 = read<ByteCode::Register>(ip); \
ByteCode::Register src2 = read<ByteCode::Register>(ip); \
printf(name "%d $%d, $%d -> $%d\n", count, src1.fIndex, src2.fIndex, target.fIndex); \
break; \
}
/**
* Operates on vectors of the specified width, so creating an Interpreter<16> means that all inputs,
* outputs, and internal calculations will be 16-wide vectors.
@ -372,264 +315,6 @@ private:
std::stack<StackFrame> fCallStack;
};
// $x = register
// @x = memory cell
// &x = parameter
void disassemble(const uint8_t** ip) {
ByteCode::Instruction inst = read<ByteCode::Instruction>(ip);
switch (inst) {
DISASSEMBLE_VECTOR_BINARY(kAddF, "addF")
DISASSEMBLE_VECTOR_BINARY(kAddI, "addI")
DISASSEMBLE_BINARY(kAnd, "and")
DISASSEMBLE_BINARY(kCompareEQF, "compare eqF")
DISASSEMBLE_BINARY(kCompareEQI, "compare eqI")
DISASSEMBLE_BINARY(kCompareNEQF, "compare neqF")
DISASSEMBLE_BINARY(kCompareNEQI, "compare neqI")
DISASSEMBLE_BINARY(kCompareGTF, "compare gtF")
DISASSEMBLE_BINARY(kCompareGTS, "compare gtS")
DISASSEMBLE_BINARY(kCompareGTU, "compare gtU")
DISASSEMBLE_BINARY(kCompareGTEQF, "compare gteqF")
DISASSEMBLE_BINARY(kCompareGTEQS, "compare gteqS")
DISASSEMBLE_BINARY(kCompareGTEQU, "compare gteqU")
DISASSEMBLE_BINARY(kCompareLTF, "compare ltF")
DISASSEMBLE_BINARY(kCompareLTS, "compare ltS")
DISASSEMBLE_BINARY(kCompareLTU, "compare ltU")
DISASSEMBLE_BINARY(kCompareLTEQF, "compare lteqF")
DISASSEMBLE_BINARY(kCompareLTEQS, "compare lteqS")
DISASSEMBLE_BINARY(kCompareLTEQU, "compare lteqU")
DISASSEMBLE_VECTOR_BINARY(kSubtractF, "subF")
DISASSEMBLE_VECTOR_BINARY(kSubtractI, "subI")
DISASSEMBLE_VECTOR_BINARY(kDivideF, "divF")
DISASSEMBLE_VECTOR_BINARY(kDivideS, "divS")
DISASSEMBLE_VECTOR_BINARY(kDivideU, "divU")
DISASSEMBLE_VECTOR_BINARY(kRemainderS, "remS")
DISASSEMBLE_VECTOR_BINARY(kRemainderU, "remU")
DISASSEMBLE_VECTOR_BINARY(kRemainderF, "remF")
DISASSEMBLE_VECTOR_BINARY(kMultiplyF, "mulF")
DISASSEMBLE_VECTOR_BINARY(kMultiplyI, "mulI")
DISASSEMBLE_BINARY(kOr, "or")
DISASSEMBLE_BINARY(kXor, "xor")
DISASSEMBLE_0(kNop, "nop")
case ByteCode::Instruction::kBoundsCheck: {
ByteCode::Register r = read<ByteCode::Register>(ip);
int length = read<int>(ip);
printf("boundsCheck 0 <= $%d < %d\n", r.fIndex, length);
break;
}
case ByteCode::Instruction::kBranch:
printf("branch %d\n", read<ByteCode::Pointer>(ip).fAddress);
break;
case ByteCode::Instruction::kBranchIfAllFalse:
printf("branchIfAllFalse %d\n", read<ByteCode::Pointer>(ip).fAddress);
break;
DISASSEMBLE_0(kBreak, "break")
case ByteCode::Instruction::kCall: {
ByteCode::Register target = read<ByteCode::Register>(ip);
uint8_t idx = read<uint8_t>(ip);
ByteCode::Register args = read<ByteCode::Register>(ip);
ByteCodeFunction* f = fCode->fFunctions[idx].get();
printf("call %s($%d...) -> $%d", f->fName.c_str(), args.fIndex, target.fIndex);
printf("\n");
break;
}
case ByteCode::Instruction::kCallExternal: {
ByteCode::Register target = read<ByteCode::Register>(ip);
uint8_t idx = read<uint8_t>(ip);
uint8_t targetCount = read<uint8_t>(ip);
ByteCode::Register args = read<ByteCode::Register>(ip);
uint8_t argCount = read<uint8_t>(ip);
ExternalValue* ev = fCode->fExternalValues[idx];
printf("callExternal %s($%d(%d)...) -> $%d(%d)", String(ev->fName).c_str(),
args.fIndex, argCount, target.fIndex, targetCount);
printf("\n");
break;
}
DISASSEMBLE_0(kContinue, "continue")
DISASSEMBLE_UNARY(kCopy, "copy")
DISASSEMBLE_UNARY(kCos, "cos")
DISASSEMBLE_UNARY(kFloatToSigned, "FtoS")
DISASSEMBLE_UNARY(kFloatToUnsigned, "FtoU")
case ByteCode::Instruction::kImmediate: {
ByteCode::Register target = read<ByteCode::Register>(ip);
ByteCode::Immediate src = read<ByteCode::Immediate>(ip);
printf("immediate (%d | %f) -> $%d\n", src.fInt, src.fFloat, target.fIndex);
break;
}
DISASSEMBLE_UNARY(kInverse2x2, "inverse2x2")
DISASSEMBLE_UNARY(kInverse3x3, "inverse3x3")
DISASSEMBLE_UNARY(kInverse4x4, "inverse4x4")
DISASSEMBLE_VECTOR_UNARY(kLoad, "load")
case ByteCode::Instruction::kLoadDirect: {
ByteCode::Register target = read<ByteCode::Register>(ip);
ByteCode::Pointer src = read<ByteCode::Pointer>(ip);
printf("loadDirect @%d -> $%d\n", src.fAddress, target.fIndex);
break;
}
case ByteCode::Instruction::kLoadDirectN: {
uint8_t count = read<uint8_t>(ip);
ByteCode::Register target = read<ByteCode::Register>(ip);
ByteCode::Pointer src = read<ByteCode::Pointer>(ip);
printf("loadDirect%d @%d -> $%d\n", count, src.fAddress, target.fIndex);
break;
}
DISASSEMBLE_VECTOR_UNARY(kLoadParameter, "loadParameter")
case ByteCode::Instruction::kLoadParameterDirect: {
ByteCode::Register target = read<ByteCode::Register>(ip);
ByteCode::Pointer src = read<ByteCode::Pointer>(ip);
printf("loadParameterDirect &%d -> $%d\n", src.fAddress, target.fIndex);
break;
}
case ByteCode::Instruction::kLoadParameterDirectN: {
uint8_t count = read<uint8_t>(ip);
ByteCode::Register target = read<ByteCode::Register>(ip);
ByteCode::Pointer src = read<ByteCode::Pointer>(ip);
printf("loadParameterDirect%d &%d -> $%d\n", count, src.fAddress, target.fIndex);
break;
}
DISASSEMBLE_VECTOR_UNARY(kLoadStack, "loadStack")
case ByteCode::Instruction::kLoadStackDirect: {
ByteCode::Register target = read<ByteCode::Register>(ip);
ByteCode::Pointer src = read<ByteCode::Pointer>(ip);
printf("loadStackDirect @%d -> $%d\n", src.fAddress, target.fIndex);
break;
}
case ByteCode::Instruction::kLoadStackDirectN: {
uint8_t count = read<uint8_t>(ip);
ByteCode::Register target = read<ByteCode::Register>(ip);
ByteCode::Pointer src = read<ByteCode::Pointer>(ip);
printf("loadStackDirect%d @%d -> $%d\n", count, src.fAddress, target.fIndex);
break;
}
DISASSEMBLE_0(kLoopBegin, "loopBegin")
DISASSEMBLE_0(kLoopEnd, "loopEnd")
DISASSEMBLE_1(kLoopMask, "loopMask")
DISASSEMBLE_0(kLoopNext, "loopNext")
DISASSEMBLE_0(kMaskNegate, "maskNegate")
DISASSEMBLE_0(kMaskPop, "maskPop")
DISASSEMBLE_1(kMaskPush, "maskPush")
case ByteCode::Instruction::kMatrixMultiply: {
ByteCode::Register target = read<ByteCode::Register>(ip);
ByteCode::Register left = read<ByteCode::Register>(ip);
ByteCode::Register right = read<ByteCode::Register>(ip);
uint8_t leftColsAndRightRows = read<uint8_t>(ip);
uint8_t leftRows = read<uint8_t>(ip);
uint8_t rightColumns = read<uint8_t>(ip);
printf("matrixMultiply $%d, $%d, %d, %d, %d -> $%d\n", left.fIndex, right.fIndex,
leftColsAndRightRows, leftRows, rightColumns, target.fIndex);
break;
}
case ByteCode::Instruction::kMatrixToMatrix: {
ByteCode::Register target = read<ByteCode::Register>(ip);
ByteCode::Register src = read<ByteCode::Register>(ip);
uint8_t srcColumns = read<uint8_t>(ip);
uint8_t srcRows = read<uint8_t>(ip);
uint8_t dstColumns = read<uint8_t>(ip);
uint8_t dstRows = read<uint8_t>(ip);
printf("matrixToMatrix $%d, %dx%d to %dx%d -> $%d\n", src.fIndex, srcColumns,
srcRows, dstColumns, dstRows, target.fIndex);
break;
}
DISASSEMBLE_UNARY(kNegateF, "negateF")
DISASSEMBLE_UNARY(kNegateS, "negateS")
DISASSEMBLE_UNARY(kNot, "not")
case ByteCode::Instruction::kReadExternal: {
ByteCode::Register target = read<ByteCode::Register>(ip);
uint8_t count = read<uint8_t>(ip);
uint8_t index = read<uint8_t>(ip);
printf("readExternal %d, %d -> $%d\n", count, index, target.fIndex);
break;
}
DISASSEMBLE_1(kPrint, "print")
DISASSEMBLE_0(kReturn, "return")
DISASSEMBLE_1(kReturnValue, "returnValue")
case ByteCode::Instruction::kScalarToMatrix: {
ByteCode::Register target = read<ByteCode::Register>(ip);
ByteCode::Register src = read<ByteCode::Register>(ip);
uint8_t columns = read<uint8_t>(ip);
uint8_t rows = read<uint8_t>(ip);
printf("scalarToMatrix $%d, %dx%d -> $%d\n", src.fIndex, columns, rows,
target.fIndex);
break;
}
case ByteCode::Instruction::kSelect: {
ByteCode::Register target = read<ByteCode::Register>(ip);
ByteCode::Register test = read<ByteCode::Register>(ip);
ByteCode::Register src1 = read<ByteCode::Register>(ip);
ByteCode::Register src2 = read<ByteCode::Register>(ip);
printf("select $%d, $%d, $%d -> %d\n", test.fIndex, src1.fIndex, src2.fIndex,
target.fIndex);
break;
}
DISASSEMBLE_BINARY(kShiftLeft, "shiftLeft")
DISASSEMBLE_BINARY(kShiftRightS, "shiftRightS")
DISASSEMBLE_BINARY(kShiftRightU, "shiftRightU")
DISASSEMBLE_UNARY(kSignedToFloat, "signedToFloat")
DISASSEMBLE_UNARY(kSin, "sin")
case ByteCode::Instruction::kSplat: {
uint8_t count = read<uint8_t>(ip);
ByteCode::Pointer target = read<ByteCode::Pointer>(ip);
ByteCode::Register src = read<ByteCode::Register>(ip);
printf("splat%d $%d -> @%d\n", count, src.fIndex, target.fAddress);
break;
}
DISASSEMBLE_UNARY(kSqrt, "sqrt")
DISASSEMBLE_VECTOR_UNARY(kStore, "store")
case ByteCode::Instruction::kStoreDirect: {
ByteCode::Pointer target = read<ByteCode::Pointer>(ip);
ByteCode::Register src = read<ByteCode::Register>(ip);
printf("store $%d -> @%d\n", src.fIndex, target.fAddress);
break;
}
case ByteCode::Instruction::kStoreDirectN: {
uint8_t count = read<uint8_t>(ip);
ByteCode::Pointer target = read<ByteCode::Pointer>(ip);
ByteCode::Register src = read<ByteCode::Register>(ip);
printf("store%d $%d -> @%d\n", count, src.fIndex, target.fAddress);
break;
}
DISASSEMBLE_VECTOR_UNARY(kStoreParameter, "storeParameter")
case ByteCode::Instruction::kStoreParameterDirect: {
ByteCode::Pointer target = read<ByteCode::Pointer>(ip);
ByteCode::Register src = read<ByteCode::Register>(ip);
printf("storeParameterDirect $%d -> &%d\n", src.fIndex, target.fAddress);
break;
}
case ByteCode::Instruction::kStoreParameterDirectN: {
uint8_t count = read<uint8_t>(ip);
ByteCode::Pointer target = read<ByteCode::Pointer>(ip);
ByteCode::Register src = read<ByteCode::Register>(ip);
printf("storeParameterDirect%d $%d -> &%d\n", count, src.fIndex, target.fAddress);
break;
}
DISASSEMBLE_VECTOR_UNARY(kStoreStack, "storeStack")
case ByteCode::Instruction::kStoreStackDirect: {
ByteCode::Pointer target = read<ByteCode::Pointer>(ip);
ByteCode::Register src = read<ByteCode::Register>(ip);
printf("storeStackDirect $%d -> @%d\n", src.fIndex, target.fAddress);
break;
}
case ByteCode::Instruction::kStoreStackDirectN: {
uint8_t count = read<uint8_t>(ip);
ByteCode::Pointer target = read<ByteCode::Pointer>(ip);
ByteCode::Register src = read<ByteCode::Register>(ip);
printf("storeStackDirect%d $%d -> @%d\n", count, src.fIndex, target.fAddress);
break;
}
DISASSEMBLE_UNARY(kTan, "tan")
DISASSEMBLE_UNARY(kUnsignedToFloat, "unsignedToFloat")
case ByteCode::Instruction::kWriteExternal: {
uint8_t index = read<uint8_t>(ip);
uint8_t count = read<uint8_t>(ip);
ByteCode::Register src = read<ByteCode::Register>(ip);
printf("writeExternal $%d, %d -> %d\n", src.fIndex, count, index);
break;
}
default:
printf("unsupported: %d\n", (int) inst);
SkASSERT(false);
}
}
static Vector VecMod(Vector x, Vector y) {
return Vector(x.fFloat - skvx::trunc(x.fFloat / y.fFloat) * y.fFloat);
}
@ -965,15 +650,14 @@ private:
#ifdef SKSL_THREADED_CODE
#ifdef TRACE
const uint8_t* trace_ip = ip;
printf("0: ");
disassemble(&trace_ip);
printf("0: %s\n", fCode->disassemble(&trace_ip).c_str());
#endif
goto *labels[(int) read<ByteCode::Instruction>(&ip)];
#else
for (;;) {
#ifdef TRACE
const uint8_t* trace_ip = ip;
disassemble(&trace_ip);
printf("%s\n", fCode->disassemble(&trace_ip).c_str());
#endif
ByteCode::Instruction inst = read<ByteCode::Instruction>(&ip);
switch (inst) {

View File

@ -112,7 +112,7 @@ void vec_test(skiatest::Reporter* r, const char* src) {
out_v[4*i + 0], out_v[4*i + 1], out_v[4*i + 2], out_v[4*i + 3],
out_s[4*i + 0], out_s[4*i + 1], out_s[4*i + 2], out_s[4*i + 3]);
}
main4->disassemble();
printf("%s", interpreter4.getCode().disassembleFunction(main4).c_str());
REPORT_FAILURE(r, "VecInterpreter mismatch", SkString());
}
}
@ -148,7 +148,7 @@ void test(skiatest::Reporter* r, const char* src, float inR, float inG, float in
printf(" expected (%f, %f, %f, %f), but received (%f, %f, %f, %f)\n", expectedR,
expectedG, expectedB, expectedA, inoutColor[0].fFloat[0],
inoutColor[1].fFloat[0], inoutColor[2].fFloat[0], inoutColor[3].fFloat[0]);
main->disassemble();
printf("%s", interpreter.getCode().disassembleFunction(main).c_str());
}
REPORTER_ASSERT(r, inoutColor[0].fFloat[0] == expectedR);
REPORTER_ASSERT(r, inoutColor[1].fFloat[0] == expectedG);

View File

@ -340,6 +340,29 @@ void ParticlesSlide::draw(SkCanvas* canvas) {
};
uniformsGui(effect->effectCode(), effect->effectUniforms());
uniformsGui(effect->particleCode(), effect->particleUniforms());
auto showDisassembly = [](const SkSL::ByteCode* code) {
if (!code) {
return;
}
SkSL::String result;
for (int i = 0; i < code->getFunctionCount(); ++i) {
if (i != 0) {
result.append("\n");
}
const SkSL::ByteCodeFunction* f = code->getFunction(i);
result.appendf("%s\n%s", f->name().c_str(),
code->disassembleFunction(f).c_str());
}
ImGui::TextUnformatted(result.c_str());
};
if (ImGui::TreeNode("Disassembly")) {
showDisassembly(effect->effectCode());
showDisassembly(effect->particleCode());
ImGui::TreePop();
}
if (remove) {
fRunning.removeShuffle(i);
}