1 /* 2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef PANDA_DISASSEMBLY_H 17 #define PANDA_DISASSEMBLY_H 18 19 #include "compiler_options.h" 20 #include "macros.h" 21 #include <fstream> 22 #include <string> 23 #include <variant> 24 #include <memory> 25 26 namespace ark::compiler { 27 28 class Codegen; 29 class Encoder; 30 class Inst; 31 class StackMap; 32 33 class CodeItem { 34 public: CodeItem(size_t position,size_t cursorOffset,size_t depth)35 CodeItem(size_t position, size_t cursorOffset, size_t depth) 36 : position_(position), cursorOffset_(cursorOffset), depth_(depth) 37 { 38 } GetPosition()39 size_t GetPosition() const 40 { 41 return position_; 42 } GetCursorOffset()43 size_t GetCursorOffset() const 44 { 45 return cursorOffset_; 46 } GetDepth()47 size_t GetDepth() const 48 { 49 return depth_; 50 } 51 52 private: 53 size_t position_ {0}; 54 size_t cursorOffset_ {0}; 55 size_t depth_ {0}; 56 }; 57 58 using DisassemblyItem = std::variant<CodeItem, std::string>; 59 60 class Disassembly { 61 public: 62 explicit Disassembly(const Codegen *codegen); 63 ~Disassembly() = default; 64 NO_COPY_SEMANTIC(Disassembly); 65 NO_MOVE_SEMANTIC(Disassembly); 66 67 void Init(); 68 GetStream()69 std::ostream &GetStream() 70 { 71 return *stream_; 72 } 73 std::string_view GetIndent(uint32_t depth); GetDepth()74 uint32_t GetDepth() const 75 { 76 return depth_; 77 } GetPosition()78 uint32_t GetPosition() const 79 { 80 return position_; 81 } SetPosition(uint32_t pos)82 void SetPosition(uint32_t pos) 83 { 84 position_ = pos; 85 } GetEncoder()86 const Encoder *GetEncoder() const 87 { 88 return encoder_; 89 } SetEncoder(const Encoder * encoder)90 void SetEncoder(const Encoder *encoder) 91 { 92 encoder_ = encoder; 93 } 94 void PrintChapter(std::string_view name); 95 void IncreaseDepth(); DecreaseDepth()96 void DecreaseDepth() 97 { 98 depth_--; 99 } IsEnabled()100 bool IsEnabled() const 101 { 102 return isEnabled_; 103 } IsCodeEnabled()104 bool IsCodeEnabled() const 105 { 106 return isCodeEnabled_; 107 } GetItems()108 std::vector<DisassemblyItem> &GetItems() 109 { 110 return items_; 111 } 112 113 void PrintMethodEntry(const Codegen *codegen); 114 void PrintCodeInfo(const Codegen *codegen); 115 void PrintCodeStatistics(const Codegen *codegen); 116 void PrintStackMap(const Codegen *codegen); 117 AddCode(size_t position,size_t cursorOffset,size_t depth)118 void AddCode(size_t position, size_t cursorOffset, size_t depth) 119 { 120 CodeItem item(position, cursorOffset, depth); 121 items_.emplace_back(item); 122 } 123 124 private: 125 void FlushDisasm(); 126 127 private: 128 using StreamDeleterType = void (*)(std::ostream *stream); 129 const Codegen *codegen_ {nullptr}; 130 const Encoder *encoder_ {nullptr}; 131 std::unique_ptr<std::ostream, StreamDeleterType> stream_; 132 uint32_t depth_ {0}; 133 uint32_t position_ {0}; 134 bool isEnabled_ {false}; 135 bool isCodeEnabled_ {false}; 136 std::vector<DisassemblyItem> items_; 137 138 friend class ScopedDisasmPrinter; 139 }; 140 141 class ScopedDisasmPrinter { 142 public: 143 ScopedDisasmPrinter(Codegen *codegen, const std::string &msg); 144 ScopedDisasmPrinter(Codegen *codegen, const Inst *inst); 145 ~ScopedDisasmPrinter(); 146 147 NO_COPY_SEMANTIC(ScopedDisasmPrinter); 148 NO_MOVE_SEMANTIC(ScopedDisasmPrinter); 149 150 private: 151 Disassembly *disasm_ {nullptr}; 152 }; 153 154 class ItemAppender { 155 public: ItemAppender(Disassembly * disasm)156 explicit ItemAppender(Disassembly *disasm) : disasm_(disasm) {} ~ItemAppender()157 ~ItemAppender() 158 { 159 disasm_->GetItems().emplace_back(std::move(ss_).str()); 160 } 161 162 NO_COPY_SEMANTIC(ItemAppender); 163 NO_MOVE_SEMANTIC(ItemAppender); 164 GetStream()165 std::ostringstream &GetStream() 166 { 167 return ss_; 168 } 169 170 private: 171 Disassembly *disasm_; 172 std::ostringstream ss_; 173 }; 174 175 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 176 #define DISASM_VAR_CONCAT2(a, b) a##b 177 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 178 #define DISASM_VAR_CONCAT(a, b) DISASM_VAR_CONCAT2(a, b) 179 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 180 #define SCOPED_DISASM_INST(codegen, inst) ScopedDisasmPrinter DISASM_VAR_CONCAT(disasm_, __LINE__)(codegen, inst) 181 #ifndef NDEBUG 182 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 183 #define SCOPED_DISASM_STR(codegen, str) ScopedDisasmPrinter DISASM_VAR_CONCAT(disasm_, __LINE__)(codegen, str) 184 #else 185 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 186 #define SCOPED_DISASM_STR(codegen, str) (void)codegen 187 #endif 188 189 } // namespace ark::compiler 190 191 #endif // PANDA_DISASSEMBLY_H 192