/* * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "program_dump.h" #include "abc2program_log.h" #include "common/abc_file_utils.h" namespace panda::abc2program { void PandasmProgramDumper::Dump(std::ostream &os, const pandasm::Program &program) { program_ = &program; os << std::flush; DumpAbcFilePath(os); DumpLiteralArrayTable(os); DumpRecordTable(os); DumpFunctionTable(os); DumpStrings(os); } void PandasmProgramDumper::SetAbcFilePath(const std::string &abc_file_path) { abc_file_path_ = abc_file_path; } void PandasmProgramDumper::DumpAbcFilePath(std::ostream &os) const { if (abc_file_path_.empty()) { return; } std::string file_abs_path = os::file::File::GetAbsolutePath(abc_file_path_).Value(); os << DUMP_TITLE_SOURCE_BINARY << file_abs_path << DUMP_CONTENT_DOUBLE_ENDL; } void PandasmProgramDumper::DumpLanguage(std::ostream &os, const panda::panda_file::SourceLang lang) const { os << DUMP_TITLE_LANGUAGE; if (lang == panda::panda_file::SourceLang::ECMASCRIPT) { os << DUMP_CONTENT_ECMASCRIPT; } else if (lang == panda::panda_file::SourceLang::JAVASCRIPT) { os << DUMP_CONTENT_JAVASCRIPT; } else if (lang == panda::panda_file::SourceLang::TYPESCRIPT) { os << DUMP_CONTENT_TYPESCRIPT; } else if (lang == panda::panda_file::SourceLang::ARKTS) { os << DUMP_CONTENT_ARKTS; } else { os << DUMP_CONTENT_PANDA_ASSEMBLY; } os << DUMP_CONTENT_SINGLE_ENDL; } void PandasmProgramDumper::DumpProgramLanguage(std::ostream &os) const { DumpLanguage(os, program_->lang); } void PandasmProgramDumper::DumpRecordLanguage(std::ostream &os, const pandasm::Record &record) const { DumpLanguage(os, record.language); } void PandasmProgramDumper::DumpFunctionLanguage(std::ostream &os, const pandasm::Function &function) const { DumpLanguage(os, function.language); } void PandasmProgramDumper::DumpLiteralArrayTable(std::ostream &os) const { os << DUMP_TITLE_SEPARATOR; os << DUMP_TITLE_LITERALS; os << DUMP_CONTENT_DOUBLE_ENDL; auto it = program_->literalarray_table.begin(); auto end = program_->literalarray_table.end(); // In normalized mode, sort dump result of literal arrays before output. if (is_normalized_) { std::vector literal_arrays; for (; it != end; ++it) { auto id = PandasmDumperUtils::GetLiteralArrayIdFromName(it->first); auto lit_arr = SerializeLiteralArray(it->second, id); lit_arr += DUMP_CONTENT_DOUBLE_ENDL; literal_arrays.emplace_back(lit_arr); } std::sort(literal_arrays.begin(), literal_arrays.end()); for (auto &str : literal_arrays) { os << str; } } else { for (; it != end; ++it) { os << it->first << DUMP_CONTENT_SPACE; auto id = PandasmDumperUtils::GetLiteralArrayIdFromName(it->first); os << SerializeLiteralArray(it->second, id); os << DUMP_CONTENT_DOUBLE_ENDL; } } os << DUMP_CONTENT_DOUBLE_ENDL; } void PandasmProgramDumper::DumpRecordTable(std::ostream &os) const { os << DUMP_TITLE_SEPARATOR; os << DUMP_TITLE_RECORDS; os << DUMP_CONTENT_DOUBLE_ENDL; for (const auto &it : program_->record_table) { if (is_normalized_ && is_debug_ && it.first == SLOT_NUMBER_RECORD_NAME) { continue; } DumpRecord(os, it.second); } os << DUMP_CONTENT_SINGLE_ENDL; } void PandasmProgramDumper::DumpRecord(std::ostream &os, const pandasm::Record &record) const { DumpRecordLanguage(os, record); if (is_normalized_) { if (AbcFileUtils::IsGlobalTypeName(record.name)) { return; } if (AbcFileUtils::IsESTypeAnnotationName(record.name)) { return; } } os << DUMP_TITLE_RECORD << record.name; if (DumpRecordMetaData(os, record)) { DumpFieldList(os, record); } DumpRecordSourceFile(os, record); } bool PandasmProgramDumper::DumpRecordMetaData(std::ostream &os, const pandasm::Record &record) const { if (record.metadata->IsForeign()) { os << DUMP_CONTENT_SPACE << DUMP_CONTENT_ATTR_EXTERNAL; os << DUMP_CONTENT_SINGLE_ENDL; return false; } return true; } void PandasmProgramDumper::DumpFieldList(std::ostream &os, const pandasm::Record &record) const { os << DUMP_CONTENT_SPACE << DUMP_CONTENT_LEFT_CURLY_BRACKET << DUMP_CONTENT_SINGLE_ENDL; for (const auto &it : record.field_list) { DumpField(os, it); } os << DUMP_CONTENT_RIGHT_CURLY_BRACKET << DUMP_CONTENT_SINGLE_ENDL; } void PandasmProgramDumper::DumpField(std::ostream &os, const pandasm::Field &field) const { os << DUMP_CONTENT_TAB << field.type.GetPandasmName() << DUMP_CONTENT_SPACE << field.name; DumpFieldMetaData(os, field); os << DUMP_CONTENT_SINGLE_ENDL; } void PandasmProgramDumper::DumpFieldMetaData(std::ostream &os, const pandasm::Field &field) const { if (field.metadata->GetValue()) { DumpScalarValue(os, *(field.metadata->GetValue())); } } void PandasmProgramDumper::DumpAnnotationData(std::ostream &os, const pandasm::AnnotationData &anno) const { os << DUMP_CONTENT_SPACE << anno.GetName() << DUMP_CONTENT_SINGLE_ENDL; for (const auto &element : anno.GetElements()) { os << DUMP_CONTENT_SPACE << element.GetName(); if (element.GetValue()->IsArray()) { DumpArrayValue(os, *(element.GetValue()->GetAsArray())); } else { DumpScalarValue(os, *(element.GetValue()->GetAsScalar())); } } } void PandasmProgramDumper::DumpArrayValue(std::ostream &os, const pandasm::ArrayValue &array) const { for (const auto &val : array.GetValues()) { DumpScalarValue(os, val); } } void PandasmProgramDumper::DumpScalarValue(std::ostream &os, const pandasm::ScalarValue &scalar) const { switch (scalar.GetType()) { case pandasm::Value::Type::U1: case pandasm::Value::Type::I8: case pandasm::Value::Type::U8: case pandasm::Value::Type::I16: case pandasm::Value::Type::U16: case pandasm::Value::Type::I32: case pandasm::Value::Type::U32: case pandasm::Value::Type::I64: case pandasm::Value::Type::U64: case pandasm::Value::Type::STRING_NULLPTR: { os << DUMP_CONTENT_SPACE << scalar.GetValue(); break; } case pandasm::Value::Type::F32: os << DUMP_CONTENT_SPACE << scalar.GetValue(); break; case pandasm::Value::Type::F64: { os << DUMP_CONTENT_SPACE << scalar.GetValue(); break; } case pandasm::Value::Type::STRING: case pandasm::Value::Type::METHOD: case pandasm::Value::Type::ENUM: case pandasm::Value::Type::LITERALARRAY: { if (!is_normalized_) { os << DUMP_CONTENT_SPACE << scalar.GetValue(); } else { auto literal_array_id_name = scalar.GetValue(); auto it = program_->literalarray_table.find(literal_array_id_name); ASSERT(it != program_->literalarray_table.end()); auto id = PandasmDumperUtils::GetLiteralArrayIdFromName(literal_array_id_name); os << DUMP_CONTENT_SPACE << SerializeLiteralArray(it->second, id); } break; } case pandasm::Value::Type::RECORD: { pandasm::Type type = scalar.GetValue(); os << DUMP_CONTENT_SPACE << type.GetComponentName() << DUMP_CONTENT_SPACE << type.GetName(); break; } case pandasm::Value::Type::ANNOTATION: { DumpAnnotationData(os, scalar.GetValue()); break; } default : break; } } void PandasmProgramDumper::DumpRecordSourceFile(std::ostream &os, const pandasm::Record &record) const { os << DUMP_TITLE_RECORD_SOURCE_FILE << record.source_file << DUMP_CONTENT_DOUBLE_ENDL; } void PandasmProgramDumper::DumpFunctionTable(std::ostream &os) { os << DUMP_TITLE_SEPARATOR; os << DUMP_TITLE_METHODS; os << DUMP_CONTENT_DOUBLE_ENDL; for (const auto &it : program_->function_table) { DumpFunction(os, it.second); } } void PandasmProgramDumper::DumpFunction(std::ostream &os, const pandasm::Function &function) { regs_num_ = function.regs_num; DumpFunctionKind(os, function); if (!is_normalized_ || !is_debug_) { DumpFunctionAnnotations(os, function); } DumpFunctionLanguage(os, function); DumpFunctionHead(os, function); DumpFunctionBody(os, function); } void PandasmProgramDumper::DumpFunctionKind(std::ostream &os, const pandasm::Function &function) const { os << DUMP_TITLE_FUNCTION_KIND << PandasmDumperUtils::GetFunctionKindString(function.function_kind); os << DUMP_CONTENT_SINGLE_ENDL; } void PandasmProgramDumper::DumpFunctionAnnotations(std::ostream &os, const pandasm::Function &function) const { for (auto &annotation : function.metadata->GetAnnotations()) { DumpAnnotationData(os, annotation); os << DUMP_CONTENT_SINGLE_ENDL; } } void PandasmProgramDumper::DumpFunctionHead(std::ostream &os, const pandasm::Function &function) const { os << DUMP_TITLE_FUNCTION; DumpFunctionReturnType(os, function); DumpFunctionName(os, function); DumpFunctionParams(os, function); os << DUMP_CONTENT_SPACE << DUMP_CONTENT_LEFT_CURLY_BRACKET << DUMP_CONTENT_SINGLE_ENDL; } void PandasmProgramDumper::DumpFunctionReturnType(std::ostream &os, const pandasm::Function &function) const { os << function.return_type.GetPandasmName() << DUMP_CONTENT_SPACE; } void PandasmProgramDumper::DumpFunctionName(std::ostream &os, const pandasm::Function &function) const { os << function.name; } void PandasmProgramDumper::DumpFunctionParams(std::ostream &os, const pandasm::Function &function) const { os << DUMP_CONTENT_LEFT_PARENTHESIS; if (function.params.size() > 0) { DumpFunctionParamAtIndex(os, function.params[0], 0); for (size_t i = 1; i < function.params.size(); ++i) { os << DUMP_CONTENT_COMMA << DUMP_CONTENT_SPACE; DumpFunctionParamAtIndex(os, function.params[i], i); } } os << DUMP_CONTENT_RIGHT_PARENTHESIS; } void PandasmProgramDumper::DumpFunctionParamAtIndex(std::ostream &os, const pandasm::Function::Parameter ¶m, size_t idx) const { os << param.type.GetPandasmName() << DUMP_CONTENT_SPACE << DUMP_CONTENT_FUNCTION_PARAM_NAME_PREFIX << idx; } void PandasmProgramDumper::DumpFunctionAttributes(std::ostream &os, const pandasm::Function &function) const { log::Unimplemented(__PRETTY_FUNCTION__); } void PandasmProgramDumper::DumpFunctionBody(std::ostream &os, const pandasm::Function &function) { DumpFunctionIns(os, function); DumpFunctionCatchBlocks(os, function); DumpFunctionDebugInfo(os, function); os << "}" << DUMP_CONTENT_DOUBLE_ENDL; } void PandasmProgramDumper::DumpFunctionIns(std::ostream &os, const pandasm::Function &function) { if (is_normalized_) { DumpNormalizedFunctionIns(os, function); } else { DumpOriginalFunctionIns(os, function); } } void PandasmProgramDumper::DumpOriginalFunctionIns(std::ostream &os, const pandasm::Function &function) { for (const pandasm::Ins &pa_ins : function.ins) { std::string insStr = pa_ins.ToString("", true, regs_num_); os << DUMP_CONTENT_TAB << std::setw(LINE_WIDTH) << std::left << insStr << DUMP_CONTENT_LINE_NUMBER << pa_ins.ins_debug.line_number; os << std::setw(COLUMN_WIDTH) << std::left << DUMP_CONTENT_SPACE << DUMP_CONTENT_COLUMN_NUMBER << pa_ins.ins_debug.column_number << DUMP_CONTENT_SINGLE_ENDL; } } void PandasmProgramDumper::DumpNormalizedFunctionIns(std::ostream &os, const pandasm::Function &function) { GetOriginalDumpIns(function); GetInvalidOpLabelMap(); UpdateLabels4DumpIns(original_dump_ins_ptrs_, invalid_op_label_map_); GetFinalDumpIns(); GetFinalLabelMap(); UpdateLabels4DumpIns(final_dump_ins_ptrs_, final_label_map_); DumpFinalIns(os); } void PandasmProgramDumper::GetOriginalDumpIns(const pandasm::Function &function) { original_dump_ins_.clear(); original_dump_ins_ptrs_.clear(); original_ins_index_map_.clear(); for (const pandasm::Ins &pa_ins : function.ins) { original_dump_ins_.emplace_back(PandasmDumperUtils::DeepCopyIns(pa_ins)); } uint32_t idx = 0; for (pandasm::Ins &pa_ins : original_dump_ins_) { original_dump_ins_ptrs_.emplace_back(&pa_ins); original_ins_index_map_[&pa_ins] = idx; idx++; } } void PandasmProgramDumper::GetFinalDumpIns() { final_dump_ins_ptrs_.clear(); final_ins_index_map_.clear(); uint32_t idx = 0; for (pandasm::Ins *pa_ins : original_dump_ins_ptrs_) { final_ins_index_map_[pa_ins] = idx; if (pa_ins->opcode != pandasm::Opcode::INVALID) { final_dump_ins_ptrs_.emplace_back(pa_ins); idx++; } } } void PandasmProgramDumper::DumpFinalIns(std::ostream &os) { for (pandasm::Ins *pa_ins : final_dump_ins_ptrs_) { if (PandasmDumperUtils::IsMatchLiteralId(*pa_ins)) { ReplaceLiteralId4Ins(*pa_ins); } std::string insStr = pa_ins->ToString("", true, regs_num_); os << DUMP_CONTENT_TAB << std::setw(LINE_WIDTH) << std::left << insStr << DUMP_CONTENT_LINE_NUMBER << pa_ins->ins_debug.line_number; os << std::setw(COLUMN_WIDTH) << std::left << DUMP_CONTENT_SPACE << DUMP_CONTENT_COLUMN_NUMBER << pa_ins->ins_debug.column_number << DUMP_CONTENT_SINGLE_ENDL; } } void PandasmProgramDumper::GetInvalidOpLabelMap() { invalid_op_label_map_.clear(); size_t dump_ins_size = original_dump_ins_.size(); for (size_t i = 0; i < dump_ins_size; ++i) { pandasm::Ins &curr_ins = original_dump_ins_[i]; if (curr_ins.opcode == pandasm::Opcode::INVALID) { HandleInvalidopInsLabel(i, curr_ins); } } } void PandasmProgramDumper::HandleInvalidopInsLabel(size_t invalid_op_idx, pandasm::Ins &invalid_op_ins) { if (!invalid_op_ins.set_label) { return; } pandasm::Ins *nearest_valid_op_ins = GetNearestValidopIns4InvalidopIns(invalid_op_idx); if (nearest_valid_op_ins == nullptr) { return; } if (!nearest_valid_op_ins->set_label) { // here, the invalid op ins and its nearest valid op ins has the same label // the invalid op will be removed, so the label is still unique for each inst nearest_valid_op_ins->label = invalid_op_ins.label; nearest_valid_op_ins->set_label = true; } invalid_op_label_map_.emplace(invalid_op_ins.label, nearest_valid_op_ins->label); } pandasm::Ins *PandasmProgramDumper::GetNearestValidopIns4InvalidopIns(size_t invalid_op_ins_idx) { size_t dump_ins_size = original_dump_ins_.size(); // search downwards for (size_t i = invalid_op_ins_idx + 1; i < dump_ins_size; ++i) { pandasm::Ins &curr_ins = original_dump_ins_[i]; if (curr_ins.opcode != pandasm::Opcode::INVALID) { return &curr_ins; } } // search upwards for (size_t i = 0; i < invalid_op_ins_idx; ++i) { pandasm::Ins &curr_ins = original_dump_ins_[invalid_op_ins_idx - i - 1]; if (curr_ins.opcode != pandasm::Opcode::INVALID) { return &curr_ins; } } return nullptr; } void PandasmProgramDumper::UpdateLabels4DumpIns(std::vector &dump_ins, const LabelMap &label_map) const { size_t dump_ins_size = dump_ins.size(); for (size_t i = 0; i < dump_ins_size; ++i) { UpdateLabels4DumpInsAtIndex(i, dump_ins, label_map); } } void PandasmProgramDumper::UpdateLabels4DumpInsAtIndex(size_t idx, std::vector &dump_ins, const LabelMap &label_map) const { pandasm::Ins *curr_ins = dump_ins[idx]; std::string mapped_label = PandasmDumperUtils::GetMappedLabel(curr_ins->label, label_map); if (mapped_label != "") { curr_ins->label = mapped_label; } if (curr_ins->IsJump()) { mapped_label = PandasmDumperUtils::GetMappedLabel(curr_ins->ids[0], label_map); if (mapped_label != "") { curr_ins->ids.clear(); curr_ins->ids.emplace_back(mapped_label); } } } void PandasmProgramDumper::GetFinalLabelMap() { final_label_map_.clear(); size_t dump_ins_size = final_dump_ins_ptrs_.size(); for (size_t i = 0; i < dump_ins_size; ++i) { HandleFinalLabelAtIndex(i); } } void PandasmProgramDumper::HandleFinalLabelAtIndex(size_t idx) { pandasm::Ins *curr_ins = final_dump_ins_ptrs_[idx]; std::string new_label_name = AbcFileUtils::GetLabelNameByInstIdx(idx); if (curr_ins->set_label) { final_label_map_.emplace(curr_ins->label, new_label_name); } else { curr_ins->label = new_label_name; curr_ins->set_label = true; } } void PandasmProgramDumper::DumpFunctionCatchBlocks(std::ostream &os, const pandasm::Function &function) const { if (is_normalized_) { DumpNormalizedFunctionCatchBlocks(os, function); } else { DumpOriginalFunctionCatchBlocks(os, function); } } void PandasmProgramDumper::DumpOriginalFunctionCatchBlocks(std::ostream &os, const pandasm::Function &function) const { for (const pandasm::Function::CatchBlock &catch_block : function.catch_blocks) { DumpCatchBlock(os, catch_block); } } void PandasmProgramDumper::DumpNormalizedFunctionCatchBlocks(std::ostream &os, const pandasm::Function &function) const { std::vector catch_blocks; for (const pandasm::Function::CatchBlock &catch_block : function.catch_blocks) { catch_blocks.emplace_back(PandasmDumperUtils::DeepCopyCatchBlock(catch_block)); } for (pandasm::Function::CatchBlock &catch_block : catch_blocks) { UpdateCatchBlock(catch_block); } for (const pandasm::Function::CatchBlock &catch_block : catch_blocks) { DumpCatchBlock(os, catch_block); } } void PandasmProgramDumper::UpdateCatchBlock(pandasm::Function::CatchBlock &catch_block) const { catch_block.try_begin_label = GetUpdatedCatchBlockLabel(catch_block.try_begin_label); catch_block.try_end_label = GetUpdatedCatchBlockLabel(catch_block.try_end_label); catch_block.catch_begin_label = GetUpdatedCatchBlockLabel(catch_block.catch_begin_label); catch_block.catch_end_label = GetUpdatedCatchBlockLabel(catch_block.catch_end_label); } std::string PandasmProgramDumper::GetUpdatedCatchBlockLabel(const std::string &orignal_label) const { std::string mapped_label1 = PandasmDumperUtils::GetMappedLabel(orignal_label, invalid_op_label_map_); if (mapped_label1 == "") { return orignal_label; } std::string mapped_label2 = PandasmDumperUtils::GetMappedLabel(mapped_label1, final_label_map_); if (mapped_label2 == "") { return mapped_label1; } return mapped_label2; } void PandasmProgramDumper::DumpCatchBlock(std::ostream &os, const pandasm::Function::CatchBlock &catch_block) const { if (catch_block.exception_record.empty()) { os << DUMP_TITLE_CATCH_ALL << DUMP_CONTENT_SINGLE_ENDL; } else { os << DUMP_TITLE_CATCH << DUMP_CONTENT_SINGLE_ENDL; } os << DUMP_CONTENT_TAB << DUMP_CONTENT_TRY_BEGIN_LABEL << catch_block.try_begin_label << DUMP_CONTENT_SINGLE_ENDL; os << DUMP_CONTENT_TAB << DUMP_CONTENT_TRY_END_LABEL << catch_block.try_end_label << DUMP_CONTENT_SINGLE_ENDL; os << DUMP_CONTENT_TAB << DUMP_CONTENT_CATCH_BEGIN_LABEL << catch_block.catch_begin_label << DUMP_CONTENT_SINGLE_ENDL; if (!is_normalized_) { os << DUMP_CONTENT_TAB << DUMP_CONTENT_CATCH_END_LABEL << catch_block.catch_end_label << DUMP_CONTENT_SINGLE_ENDL; } } void PandasmProgramDumper::DumpFunctionDebugInfo(std::ostream &os, const pandasm::Function &function) { if (function.local_variable_debug.empty()) { return; } std::map local_variable_table; if (is_normalized_) { UpdateLocalVarMap(function, local_variable_table); } else { for (const auto &variable_info : function.local_variable_debug) { local_variable_table[variable_info.reg] = variable_info; } } os << DUMP_CONTENT_SINGLE_ENDL; if (local_variable_table.empty()) { return; } os << DUMP_TITLE_LOCAL_VAR_TABLE; os << DUMP_CONTENT_SINGLE_ENDL; os << DUMP_CONTENT_LOCAL_VAR_TABLE; for (const auto &iter : local_variable_table) { const auto &variable_info = iter.second; os << DUMP_CONTENT_TAB << std::setw(START_WIDTH) << std::right << variable_info.start << DUMP_CONTENT_TRIPLE_SPACES; os << std::setw(END_WIDTH) << std::right << variable_info.length << DUMP_CONTENT_DOUBLE_SPACES; os << std::setw(REG_WIDTH) << std::right << variable_info.reg << DUMP_CONTENT_DOUBLE_SPACES; os << std::setw(NAME_WIDTH) << std::right << variable_info.name << DUMP_CONTENT_NONUPLE_SPACES << variable_info.signature; if (!variable_info.signature_type.empty() && variable_info.signature_type != variable_info.signature) { os << " (" << variable_info.signature_type << ")"; } os << DUMP_CONTENT_SINGLE_ENDL; } } void PandasmProgramDumper::UpdateLocalVarMap(const pandasm::Function &function, std::map& local_variable_table) { std::unordered_map original_to_final_index_map_; uint32_t max_original_idx = 0; uint32_t max_final_idx = 0; for (const auto &[key, value] : original_ins_index_map_) { uint32_t final_idx = final_ins_index_map_[key]; original_to_final_index_map_[value] = final_idx; if (value > max_original_idx) { max_original_idx = value; max_final_idx = final_idx; } } original_to_final_index_map_[max_original_idx + 1] = max_final_idx; for (const auto &variable_info : function.local_variable_debug) { uint32_t original_start = variable_info.start; uint32_t original_end = variable_info.length + variable_info.start; uint32_t new_start = original_to_final_index_map_[original_start]; uint32_t new_length = original_to_final_index_map_[original_end] - new_start; panda::pandasm::debuginfo::LocalVariable local_var = {variable_info.name, variable_info.signature, variable_info.signature_type, variable_info.reg, new_start, new_length}; local_variable_table[variable_info.reg] = local_var; } } void PandasmProgramDumper::DumpStrings(std::ostream &os) const { if (is_normalized_) { return; } os << DUMP_TITLE_SEPARATOR; os << DUMP_TITLE_STRING; for (const std::string &str : program_->strings) { os << str << DUMP_CONTENT_SINGLE_ENDL; } } void PandasmProgramDumper::ReplaceLiteralId4Ins(pandasm::Ins &pa_ins) const { size_t idx = PandasmDumperUtils::GetLiteralIdIndex4Ins(pa_ins); std::string id_str = pa_ins.ids[idx]; auto it = program_->literalarray_table.find(id_str); ASSERT(it != program_->literalarray_table.end()); const pandasm::LiteralArray &literal_array = it->second; auto id = PandasmDumperUtils::GetLiteralArrayIdFromName(it->first); std::string replaced_value = SerializeLiteralArray(literal_array, id); pa_ins.ids[idx] = replaced_value; } std::string PandasmProgramDumper::SerializeLiteralArray(const pandasm::LiteralArray &lit_array, uint32_t id) const { if (lit_array.literals_.empty()) { return ""; } std::stringstream ss; ss << DUMP_CONTENT_LEFT_CURLY_BRACKET << DUMP_CONTENT_SPACE; ss << lit_array.literals_.size(); ss << DUMP_CONTENT_SPACE << DUMP_CONTENT_LEFT_SQUARE_BRACKET << DUMP_CONTENT_SPACE; processing_literal_array_id_set_.emplace(id); SerializeLiterals(lit_array, ss); processing_literal_array_id_set_.erase(id); ss << DUMP_CONTENT_RIGHT_SQUARE_BRACKET << DUMP_CONTENT_RIGHT_CURLY_BRACKET; return ss.str(); } void PandasmProgramDumper::SerializeLiterals(const pandasm::LiteralArray &lit_array, std::stringstream &os) const { for (size_t i = 0; i < lit_array.literals_.size(); i++) { SerializeLiteralsAtIndex(lit_array, os, i); os << DUMP_CONTENT_COMMA << DUMP_CONTENT_SPACE; } } void PandasmProgramDumper::SerializeLiteralsAtIndex( const pandasm::LiteralArray &lit_array, std::stringstream &os, size_t i) const { const panda_file::LiteralTag &tag = lit_array.literals_[i].tag_; os << PandasmDumperUtils::LiteralTagToString(tag) << DUMP_CONTENT_COLON; const auto &val = lit_array.literals_[i].value_; switch (tag) { case panda_file::LiteralTag::BOOL: os << (std::get(val)); break; case panda_file::LiteralTag::LITERALBUFFERINDEX: case panda_file::LiteralTag::INTEGER: os << (bit_cast(std::get(val))); break; case panda_file::LiteralTag::DOUBLE: os << (std::get(val)); break; case panda_file::LiteralTag::STRING: os << "\"" << (std::get(val)) << "\""; break; case panda_file::LiteralTag::METHOD: case panda_file::LiteralTag::GETTER: case panda_file::LiteralTag::SETTER: case panda_file::LiteralTag::GENERATORMETHOD: case panda_file::LiteralTag::ASYNCGENERATORMETHOD: os << (std::get(val)); break; case panda_file::LiteralTag::NULLVALUE: case panda_file::LiteralTag::ACCESSOR: os << (static_cast(bit_cast(std::get(val)))); break; case panda_file::LiteralTag::METHODAFFILIATE: os << (std::get(val)); break; case panda_file::LiteralTag::LITERALARRAY: SerializeNestedLiteralArrayById(os, std::get(val)); break; case panda_file::LiteralTag::BUILTINTYPEINDEX: os << (static_cast(std::get(val))); break; case panda_file::LiteralTag::TAGVALUE: os << (static_cast(std::get(val))); break; default: UNREACHABLE(); } } void PandasmProgramDumper::SerializeNestedLiteralArrayById( std::stringstream &os, const std::string &literal_array_id_name) const { if (!is_normalized_) { os << literal_array_id_name; return; } auto id = PandasmDumperUtils::GetLiteralArrayIdFromName(literal_array_id_name); if (processing_literal_array_id_set_.find(id) == processing_literal_array_id_set_.end()) { auto it = program_->literalarray_table.find(literal_array_id_name); ASSERT(it != program_->literalarray_table.end()); os << SerializeLiteralArray(it->second, id); } else { UNREACHABLE(); } } } // namespace panda::abc2program