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