1 /*
2 * Copyright (c) 2024-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 "program_dump.h"
17 #include "abc2program_log.h"
18 #include "common/abc_file_utils.h"
19
20 namespace panda::abc2program {
21
Dump(std::ostream & os,const pandasm::Program & program)22 void PandasmProgramDumper::Dump(std::ostream &os, const pandasm::Program &program)
23 {
24 program_ = &program;
25 os << std::flush;
26 DumpAbcFilePath(os);
27 DumpLiteralArrayTable(os);
28 DumpRecordTable(os);
29 DumpFunctionTable(os);
30 DumpStrings(os);
31 }
32
SetAbcFilePath(const std::string & abc_file_path)33 void PandasmProgramDumper::SetAbcFilePath(const std::string &abc_file_path)
34 {
35 abc_file_path_ = abc_file_path;
36 }
37
DumpAbcFilePath(std::ostream & os) const38 void PandasmProgramDumper::DumpAbcFilePath(std::ostream &os) const
39 {
40 if (abc_file_path_.empty()) {
41 return;
42 }
43 std::string file_abs_path = os::file::File::GetAbsolutePath(abc_file_path_).Value();
44 os << DUMP_TITLE_SOURCE_BINARY << file_abs_path << DUMP_CONTENT_DOUBLE_ENDL;
45 }
46
DumpLanguage(std::ostream & os,const panda::panda_file::SourceLang lang) const47 void PandasmProgramDumper::DumpLanguage(std::ostream &os, const panda::panda_file::SourceLang lang) const
48 {
49 os << DUMP_TITLE_LANGUAGE;
50 if (lang == panda::panda_file::SourceLang::ECMASCRIPT) {
51 os << DUMP_CONTENT_ECMASCRIPT;
52 } else if (lang == panda::panda_file::SourceLang::JAVASCRIPT) {
53 os << DUMP_CONTENT_JAVASCRIPT;
54 } else if (lang == panda::panda_file::SourceLang::TYPESCRIPT) {
55 os << DUMP_CONTENT_TYPESCRIPT;
56 } else if (lang == panda::panda_file::SourceLang::ARKTS) {
57 os << DUMP_CONTENT_ARKTS;
58 } else {
59 os << DUMP_CONTENT_PANDA_ASSEMBLY;
60 }
61 os << DUMP_CONTENT_SINGLE_ENDL;
62 }
63
DumpProgramLanguage(std::ostream & os) const64 void PandasmProgramDumper::DumpProgramLanguage(std::ostream &os) const
65 {
66 DumpLanguage(os, program_->lang);
67 }
68
DumpRecordLanguage(std::ostream & os,const pandasm::Record & record) const69 void PandasmProgramDumper::DumpRecordLanguage(std::ostream &os, const pandasm::Record &record) const
70 {
71 DumpLanguage(os, record.language);
72 }
73
DumpFunctionLanguage(std::ostream & os,const pandasm::Function & function) const74 void PandasmProgramDumper::DumpFunctionLanguage(std::ostream &os, const pandasm::Function &function) const
75 {
76 DumpLanguage(os, function.language);
77 }
78
DumpLiteralArrayTable(std::ostream & os) const79 void PandasmProgramDumper::DumpLiteralArrayTable(std::ostream &os) const
80 {
81 os << DUMP_TITLE_SEPARATOR;
82 os << DUMP_TITLE_LITERALS;
83 os << DUMP_CONTENT_DOUBLE_ENDL;
84 auto it = program_->literalarray_table.begin();
85 auto end = program_->literalarray_table.end();
86 // In normalized mode, sort dump result of literal arrays before output.
87 if (is_normalized_) {
88 std::vector<std::string> literal_arrays;
89 for (; it != end; ++it) {
90 auto id = PandasmDumperUtils::GetLiteralArrayIdFromName(it->first);
91 auto lit_arr = SerializeLiteralArray(it->second, id);
92 lit_arr += DUMP_CONTENT_DOUBLE_ENDL;
93 literal_arrays.emplace_back(lit_arr);
94 }
95 std::sort(literal_arrays.begin(), literal_arrays.end());
96 for (auto &str : literal_arrays) {
97 os << str;
98 }
99 } else {
100 for (; it != end; ++it) {
101 os << it->first << DUMP_CONTENT_SPACE;
102 auto id = PandasmDumperUtils::GetLiteralArrayIdFromName(it->first);
103 os << SerializeLiteralArray(it->second, id);
104 os << DUMP_CONTENT_DOUBLE_ENDL;
105 }
106 }
107 os << DUMP_CONTENT_DOUBLE_ENDL;
108 }
109
DumpRecordTable(std::ostream & os) const110 void PandasmProgramDumper::DumpRecordTable(std::ostream &os) const
111 {
112 os << DUMP_TITLE_SEPARATOR;
113 os << DUMP_TITLE_RECORDS;
114 os << DUMP_CONTENT_DOUBLE_ENDL;
115 for (const auto &it : program_->record_table) {
116 if (is_normalized_ && is_debug_ && it.first == SLOT_NUMBER_RECORD_NAME) {
117 continue;
118 }
119 DumpRecord(os, it.second);
120 }
121 os << DUMP_CONTENT_SINGLE_ENDL;
122 }
123
DumpRecord(std::ostream & os,const pandasm::Record & record) const124 void PandasmProgramDumper::DumpRecord(std::ostream &os, const pandasm::Record &record) const
125 {
126 DumpRecordLanguage(os, record);
127 if (is_normalized_) {
128 if (AbcFileUtils::IsGlobalTypeName(record.name)) {
129 return;
130 }
131 if (AbcFileUtils::IsESTypeAnnotationName(record.name)) {
132 return;
133 }
134 }
135 os << DUMP_TITLE_RECORD << record.name;
136 if (DumpRecordMetaData(os, record)) {
137 DumpFieldList(os, record);
138 }
139 DumpRecordSourceFile(os, record);
140 }
141
DumpRecordMetaData(std::ostream & os,const pandasm::Record & record) const142 bool PandasmProgramDumper::DumpRecordMetaData(std::ostream &os, const pandasm::Record &record) const
143 {
144 if (record.metadata->IsForeign()) {
145 os << DUMP_CONTENT_SPACE << DUMP_CONTENT_ATTR_EXTERNAL;
146 os << DUMP_CONTENT_SINGLE_ENDL;
147 return false;
148 }
149 return true;
150 }
151
DumpFieldList(std::ostream & os,const pandasm::Record & record) const152 void PandasmProgramDumper::DumpFieldList(std::ostream &os, const pandasm::Record &record) const
153 {
154 os << DUMP_CONTENT_SPACE << DUMP_CONTENT_LEFT_CURLY_BRACKET << DUMP_CONTENT_SINGLE_ENDL;
155 for (const auto &it : record.field_list) {
156 DumpField(os, it);
157 }
158 os << DUMP_CONTENT_RIGHT_CURLY_BRACKET << DUMP_CONTENT_SINGLE_ENDL;
159 }
160
DumpField(std::ostream & os,const pandasm::Field & field) const161 void PandasmProgramDumper::DumpField(std::ostream &os, const pandasm::Field &field) const
162 {
163 os << DUMP_CONTENT_TAB << field.type.GetPandasmName() << DUMP_CONTENT_SPACE << field.name;
164 DumpFieldMetaData(os, field);
165 os << DUMP_CONTENT_SINGLE_ENDL;
166 }
167
DumpFieldMetaData(std::ostream & os,const pandasm::Field & field) const168 void PandasmProgramDumper::DumpFieldMetaData(std::ostream &os, const pandasm::Field &field) const
169 {
170 if (field.metadata->GetValue()) {
171 DumpScalarValue(os, *(field.metadata->GetValue()));
172 }
173 }
174
DumpAnnotationData(std::ostream & os,const pandasm::AnnotationData & anno) const175 void PandasmProgramDumper::DumpAnnotationData(std::ostream &os, const pandasm::AnnotationData &anno) const
176 {
177 os << DUMP_CONTENT_SPACE << anno.GetName() << DUMP_CONTENT_SINGLE_ENDL;
178 for (const auto &element : anno.GetElements()) {
179 os << DUMP_CONTENT_SPACE << element.GetName();
180 if (element.GetValue()->IsArray()) {
181 DumpArrayValue(os, *(element.GetValue()->GetAsArray()));
182 } else {
183 DumpScalarValue(os, *(element.GetValue()->GetAsScalar()));
184 }
185 }
186 }
187
DumpArrayValue(std::ostream & os,const pandasm::ArrayValue & array) const188 void PandasmProgramDumper::DumpArrayValue(std::ostream &os, const pandasm::ArrayValue &array) const
189 {
190 for (const auto &val : array.GetValues()) {
191 DumpScalarValue(os, val);
192 }
193 }
DumpScalarValue(std::ostream & os,const pandasm::ScalarValue & scalar) const194 void PandasmProgramDumper::DumpScalarValue(std::ostream &os, const pandasm::ScalarValue &scalar) const
195 {
196 switch (scalar.GetType()) {
197 case pandasm::Value::Type::U1:
198 case pandasm::Value::Type::I8:
199 case pandasm::Value::Type::U8:
200 case pandasm::Value::Type::I16:
201 case pandasm::Value::Type::U16:
202 case pandasm::Value::Type::I32:
203 case pandasm::Value::Type::U32:
204 case pandasm::Value::Type::I64:
205 case pandasm::Value::Type::U64:
206 case pandasm::Value::Type::STRING_NULLPTR: {
207 os << DUMP_CONTENT_SPACE << scalar.GetValue<uint64_t>();
208 break;
209 }
210 case pandasm::Value::Type::F32:
211 os << DUMP_CONTENT_SPACE << scalar.GetValue<float>();
212 break;
213 case pandasm::Value::Type::F64: {
214 os << DUMP_CONTENT_SPACE << scalar.GetValue<double>();
215 break;
216 }
217 case pandasm::Value::Type::STRING:
218 case pandasm::Value::Type::METHOD:
219 case pandasm::Value::Type::ENUM:
220 case pandasm::Value::Type::LITERALARRAY: {
221 if (!is_normalized_) {
222 os << DUMP_CONTENT_SPACE << scalar.GetValue<std::string>();
223 } else {
224 auto literal_array_id_name = scalar.GetValue<std::string>();
225 auto it = program_->literalarray_table.find(literal_array_id_name);
226 ASSERT(it != program_->literalarray_table.end());
227 auto id = PandasmDumperUtils::GetLiteralArrayIdFromName(literal_array_id_name);
228 os << DUMP_CONTENT_SPACE << SerializeLiteralArray(it->second, id);
229 }
230 break;
231 }
232 case pandasm::Value::Type::RECORD: {
233 pandasm::Type type = scalar.GetValue<pandasm::Type>();
234 os << DUMP_CONTENT_SPACE << type.GetComponentName() << DUMP_CONTENT_SPACE << type.GetName();
235 break;
236 }
237 case pandasm::Value::Type::ANNOTATION: {
238 DumpAnnotationData(os, scalar.GetValue<pandasm::AnnotationData>());
239 break;
240 }
241 default :
242 break;
243 }
244 }
245
DumpRecordSourceFile(std::ostream & os,const pandasm::Record & record) const246 void PandasmProgramDumper::DumpRecordSourceFile(std::ostream &os, const pandasm::Record &record) const
247 {
248 os << DUMP_TITLE_RECORD_SOURCE_FILE << record.source_file << DUMP_CONTENT_DOUBLE_ENDL;
249 }
250
DumpFunctionTable(std::ostream & os)251 void PandasmProgramDumper::DumpFunctionTable(std::ostream &os)
252 {
253 os << DUMP_TITLE_SEPARATOR;
254 os << DUMP_TITLE_METHODS;
255 os << DUMP_CONTENT_DOUBLE_ENDL;
256 for (const auto &it : program_->function_table) {
257 DumpFunction(os, it.second);
258 }
259 }
260
DumpFunction(std::ostream & os,const pandasm::Function & function)261 void PandasmProgramDumper::DumpFunction(std::ostream &os, const pandasm::Function &function)
262 {
263 regs_num_ = function.regs_num;
264 DumpFunctionKind(os, function);
265 if (!is_normalized_ || !is_debug_) {
266 DumpFunctionAnnotations(os, function);
267 }
268 DumpFunctionLanguage(os, function);
269 DumpFunctionHead(os, function);
270 DumpFunctionBody(os, function);
271 }
272
DumpFunctionKind(std::ostream & os,const pandasm::Function & function) const273 void PandasmProgramDumper::DumpFunctionKind(std::ostream &os, const pandasm::Function &function) const
274 {
275 os << DUMP_TITLE_FUNCTION_KIND << PandasmDumperUtils::GetFunctionKindString(function.function_kind);
276 os << DUMP_CONTENT_SINGLE_ENDL;
277 }
278
DumpFunctionAnnotations(std::ostream & os,const pandasm::Function & function) const279 void PandasmProgramDumper::DumpFunctionAnnotations(std::ostream &os, const pandasm::Function &function) const
280 {
281 for (auto &annotation : function.metadata->GetAnnotations()) {
282 DumpAnnotationData(os, annotation);
283 os << DUMP_CONTENT_SINGLE_ENDL;
284 }
285 }
286
DumpFunctionHead(std::ostream & os,const pandasm::Function & function) const287 void PandasmProgramDumper::DumpFunctionHead(std::ostream &os, const pandasm::Function &function) const
288 {
289 os << DUMP_TITLE_FUNCTION;
290 DumpFunctionReturnType(os, function);
291 DumpFunctionName(os, function);
292 DumpFunctionParams(os, function);
293 os << DUMP_CONTENT_SPACE << DUMP_CONTENT_LEFT_CURLY_BRACKET << DUMP_CONTENT_SINGLE_ENDL;
294 }
295
DumpFunctionReturnType(std::ostream & os,const pandasm::Function & function) const296 void PandasmProgramDumper::DumpFunctionReturnType(std::ostream &os, const pandasm::Function &function) const
297 {
298 os << function.return_type.GetPandasmName() << DUMP_CONTENT_SPACE;
299 }
300
DumpFunctionName(std::ostream & os,const pandasm::Function & function) const301 void PandasmProgramDumper::DumpFunctionName(std::ostream &os, const pandasm::Function &function) const
302 {
303 os << function.name;
304 }
305
DumpFunctionParams(std::ostream & os,const pandasm::Function & function) const306 void PandasmProgramDumper::DumpFunctionParams(std::ostream &os, const pandasm::Function &function) const
307 {
308 os << DUMP_CONTENT_LEFT_PARENTHESIS;
309 if (function.params.size() > 0) {
310 DumpFunctionParamAtIndex(os, function.params[0], 0);
311 for (size_t i = 1; i < function.params.size(); ++i) {
312 os << DUMP_CONTENT_COMMA << DUMP_CONTENT_SPACE;
313 DumpFunctionParamAtIndex(os, function.params[i], i);
314 }
315 }
316 os << DUMP_CONTENT_RIGHT_PARENTHESIS;
317 }
318
DumpFunctionParamAtIndex(std::ostream & os,const pandasm::Function::Parameter & param,size_t idx) const319 void PandasmProgramDumper::DumpFunctionParamAtIndex(std::ostream &os,
320 const pandasm::Function::Parameter ¶m,
321 size_t idx) const
322 {
323 os << param.type.GetPandasmName() << DUMP_CONTENT_SPACE << DUMP_CONTENT_FUNCTION_PARAM_NAME_PREFIX << idx;
324 }
325
DumpFunctionAttributes(std::ostream & os,const pandasm::Function & function) const326 void PandasmProgramDumper::DumpFunctionAttributes(std::ostream &os, const pandasm::Function &function) const
327 {
328 log::Unimplemented(__PRETTY_FUNCTION__);
329 }
330
DumpFunctionBody(std::ostream & os,const pandasm::Function & function)331 void PandasmProgramDumper::DumpFunctionBody(std::ostream &os, const pandasm::Function &function)
332 {
333 DumpFunctionIns(os, function);
334 DumpFunctionCatchBlocks(os, function);
335 DumpFunctionDebugInfo(os, function);
336 os << "}" << DUMP_CONTENT_DOUBLE_ENDL;
337 }
338
DumpFunctionIns(std::ostream & os,const pandasm::Function & function)339 void PandasmProgramDumper::DumpFunctionIns(std::ostream &os, const pandasm::Function &function)
340 {
341 if (is_normalized_) {
342 DumpNormalizedFunctionIns(os, function);
343 } else {
344 DumpOriginalFunctionIns(os, function);
345 }
346 }
347
DumpOriginalFunctionIns(std::ostream & os,const pandasm::Function & function)348 void PandasmProgramDumper::DumpOriginalFunctionIns(std::ostream &os, const pandasm::Function &function)
349 {
350 for (const pandasm::InsPtr &pa_ins : function.ins) {
351 std::string insStr = pa_ins->ToString("", true, regs_num_);
352 os << DUMP_CONTENT_TAB << std::setw(LINE_WIDTH)
353 << std::left << insStr
354 << DUMP_CONTENT_LINE_NUMBER << pa_ins->ins_debug.line_number;
355 os << std::setw(COLUMN_WIDTH) << std::left << DUMP_CONTENT_SPACE
356 << DUMP_CONTENT_COLUMN_NUMBER << pa_ins->ins_debug.column_number
357 << DUMP_CONTENT_SINGLE_ENDL;
358 }
359 }
360
DumpNormalizedFunctionIns(std::ostream & os,const pandasm::Function & function)361 void PandasmProgramDumper::DumpNormalizedFunctionIns(std::ostream &os, const pandasm::Function &function)
362 {
363 GetFinalDumpIns(function);
364 UpdateLabels4DumpIns(final_dump_ins_ptrs_, label_map_);
365 DumpFinalIns(os);
366 }
367
GetFinalDumpIns(const pandasm::Function & function)368 void PandasmProgramDumper::GetFinalDumpIns(const pandasm::Function &function)
369 {
370 label_map_.clear();
371 final_dump_ins_ptrs_.clear();
372 original_to_final_index_map_.clear();
373 size_t valid_op_cnt = 0;
374 for (size_t idx = 0; idx < function.ins.size(); idx++) {
375 auto &ins = function.ins[idx];
376 original_to_final_index_map_.emplace(idx, valid_op_cnt);
377 if (ins->IsLabel()) {
378 label_map_.emplace(ins->Label(), AbcFileUtils::GetLabelNameByInstIdx(valid_op_cnt));
379 } else {
380 valid_op_cnt++;
381 final_dump_ins_ptrs_.emplace_back(ins->DeepCopy());
382 }
383 }
384 original_to_final_index_map_.emplace(function.ins.size(), final_dump_ins_ptrs_.size());
385 }
386
DumpFinalIns(std::ostream & os)387 void PandasmProgramDumper::DumpFinalIns(std::ostream &os)
388 {
389 size_t idx = 0;
390 for (pandasm::InsPtr &pa_ins : final_dump_ins_ptrs_) {
391 if (PandasmDumperUtils::IsMatchLiteralId(pa_ins)) {
392 ReplaceLiteralId4Ins(pa_ins);
393 }
394
395 std::string insStr = AbcFileUtils::GetLabelNameByInstIdx(idx++) + ": " + pa_ins->ToString("", true, regs_num_);
396 os << DUMP_CONTENT_TAB << std::setw(LINE_WIDTH)
397 << std::left << insStr
398 << DUMP_CONTENT_LINE_NUMBER << pa_ins->ins_debug.line_number;
399 os << std::setw(COLUMN_WIDTH) << std::left << DUMP_CONTENT_SPACE
400 << DUMP_CONTENT_COLUMN_NUMBER << pa_ins->ins_debug.column_number
401 << DUMP_CONTENT_SINGLE_ENDL;
402 }
403 }
404
UpdateLabels4DumpIns(std::vector<pandasm::InsPtr> & dump_ins,const LabelMap & label_map) const405 void PandasmProgramDumper::UpdateLabels4DumpIns(std::vector<pandasm::InsPtr> &dump_ins, const LabelMap &label_map) const
406 {
407 size_t dump_ins_size = dump_ins.size();
408 for (size_t i = 0; i < dump_ins_size; ++i) {
409 UpdateLabels4DumpInsAtIndex(i, dump_ins, label_map);
410 }
411 }
412
UpdateLabels4DumpInsAtIndex(size_t idx,std::vector<pandasm::InsPtr> & dump_ins,const LabelMap & label_map) const413 void PandasmProgramDumper::UpdateLabels4DumpInsAtIndex(size_t idx, std::vector<pandasm::InsPtr> &dump_ins,
414 const LabelMap &label_map) const
415 {
416 pandasm::InsPtr &curr_ins = dump_ins[idx];
417 if (curr_ins->IsJump()) {
418 std::string mapped_label = PandasmDumperUtils::GetMappedLabel(curr_ins->GetId(0), label_map);
419 if (mapped_label != "") {
420 curr_ins->SetId(0, mapped_label);
421 }
422 }
423 }
424
DumpFunctionCatchBlocks(std::ostream & os,const pandasm::Function & function) const425 void PandasmProgramDumper::DumpFunctionCatchBlocks(std::ostream &os, const pandasm::Function &function) const
426 {
427 if (is_normalized_) {
428 DumpNormalizedFunctionCatchBlocks(os, function);
429 } else {
430 DumpOriginalFunctionCatchBlocks(os, function);
431 }
432 }
433
DumpOriginalFunctionCatchBlocks(std::ostream & os,const pandasm::Function & function) const434 void PandasmProgramDumper::DumpOriginalFunctionCatchBlocks(std::ostream &os,
435 const pandasm::Function &function) const
436 {
437 for (const pandasm::Function::CatchBlock &catch_block : function.catch_blocks) {
438 DumpCatchBlock(os, catch_block);
439 }
440 }
441
DumpNormalizedFunctionCatchBlocks(std::ostream & os,const pandasm::Function & function) const442 void PandasmProgramDumper::DumpNormalizedFunctionCatchBlocks(std::ostream &os,
443 const pandasm::Function &function) const
444 {
445 std::vector<pandasm::Function::CatchBlock> catch_blocks;
446 for (const pandasm::Function::CatchBlock &catch_block : function.catch_blocks) {
447 catch_blocks.emplace_back(PandasmDumperUtils::DeepCopyCatchBlock(catch_block));
448 }
449 for (pandasm::Function::CatchBlock &catch_block : catch_blocks) {
450 UpdateCatchBlock(catch_block);
451 }
452 for (const pandasm::Function::CatchBlock &catch_block : catch_blocks) {
453 DumpCatchBlock(os, catch_block);
454 }
455 }
456
UpdateCatchBlock(pandasm::Function::CatchBlock & catch_block) const457 void PandasmProgramDumper::UpdateCatchBlock(pandasm::Function::CatchBlock &catch_block) const
458 {
459 catch_block.try_begin_label = GetUpdatedCatchBlockLabel(catch_block.try_begin_label);
460 catch_block.try_end_label = GetUpdatedCatchBlockLabel(catch_block.try_end_label);
461 catch_block.catch_begin_label = GetUpdatedCatchBlockLabel(catch_block.catch_begin_label);
462 catch_block.catch_end_label = GetUpdatedCatchBlockLabel(catch_block.catch_end_label);
463 }
464
GetUpdatedCatchBlockLabel(const std::string & orignal_label) const465 std::string PandasmProgramDumper::GetUpdatedCatchBlockLabel(const std::string &orignal_label) const
466 {
467 std::string mapped_label1 = PandasmDumperUtils::GetMappedLabel(orignal_label, label_map_);
468 if (mapped_label1 == "") {
469 return orignal_label;
470 }
471 return mapped_label1;
472 }
473
DumpCatchBlock(std::ostream & os,const pandasm::Function::CatchBlock & catch_block) const474 void PandasmProgramDumper::DumpCatchBlock(std::ostream &os, const pandasm::Function::CatchBlock &catch_block) const
475 {
476 if (catch_block.exception_record.empty()) {
477 os << DUMP_TITLE_CATCH_ALL << DUMP_CONTENT_SINGLE_ENDL;
478 } else {
479 os << DUMP_TITLE_CATCH << DUMP_CONTENT_SINGLE_ENDL;
480 }
481 os << DUMP_CONTENT_TAB << DUMP_CONTENT_TRY_BEGIN_LABEL
482 << catch_block.try_begin_label << DUMP_CONTENT_SINGLE_ENDL;
483 os << DUMP_CONTENT_TAB << DUMP_CONTENT_TRY_END_LABEL
484 << catch_block.try_end_label << DUMP_CONTENT_SINGLE_ENDL;
485 os << DUMP_CONTENT_TAB << DUMP_CONTENT_CATCH_BEGIN_LABEL
486 << catch_block.catch_begin_label << DUMP_CONTENT_SINGLE_ENDL;
487 if (!is_normalized_) {
488 os << DUMP_CONTENT_TAB << DUMP_CONTENT_CATCH_END_LABEL
489 << catch_block.catch_end_label << DUMP_CONTENT_SINGLE_ENDL;
490 }
491 }
492
DumpFunctionDebugInfo(std::ostream & os,const pandasm::Function & function)493 void PandasmProgramDumper::DumpFunctionDebugInfo(std::ostream &os, const pandasm::Function &function)
494 {
495 if (function.local_variable_debug.empty()) {
496 return;
497 }
498 std::map<int32_t, panda::pandasm::debuginfo::LocalVariable> local_variable_table;
499 if (is_normalized_) {
500 UpdateLocalVarMap(function, local_variable_table);
501 } else {
502 for (const auto &variable_info : function.local_variable_debug) {
503 local_variable_table[variable_info.reg] = variable_info;
504 }
505 }
506
507 os << DUMP_CONTENT_SINGLE_ENDL;
508 if (local_variable_table.empty()) {
509 return;
510 }
511
512 os << DUMP_TITLE_LOCAL_VAR_TABLE;
513 os << DUMP_CONTENT_SINGLE_ENDL;
514 os << DUMP_CONTENT_LOCAL_VAR_TABLE;
515 for (const auto &iter : local_variable_table) {
516 const auto &variable_info = iter.second;
517 os << DUMP_CONTENT_TAB
518 << std::setw(START_WIDTH) << std::right << variable_info.start << DUMP_CONTENT_TRIPLE_SPACES;
519 os << std::setw(END_WIDTH) << std::right << variable_info.length << DUMP_CONTENT_DOUBLE_SPACES;
520 os << std::setw(REG_WIDTH) << std::right << variable_info.reg << DUMP_CONTENT_DOUBLE_SPACES;
521 os << std::setw(NAME_WIDTH)
522 << std::right << variable_info.name << DUMP_CONTENT_NONUPLE_SPACES << variable_info.signature;
523 if (!variable_info.signature_type.empty() && variable_info.signature_type != variable_info.signature) {
524 os << " (" << variable_info.signature_type << ")";
525 }
526 os << DUMP_CONTENT_SINGLE_ENDL;
527 }
528 }
529
UpdateLocalVarMap(const pandasm::Function & function,std::map<int32_t,panda::pandasm::debuginfo::LocalVariable> & local_variable_table)530 void PandasmProgramDumper::UpdateLocalVarMap(const pandasm::Function &function,
531 std::map<int32_t, panda::pandasm::debuginfo::LocalVariable>& local_variable_table)
532 {
533 for (const auto &variable_info : function.local_variable_debug) {
534 uint32_t original_start = variable_info.start;
535 uint32_t original_end = variable_info.length + variable_info.start;
536 uint32_t new_start = original_to_final_index_map_[original_start];
537 uint32_t new_length = original_to_final_index_map_[original_end] - new_start;
538 panda::pandasm::debuginfo::LocalVariable local_var = {variable_info.name,
539 variable_info.signature,
540 variable_info.signature_type,
541 variable_info.reg,
542 new_start,
543 new_length};
544 local_variable_table[variable_info.reg] = local_var;
545 }
546 }
547
DumpStrings(std::ostream & os) const548 void PandasmProgramDumper::DumpStrings(std::ostream &os) const
549 {
550 if (is_normalized_) {
551 return;
552 }
553 os << DUMP_TITLE_SEPARATOR;
554 os << DUMP_TITLE_STRING;
555 for (const std::string &str : program_->strings) {
556 os << str << DUMP_CONTENT_SINGLE_ENDL;
557 }
558 }
559
ReplaceLiteralId4Ins(pandasm::InsPtr & pa_ins) const560 void PandasmProgramDumper::ReplaceLiteralId4Ins(pandasm::InsPtr &pa_ins) const
561 {
562 size_t idx = PandasmDumperUtils::GetLiteralIdIndex4Ins(pa_ins);
563 std::string id_str = pa_ins->GetId(idx);
564 auto it = program_->literalarray_table.find(id_str);
565 ASSERT(it != program_->literalarray_table.end());
566 const pandasm::LiteralArray &literal_array = it->second;
567 auto id = PandasmDumperUtils::GetLiteralArrayIdFromName(it->first);
568 std::string replaced_value = SerializeLiteralArray(literal_array, id);
569 pa_ins->SetId(idx, replaced_value);
570 }
571
SerializeLiteralArray(const pandasm::LiteralArray & lit_array,uint32_t id) const572 std::string PandasmProgramDumper::SerializeLiteralArray(const pandasm::LiteralArray &lit_array, uint32_t id) const
573 {
574 if (lit_array.literals_.empty()) {
575 return "";
576 }
577 std::stringstream ss;
578 ss << DUMP_CONTENT_LEFT_CURLY_BRACKET << DUMP_CONTENT_SPACE;
579 ss << lit_array.literals_.size();
580 ss << DUMP_CONTENT_SPACE << DUMP_CONTENT_LEFT_SQUARE_BRACKET << DUMP_CONTENT_SPACE;
581 processing_literal_array_id_set_.emplace(id);
582 SerializeLiterals(lit_array, ss);
583 processing_literal_array_id_set_.erase(id);
584 ss << DUMP_CONTENT_RIGHT_SQUARE_BRACKET << DUMP_CONTENT_RIGHT_CURLY_BRACKET;
585 return ss.str();
586 }
587
SerializeLiterals(const pandasm::LiteralArray & lit_array,std::stringstream & os) const588 void PandasmProgramDumper::SerializeLiterals(const pandasm::LiteralArray &lit_array, std::stringstream &os) const
589 {
590 for (size_t i = 0; i < lit_array.literals_.size(); i++) {
591 SerializeLiteralsAtIndex(lit_array, os, i);
592 os << DUMP_CONTENT_COMMA << DUMP_CONTENT_SPACE;
593 }
594 }
595
SerializeLiteralsAtIndex(const pandasm::LiteralArray & lit_array,std::stringstream & os,size_t i) const596 void PandasmProgramDumper::SerializeLiteralsAtIndex(
597 const pandasm::LiteralArray &lit_array, std::stringstream &os, size_t i) const
598 {
599 const panda_file::LiteralTag &tag = lit_array.literals_[i].tag_;
600 os << PandasmDumperUtils::LiteralTagToString(tag) << DUMP_CONTENT_COLON;
601 const auto &val = lit_array.literals_[i].value_;
602 switch (tag) {
603 case panda_file::LiteralTag::BOOL:
604 os << (std::get<bool>(val));
605 break;
606 case panda_file::LiteralTag::LITERALBUFFERINDEX:
607 case panda_file::LiteralTag::INTEGER:
608 os << (bit_cast<int32_t>(std::get<uint32_t>(val)));
609 break;
610 case panda_file::LiteralTag::DOUBLE:
611 os << (std::get<double>(val));
612 break;
613 case panda_file::LiteralTag::STRING:
614 os << "\"" << (std::get<std::string>(val)) << "\"";
615 break;
616 case panda_file::LiteralTag::METHOD:
617 case panda_file::LiteralTag::GETTER:
618 case panda_file::LiteralTag::SETTER:
619 case panda_file::LiteralTag::GENERATORMETHOD:
620 case panda_file::LiteralTag::ASYNCGENERATORMETHOD:
621 case panda_file::LiteralTag::ETS_IMPLEMENTS:
622 os << (std::get<std::string>(val));
623 break;
624 case panda_file::LiteralTag::NULLVALUE:
625 case panda_file::LiteralTag::ACCESSOR:
626 os << (static_cast<int16_t>(bit_cast<int8_t>(std::get<uint8_t>(val))));
627 break;
628 case panda_file::LiteralTag::METHODAFFILIATE:
629 os << (std::get<uint16_t>(val));
630 break;
631 case panda_file::LiteralTag::LITERALARRAY:
632 SerializeNestedLiteralArrayById(os, std::get<std::string>(val));
633 break;
634 case panda_file::LiteralTag::BUILTINTYPEINDEX:
635 os << (static_cast<int16_t>(std::get<uint8_t>(val)));
636 break;
637 case panda_file::LiteralTag::TAGVALUE:
638 os << (static_cast<int16_t>(std::get<uint8_t>(val)));
639 break;
640 default:
641 UNREACHABLE();
642 }
643 }
644
SerializeNestedLiteralArrayById(std::stringstream & os,const std::string & literal_array_id_name) const645 void PandasmProgramDumper::SerializeNestedLiteralArrayById(
646 std::stringstream &os, const std::string &literal_array_id_name) const
647 {
648 if (!is_normalized_) {
649 os << literal_array_id_name;
650 return;
651 }
652 auto id = PandasmDumperUtils::GetLiteralArrayIdFromName(literal_array_id_name);
653 if (processing_literal_array_id_set_.find(id) == processing_literal_array_id_set_.end()) {
654 auto it = program_->literalarray_table.find(literal_array_id_name);
655 ASSERT(it != program_->literalarray_table.end());
656 os << SerializeLiteralArray(it->second, id);
657 } else {
658 UNREACHABLE();
659 }
660 }
661
662 } // namespace panda::abc2program
663