• 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    pandasm::Ins ins{};
26
27    ins.opcode = BytecodeOpcodeToPandasmOpcode(bc_ins.GetOpcode());
28
29    const BytecodeInstruction::Format format = bc_ins.GetFormat();
30
31    switch (bc_ins.GetOpcode()) {
32% Panda::instructions.each do |i|
33%   imm_count = 0
34%   reg_count = 0
35%   id_count = 0
36        case BytecodeInstruction::Opcode::<%= i.opcode.upcase %>:
37%
38%   i.operands.each do |operand|
39%     if operand.imm?
40%       if operand.is_float_imm?
41            ins.imms.push_back(bit_cast<double>(bc_ins.GetImm<BytecodeInstruction::Format::<%=i.format.pretty.upcase%>, <%=imm_count%>, true>()));
42%       elsif operand.is_signed_imm?
43            ins.imms.push_back(static_cast<int64_t>(bc_ins.GetImm<BytecodeInstruction::Format::<%=i.format.pretty.upcase%>, <%=imm_count%>, true>()));
44%       elsif operand.is_unsigned_imm?
45            ins.imms.push_back(static_cast<int64_t>(bc_ins.GetImm<BytecodeInstruction::Format::<%=i.format.pretty.upcase%>, <%=imm_count%>, false>()));
46%       else
47%            raise "Incorrect imm type #{operand.type}"
48%       end
49%         imm_count += 1
50%
51%     elsif operand.reg?
52            ins.regs.push_back(bc_ins.GetVReg(<%=reg_count%>));
53%         reg_count += 1
54%     elsif operand.id?
55            ins.ids.push_back(IDToString(bc_ins, method_id, <%=id_count%>));
56%         id_count += 1
57%     end
58%   end
59            break;
60% end
61        default:
62            break;
63    }
64
65    if (ins.IsCall()) {
66        // clearing excessive arguments if there are any
67        // if format has ID in it - receive it. else instruction is indirect call and id = method_id
68        panda_file::File::EntityId id;
69
70        if (bc_ins.HasId(format, 0)) {
71            auto idx = bc_ins.GetId().AsIndex();
72            id = file_.ResolveMethodIndex(method_id, idx);
73        } else {
74            id = method_id;
75        }
76
77        panda_file::MethodDataAccessor mda(file_, id);
78        panda_file::ProtoDataAccessor pda(file_, mda.GetProtoId());
79
80        int overhead;
81
82        if (mda.IsStatic()) {
83            overhead = ins.regs.size() - pda.GetNumArgs();
84        } else {
85            overhead = ins.regs.size() - pda.GetNumArgs() - 1;
86        }
87        if (overhead < 0 || overhead > static_cast<int>(ins.regs.size())) {
88            LOG(ERROR, ABC2PROGRAM)
89                << "> error encountered in code of " << std::dec << method_id.GetOffset() << " ("
90                << "0x" << std::hex << method_id.GetOffset() << ") while disassembling call <" << ins.ToString("")
91                << ">. Invalid method id given or corrupted: calculated overhead (difference "
92                   "between amount of registers specified by instruction format and amount of function's arguments) "
93                   "exceeds number of registers specified in ISA or is lesser than 0!";
94            return ins;
95        }
96
97        for (int i = 0; i < overhead; i++) {
98            ins.regs.pop_back();
99        }
100    }
101
102    return ins;
103}
104
105}  // namespace panda::abc2program
106