arkcompiler_runtime_core/abc2program/program_dump.cpp
lixiaoyan 22f0155d08 Fix dump result comparison failed case
Description:
1. Change behavior of normalized program dump to make sure the normalized dump result of abc file compilation is same as that of source code compilation

Issue: IAFLC2
Test: test262, ark standalone build, runtime core ut

Signed-off-by: l00680486 <litengfei26@huawei.com>
Change-Id: If2fed38382e365333ef0879b701df08140088187
2024-08-22 17:45:43 +08:00

748 lines
27 KiB
C++

/*
* 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"
#include "dump_utils.h"
#include "os/file.h"
namespace panda::abc2program {
void PandasmProgramDumper::Dump(std::ostream &os, const pandasm::Program &program)
{
program_ = &program;
os << std::flush;
DumpAbcFilePath(os);
DumpProgramLanguage(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::DumpProgramLanguage(std::ostream &os) const
{
os << DUMP_TITLE_LANGUAGE;
if (program_->lang == panda::panda_file::SourceLang::ECMASCRIPT) {
os << DUMP_CONTENT_ECMASCRIPT;
} else {
os << DUMP_CONTENT_PANDA_ASSEMBLY;
}
os << DUMP_CONTENT_DOUBLE_ENDL;
}
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<std::string> 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
{
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<uint64_t>();
break;
}
case pandasm::Value::Type::F32:
os << DUMP_CONTENT_SPACE << scalar.GetValue<float>();
break;
case pandasm::Value::Type::F64: {
os << DUMP_CONTENT_SPACE << scalar.GetValue<double>();
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<std::string>();
} else {
auto literal_array_id_name = scalar.GetValue<std::string>();
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<pandasm::Type>();
os << DUMP_CONTENT_SPACE << type.GetComponentName() << DUMP_CONTENT_SPACE << type.GetName();
break;
}
case pandasm::Value::Type::ANNOTATION: {
DumpAnnotationData(os, scalar.GetValue<pandasm::AnnotationData>());
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);
}
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 &param,
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<pandasm::Ins*> &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<pandasm::Ins*> &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<pandasm::Function::CatchBlock> 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<int32_t, panda::pandasm::debuginfo::LocalVariable> 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<int32_t, panda::pandasm::debuginfo::LocalVariable>& local_variable_table)
{
std::unordered_map<uint32_t, uint32_t> 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<bool>(val));
break;
case panda_file::LiteralTag::LITERALBUFFERINDEX:
case panda_file::LiteralTag::INTEGER:
os << (bit_cast<int32_t>(std::get<uint32_t>(val)));
break;
case panda_file::LiteralTag::DOUBLE:
os << (std::get<double>(val));
break;
case panda_file::LiteralTag::STRING:
os << "\"" << (std::get<std::string>(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<std::string>(val));
break;
case panda_file::LiteralTag::NULLVALUE:
case panda_file::LiteralTag::ACCESSOR:
os << (static_cast<int16_t>(bit_cast<int8_t>(std::get<uint8_t>(val))));
break;
case panda_file::LiteralTag::METHODAFFILIATE:
os << (std::get<uint16_t>(val));
break;
case panda_file::LiteralTag::LITERALARRAY:
SerializeNestedLiteralArrayById(os, std::get<std::string>(val));
break;
case panda_file::LiteralTag::BUILTINTYPEINDEX:
os << (static_cast<int16_t>(std::get<uint8_t>(val)));
break;
case panda_file::LiteralTag::TAGVALUE:
os << (static_cast<int16_t>(std::get<uint8_t>(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