libredex/InstructionLowering.cpp
/*
 * Checks that the load-param opcodes are consistent with the method prototype.
 */
Checks that the load-param opcodes are consistent with the method prototype.
Checks that the load - param opcodes are consistent with the method prototype .
void check_load_params(DexMethod* method) {
  auto* code = method->get_code();
  auto params = code->get_param_instructions();
  auto param_ops = InstructionIterable(params);
  if (param_ops.empty()) {
    return;
  }
  auto* args_list = method->get_proto()->get_args();
  auto it = param_ops.begin();
  auto end = param_ops.end();
  reg_t next_ins = it->insn->dest();
  if (!is_static(method)) {
    auto op = it->insn->opcode();
    always_assert(op == IOPCODE_LOAD_PARAM_OBJECT);
    it.reset(code->erase(it.unwrap()));
    ++next_ins;
  }
  auto args_it = args_list->begin();
  for (; it != end; ++it) {
    auto op = it->insn->opcode();
    always_assert(next_ins == it->insn->dest());
    always_assert(args_it != args_list->end());
    auto expected_op = opcode::load_opcode(*args_it);
    always_assert(op == expected_op);
    ++args_it;
    next_ins += it->insn->dest_is_wide() ? 2 : 1;
  }
  always_assert(args_it == args_list->end());
  for (auto& mie : InstructionIterable(code)) {
    auto insn = mie.insn;
    if (insn->has_dest()) {
      always_assert_log(insn->dest() < next_ins,
                        "Instruction %s refers to a register (v%u) >= size (%u)"
                        "in method %s\n",
                        SHOW(insn),
                        insn->dest(),
                        next_ins,
                        SHOW(method));
    }
    for (size_t i = 0; i < insn->srcs_size(); ++i) {
      always_assert_log(insn->src(i) < next_ins,
                        "Instruction %s refers to a register (v%u) >= size (%u)"
                        "in method %s\n",
                        SHOW(insn),
                        insn->src(i),
                        next_ins,
                        SHOW(method));
    }
  }
}
void check_load_params ( DexMethod * method ) { auto * code = method -> get_code ( ) ; auto params = code -> get_param_instructions ( ) ; auto param_ops = InstructionIterable ( params ) ; if ( param_ops . empty ( ) ) { return ; } auto * args_list = method -> get_proto ( ) -> get_args ( ) ; auto it = param_ops . begin ( ) ; auto end = param_ops . end ( ) ; reg_t next_ins = it -> insn -> dest ( ) ; if ( ! is_static ( method ) ) { auto op = it -> insn -> opcode ( ) ; always_assert ( op == IOPCODE_LOAD_PARAM_OBJECT ) ; it . reset ( code -> erase ( it . unwrap ( ) ) ) ; ++ next_ins ; } auto args_it = args_list -> begin ( ) ; for ( ; it != end ; ++ it ) { auto op = it -> insn -> opcode ( ) ; always_assert ( next_ins == it -> insn -> dest ( ) ) ; always_assert ( args_it != args_list -> end ( ) ) ; auto expected_op = opcode :: load_opcode ( * args_it ) ; always_assert ( op == expected_op ) ; ++ args_it ; next_ins += it -> insn -> dest_is_wide ( ) ? 2 : 1 ; } always_assert ( args_it == args_list -> end ( ) ) ; for ( auto & mie : InstructionIterable ( code ) ) { auto insn = mie . insn ; if ( insn -> has_dest ( ) ) { always_assert_log ( insn -> dest ( ) < next_ins , " " " \n " , SHOW ( insn ) , insn -> dest ( ) , next_ins , SHOW ( method ) ) ; } for ( size_t i = 0 ; i < insn -> srcs_size ( ) ; ++ i ) { always_assert_log ( insn -> src ( i ) < next_ins , " " " \n " , SHOW ( insn ) , insn -> src ( i ) , next_ins , SHOW ( method ) ) ; } } }
Checks that the load-param opcodes are consistent with the method prototype.
Checks that the load - param opcodes are consistent with the method prototype .
// check that the param registers are contiguous // TODO: have load param opcodes store the actual type of the param and // check that they match the method prototype here // check that the params are at the end of the frame