/* * 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 "common/abc_code_converter.h" #include "proto_data_accessor-inl.h" #include "method_data_accessor-inl.h" namespace panda::abc2program { pandasm::Ins *AbcCodeConverter::BytecodeInstructionToPandasmInstruction(BytecodeInstruction bc_ins, panda_file::File::EntityId method_id) const { auto opcode = BytecodeOpcodeToPandasmOpcode(bc_ins.GetOpcode()); std::vector regs; std::vector imms; std::vector ids; const BytecodeInstruction::Format format = bc_ins.GetFormat(); switch (bc_ins.GetOpcode()) { % Panda::instructions.each do |i| % imm_count = 0 % reg_count = 0 % id_count = 0 case BytecodeInstruction::Opcode::<%= i.opcode.upcase %>: % % i.operands.each do |operand| % if operand.imm? % if i.jump? ids.push_back(std::to_string(static_cast(bc_ins.GetImm, <%=imm_count%>, true>()))); % elsif operand.is_float_imm? imms.push_back(bit_cast(bc_ins.GetImm, <%=imm_count%>, true>())); % elsif operand.is_signed_imm? imms.push_back(static_cast(bc_ins.GetImm, <%=imm_count%>, true>())); % elsif operand.is_unsigned_imm? imms.push_back(static_cast(bc_ins.GetImm, <%=imm_count%>, false>())); % else % raise "Incorrect imm type #{operand.type}" % end % imm_count += 1 % % elsif operand.reg? regs.push_back(bc_ins.GetVReg(<%=reg_count%>)); % reg_count += 1 % elsif operand.id? ids.push_back(IDToString(bc_ins, method_id, <%=id_count%>)); % id_count += 1 % end % end break; % end default: break; } if ((pandasm::INST_FLAGS_TABLE[static_cast(opcode)] & pandasm::InstFlags::CALL) != 0) { // clearing excessive arguments if there are any // if format has ID in it - receive it. else instruction is indirect call and id = method_id panda_file::File::EntityId id; if (bc_ins.HasId(format, 0)) { auto idx = bc_ins.GetId().AsIndex(); id = file_.ResolveMethodIndex(method_id, idx); } else { id = method_id; } panda_file::MethodDataAccessor mda(file_, id); panda_file::ProtoDataAccessor pda(file_, mda.GetProtoId()); int overhead; if (mda.IsStatic()) { overhead = regs.size() - pda.GetNumArgs(); } else { overhead = regs.size() - pda.GetNumArgs() - 1; } if (overhead < 0 || overhead > static_cast(regs.size())) { auto *ins = pandasm::Ins::CreateIns(opcode, regs, imms, ids); LOG(ERROR, ABC2PROGRAM) << "> error encountered in code of " << std::dec << method_id.GetOffset() << " (" << "0x" << std::hex << method_id.GetOffset() << ") while disassembling call <" << ins->ToString("") << ">. Invalid method id given or corrupted: calculated overhead (difference " "between amount of registers specified by instruction format and amount of function's arguments) " "exceeds number of registers specified in ISA or is lesser than 0!"; delete ins; return nullptr; } for (int i = 0; i < overhead; i++) { regs.pop_back(); } } return pandasm::Ins::CreateIns(opcode, regs, imms, ids); } } // namespace panda::abc2program