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
23 namespace panda::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 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
WriteIns(const pandasm::Ins & ins)94 void 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
WriteMetaData(const std::vector<pandasm::AnnotationData> & metaData)118 void 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
WritePosInfo(const pandasm::debuginfo::Ins & posInfo)132 void 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
WriteVariableInfo(const pandasm::debuginfo::LocalVariable & localVariableDebug)145 void 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
Dump()158 void 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
WriteProperty(const char * key,const Value & value,bool comma)211 void 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
Indent()229 void DebugInfoDumper::Indent()
230 {
231 for (int32_t i = 0; i <= indent_; i++) {
232 ss_ << " ";
233 }
234 }
235
236 } // namespace panda::es2panda::debuginfo
237