1 /*
2 * Copyright (c) 2021-2025 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 "util/es2pandaMacros.h"
19
20 #include <sstream>
21 #include <string>
22
23 namespace ark::es2panda::debuginfo {
24
DebugInfoDumper(const pandasm::Program * prog)25 DebugInfoDumper::DebugInfoDumper(const pandasm::Program *prog) : prog_(prog) {}
26
PutComma(bool comma)27 static const char *PutComma(bool comma)
28 {
29 return comma ? "," : "";
30 }
31
32 template <typename T>
WrapArray(const char * name,const std::vector<T> & array,bool comma)33 void 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
WriteIns(const pandasm::Ins & ins)91 void 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
WriteMetaData(const std::vector<pandasm::AnnotationData> & metaData)115 void 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
WritePosInfo(const pandasm::debuginfo::Ins & posInfo)129 void 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
WriteVariableInfo(const pandasm::debuginfo::LocalVariable & localVariableDebug)142 void 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
DumpFuncBody(std::string name,const pandasm::Function & func)155 void DebugInfoDumper::DumpFuncBody(std::string name, const pandasm::Function &func)
156 {
157 indent_++;
158 Indent();
159 ss_ << "{";
160 WriteProperty("name", name);
161 ss_ << std::endl;
162
163 indent_++;
164 Indent();
165 ss_ << "\"signature\": {";
166 WriteProperty("retType", func.returnType.GetName());
167 indent_++;
168 WrapArray("params", func.params, false);
169 indent_ -= 2U;
170 ss_ << std::endl;
171 Indent();
172 ss_ << "},";
173
174 WrapArray("ins", func.ins);
175 WrapArray("variables", func.localVariableDebug);
176 WriteProperty("sourceFile", func.sourceFile);
177 WriteProperty("sourceCode", func.sourceCode);
178 // icSize - parameterLength - funcName
179 WriteMetaData(func.metadata->GetAnnotations());
180
181 indent_--;
182 Indent();
183 ss_ << "}";
184 }
185
DumpFunctions(const std::map<std::string,pandasm::Function> & table)186 void DebugInfoDumper::DumpFunctions(const std::map<std::string, pandasm::Function> &table)
187 {
188 auto iter = table.begin();
189
190 for (; iter != table.end(); ++iter) {
191 DumpFuncBody(iter->first, iter->second);
192
193 if (std::next(iter) != table.end()) {
194 ss_ << ",";
195 }
196
197 ss_ << std::endl;
198 }
199 }
200
Dump()201 void DebugInfoDumper::Dump()
202 {
203 ss_ << "{\n";
204 indent_++;
205 Indent();
206 ss_ << "\"functions\": [" << std::endl;
207
208 DumpFunctions(prog_->functionStaticTable);
209 DumpFunctions(prog_->functionInstanceTable);
210
211 indent_--;
212 Indent();
213 ss_ << "]" << std::endl;
214 ss_ << "}";
215 ss_ << std::endl;
216 std::cout << ss_.str();
217 }
218
WriteProperty(const char * key,const Value & value,bool comma)219 void DebugInfoDumper::WriteProperty(const char *key, const Value &value, bool comma)
220 {
221 ss_ << std::endl;
222 indent_++;
223 Indent();
224 ss_ << "\"" << key << "\": ";
225 if (std::holds_alternative<std::string>(value)) {
226 ss_ << "\"" << std::get<std::string>(value) << "\"";
227 } else if (std::holds_alternative<size_t>(value)) {
228 ss_ << std::to_string(std::get<size_t>(value));
229 } else if (std::holds_alternative<int32_t>(value)) {
230 ss_ << std::to_string(std::get<int32_t>(value));
231 }
232
233 comma ? ss_ << "," : ss_ << std::endl;
234 indent_--;
235 }
236
Indent()237 void DebugInfoDumper::Indent()
238 {
239 for (int32_t i = 0; i <= indent_; i++) {
240 ss_ << " ";
241 }
242 }
243
244 } // namespace ark::es2panda::debuginfo
245