1 /* 2 * Copyright 2021 Google LLC 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 #ifndef SkVMVisualizer_DEFINED 8 #define SkVMVisualizer_DEFINED 9 #include <unordered_map> 10 #include <vector> 11 #include "include/core/SkSpan.h" 12 #include "include/core/SkStream.h" 13 #include "include/core/SkString.h" 14 #include "include/private/SkBitmaskEnum.h" 15 #include "include/private/SkChecksum.h" 16 #include "include/private/SkTHash.h" 17 #include "src/core/SkOpts.h" 18 #include "src/sksl/SkSLOutputStream.h" 19 #include "src/sksl/tracing/SkVMDebugTrace.h" 20 21 namespace skvm::viz { 22 enum InstructionFlags : uint8_t { 23 kNormal = 0x00, 24 kHoisted = 0x01, 25 kDead = 0x02, 26 }; 27 28 struct MachineCommand { 29 size_t address; 30 SkString label; 31 SkString command; 32 SkString extra; 33 }; 34 35 struct Instruction { 36 InstructionFlags kind = InstructionFlags::kNormal; 37 // Machine commands range (for disassembling): 38 size_t startCode = 0; 39 size_t endCode = 0; 40 int instructionIndex; // index in the actual instructions list 41 int duplicates = 0; // number of duplicates; 42 // -1 means it's a duplicate itself; 0 - it does not have dups 43 skvm::Instruction instruction; 44 bool operator == (const Instruction& o) const; 45 SkString classes() const; 46 }; 47 48 struct InstructionHash { 49 uint32_t operator()(const Instruction& i) const; 50 }; 51 52 class Visualizer { 53 public: Visualizer(SkSL::SkVMDebugTrace * debugInfo)54 explicit Visualizer(SkSL::SkVMDebugTrace* debugInfo) 55 : fDebugInfo(debugInfo), fOutput(nullptr) {} 56 ~Visualizer() = default; 57 void dump(SkWStream* output, const char* code); 58 void markAsDeadCode(std::vector<bool>& live, const std::vector<int>& newIds); 59 void finalize(const std::vector<skvm::Instruction>& all, 60 const std::vector<skvm::OptimizedInstruction>& optimized); 61 void addInstructions(std::vector<skvm::Instruction>& program); markAsDuplicate(int origin,int id)62 void markAsDuplicate(int origin, int id) { 63 ++fInstructions[origin].duplicates; 64 } 65 void addInstruction(Instruction skvm); 66 void addMachineCommands(int id, size_t start, size_t end); 67 SkString V(int reg) const; 68 private: 69 void parseDisassembler(SkWStream* output, const char* code); 70 void dumpInstruction(int id) const; 71 void dumpHead() const; 72 void dumpTail() const; 73 void formatVV(const char* op, int v1, int v2) const; 74 void formatPV(const char* op, int imm, int v1) const; 75 void formatPVV(const char* op, int imm, int v1, int v2) const; 76 void formatPVVVV(const char* op, int imm, int v1, int v2, int v3, int v4) const; 77 void formatA_(int id, const char* op) const; 78 void formatA_P(int id, const char* op, int imm) const; 79 void formatA_PH(int id, const char* op, int immA, int immB) const; 80 void formatA_PHH(int id, const char* op, int immA, int immB, int immC) const; 81 void formatA_PHV(int id, const char* op, int immA, int immB, int v) const; 82 void formatA_S(int id, const char* op, int imm) const; 83 void formatA_V(int id, const char* op, int v) const; 84 void formatA_VV(int id, const char* op, int v1, int v2) const; 85 void formatA_VVV(int id, const char* op, int v1, int v2, int v3) const; 86 void formatA_VC(int id, const char* op, int v, int imm) const; 87 88 void writeText(const char* format, ...) const SK_PRINTF_LIKE(2, 3); 89 90 SkSL::SkVMDebugTrace* fDebugInfo; 91 SkTHashMap<Instruction, size_t, InstructionHash> fIndex; 92 SkTArray<Instruction> fInstructions; 93 SkWStream* fOutput; 94 SkTHashMap<int, size_t> fToDisassembler; 95 SkTArray<MachineCommand> fAsm; 96 mutable size_t fAsmLine = 0; 97 size_t fAsmStart = 0; 98 size_t fAsmEnd = 0; 99 }; 100 } // namespace skvm::viz 101 102 namespace sknonstd { 103 template <> struct is_bitmask_enum<skvm::viz::InstructionFlags> : std::true_type {}; 104 } // namespace sknonstd 105 106 #endif // SkVMVisualizer_DEFINED 107