MethodBlock* MethodBlock::if_test(DexOpcode if_op, Location first, Location second) { always_assert(OPCODE_IF_EQ <= if_op && if_op <= OPCODE_IF_LE); DexInstruction* op = new DexInstruction(if_op); op->set_src(0, reg_num(first)); op->set_src(1, reg_num(second)); return make_if_block(op); }
void MethodBlock::binop_2addr(DexOpcode op, const Location& dest, const Location& src) { always_assert(OPCODE_ADD_INT_2ADDR <= op && op <= OPCODE_REM_DOUBLE_2ADDR); always_assert(dest.type == src.type); DexInstruction* insn = new DexInstruction(op); insn->set_src(0, reg_num(dest)); insn->set_src(1, reg_num(src)); push_instruction(insn); }
MethodBlock* MethodBlock::if_else_testz(DexOpcode if_op, Location test, MethodBlock** true_block) { always_assert(OPCODE_IF_EQZ <= if_op && if_op <= OPCODE_IF_LEZ); DexInstruction* op = new DexInstruction(if_op); op->set_src(0, reg_num(test)); return make_if_else_block(op, true_block); }
void MethodBlock::move(Location src, Location& dst) { always_assert(src.is_compatible(dst.type)); auto ch = type_shorty(dst.type); assert(ch != 'V'); DexOpcode opcode; if (ch == 'L') opcode = OPCODE_MOVE_OBJECT; else if (ch == 'J' || ch == 'D') opcode = OPCODE_MOVE_WIDE; else opcode = OPCODE_MOVE; DexInstruction* move = new DexInstruction(opcode); move->set_dest(reg_num(dst)); move->set_src(0, reg_num(src)); dst.type = src.type; push_instruction(move); }
std::unique_ptr<DexCode>& MethodCreator::to_code() { std::unique_ptr<DexCode> code(new DexCode()); code->set_registers_size(top_reg); code->set_ins_size(ins_count()); code->set_outs_size(out_count); method->set_code(std::move(code)); for (auto& mi : *meth_code->m_fmethod) { if (mi.type == MFLOW_OPCODE) { DexInstruction* insn = mi.insn; if (insn->dests_size()) { insn->set_dest(get_real_reg_num(insn->dest())); } for (int i = 0; i < static_cast<int>(insn->srcs_size()); i++) { insn->set_src(i, get_real_reg_num(insn->src(i))); } } } while (!meth_code->try_sync()) ; return method->get_code(); }