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#include "dump_utils.h" 20#include "os/file.h" 21 22namespace panda::abc2program { 23 24void PandasmProgramDumper::Dump(std::ostream &os, const pandasm::Program &program) 25{ 26 program_ = &program; 27 os << std::flush; 28 DumpAbcFilePath(os); 29 DumpProgramLanguage(os); 30 DumpLiteralArrayTable(os); 31 DumpRecordTable(os); 32 DumpFunctionTable(os); 33 DumpStrings(os); 34} 35 36void PandasmProgramDumper::SetAbcFilePath(const std::string &abc_file_path) 37{ 38 abc_file_path_ = abc_file_path; 39} 40 41void PandasmProgramDumper::DumpAbcFilePath(std::ostream &os) const 42{ 43 if (abc_file_path_.empty()) { 44 return; 45 } 46 std::string file_abs_path = os::file::File::GetAbsolutePath(abc_file_path_).Value(); 47 os << DUMP_TITLE_SOURCE_BINARY << file_abs_path << DUMP_CONTENT_DOUBLE_ENDL; 48} 49 50void PandasmProgramDumper::DumpProgramLanguage(std::ostream &os) const 51{ 52 os << DUMP_TITLE_LANGUAGE; 53 if (program_->lang == panda::panda_file::SourceLang::ECMASCRIPT) { 54 os << DUMP_CONTENT_ECMASCRIPT; 55 } else { 56 os << DUMP_CONTENT_PANDA_ASSEMBLY; 57 } 58 os << DUMP_CONTENT_DOUBLE_ENDL; 59} 60 61void PandasmProgramDumper::DumpLiteralArrayTable(std::ostream &os) const 62{ 63 os << DUMP_TITLE_SEPARATOR; 64 os << DUMP_TITLE_LITERALS; 65 os << DUMP_CONTENT_DOUBLE_ENDL; 66 auto it = program_->literalarray_table.begin(); 67 auto end = program_->literalarray_table.end(); 68 // In normalized mode, sort dump result of literal arrays before output. 69 if (is_normalized_) { 70 std::vector<std::string> literal_arrays; 71 for (; it != end; ++it) { 72 auto id = PandasmDumperUtils::GetLiteralArrayIdFromName(it->first); 73 auto lit_arr = SerializeLiteralArray(it->second, id); 74 lit_arr += DUMP_CONTENT_DOUBLE_ENDL; 75 literal_arrays.emplace_back(lit_arr); 76 } 77 std::sort(literal_arrays.begin(), literal_arrays.end()); 78 for (auto &str : literal_arrays) { 79 os << str; 80 } 81 } else { 82 for (; it != end; ++it) { 83 os << it->first << DUMP_CONTENT_SPACE; 84 auto id = PandasmDumperUtils::GetLiteralArrayIdFromName(it->first); 85 os << SerializeLiteralArray(it->second, id); 86 os << DUMP_CONTENT_DOUBLE_ENDL; 87 } 88 } 89 os << DUMP_CONTENT_DOUBLE_ENDL; 90} 91 92void PandasmProgramDumper::DumpRecordTable(std::ostream &os) const 93{ 94 os << DUMP_TITLE_SEPARATOR; 95 os << DUMP_TITLE_RECORDS; 96 os << DUMP_CONTENT_DOUBLE_ENDL; 97 for (const auto &it : program_->record_table) { 98 if (is_normalized_ && is_debug_ && it.first == SLOT_NUMBER_RECORD_NAME) { 99 continue; 100 } 101 DumpRecord(os, it.second); 102 } 103 os << DUMP_CONTENT_SINGLE_ENDL; 104} 105 106void PandasmProgramDumper::DumpRecord(std::ostream &os, const pandasm::Record &record) const 107{ 108 if (is_normalized_) { 109 if (AbcFileUtils::IsGlobalTypeName(record.name)) { 110 return; 111 } 112 if (AbcFileUtils::IsESTypeAnnotationName(record.name)) { 113 return; 114 } 115 } 116 os << DUMP_TITLE_RECORD << record.name; 117 if (DumpRecordMetaData(os, record)) { 118 DumpFieldList(os, record); 119 } 120 DumpRecordSourceFile(os, record); 121} 122 123bool PandasmProgramDumper::DumpRecordMetaData(std::ostream &os, const pandasm::Record &record) const 124{ 125 if (record.metadata->IsForeign()) { 126 os << DUMP_CONTENT_SPACE << DUMP_CONTENT_ATTR_EXTERNAL; 127 os << DUMP_CONTENT_SINGLE_ENDL; 128 return false; 129 } 130 return true; 131} 132 133void PandasmProgramDumper::DumpFieldList(std::ostream &os, const pandasm::Record &record) const 134{ 135 os << DUMP_CONTENT_SPACE << DUMP_CONTENT_LEFT_CURLY_BRACKET << DUMP_CONTENT_SINGLE_ENDL; 136 for (const auto &it : record.field_list) { 137 DumpField(os, it); 138 } 139 os << DUMP_CONTENT_RIGHT_CURLY_BRACKET << DUMP_CONTENT_SINGLE_ENDL; 140} 141 142void PandasmProgramDumper::DumpField(std::ostream &os, const pandasm::Field &field) const 143{ 144 os << DUMP_CONTENT_TAB << field.type.GetPandasmName() << DUMP_CONTENT_SPACE << field.name; 145 DumpFieldMetaData(os, field); 146 os << DUMP_CONTENT_SINGLE_ENDL; 147} 148 149void PandasmProgramDumper::DumpFieldMetaData(std::ostream &os, const pandasm::Field &field) const 150{ 151 if (field.metadata->GetValue()) { 152 DumpScalarValue(os, *(field.metadata->GetValue())); 153 } 154} 155 156void PandasmProgramDumper::DumpAnnotationData(std::ostream &os, const pandasm::AnnotationData &anno) const 157{ 158 os << DUMP_CONTENT_SPACE << anno.GetName() << DUMP_CONTENT_SINGLE_ENDL; 159 for (const auto &element : anno.GetElements()) { 160 os << DUMP_CONTENT_SPACE << element.GetName(); 161 if (element.GetValue()->IsArray()) { 162 DumpArrayValue(os, *(element.GetValue()->GetAsArray())); 163 } else { 164 DumpScalarValue(os, *(element.GetValue()->GetAsScalar())); 165 } 166 } 167} 168 169void PandasmProgramDumper::DumpArrayValue(std::ostream &os, const pandasm::ArrayValue &array) const 170{ 171 for (const auto &val : array.GetValues()) { 172 DumpScalarValue(os, val); 173 } 174} 175void PandasmProgramDumper::DumpScalarValue(std::ostream &os, const pandasm::ScalarValue &scalar) const 176{ 177 switch (scalar.GetType()) { 178 case pandasm::Value::Type::U1: 179 case pandasm::Value::Type::I8: 180 case pandasm::Value::Type::U8: 181 case pandasm::Value::Type::I16: 182 case pandasm::Value::Type::U16: 183 case pandasm::Value::Type::I32: 184 case pandasm::Value::Type::U32: 185 case pandasm::Value::Type::I64: 186 case pandasm::Value::Type::U64: 187 case pandasm::Value::Type::STRING_NULLPTR: { 188 os << DUMP_CONTENT_SPACE << scalar.GetValue<uint64_t>(); 189 break; 190 } 191 case pandasm::Value::Type::F32: 192 os << DUMP_CONTENT_SPACE << scalar.GetValue<float>(); 193 break; 194 case pandasm::Value::Type::F64: { 195 os << DUMP_CONTENT_SPACE << scalar.GetValue<double>(); 196 break; 197 } 198 case pandasm::Value::Type::STRING: 199 case pandasm::Value::Type::METHOD: 200 case pandasm::Value::Type::ENUM: 201 case pandasm::Value::Type::LITERALARRAY: { 202 if (!is_normalized_) { 203 os << DUMP_CONTENT_SPACE << scalar.GetValue<std::string>(); 204 } else { 205 auto literal_array_id_name = scalar.GetValue<std::string>(); 206 auto it = program_->literalarray_table.find(literal_array_id_name); 207 ASSERT(it != program_->literalarray_table.end()); 208 auto id = PandasmDumperUtils::GetLiteralArrayIdFromName(literal_array_id_name); 209 os << DUMP_CONTENT_SPACE << SerializeLiteralArray(it->second, id); 210 } 211 break; 212 } 213 case pandasm::Value::Type::RECORD: { 214 pandasm::Type type = scalar.GetValue<pandasm::Type>(); 215 os << DUMP_CONTENT_SPACE << type.GetComponentName() << DUMP_CONTENT_SPACE << type.GetName(); 216 break; 217 } 218 case pandasm::Value::Type::ANNOTATION: { 219 DumpAnnotationData(os, scalar.GetValue<pandasm::AnnotationData>()); 220 break; 221 } 222 default : 223 break; 224 } 225} 226 227void PandasmProgramDumper::DumpRecordSourceFile(std::ostream &os, const pandasm::Record &record) const 228{ 229 os << DUMP_TITLE_RECORD_SOURCE_FILE << record.source_file << DUMP_CONTENT_DOUBLE_ENDL; 230} 231 232void PandasmProgramDumper::DumpFunctionTable(std::ostream &os) 233{ 234 os << DUMP_TITLE_SEPARATOR; 235 os << DUMP_TITLE_METHODS; 236 os << DUMP_CONTENT_DOUBLE_ENDL; 237 for (const auto &it : program_->function_table) { 238 DumpFunction(os, it.second); 239 } 240} 241 242void PandasmProgramDumper::DumpFunction(std::ostream &os, const pandasm::Function &function) 243{ 244 regs_num_ = function.regs_num; 245 DumpFunctionKind(os, function); 246 if (!is_normalized_ || !is_debug_) { 247 DumpFunctionAnnotations(os, function); 248 } 249 DumpFunctionHead(os, function); 250 DumpFunctionBody(os, function); 251} 252 253void PandasmProgramDumper::DumpFunctionKind(std::ostream &os, const pandasm::Function &function) const 254{ 255 os << DUMP_TITLE_FUNCTION_KIND << PandasmDumperUtils::GetFunctionKindString(function.function_kind); 256 os << DUMP_CONTENT_SINGLE_ENDL; 257} 258 259void PandasmProgramDumper::DumpFunctionAnnotations(std::ostream &os, const pandasm::Function &function) const 260{ 261 for (auto &annotation : function.metadata->GetAnnotations()) { 262 DumpAnnotationData(os, annotation); 263 } 264 os << DUMP_CONTENT_SINGLE_ENDL; 265} 266 267void PandasmProgramDumper::DumpFunctionHead(std::ostream &os, const pandasm::Function &function) const 268{ 269 os << DUMP_TITLE_FUNCTION; 270 DumpFunctionReturnType(os, function); 271 DumpFunctionName(os, function); 272 DumpFunctionParams(os, function); 273 os << DUMP_CONTENT_SPACE << DUMP_CONTENT_LEFT_CURLY_BRACKET << DUMP_CONTENT_SINGLE_ENDL; 274} 275 276void PandasmProgramDumper::DumpFunctionReturnType(std::ostream &os, const pandasm::Function &function) const 277{ 278 os << function.return_type.GetPandasmName() << DUMP_CONTENT_SPACE; 279} 280 281void PandasmProgramDumper::DumpFunctionName(std::ostream &os, const pandasm::Function &function) const 282{ 283 os << function.name; 284} 285 286void PandasmProgramDumper::DumpFunctionParams(std::ostream &os, const pandasm::Function &function) const 287{ 288 os << DUMP_CONTENT_LEFT_PARENTHESIS; 289 if (function.params.size() > 0) { 290 DumpFunctionParamAtIndex(os, function.params[0], 0); 291 for (size_t i = 1; i < function.params.size(); ++i) { 292 os << DUMP_CONTENT_COMMA << DUMP_CONTENT_SPACE; 293 DumpFunctionParamAtIndex(os, function.params[i], i); 294 } 295 } 296 os << DUMP_CONTENT_RIGHT_PARENTHESIS; 297} 298 299void PandasmProgramDumper::DumpFunctionParamAtIndex(std::ostream &os, 300 const pandasm::Function::Parameter ¶m, 301 size_t idx) const 302{ 303 os << param.type.GetPandasmName() << DUMP_CONTENT_SPACE << DUMP_CONTENT_FUNCTION_PARAM_NAME_PREFIX << idx; 304} 305 306void PandasmProgramDumper::DumpFunctionAttributes(std::ostream &os, const pandasm::Function &function) const 307{ 308 log::Unimplemented(__PRETTY_FUNCTION__); 309} 310 311void PandasmProgramDumper::DumpFunctionBody(std::ostream &os, const pandasm::Function &function) 312{ 313 DumpFunctionIns(os, function); 314 DumpFunctionCatchBlocks(os, function); 315 DumpFunctionDebugInfo(os, function); 316 os << "}" << DUMP_CONTENT_DOUBLE_ENDL; 317} 318 319void PandasmProgramDumper::DumpFunctionIns(std::ostream &os, const pandasm::Function &function) 320{ 321 if (is_normalized_) { 322 DumpNormalizedFunctionIns(os, function); 323 } else { 324 DumpOriginalFunctionIns(os, function); 325 } 326} 327 328void PandasmProgramDumper::DumpOriginalFunctionIns(std::ostream &os, const pandasm::Function &function) 329{ 330 for (const pandasm::Ins &pa_ins : function.ins) { 331 std::string insStr = pa_ins.ToString("", true, regs_num_); 332 os << DUMP_CONTENT_TAB << std::setw(LINE_WIDTH) 333 << std::left << insStr 334 << DUMP_CONTENT_LINE_NUMBER << pa_ins.ins_debug.line_number; 335 os << std::setw(COLUMN_WIDTH) << std::left << DUMP_CONTENT_SPACE 336 << DUMP_CONTENT_COLUMN_NUMBER << pa_ins.ins_debug.column_number 337 << DUMP_CONTENT_SINGLE_ENDL; 338 } 339} 340 341void PandasmProgramDumper::DumpNormalizedFunctionIns(std::ostream &os, const pandasm::Function &function) 342{ 343 GetOriginalDumpIns(function); 344 GetInvalidOpLabelMap(); 345 UpdateLabels4DumpIns(original_dump_ins_ptrs_, invalid_op_label_map_); 346 GetFinalDumpIns(); 347 GetFinalLabelMap(); 348 UpdateLabels4DumpIns(final_dump_ins_ptrs_, final_label_map_); 349 DumpFinalIns(os); 350} 351 352void PandasmProgramDumper::GetOriginalDumpIns(const pandasm::Function &function) 353{ 354 original_dump_ins_.clear(); 355 original_dump_ins_ptrs_.clear(); 356 original_ins_index_map_.clear(); 357 for (const pandasm::Ins &pa_ins : function.ins) { 358 original_dump_ins_.emplace_back(PandasmDumperUtils::DeepCopyIns(pa_ins)); 359 } 360 uint32_t idx = 0; 361 for (pandasm::Ins &pa_ins : original_dump_ins_) { 362 original_dump_ins_ptrs_.emplace_back(&pa_ins); 363 original_ins_index_map_[&pa_ins] = idx; 364 idx++; 365 } 366} 367 368void PandasmProgramDumper::GetFinalDumpIns() 369{ 370 final_dump_ins_ptrs_.clear(); 371 final_ins_index_map_.clear(); 372 uint32_t idx = 0; 373 for (pandasm::Ins *pa_ins : original_dump_ins_ptrs_) { 374 final_ins_index_map_[pa_ins] = idx; 375 if (pa_ins->opcode != pandasm::Opcode::INVALID) { 376 final_dump_ins_ptrs_.emplace_back(pa_ins); 377 idx++; 378 } 379 } 380} 381 382void PandasmProgramDumper::DumpFinalIns(std::ostream &os) 383{ 384 for (pandasm::Ins *pa_ins : final_dump_ins_ptrs_) { 385 if (PandasmDumperUtils::IsMatchLiteralId(*pa_ins)) { 386 ReplaceLiteralId4Ins(*pa_ins); 387 } 388 std::string insStr = pa_ins->ToString("", true, regs_num_); 389 os << DUMP_CONTENT_TAB << std::setw(LINE_WIDTH) 390 << std::left << insStr 391 << DUMP_CONTENT_LINE_NUMBER << pa_ins->ins_debug.line_number; 392 os << std::setw(COLUMN_WIDTH) << std::left << DUMP_CONTENT_SPACE 393 << DUMP_CONTENT_COLUMN_NUMBER << pa_ins->ins_debug.column_number 394 << DUMP_CONTENT_SINGLE_ENDL; 395 } 396} 397 398void PandasmProgramDumper::GetInvalidOpLabelMap() 399{ 400 invalid_op_label_map_.clear(); 401 size_t dump_ins_size = original_dump_ins_.size(); 402 for (size_t i = 0; i < dump_ins_size; ++i) { 403 pandasm::Ins &curr_ins = original_dump_ins_[i]; 404 if (curr_ins.opcode == pandasm::Opcode::INVALID) { 405 HandleInvalidopInsLabel(i, curr_ins); 406 } 407 } 408} 409 410void PandasmProgramDumper::HandleInvalidopInsLabel(size_t invalid_op_idx, pandasm::Ins &invalid_op_ins) 411{ 412 if (!invalid_op_ins.set_label) { 413 return; 414 } 415 pandasm::Ins *nearest_valid_op_ins = GetNearestValidopIns4InvalidopIns(invalid_op_idx); 416 if (nearest_valid_op_ins == nullptr) { 417 return; 418 } 419 if (!nearest_valid_op_ins->set_label) { 420 // here, the invalid op ins and its nearest valid op ins has the same label 421 // the invalid op will be removed, so the label is still unique for each inst 422 nearest_valid_op_ins->label = invalid_op_ins.label; 423 nearest_valid_op_ins->set_label = true; 424 } 425 invalid_op_label_map_.emplace(invalid_op_ins.label, nearest_valid_op_ins->label); 426} 427 428pandasm::Ins *PandasmProgramDumper::GetNearestValidopIns4InvalidopIns(size_t invalid_op_ins_idx) 429{ 430 size_t dump_ins_size = original_dump_ins_.size(); 431 // search downwards 432 for (size_t i = invalid_op_ins_idx + 1; i < dump_ins_size; ++i) { 433 pandasm::Ins &curr_ins = original_dump_ins_[i]; 434 if (curr_ins.opcode != pandasm::Opcode::INVALID) { 435 return &curr_ins; 436 } 437 } 438 // search upwards 439 for (size_t i = 0; i < invalid_op_ins_idx; ++i) { 440 pandasm::Ins &curr_ins = original_dump_ins_[invalid_op_ins_idx - i - 1]; 441 if (curr_ins.opcode != pandasm::Opcode::INVALID) { 442 return &curr_ins; 443 } 444 } 445 return nullptr; 446} 447 448void PandasmProgramDumper::UpdateLabels4DumpIns(std::vector<pandasm::Ins*> &dump_ins, const LabelMap &label_map) const 449{ 450 size_t dump_ins_size = dump_ins.size(); 451 for (size_t i = 0; i < dump_ins_size; ++i) { 452 UpdateLabels4DumpInsAtIndex(i, dump_ins, label_map); 453 } 454} 455 456void PandasmProgramDumper::UpdateLabels4DumpInsAtIndex(size_t idx, std::vector<pandasm::Ins*> &dump_ins, 457 const LabelMap &label_map) const 458{ 459 pandasm::Ins *curr_ins = dump_ins[idx]; 460 std::string mapped_label = PandasmDumperUtils::GetMappedLabel(curr_ins->label, label_map); 461 if (mapped_label != "") { 462 curr_ins->label = mapped_label; 463 } 464 if (curr_ins->IsJump()) { 465 mapped_label = PandasmDumperUtils::GetMappedLabel(curr_ins->ids[0], label_map); 466 if (mapped_label != "") { 467 curr_ins->ids.clear(); 468 curr_ins->ids.emplace_back(mapped_label); 469 } 470 } 471} 472 473void PandasmProgramDumper::GetFinalLabelMap() 474{ 475 final_label_map_.clear(); 476 size_t dump_ins_size = final_dump_ins_ptrs_.size(); 477 for (size_t i = 0; i < dump_ins_size; ++i) { 478 HandleFinalLabelAtIndex(i); 479 } 480} 481 482void PandasmProgramDumper::HandleFinalLabelAtIndex(size_t idx) 483{ 484 pandasm::Ins *curr_ins = final_dump_ins_ptrs_[idx]; 485 std::string new_label_name = AbcFileUtils::GetLabelNameByInstIdx(idx); 486 if (curr_ins->set_label) { 487 final_label_map_.emplace(curr_ins->label, new_label_name); 488 } else { 489 curr_ins->label = new_label_name; 490 curr_ins->set_label = true; 491 } 492} 493 494void PandasmProgramDumper::DumpFunctionCatchBlocks(std::ostream &os, const pandasm::Function &function) const 495{ 496 if (is_normalized_) { 497 DumpNormalizedFunctionCatchBlocks(os, function); 498 } else { 499 DumpOriginalFunctionCatchBlocks(os, function); 500 } 501} 502 503void PandasmProgramDumper::DumpOriginalFunctionCatchBlocks(std::ostream &os, 504 const pandasm::Function &function) const 505{ 506 for (const pandasm::Function::CatchBlock &catch_block : function.catch_blocks) { 507 DumpCatchBlock(os, catch_block); 508 } 509} 510 511void PandasmProgramDumper::DumpNormalizedFunctionCatchBlocks(std::ostream &os, 512 const pandasm::Function &function) const 513{ 514 std::vector<pandasm::Function::CatchBlock> catch_blocks; 515 for (const pandasm::Function::CatchBlock &catch_block : function.catch_blocks) { 516 catch_blocks.emplace_back(PandasmDumperUtils::DeepCopyCatchBlock(catch_block)); 517 } 518 for (pandasm::Function::CatchBlock &catch_block : catch_blocks) { 519 UpdateCatchBlock(catch_block); 520 } 521 for (const pandasm::Function::CatchBlock &catch_block : catch_blocks) { 522 DumpCatchBlock(os, catch_block); 523 } 524} 525 526void PandasmProgramDumper::UpdateCatchBlock(pandasm::Function::CatchBlock &catch_block) const 527{ 528 catch_block.try_begin_label = GetUpdatedCatchBlockLabel(catch_block.try_begin_label); 529 catch_block.try_end_label = GetUpdatedCatchBlockLabel(catch_block.try_end_label); 530 catch_block.catch_begin_label = GetUpdatedCatchBlockLabel(catch_block.catch_begin_label); 531 catch_block.catch_end_label = GetUpdatedCatchBlockLabel(catch_block.catch_end_label); 532} 533 534std::string PandasmProgramDumper::GetUpdatedCatchBlockLabel(const std::string &orignal_label) const 535{ 536 std::string mapped_label1 = PandasmDumperUtils::GetMappedLabel(orignal_label, invalid_op_label_map_); 537 if (mapped_label1 == "") { 538 return orignal_label; 539 } 540 std::string mapped_label2 = PandasmDumperUtils::GetMappedLabel(mapped_label1, final_label_map_); 541 if (mapped_label2 == "") { 542 return mapped_label1; 543 } 544 return mapped_label2; 545} 546 547void PandasmProgramDumper::DumpCatchBlock(std::ostream &os, const pandasm::Function::CatchBlock &catch_block) const 548{ 549 if (catch_block.exception_record.empty()) { 550 os << DUMP_TITLE_CATCH_ALL << DUMP_CONTENT_SINGLE_ENDL; 551 } else { 552 os << DUMP_TITLE_CATCH << DUMP_CONTENT_SINGLE_ENDL; 553 } 554 os << DUMP_CONTENT_TAB << DUMP_CONTENT_TRY_BEGIN_LABEL 555 << catch_block.try_begin_label << DUMP_CONTENT_SINGLE_ENDL; 556 os << DUMP_CONTENT_TAB << DUMP_CONTENT_TRY_END_LABEL 557 << catch_block.try_end_label << DUMP_CONTENT_SINGLE_ENDL; 558 os << DUMP_CONTENT_TAB << DUMP_CONTENT_CATCH_BEGIN_LABEL 559 << catch_block.catch_begin_label << DUMP_CONTENT_SINGLE_ENDL; 560 if (!is_normalized_) { 561 os << DUMP_CONTENT_TAB << DUMP_CONTENT_CATCH_END_LABEL 562 << catch_block.catch_end_label << DUMP_CONTENT_SINGLE_ENDL; 563 } 564} 565 566void PandasmProgramDumper::DumpFunctionDebugInfo(std::ostream &os, const pandasm::Function &function) 567{ 568 if (function.local_variable_debug.empty()) { 569 return; 570 } 571 std::map<int32_t, panda::pandasm::debuginfo::LocalVariable> local_variable_table; 572 if (is_normalized_) { 573 UpdateLocalVarMap(function, local_variable_table); 574 } else { 575 for (const auto &variable_info : function.local_variable_debug) { 576 local_variable_table[variable_info.reg] = variable_info; 577 } 578 } 579 580 os << DUMP_CONTENT_SINGLE_ENDL; 581 if (local_variable_table.empty()) { 582 return; 583 } 584 585 os << DUMP_TITLE_LOCAL_VAR_TABLE; 586 os << DUMP_CONTENT_SINGLE_ENDL; 587 os << DUMP_CONTENT_LOCAL_VAR_TABLE; 588 for (const auto &iter : local_variable_table) { 589 const auto &variable_info = iter.second; 590 os << DUMP_CONTENT_TAB 591 << std::setw(START_WIDTH) << std::right << variable_info.start << DUMP_CONTENT_TRIPLE_SPACES; 592 os << std::setw(END_WIDTH) << std::right << variable_info.length << DUMP_CONTENT_DOUBLE_SPACES; 593 os << std::setw(REG_WIDTH) << std::right << variable_info.reg << DUMP_CONTENT_DOUBLE_SPACES; 594 os << std::setw(NAME_WIDTH) 595 << std::right << variable_info.name << DUMP_CONTENT_NONUPLE_SPACES << variable_info.signature; 596 if (!variable_info.signature_type.empty() && variable_info.signature_type != variable_info.signature) { 597 os << " (" << variable_info.signature_type << ")"; 598 } 599 os << DUMP_CONTENT_SINGLE_ENDL; 600 } 601} 602 603void PandasmProgramDumper::UpdateLocalVarMap(const pandasm::Function &function, 604 std::map<int32_t, panda::pandasm::debuginfo::LocalVariable>& local_variable_table) 605{ 606 std::unordered_map<uint32_t, uint32_t> original_to_final_index_map_; 607 uint32_t max_original_idx = 0; 608 uint32_t max_final_idx = 0; 609 for (const auto &[key, value] : original_ins_index_map_) { 610 uint32_t final_idx = final_ins_index_map_[key]; 611 original_to_final_index_map_[value] = final_idx; 612 if (value > max_original_idx) { 613 max_original_idx = value; 614 max_final_idx = final_idx; 615 } 616 } 617 original_to_final_index_map_[max_original_idx + 1] = max_final_idx; 618 619 for (const auto &variable_info : function.local_variable_debug) { 620 uint32_t original_start = variable_info.start; 621 uint32_t original_end = variable_info.length + variable_info.start; 622 uint32_t new_start = original_to_final_index_map_[original_start]; 623 uint32_t new_length = original_to_final_index_map_[original_end] - new_start; 624 panda::pandasm::debuginfo::LocalVariable local_var = {variable_info.name, 625 variable_info.signature, 626 variable_info.signature_type, 627 variable_info.reg, 628 new_start, 629 new_length}; 630 local_variable_table[variable_info.reg] = local_var; 631 } 632} 633 634void PandasmProgramDumper::DumpStrings(std::ostream &os) const 635{ 636 if (is_normalized_) { 637 return; 638 } 639 os << DUMP_TITLE_SEPARATOR; 640 os << DUMP_TITLE_STRING; 641 for (const std::string &str : program_->strings) { 642 os << str << DUMP_CONTENT_SINGLE_ENDL; 643 } 644} 645 646void PandasmProgramDumper::ReplaceLiteralId4Ins(pandasm::Ins &pa_ins) const 647{ 648 size_t idx = PandasmDumperUtils::GetLiteralIdIndex4Ins(pa_ins); 649 std::string id_str = pa_ins.ids[idx]; 650 auto it = program_->literalarray_table.find(id_str); 651 ASSERT(it != program_->literalarray_table.end()); 652 const pandasm::LiteralArray &literal_array = it->second; 653 auto id = PandasmDumperUtils::GetLiteralArrayIdFromName(it->first); 654 std::string replaced_value = SerializeLiteralArray(literal_array, id); 655 pa_ins.ids[idx] = replaced_value; 656} 657 658std::string PandasmProgramDumper::SerializeLiteralArray(const pandasm::LiteralArray &lit_array, uint32_t id) const 659{ 660 if (lit_array.literals_.empty()) { 661 return ""; 662 } 663 std::stringstream ss; 664 ss << DUMP_CONTENT_LEFT_CURLY_BRACKET << DUMP_CONTENT_SPACE; 665 ss << lit_array.literals_.size(); 666 ss << DUMP_CONTENT_SPACE << DUMP_CONTENT_LEFT_SQUARE_BRACKET << DUMP_CONTENT_SPACE; 667 processing_literal_array_id_set_.emplace(id); 668 SerializeLiterals(lit_array, ss); 669 processing_literal_array_id_set_.erase(id); 670 ss << DUMP_CONTENT_RIGHT_SQUARE_BRACKET << DUMP_CONTENT_RIGHT_CURLY_BRACKET; 671 return ss.str(); 672} 673 674void PandasmProgramDumper::SerializeLiterals(const pandasm::LiteralArray &lit_array, std::stringstream &os) const 675{ 676 for (size_t i = 0; i < lit_array.literals_.size(); i++) { 677 SerializeLiteralsAtIndex(lit_array, os, i); 678 os << DUMP_CONTENT_COMMA << DUMP_CONTENT_SPACE; 679 } 680} 681 682void PandasmProgramDumper::SerializeLiteralsAtIndex( 683 const pandasm::LiteralArray &lit_array, std::stringstream &os, size_t i) const 684{ 685 const panda_file::LiteralTag &tag = lit_array.literals_[i].tag_; 686 os << PandasmDumperUtils::LiteralTagToString(tag) << DUMP_CONTENT_COLON; 687 const auto &val = lit_array.literals_[i].value_; 688 switch (tag) { 689 case panda_file::LiteralTag::BOOL: 690 os << (std::get<bool>(val)); 691 break; 692 case panda_file::LiteralTag::LITERALBUFFERINDEX: 693 case panda_file::LiteralTag::INTEGER: 694 os << (bit_cast<int32_t>(std::get<uint32_t>(val))); 695 break; 696 case panda_file::LiteralTag::DOUBLE: 697 os << (std::get<double>(val)); 698 break; 699 case panda_file::LiteralTag::STRING: 700 os << "\"" << (std::get<std::string>(val)) << "\""; 701 break; 702 case panda_file::LiteralTag::METHOD: 703 case panda_file::LiteralTag::GETTER: 704 case panda_file::LiteralTag::SETTER: 705 case panda_file::LiteralTag::GENERATORMETHOD: 706 case panda_file::LiteralTag::ASYNCGENERATORMETHOD: 707 os << (std::get<std::string>(val)); 708 break; 709 case panda_file::LiteralTag::NULLVALUE: 710 case panda_file::LiteralTag::ACCESSOR: 711 os << (static_cast<int16_t>(bit_cast<int8_t>(std::get<uint8_t>(val)))); 712 break; 713 case panda_file::LiteralTag::METHODAFFILIATE: 714 os << (std::get<uint16_t>(val)); 715 break; 716 case panda_file::LiteralTag::LITERALARRAY: 717 SerializeNestedLiteralArrayById(os, std::get<std::string>(val)); 718 break; 719 case panda_file::LiteralTag::BUILTINTYPEINDEX: 720 os << (static_cast<int16_t>(std::get<uint8_t>(val))); 721 break; 722 case panda_file::LiteralTag::TAGVALUE: 723 os << (static_cast<int16_t>(std::get<uint8_t>(val))); 724 break; 725 default: 726 UNREACHABLE(); 727 } 728} 729 730void PandasmProgramDumper::SerializeNestedLiteralArrayById( 731 std::stringstream &os, const std::string &literal_array_id_name) const 732{ 733 if (!is_normalized_) { 734 os << literal_array_id_name; 735 return; 736 } 737 auto id = PandasmDumperUtils::GetLiteralArrayIdFromName(literal_array_id_name); 738 if (processing_literal_array_id_set_.find(id) == processing_literal_array_id_set_.end()) { 739 auto it = program_->literalarray_table.find(literal_array_id_name); 740 ASSERT(it != program_->literalarray_table.end()); 741 os << SerializeLiteralArray(it->second, id); 742 } else { 743 UNREACHABLE(); 744 } 745} 746 747} // namespace panda::abc2program 748