1/* 2 * Copyright (c) 2021 - 2023 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#include "debuginfoDumper.h" 17 18#include "macros.h" 19 20#include <sstream> 21#include <string> 22 23namespace ark::es2panda::debuginfo { 24 25DebugInfoDumper::DebugInfoDumper(const pandasm::Program *prog) : prog_(prog) {} 26 27static const char *PutComma(bool comma) 28{ 29 return comma ? "," : ""; 30} 31 32template <typename T> 33void DebugInfoDumper::WrapArray(const char *name, const std::vector<T> &array, bool comma) 34{ 35 ss_ << std::endl; 36 Indent(); 37 ss_ << "\"" << name << "\": " 38 << "["; 39 40 if (array.empty()) { 41 ss_ << "]" << PutComma(comma); 42 return; 43 } 44 45 ss_ << "\n"; 46 indent_++; 47 // dump VariableDebugInfo in reverse order to match ts2panda 48 // NOLINTNEXTLINE 49 if constexpr (std::is_same_v<T, pandasm::debuginfo::LocalVariable>) { 50 typename std::vector<T>::const_reverse_iterator elem; 51 for (elem = array.rbegin(); elem != array.rend(); ++elem) { 52 Indent(); 53 WriteVariableInfo(*elem); 54 (std::next(elem) == array.rend()) ? ss_ << "" : ss_ << ","; 55 ss_ << "\n"; 56 } 57 // NOLINTNEXTLINE 58 } else { 59 typename std::vector<T>::const_iterator elem; 60 for (elem = array.begin(); elem != array.end(); ++elem) { 61 Indent(); 62 // NOLINTNEXTLINE 63 if constexpr (std::is_same_v<T, pandasm::Ins>) { 64 WriteIns(*elem); 65 // NOLINTNEXTLINE 66 } else if constexpr (std::is_same_v<T, pandasm::Function::Parameter>) { 67 ss_ << "\"" << (*elem).type.GetName() << "\""; 68 // NOLINTNEXTLINE 69 } else if constexpr (std::is_same_v<T, std::string>) { 70 ss_ << "\"" << *elem << "\""; 71 // NOLINTNEXTLINE 72 } else if constexpr (std::is_same_v<T, std::variant<int64_t, double>>) { 73 ss_ << (std::holds_alternative<int64_t>(*elem) ? std::to_string(std::get<int64_t>(*elem)) 74 : std::to_string(std::get<double>(*elem))); 75 // NOLINTNEXTLINE 76 } else { 77 ss_ << std::to_string(*elem); 78 } 79 80 (std::next(elem) == array.end()) ? ss_ << "" : ss_ << ","; 81 ss_ << "\n"; 82 } 83 } 84 85 indent_--; 86 Indent(); 87 88 ss_ << "]" << PutComma(comma); 89} 90 91void DebugInfoDumper::WriteIns(const pandasm::Ins &ins) 92{ 93 ss_ << "{"; 94 { 95 pandasm::Ins insCopy; 96 insCopy.opcode = ins.opcode; 97 insCopy.setLabel = ins.setLabel; 98 insCopy.label = ins.label; 99 WriteProperty("opcode", insCopy.ToString()); 100 } 101 indent_++; 102 WrapArray("regs", ins.regs); 103 WrapArray("ids", ins.ids); 104 WrapArray("imms", ins.imms); 105 ss_ << std::endl; 106 Indent(); 107 ss_ << "\"label\": " 108 << "\"" << ins.label << "\","; 109 WritePosInfo(ins.insDebug); 110 indent_--; 111 Indent(); 112 ss_ << "}"; 113} 114 115void DebugInfoDumper::WriteMetaData(const std::vector<pandasm::AnnotationData> &metaData) 116{ 117 for (const auto &it : metaData) { 118 for (const auto &elem : it.GetElements()) { 119 pandasm::ScalarValue *value = elem.GetValue()->GetAsScalar(); 120 if (value->GetType() == pandasm::Value::Type::STRING) { 121 WriteProperty(elem.GetName().c_str(), value->GetValue<std::string>(), false); 122 } else if (value->GetType() == pandasm::Value::Type::U32) { 123 WriteProperty(elem.GetName().c_str(), value->GetValue<size_t>()); 124 } 125 } 126 } 127} 128 129void DebugInfoDumper::WritePosInfo(const pandasm::debuginfo::Ins &posInfo) 130{ 131 ss_ << std::endl; 132 Indent(); 133 ss_ << "\"debug_pos_info\": {"; 134 WriteProperty("boundLeft", posInfo.boundLeft); 135 WriteProperty("boundRight", posInfo.boundRight); 136 WriteProperty("sourceLineNum", static_cast<int32_t>(posInfo.lineNumber)); 137 WriteProperty("wholeLine", posInfo.wholeLine, false); 138 Indent(); 139 ss_ << "}" << std::endl; 140} 141 142void DebugInfoDumper::WriteVariableInfo(const pandasm::debuginfo::LocalVariable &localVariableDebug) 143{ 144 ss_ << "{"; 145 WriteProperty("name", localVariableDebug.name); 146 WriteProperty("signature", localVariableDebug.signature); 147 WriteProperty("signatureType", localVariableDebug.signatureType); 148 WriteProperty("reg", localVariableDebug.reg); 149 WriteProperty("start", static_cast<size_t>(localVariableDebug.start)); 150 WriteProperty("length", static_cast<size_t>(localVariableDebug.length), false); 151 Indent(); 152 ss_ << "}"; 153} 154 155void DebugInfoDumper::Dump() 156{ 157 ss_ << "{\n"; 158 indent_++; 159 Indent(); 160 ss_ << "\"functions\": [" << std::endl; 161 162 auto iter = prog_->functionTable.begin(); 163 164 for (; iter != prog_->functionTable.end(); ++iter) { 165 indent_++; 166 Indent(); 167 ss_ << "{"; 168 WriteProperty("name", iter->first); 169 ss_ << std::endl; 170 171 indent_++; 172 Indent(); 173 ss_ << "\"signature\": {"; 174 WriteProperty("retType", iter->second.returnType.GetName()); 175 indent_++; 176 WrapArray("params", iter->second.params, false); 177 indent_ -= 2U; 178 ss_ << std::endl; 179 Indent(); 180 ss_ << "},"; 181 182 WrapArray("ins", iter->second.ins); 183 WrapArray("variables", iter->second.localVariableDebug); 184 WriteProperty("sourceFile", iter->second.sourceFile); 185 WriteProperty("sourceCode", iter->second.sourceCode); 186 // icSize - parameterLength - funcName 187 WriteMetaData(iter->second.metadata->GetAnnotations()); 188 189 indent_--; 190 Indent(); 191 ss_ << "}"; 192 193 if (std::next(iter) != prog_->functionTable.end()) { 194 ss_ << ","; 195 } 196 197 ss_ << std::endl; 198 } 199 200 indent_--; 201 Indent(); 202 ss_ << "]" << std::endl; 203 ss_ << "}"; 204 ss_ << std::endl; 205 std::cout << ss_.str(); 206} 207 208void DebugInfoDumper::WriteProperty(const char *key, const Value &value, bool comma) 209{ 210 ss_ << std::endl; 211 indent_++; 212 Indent(); 213 ss_ << "\"" << key << "\": "; 214 if (std::holds_alternative<std::string>(value)) { 215 ss_ << "\"" << std::get<std::string>(value) << "\""; 216 } else if (std::holds_alternative<size_t>(value)) { 217 ss_ << std::to_string(std::get<size_t>(value)); 218 } else if (std::holds_alternative<int32_t>(value)) { 219 ss_ << std::to_string(std::get<int32_t>(value)); 220 } 221 222 comma ? ss_ << "," : ss_ << std::endl; 223 indent_--; 224} 225 226void DebugInfoDumper::Indent() 227{ 228 for (int32_t i = 0; i <= indent_; i++) { 229 ss_ << " "; 230 } 231} 232 233} // namespace ark::es2panda::debuginfo 234