* Copyright (c) 2026 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 "disassembler.h"
#include "utils/logger.h"
namespace panda::disasm {
void Disassembler::DumpLiteralArrayByOffset(uint32_t offset, std::stringstream &ss,
std::unordered_set<uint32_t> &visiting) const
{
if (!visiting.insert(offset).second) {
LOG(ERROR, DISASSEMBLER) << "> recursive literal array reference at 0x" << std::hex << offset;
ss << "\"<recursive literal array 0x" << std::hex << offset << ">\"";
return;
}
pandasm::LiteralArray lit_array;
GetLiteralArrayByOffset(&lit_array, panda_file::File::EntityId(offset));
DumpLiteralArrayContent(lit_array, ss, visiting);
visiting.erase(offset);
}
void Disassembler::DumpLiteralArrayContent(const pandasm::LiteralArray &literal_array, std::stringstream &ss,
std::unordered_set<uint32_t> &visiting) const
{
ss << "[";
bool firstItem = true;
for (const auto &item : literal_array.literals_) {
if (!firstItem) {
ss << ", ";
} else {
firstItem = false;
}
switch (item.tag_) {
case panda_file::LiteralTag::DOUBLE: {
ss << std::get<double>(item.value_);
break;
}
case panda_file::LiteralTag::BOOL: {
ss << std::get<bool>(item.value_);
break;
}
case panda_file::LiteralTag::STRING: {
ss << "\"" << std::get<std::string>(item.value_) << "\"";
break;
}
case panda_file::LiteralTag::LITERALARRAY: {
std::string offsetStr = std::get<std::string>(item.value_);
uint32_t litArrayOffset = std::stoi(offsetStr, nullptr, 16);
DumpLiteralArrayByOffset(litArrayOffset, ss, visiting);
break;
}
case panda_file::LiteralTag::BUILTINTYPEINDEX: {
break;
}
default: {
UNREACHABLE();
break;
}
}
}
ss << "]";
}
void Disassembler::DumpLiteralArray(const pandasm::LiteralArray &literal_array, std::stringstream &ss) const
{
std::unordered_set<uint32_t> visiting;
DumpLiteralArrayContent(literal_array, ss, visiting);
}
std::string Disassembler::getLiteralArrayTypeByOffset(uint32_t offset, std::unordered_set<uint32_t> &visiting) const
{
if (!visiting.insert(offset).second) {
LOG(ERROR, DISASSEMBLER) << "> recursive literal array type reference at 0x" << std::hex << offset;
return "any[]";
}
pandasm::LiteralArray lit_array;
GetLiteralArrayByOffset(&lit_array, panda_file::File::EntityId(offset));
auto result = getLiteralArrayTypeContent(lit_array, visiting);
visiting.erase(offset);
return result;
}
std::string Disassembler::getLiteralArrayTypeContent(const pandasm::LiteralArray &literal_array,
std::unordered_set<uint32_t> &visiting) const
{
[[maybe_unused]] auto size = literal_array.literals_.size();
ASSERT(size > 0);
switch (literal_array.literals_[0].tag_) {
case panda_file::LiteralTag::DOUBLE: {
return "f64[]";
}
case panda_file::LiteralTag::BOOL: {
return "u1[]";
}
case panda_file::LiteralTag::STRING: {
return "panda.String[]";
}
case panda_file::LiteralTag::LITERALARRAY: {
std::string offsetStr = std::get<std::string>(literal_array.literals_[0].value_);
uint32_t litArrayOffset = std::stoi(offsetStr, nullptr, 16);
return getLiteralArrayTypeByOffset(litArrayOffset, visiting) + "[]";
}
case panda_file::LiteralTag::BUILTINTYPEINDEX: {
uint8_t typeIndex = std::get<uint8_t>(literal_array.literals_[0].value_);
static constexpr uint8_t emptyLiteralArrayWithNumberType = 0;
static constexpr uint8_t emptyLiteralArrayWithBooleanType = 1;
static constexpr uint8_t emptyLiteralArrayWithStringType = 2;
switch (typeIndex) {
case emptyLiteralArrayWithNumberType:
return "f64[]";
case emptyLiteralArrayWithBooleanType:
return "u1[]";
case emptyLiteralArrayWithStringType:
return "panda.String[]";
default:
UNREACHABLE();
break;
}
}
default: {
UNREACHABLE();
break;
}
}
}
std::string Disassembler::getLiteralArrayTypeFromValue(const pandasm::LiteralArray &literal_array) const
{
std::unordered_set<uint32_t> visiting;
return getLiteralArrayTypeContent(literal_array, visiting);
}
}