ah 536154a11b Fix codecheck warnings of the master branch in runtime _core
Signed-off-by: ah <liangahui@h-partners.com>
2024-05-30 16:21:44 +08:00

244 lines
7.5 KiB
C++

/**
* Copyright (c) 2021-2022 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.
*/
#ifndef ASSEMBLER_ASSEMBLY_INS_H
#define ASSEMBLER_ASSEMBLY_INS_H
#include <array>
#include <string>
#include <string_view>
#include <unordered_map>
#include <variant>
#include <vector>
#include "assembly-debug.h"
#include "bytecode_emitter.h"
#include "file_items.h"
#include "isa.h"
#include "lexer.h"
namespace panda::pandasm {
enum class Opcode {
#define OPLIST(opcode, name, optype, width, flags, def_idx, use_idxs) opcode,
PANDA_INSTRUCTION_LIST(OPLIST)
#undef OPLIST
INVALID,
NUM_OPCODES = INVALID
};
enum InstFlags {
NONE = 0,
JUMP = (1U << 0U),
COND = (1U << 1U),
CALL = (1U << 2U),
RETURN = (1U << 3U),
ACC_READ = (1U << 4U),
ACC_WRITE = (1U << 5U),
PSEUDO = (1U << 6U),
THROWING = (1U << 7U),
METHOD_ID = (1U << 8U),
FIELD_ID = (1U << 9U),
TYPE_ID = (1U << 10U),
STRING_ID = (1U << 11U),
LITERALARRAY_ID = (1U << 12U),
CALL_RANGE = (1U << 13U)
};
constexpr int INVALID_REG_IDX = -1;
constexpr size_t MAX_NUMBER_OF_SRC_REGS = 4; // TODO(mbolshov): auto-generate
constexpr InstFlags operator|(InstFlags a, InstFlags b)
{
using utype = std::underlying_type_t<InstFlags>;
return static_cast<InstFlags>(static_cast<utype>(a) | static_cast<utype>(b));
}
#define OPLIST(opcode, name, optype, width, flags, def_idx, use_idxs) flags,
constexpr std::array<unsigned, static_cast<size_t>(Opcode::NUM_OPCODES)> INST_FLAGS_TABLE = {
PANDA_INSTRUCTION_LIST(OPLIST)};
#undef OPLIST
#define OPLIST(opcode, name, optype, width, flags, def_idx, use_idxs) width,
constexpr std::array<size_t, static_cast<size_t>(Opcode::NUM_OPCODES)> INST_WIDTH_TABLE = {
PANDA_INSTRUCTION_LIST(OPLIST)};
#undef OPLIST
#define OPLIST(opcode, name, optype, width, flags, def_idx, use_idxs) def_idx,
constexpr std::array<int, static_cast<size_t>(Opcode::NUM_OPCODES)> DEF_IDX_TABLE = {PANDA_INSTRUCTION_LIST(OPLIST)};
#undef OPLIST
#define OPLIST(opcode, name, optype, width, flags, def_idx, use_idxs) use_idxs,
// clang-format off
constexpr std::array<std::array<int, MAX_NUMBER_OF_SRC_REGS>,
static_cast<size_t>(Opcode::NUM_OPCODES)> USE_IDXS_TABLE = {PANDA_INSTRUCTION_LIST(OPLIST)};
// clang-format on
#undef OPLIST
struct Ins {
using IType = std::variant<int64_t, double>;
constexpr static uint16_t ACCUMULATOR = -1;
constexpr static size_t MAX_CALL_SHORT_ARGS = 2;
constexpr static size_t MAX_CALL_ARGS = 4;
constexpr static uint16_t MAX_NON_RANGE_CALL_REG = 15;
constexpr static uint16_t MAX_RANGE_CALL_START_REG = 255;
Opcode opcode = Opcode::INVALID; /* operation type */
std::vector<uint16_t> regs; /* list of arguments - registers */
std::vector<std::string> ids; /* list of arguments - identifiers */
std::vector<IType> imms; /* list of arguments - immediates */
std::string label; /* label at the beginning of a line */
bool set_label = false; /* whether this label is defined */
debuginfo::Ins ins_debug;
std::string ToString(std::string endline = "", bool print_args = false, size_t first_arg_idx = 0) const;
bool Emit(BytecodeEmitter &emitter, panda_file::MethodItem *method,
const std::unordered_map<std::string, panda_file::BaseMethodItem *> &methods,
const std::unordered_map<std::string, panda_file::BaseFieldItem *> &fields,
const std::unordered_map<std::string, panda_file::BaseClassItem *> &classes,
const std::unordered_map<std::string, panda_file::StringItem *> &strings,
const std::unordered_map<std::string, panda_file::LiteralArrayItem *> &literalarrays,
const std::unordered_map<std::string_view, panda::Label> &labels) const;
size_t OperandListLength() const
{
return regs.size() + ids.size() + imms.size();
}
bool HasFlag(InstFlags flag) const
{
if (opcode == Opcode::INVALID) { // TODO(mbolshov): introduce 'label' opcode for labels
return false;
}
return (INST_FLAGS_TABLE[static_cast<size_t>(opcode)] & flag) != 0;
}
bool CanThrow() const
{
return HasFlag(InstFlags::THROWING) || HasFlag(InstFlags::METHOD_ID) || HasFlag(InstFlags::FIELD_ID) ||
HasFlag(InstFlags::TYPE_ID) || HasFlag(InstFlags::STRING_ID);
}
bool IsJump() const
{
return HasFlag(InstFlags::JUMP);
}
bool IsConditionalJump() const
{
return IsJump() && HasFlag(InstFlags::COND);
}
bool IsCall() const
{ // Non-range call
return HasFlag(InstFlags::CALL);
}
bool IsCallRange() const
{ // Range call
return HasFlag(InstFlags::CALL_RANGE);
}
bool IsPseudoCall() const
{
return HasFlag(InstFlags::PSEUDO) && HasFlag(InstFlags::CALL);
}
bool IsReturn() const
{
return HasFlag(InstFlags::RETURN);
}
size_t MaxRegEncodingWidth() const
{
if (opcode == Opcode::INVALID) {
return 0;
}
return INST_WIDTH_TABLE[static_cast<size_t>(opcode)];
}
std::vector<uint16_t> Uses() const
{
if (IsPseudoCall()) {
return regs;
}
if (opcode == Opcode::INVALID) {
return {};
}
auto use_idxs = USE_IDXS_TABLE[static_cast<size_t>(opcode)];
std::vector<uint16_t> res(MAX_NUMBER_OF_SRC_REGS + 1);
if (HasFlag(InstFlags::ACC_READ)) {
res.push_back(Ins::ACCUMULATOR);
}
for (auto idx : use_idxs) {
if (idx == INVALID_REG_IDX) {
break;
}
ASSERT(static_cast<size_t>(idx) < regs.size());
res.emplace_back(regs[idx]);
}
return res;
}
std::optional<size_t> Def() const
{
if (opcode == Opcode::INVALID) {
return {};
}
auto def_idx = DEF_IDX_TABLE[static_cast<size_t>(opcode)];
if (def_idx != INVALID_REG_IDX) {
return regs[def_idx];
}
if (HasFlag(InstFlags::ACC_WRITE)) {
return Ins::ACCUMULATOR;
}
return {};
}
bool IsValidToEmit() const
{
const auto INVALID_REG_NUM = 1U << MaxRegEncodingWidth();
for (auto reg : regs) {
if (reg >= INVALID_REG_NUM) {
return false;
}
}
return true;
}
bool HasDebugInfo() const
{
return ins_debug.line_number != 0;
}
private:
std::string OperandsToString(bool print_args = false, size_t first_arg_idx = 0) const;
std::string RegsToString(bool &first, bool print_args = false, size_t first_arg_idx = 0) const;
std::string ImmsToString(bool &first) const;
std::string IdsToString(bool &first) const;
std::string IdToString(size_t idx, bool is_first) const;
std::string ImmToString(size_t idx, bool is_first) const;
std::string RegToString(size_t idx, bool is_first, bool print_args = false, size_t first_arg_idx = 0) const;
};
} // namespace panda::pandasm
#endif // ASSEMBLER_ASSEMBLY_INS_H