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