blob: 34e803e8d8ce773046ca331f289aa4491edc6839 [file] [log] [blame]
/*
* Copyright 2021 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/private/SkTOptional.h"
#include "src/sksl/tracing/SkVMDebugTrace.h"
#include "src/utils/SkBitSet.h"
namespace SkSL {
/**
* Plays back a SkVM debug trace, allowing its contents to be viewed like a traditional debugger.
*/
class SkVMDebugTracePlayer {
public:
/** Resets playback. */
void reset(sk_sp<SkVMDebugTrace> trace);
/** Advances the simulation to the next Line op. */
void step();
/** Advances the simulation to the next Line op, skipping past matched Enter/Exit pairs. */
void stepOver();
/** Advances the simulation until we exit from the current stack frame. */
void stepOut();
/** Returns true if we have reached the end of the trace. */
bool traceHasCompleted() const;
/** Retrieves the cursor position. */
size_t cursor() { return fCursor; }
/** Retrieves the current line. */
int32_t getCurrentLine() const;
/** Returns the call stack as an array of FunctionInfo indices. */
std::vector<int> getCallStack() const;
/** Returns the size of the call stack. */
int getStackDepth() const;
/** Returns variables from a stack frame, or from global scope. */
struct VariableData {
int fSlotIndex;
bool fDirty; // has this slot been written-to since the last step call?
int32_t fValue; // caller must type-pun bits to float/bool based on slot type
};
std::vector<VariableData> getLocalVariables(int stackFrameIndex) const;
std::vector<VariableData> getGlobalVariables() const;
private:
/**
* Executes the trace op at the passed-in cursor position. Returns true if we've reached a line
* or exit trace op, which indicate a stopping point.
*/
bool execute(size_t position);
/** Returns a vector of the indices and values of each slot that is enabled in `bits`. */
std::vector<VariableData> getVariablesForDisplayMask(const SkBitSet& bits) const;
struct StackFrame {
int32_t fFunction; // from fFuncInfo
int32_t fLine; // our current line number within the function
SkBitSet fDisplayMask; // the variable slots which have been touched in this function
};
sk_sp<SkVMDebugTrace> fDebugTrace;
size_t fCursor = 0; // position of the read head
std::vector<int32_t> fSlots; // values in each slot
std::vector<StackFrame> fStack; // the execution stack
skstd::optional<SkBitSet> fDirtyMask; // variable slots touched during the most-recently
// executed step
};
} // namespace SkSL