1/* 2 * Copyright (c) 2021-2022 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 panda::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 if (std::holds_alternative<int64_t>(*elem)) { 74 ss_ << std::to_string(std::get<int64_t>(*elem)); 75 } else { 76 ss_ << std::to_string(std::get<double>(*elem)); 77 } 78 // NOLINTNEXTLINE 79 } else { 80 ss_ << std::to_string(*elem); 81 } 82 83 (std::next(elem) == array.end()) ? ss_ << "" : ss_ << ","; 84 ss_ << "\n"; 85 } 86 } 87 88 indent_--; 89 Indent(); 90 91 ss_ << "]" << PutComma(comma); 92} 93 94void DebugInfoDumper::WriteIns(const pandasm::Ins &ins) 95{ 96 ss_ << "{"; 97 { 98 pandasm::Ins insCopy; 99 insCopy.opcode = ins.opcode; 100 insCopy.set_label = ins.set_label; 101 insCopy.label = ins.label; 102 WriteProperty("opcode", insCopy.ToString()); 103 } 104 indent_++; 105 WrapArray("regs", ins.regs); 106 WrapArray("ids", ins.ids); 107 WrapArray("imms", ins.imms); 108 ss_ << std::endl; 109 Indent(); 110 ss_ << "\"label\": " 111 << "\"" << ins.label << "\","; 112 WritePosInfo(ins.ins_debug); 113 indent_--; 114 Indent(); 115 ss_ << "}"; 116} 117 118void DebugInfoDumper::WriteMetaData(const std::vector<pandasm::AnnotationData> &metaData) 119{ 120 for (const auto &it : metaData) { 121 for (const auto &elem : it.GetElements()) { 122 pandasm::ScalarValue *value = elem.GetValue()->GetAsScalar(); 123 if (value->GetType() == pandasm::Value::Type::STRING) { 124 WriteProperty(elem.GetName().c_str(), value->GetValue<std::string>(), false); 125 } else if (value->GetType() == pandasm::Value::Type::U32) { 126 WriteProperty(elem.GetName().c_str(), value->GetValue<size_t>()); 127 } 128 } 129 } 130} 131 132void DebugInfoDumper::WritePosInfo(const pandasm::debuginfo::Ins &posInfo) 133{ 134 ss_ << std::endl; 135 Indent(); 136 ss_ << "\"debug_pos_info\": {"; 137 WriteProperty("boundLeft", posInfo.bound_left); 138 WriteProperty("boundRight", posInfo.bound_right); 139 WriteProperty("sourceLineNum", static_cast<int32_t>(posInfo.line_number)); 140 WriteProperty("wholeLine", posInfo.whole_line, false); 141 Indent(); 142 ss_ << "}" << std::endl; 143} 144 145void DebugInfoDumper::WriteVariableInfo(const pandasm::debuginfo::LocalVariable &localVariableDebug) 146{ 147 ss_ << "{"; 148 WriteProperty("name", localVariableDebug.name); 149 WriteProperty("signature", localVariableDebug.signature); 150 WriteProperty("signatureType", localVariableDebug.signature_type); 151 WriteProperty("reg", localVariableDebug.reg); 152 WriteProperty("start", static_cast<size_t>(localVariableDebug.start)); 153 WriteProperty("length", static_cast<size_t>(localVariableDebug.length), false); 154 Indent(); 155 ss_ << "}"; 156} 157 158void DebugInfoDumper::Dump() 159{ 160 ss_ << "{\n"; 161 indent_++; 162 Indent(); 163 ss_ << "\"functions\": [" << std::endl; 164 165 auto iter = prog_->function_table.begin(); 166 167 for (; iter != prog_->function_table.end(); ++iter) { 168 indent_++; 169 Indent(); 170 ss_ << "{"; 171 WriteProperty("name", iter->first); 172 ss_ << std::endl; 173 174 indent_++; 175 Indent(); 176 ss_ << "\"signature\": {"; 177 WriteProperty("retType", iter->second.return_type.GetName()); 178 indent_++; 179 WrapArray("params", iter->second.params, false); 180 indent_ -= 2U; 181 ss_ << std::endl; 182 Indent(); 183 ss_ << "},"; 184 185 WrapArray("ins", iter->second.ins); 186 WrapArray("variables", iter->second.local_variable_debug); 187 WriteProperty("sourceFile", iter->second.source_file); 188 WriteProperty("sourceCode", iter->second.source_code); 189 // icSize - parameterLength - funcName 190 WriteMetaData(iter->second.metadata->GetAnnotations()); 191 192 indent_--; 193 Indent(); 194 ss_ << "}"; 195 196 if (std::next(iter) != prog_->function_table.end()) { 197 ss_ << ","; 198 } 199 200 ss_ << std::endl; 201 } 202 203 indent_--; 204 Indent(); 205 ss_ << "]" << std::endl; 206 ss_ << "}"; 207 ss_ << std::endl; 208 std::cout << ss_.str(); 209} 210 211void DebugInfoDumper::WriteProperty(const char *key, const Value &value, bool comma) 212{ 213 ss_ << std::endl; 214 indent_++; 215 Indent(); 216 ss_ << "\"" << key << "\": "; 217 if (std::holds_alternative<std::string>(value)) { 218 ss_ << "\"" << std::get<std::string>(value) << "\""; 219 } else if (std::holds_alternative<size_t>(value)) { 220 ss_ << std::to_string(std::get<size_t>(value)); 221 } else if (std::holds_alternative<int32_t>(value)) { 222 ss_ << std::to_string(std::get<int32_t>(value)); 223 } 224 225 comma ? ss_ << "," : ss_ << std::endl; 226 indent_--; 227} 228 229void DebugInfoDumper::Indent() 230{ 231 for (int32_t i = 0; i <= indent_; i++) { 232 ss_ << " "; 233 } 234} 235 236} // namespace panda::es2panda::debuginfo 237