mirror of
https://gitee.com/openharmony/arkcompiler_runtime_core
synced 2024-11-23 14:50:51 +00:00
22f0155d08
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
748 lines
27 KiB
C++
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 ¶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<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
|