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