• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &param,
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