• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "common/abc_code_converter.h"
17#include "proto_data_accessor-inl.h"
18#include "method_data_accessor-inl.h"
19
20namespace panda::abc2program {
21
22pandasm::Ins *AbcCodeConverter::BytecodeInstructionToPandasmInstruction(BytecodeInstruction bc_ins,
23                                                                       panda_file::File::EntityId method_id) const
24{
25    auto opcode = BytecodeOpcodeToPandasmOpcode(bc_ins.GetOpcode());
26    std::vector<uint16_t> regs;
27    std::vector<pandasm::IType> imms;
28    std::vector<std::string> ids;
29
30    const BytecodeInstruction::Format format = bc_ins.GetFormat();
31
32    switch (bc_ins.GetOpcode()) {
33% Panda::instructions.each do |i|
34%   imm_count = 0
35%   reg_count = 0
36%   id_count = 0
37        case BytecodeInstruction::Opcode::<%= i.opcode.upcase %>:
38%
39%   i.operands.each do |operand|
40%     if operand.imm?
41%       if i.jump?
42            ids.push_back(std::to_string(static_cast<int32_t>(bc_ins.GetImm<BytecodeInstruction::Format::<%=i.format.pretty.upcase%>, <%=imm_count%>, true>())));
43%       elsif operand.is_float_imm?
44            imms.push_back(bit_cast<double>(bc_ins.GetImm<BytecodeInstruction::Format::<%=i.format.pretty.upcase%>, <%=imm_count%>, true>()));
45%       elsif operand.is_signed_imm?
46            imms.push_back(static_cast<int64_t>(bc_ins.GetImm<BytecodeInstruction::Format::<%=i.format.pretty.upcase%>, <%=imm_count%>, true>()));
47%       elsif operand.is_unsigned_imm?
48            imms.push_back(static_cast<int64_t>(bc_ins.GetImm<BytecodeInstruction::Format::<%=i.format.pretty.upcase%>, <%=imm_count%>, false>()));
49%       else
50%            raise "Incorrect imm type #{operand.type}"
51%       end
52%         imm_count += 1
53%
54%     elsif operand.reg?
55            regs.push_back(bc_ins.GetVReg(<%=reg_count%>));
56%         reg_count += 1
57%     elsif operand.id?
58            ids.push_back(IDToString(bc_ins, method_id, <%=id_count%>));
59%         id_count += 1
60%     end
61%   end
62            break;
63% end
64        default:
65            break;
66    }
67
68    if ((pandasm::INST_FLAGS_TABLE[static_cast<size_t>(opcode)] & pandasm::InstFlags::CALL) != 0) {
69        // clearing excessive arguments if there are any
70        // if format has ID in it - receive it. else instruction is indirect call and id = method_id
71        panda_file::File::EntityId id;
72
73        if (bc_ins.HasId(format, 0)) {
74            auto idx = bc_ins.GetId().AsIndex();
75            id = file_.ResolveMethodIndex(method_id, idx);
76        } else {
77            id = method_id;
78        }
79
80        panda_file::MethodDataAccessor mda(file_, id);
81        panda_file::ProtoDataAccessor pda(file_, mda.GetProtoId());
82
83        int overhead;
84
85        if (mda.IsStatic()) {
86            overhead = regs.size() - pda.GetNumArgs();
87        } else {
88            overhead = regs.size() - pda.GetNumArgs() - 1;
89        }
90        if (overhead < 0 || overhead > static_cast<int>(regs.size())) {
91            auto *ins = pandasm::Ins::CreateIns(opcode, regs, imms, ids);
92            LOG(ERROR, ABC2PROGRAM)
93                << "> error encountered in code of " << std::dec << method_id.GetOffset() << " ("
94                << "0x" << std::hex << method_id.GetOffset() << ") while disassembling call <" << ins->ToString("")
95                << ">. Invalid method id given or corrupted: calculated overhead (difference "
96                   "between amount of registers specified by instruction format and amount of function's arguments) "
97                   "exceeds number of registers specified in ISA or is lesser than 0!";
98            delete ins;
99            return nullptr;
100        }
101
102        for (int i = 0; i < overhead; i++) {
103            regs.pop_back();
104        }
105    }
106
107    return pandasm::Ins::CreateIns(opcode, regs, imms, ids);
108}
109
110}  // namespace panda::abc2program
111