1 /*
2 * Copyright (c) 2024 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::Ins &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 GetOriginalDumpIns(function);
364 GetInvalidOpLabelMap();
365 UpdateLabels4DumpIns(original_dump_ins_ptrs_, invalid_op_label_map_);
366 GetFinalDumpIns();
367 GetFinalLabelMap();
368 UpdateLabels4DumpIns(final_dump_ins_ptrs_, final_label_map_);
369 DumpFinalIns(os);
370 }
371
GetOriginalDumpIns(const pandasm::Function & function)372 void PandasmProgramDumper::GetOriginalDumpIns(const pandasm::Function &function)
373 {
374 original_dump_ins_.clear();
375 original_dump_ins_ptrs_.clear();
376 original_ins_index_map_.clear();
377 for (const pandasm::Ins &pa_ins : function.ins) {
378 original_dump_ins_.emplace_back(PandasmDumperUtils::DeepCopyIns(pa_ins));
379 }
380 uint32_t idx = 0;
381 for (pandasm::Ins &pa_ins : original_dump_ins_) {
382 original_dump_ins_ptrs_.emplace_back(&pa_ins);
383 original_ins_index_map_[&pa_ins] = idx;
384 idx++;
385 }
386 }
387
GetFinalDumpIns()388 void PandasmProgramDumper::GetFinalDumpIns()
389 {
390 final_dump_ins_ptrs_.clear();
391 final_ins_index_map_.clear();
392 uint32_t idx = 0;
393 for (pandasm::Ins *pa_ins : original_dump_ins_ptrs_) {
394 final_ins_index_map_[pa_ins] = idx;
395 if (pa_ins->opcode != pandasm::Opcode::INVALID) {
396 final_dump_ins_ptrs_.emplace_back(pa_ins);
397 idx++;
398 }
399 }
400 }
401
DumpFinalIns(std::ostream & os)402 void PandasmProgramDumper::DumpFinalIns(std::ostream &os)
403 {
404 for (pandasm::Ins *pa_ins : final_dump_ins_ptrs_) {
405 if (PandasmDumperUtils::IsMatchLiteralId(*pa_ins)) {
406 ReplaceLiteralId4Ins(*pa_ins);
407 }
408 std::string insStr = pa_ins->ToString("", true, regs_num_);
409 os << DUMP_CONTENT_TAB << std::setw(LINE_WIDTH)
410 << std::left << insStr
411 << DUMP_CONTENT_LINE_NUMBER << pa_ins->ins_debug.line_number;
412 os << std::setw(COLUMN_WIDTH) << std::left << DUMP_CONTENT_SPACE
413 << DUMP_CONTENT_COLUMN_NUMBER << pa_ins->ins_debug.column_number
414 << DUMP_CONTENT_SINGLE_ENDL;
415 }
416 }
417
GetInvalidOpLabelMap()418 void PandasmProgramDumper::GetInvalidOpLabelMap()
419 {
420 invalid_op_label_map_.clear();
421 size_t dump_ins_size = original_dump_ins_.size();
422 for (size_t i = 0; i < dump_ins_size; ++i) {
423 pandasm::Ins &curr_ins = original_dump_ins_[i];
424 if (curr_ins.opcode == pandasm::Opcode::INVALID) {
425 HandleInvalidopInsLabel(i, curr_ins);
426 }
427 }
428 }
429
HandleInvalidopInsLabel(size_t invalid_op_idx,pandasm::Ins & invalid_op_ins)430 void PandasmProgramDumper::HandleInvalidopInsLabel(size_t invalid_op_idx, pandasm::Ins &invalid_op_ins)
431 {
432 if (!invalid_op_ins.set_label) {
433 return;
434 }
435 pandasm::Ins *nearest_valid_op_ins = GetNearestValidopIns4InvalidopIns(invalid_op_idx);
436 if (nearest_valid_op_ins == nullptr) {
437 return;
438 }
439 if (!nearest_valid_op_ins->set_label) {
440 // here, the invalid op ins and its nearest valid op ins has the same label
441 // the invalid op will be removed, so the label is still unique for each inst
442 nearest_valid_op_ins->label = invalid_op_ins.label;
443 nearest_valid_op_ins->set_label = true;
444 }
445 invalid_op_label_map_.emplace(invalid_op_ins.label, nearest_valid_op_ins->label);
446 }
447
GetNearestValidopIns4InvalidopIns(size_t invalid_op_ins_idx)448 pandasm::Ins *PandasmProgramDumper::GetNearestValidopIns4InvalidopIns(size_t invalid_op_ins_idx)
449 {
450 size_t dump_ins_size = original_dump_ins_.size();
451 // search downwards
452 for (size_t i = invalid_op_ins_idx + 1; i < dump_ins_size; ++i) {
453 pandasm::Ins &curr_ins = original_dump_ins_[i];
454 if (curr_ins.opcode != pandasm::Opcode::INVALID) {
455 return &curr_ins;
456 }
457 }
458 // search upwards
459 for (size_t i = 0; i < invalid_op_ins_idx; ++i) {
460 pandasm::Ins &curr_ins = original_dump_ins_[invalid_op_ins_idx - i - 1];
461 if (curr_ins.opcode != pandasm::Opcode::INVALID) {
462 return &curr_ins;
463 }
464 }
465 return nullptr;
466 }
467
UpdateLabels4DumpIns(std::vector<pandasm::Ins * > & dump_ins,const LabelMap & label_map) const468 void PandasmProgramDumper::UpdateLabels4DumpIns(std::vector<pandasm::Ins*> &dump_ins, const LabelMap &label_map) const
469 {
470 size_t dump_ins_size = dump_ins.size();
471 for (size_t i = 0; i < dump_ins_size; ++i) {
472 UpdateLabels4DumpInsAtIndex(i, dump_ins, label_map);
473 }
474 }
475
UpdateLabels4DumpInsAtIndex(size_t idx,std::vector<pandasm::Ins * > & dump_ins,const LabelMap & label_map) const476 void PandasmProgramDumper::UpdateLabels4DumpInsAtIndex(size_t idx, std::vector<pandasm::Ins*> &dump_ins,
477 const LabelMap &label_map) const
478 {
479 pandasm::Ins *curr_ins = dump_ins[idx];
480 std::string mapped_label = PandasmDumperUtils::GetMappedLabel(curr_ins->label, label_map);
481 if (mapped_label != "") {
482 curr_ins->label = mapped_label;
483 }
484 if (curr_ins->IsJump()) {
485 mapped_label = PandasmDumperUtils::GetMappedLabel(curr_ins->ids[0], label_map);
486 if (mapped_label != "") {
487 curr_ins->ids.clear();
488 curr_ins->ids.emplace_back(mapped_label);
489 }
490 }
491 }
492
GetFinalLabelMap()493 void PandasmProgramDumper::GetFinalLabelMap()
494 {
495 final_label_map_.clear();
496 size_t dump_ins_size = final_dump_ins_ptrs_.size();
497 for (size_t i = 0; i < dump_ins_size; ++i) {
498 HandleFinalLabelAtIndex(i);
499 }
500 }
501
HandleFinalLabelAtIndex(size_t idx)502 void PandasmProgramDumper::HandleFinalLabelAtIndex(size_t idx)
503 {
504 pandasm::Ins *curr_ins = final_dump_ins_ptrs_[idx];
505 std::string new_label_name = AbcFileUtils::GetLabelNameByInstIdx(idx);
506 if (curr_ins->set_label) {
507 final_label_map_.emplace(curr_ins->label, new_label_name);
508 } else {
509 curr_ins->label = new_label_name;
510 curr_ins->set_label = true;
511 }
512 }
513
DumpFunctionCatchBlocks(std::ostream & os,const pandasm::Function & function) const514 void PandasmProgramDumper::DumpFunctionCatchBlocks(std::ostream &os, const pandasm::Function &function) const
515 {
516 if (is_normalized_) {
517 DumpNormalizedFunctionCatchBlocks(os, function);
518 } else {
519 DumpOriginalFunctionCatchBlocks(os, function);
520 }
521 }
522
DumpOriginalFunctionCatchBlocks(std::ostream & os,const pandasm::Function & function) const523 void PandasmProgramDumper::DumpOriginalFunctionCatchBlocks(std::ostream &os,
524 const pandasm::Function &function) const
525 {
526 for (const pandasm::Function::CatchBlock &catch_block : function.catch_blocks) {
527 DumpCatchBlock(os, catch_block);
528 }
529 }
530
DumpNormalizedFunctionCatchBlocks(std::ostream & os,const pandasm::Function & function) const531 void PandasmProgramDumper::DumpNormalizedFunctionCatchBlocks(std::ostream &os,
532 const pandasm::Function &function) const
533 {
534 std::vector<pandasm::Function::CatchBlock> catch_blocks;
535 for (const pandasm::Function::CatchBlock &catch_block : function.catch_blocks) {
536 catch_blocks.emplace_back(PandasmDumperUtils::DeepCopyCatchBlock(catch_block));
537 }
538 for (pandasm::Function::CatchBlock &catch_block : catch_blocks) {
539 UpdateCatchBlock(catch_block);
540 }
541 for (const pandasm::Function::CatchBlock &catch_block : catch_blocks) {
542 DumpCatchBlock(os, catch_block);
543 }
544 }
545
UpdateCatchBlock(pandasm::Function::CatchBlock & catch_block) const546 void PandasmProgramDumper::UpdateCatchBlock(pandasm::Function::CatchBlock &catch_block) const
547 {
548 catch_block.try_begin_label = GetUpdatedCatchBlockLabel(catch_block.try_begin_label);
549 catch_block.try_end_label = GetUpdatedCatchBlockLabel(catch_block.try_end_label);
550 catch_block.catch_begin_label = GetUpdatedCatchBlockLabel(catch_block.catch_begin_label);
551 catch_block.catch_end_label = GetUpdatedCatchBlockLabel(catch_block.catch_end_label);
552 }
553
GetUpdatedCatchBlockLabel(const std::string & orignal_label) const554 std::string PandasmProgramDumper::GetUpdatedCatchBlockLabel(const std::string &orignal_label) const
555 {
556 std::string mapped_label1 = PandasmDumperUtils::GetMappedLabel(orignal_label, invalid_op_label_map_);
557 if (mapped_label1 == "") {
558 return orignal_label;
559 }
560 std::string mapped_label2 = PandasmDumperUtils::GetMappedLabel(mapped_label1, final_label_map_);
561 if (mapped_label2 == "") {
562 return mapped_label1;
563 }
564 return mapped_label2;
565 }
566
DumpCatchBlock(std::ostream & os,const pandasm::Function::CatchBlock & catch_block) const567 void PandasmProgramDumper::DumpCatchBlock(std::ostream &os, const pandasm::Function::CatchBlock &catch_block) const
568 {
569 if (catch_block.exception_record.empty()) {
570 os << DUMP_TITLE_CATCH_ALL << DUMP_CONTENT_SINGLE_ENDL;
571 } else {
572 os << DUMP_TITLE_CATCH << DUMP_CONTENT_SINGLE_ENDL;
573 }
574 os << DUMP_CONTENT_TAB << DUMP_CONTENT_TRY_BEGIN_LABEL
575 << catch_block.try_begin_label << DUMP_CONTENT_SINGLE_ENDL;
576 os << DUMP_CONTENT_TAB << DUMP_CONTENT_TRY_END_LABEL
577 << catch_block.try_end_label << DUMP_CONTENT_SINGLE_ENDL;
578 os << DUMP_CONTENT_TAB << DUMP_CONTENT_CATCH_BEGIN_LABEL
579 << catch_block.catch_begin_label << DUMP_CONTENT_SINGLE_ENDL;
580 if (!is_normalized_) {
581 os << DUMP_CONTENT_TAB << DUMP_CONTENT_CATCH_END_LABEL
582 << catch_block.catch_end_label << DUMP_CONTENT_SINGLE_ENDL;
583 }
584 }
585
DumpFunctionDebugInfo(std::ostream & os,const pandasm::Function & function)586 void PandasmProgramDumper::DumpFunctionDebugInfo(std::ostream &os, const pandasm::Function &function)
587 {
588 if (function.local_variable_debug.empty()) {
589 return;
590 }
591 std::map<int32_t, panda::pandasm::debuginfo::LocalVariable> local_variable_table;
592 if (is_normalized_) {
593 UpdateLocalVarMap(function, local_variable_table);
594 } else {
595 for (const auto &variable_info : function.local_variable_debug) {
596 local_variable_table[variable_info.reg] = variable_info;
597 }
598 }
599
600 os << DUMP_CONTENT_SINGLE_ENDL;
601 if (local_variable_table.empty()) {
602 return;
603 }
604
605 os << DUMP_TITLE_LOCAL_VAR_TABLE;
606 os << DUMP_CONTENT_SINGLE_ENDL;
607 os << DUMP_CONTENT_LOCAL_VAR_TABLE;
608 for (const auto &iter : local_variable_table) {
609 const auto &variable_info = iter.second;
610 os << DUMP_CONTENT_TAB
611 << std::setw(START_WIDTH) << std::right << variable_info.start << DUMP_CONTENT_TRIPLE_SPACES;
612 os << std::setw(END_WIDTH) << std::right << variable_info.length << DUMP_CONTENT_DOUBLE_SPACES;
613 os << std::setw(REG_WIDTH) << std::right << variable_info.reg << DUMP_CONTENT_DOUBLE_SPACES;
614 os << std::setw(NAME_WIDTH)
615 << std::right << variable_info.name << DUMP_CONTENT_NONUPLE_SPACES << variable_info.signature;
616 if (!variable_info.signature_type.empty() && variable_info.signature_type != variable_info.signature) {
617 os << " (" << variable_info.signature_type << ")";
618 }
619 os << DUMP_CONTENT_SINGLE_ENDL;
620 }
621 }
622
UpdateLocalVarMap(const pandasm::Function & function,std::map<int32_t,panda::pandasm::debuginfo::LocalVariable> & local_variable_table)623 void PandasmProgramDumper::UpdateLocalVarMap(const pandasm::Function &function,
624 std::map<int32_t, panda::pandasm::debuginfo::LocalVariable>& local_variable_table)
625 {
626 std::unordered_map<uint32_t, uint32_t> original_to_final_index_map_;
627 uint32_t max_original_idx = 0;
628 uint32_t max_final_idx = 0;
629 for (const auto &[key, value] : original_ins_index_map_) {
630 uint32_t final_idx = final_ins_index_map_[key];
631 original_to_final_index_map_[value] = final_idx;
632 if (value > max_original_idx) {
633 max_original_idx = value;
634 max_final_idx = final_idx;
635 }
636 }
637 original_to_final_index_map_[max_original_idx + 1] = max_final_idx;
638
639 for (const auto &variable_info : function.local_variable_debug) {
640 uint32_t original_start = variable_info.start;
641 uint32_t original_end = variable_info.length + variable_info.start;
642 uint32_t new_start = original_to_final_index_map_[original_start];
643 uint32_t new_length = original_to_final_index_map_[original_end] - new_start;
644 panda::pandasm::debuginfo::LocalVariable local_var = {variable_info.name,
645 variable_info.signature,
646 variable_info.signature_type,
647 variable_info.reg,
648 new_start,
649 new_length};
650 local_variable_table[variable_info.reg] = local_var;
651 }
652 }
653
DumpStrings(std::ostream & os) const654 void PandasmProgramDumper::DumpStrings(std::ostream &os) const
655 {
656 if (is_normalized_) {
657 return;
658 }
659 os << DUMP_TITLE_SEPARATOR;
660 os << DUMP_TITLE_STRING;
661 for (const std::string &str : program_->strings) {
662 os << str << DUMP_CONTENT_SINGLE_ENDL;
663 }
664 }
665
ReplaceLiteralId4Ins(pandasm::Ins & pa_ins) const666 void PandasmProgramDumper::ReplaceLiteralId4Ins(pandasm::Ins &pa_ins) const
667 {
668 size_t idx = PandasmDumperUtils::GetLiteralIdIndex4Ins(pa_ins);
669 std::string id_str = pa_ins.ids[idx];
670 auto it = program_->literalarray_table.find(id_str);
671 ASSERT(it != program_->literalarray_table.end());
672 const pandasm::LiteralArray &literal_array = it->second;
673 auto id = PandasmDumperUtils::GetLiteralArrayIdFromName(it->first);
674 std::string replaced_value = SerializeLiteralArray(literal_array, id);
675 pa_ins.ids[idx] = replaced_value;
676 }
677
SerializeLiteralArray(const pandasm::LiteralArray & lit_array,uint32_t id) const678 std::string PandasmProgramDumper::SerializeLiteralArray(const pandasm::LiteralArray &lit_array, uint32_t id) const
679 {
680 if (lit_array.literals_.empty()) {
681 return "";
682 }
683 std::stringstream ss;
684 ss << DUMP_CONTENT_LEFT_CURLY_BRACKET << DUMP_CONTENT_SPACE;
685 ss << lit_array.literals_.size();
686 ss << DUMP_CONTENT_SPACE << DUMP_CONTENT_LEFT_SQUARE_BRACKET << DUMP_CONTENT_SPACE;
687 processing_literal_array_id_set_.emplace(id);
688 SerializeLiterals(lit_array, ss);
689 processing_literal_array_id_set_.erase(id);
690 ss << DUMP_CONTENT_RIGHT_SQUARE_BRACKET << DUMP_CONTENT_RIGHT_CURLY_BRACKET;
691 return ss.str();
692 }
693
SerializeLiterals(const pandasm::LiteralArray & lit_array,std::stringstream & os) const694 void PandasmProgramDumper::SerializeLiterals(const pandasm::LiteralArray &lit_array, std::stringstream &os) const
695 {
696 for (size_t i = 0; i < lit_array.literals_.size(); i++) {
697 SerializeLiteralsAtIndex(lit_array, os, i);
698 os << DUMP_CONTENT_COMMA << DUMP_CONTENT_SPACE;
699 }
700 }
701
SerializeLiteralsAtIndex(const pandasm::LiteralArray & lit_array,std::stringstream & os,size_t i) const702 void PandasmProgramDumper::SerializeLiteralsAtIndex(
703 const pandasm::LiteralArray &lit_array, std::stringstream &os, size_t i) const
704 {
705 const panda_file::LiteralTag &tag = lit_array.literals_[i].tag_;
706 os << PandasmDumperUtils::LiteralTagToString(tag) << DUMP_CONTENT_COLON;
707 const auto &val = lit_array.literals_[i].value_;
708 switch (tag) {
709 case panda_file::LiteralTag::BOOL:
710 os << (std::get<bool>(val));
711 break;
712 case panda_file::LiteralTag::LITERALBUFFERINDEX:
713 case panda_file::LiteralTag::INTEGER:
714 os << (bit_cast<int32_t>(std::get<uint32_t>(val)));
715 break;
716 case panda_file::LiteralTag::DOUBLE:
717 os << (std::get<double>(val));
718 break;
719 case panda_file::LiteralTag::STRING:
720 os << "\"" << (std::get<std::string>(val)) << "\"";
721 break;
722 case panda_file::LiteralTag::METHOD:
723 case panda_file::LiteralTag::GETTER:
724 case panda_file::LiteralTag::SETTER:
725 case panda_file::LiteralTag::GENERATORMETHOD:
726 case panda_file::LiteralTag::ASYNCGENERATORMETHOD:
727 os << (std::get<std::string>(val));
728 break;
729 case panda_file::LiteralTag::NULLVALUE:
730 case panda_file::LiteralTag::ACCESSOR:
731 os << (static_cast<int16_t>(bit_cast<int8_t>(std::get<uint8_t>(val))));
732 break;
733 case panda_file::LiteralTag::METHODAFFILIATE:
734 os << (std::get<uint16_t>(val));
735 break;
736 case panda_file::LiteralTag::LITERALARRAY:
737 SerializeNestedLiteralArrayById(os, std::get<std::string>(val));
738 break;
739 case panda_file::LiteralTag::BUILTINTYPEINDEX:
740 os << (static_cast<int16_t>(std::get<uint8_t>(val)));
741 break;
742 case panda_file::LiteralTag::TAGVALUE:
743 os << (static_cast<int16_t>(std::get<uint8_t>(val)));
744 break;
745 default:
746 UNREACHABLE();
747 }
748 }
749
SerializeNestedLiteralArrayById(std::stringstream & os,const std::string & literal_array_id_name) const750 void PandasmProgramDumper::SerializeNestedLiteralArrayById(
751 std::stringstream &os, const std::string &literal_array_id_name) const
752 {
753 if (!is_normalized_) {
754 os << literal_array_id_name;
755 return;
756 }
757 auto id = PandasmDumperUtils::GetLiteralArrayIdFromName(literal_array_id_name);
758 if (processing_literal_array_id_set_.find(id) == processing_literal_array_id_set_.end()) {
759 auto it = program_->literalarray_table.find(literal_array_id_name);
760 ASSERT(it != program_->literalarray_table.end());
761 os << SerializeLiteralArray(it->second, id);
762 } else {
763 UNREACHABLE();
764 }
765 }
766
767 } // namespace panda::abc2program
768