void MethodBlock::iget(DexField* field, Location obj, Location& dst) { always_assert(field->is_concrete() && !(field->get_access() & ACC_STATIC)); DexOpcode opcode; char t = type_shorty(field->get_type()); switch (t) { case 'Z': opcode = OPCODE_IGET_BOOLEAN; break; case 'B': opcode = OPCODE_IGET_BYTE; break; case 'S': opcode = OPCODE_IGET_SHORT; break; case 'C': opcode = OPCODE_IGET_CHAR; break; case 'I': case 'F': opcode = OPCODE_IGET; break; case 'J': case 'D': opcode = OPCODE_IGET_WIDE; break; case 'L': case '[': opcode = OPCODE_IGET_OBJECT; break; default: always_assert(false); break; } ifield_op(opcode, field, obj, dst); }
void MethodBlock::sput(DexField* field, Location src) { always_assert(field->is_concrete() && is_static(field)); IROpcode opcode; char t = type_shorty(field->get_type()); switch (t) { case 'Z': opcode = OPCODE_SPUT_BOOLEAN; break; case 'B': opcode = OPCODE_SPUT_BYTE; break; case 'S': opcode = OPCODE_SPUT_SHORT; break; case 'C': opcode = OPCODE_SPUT_CHAR; break; case 'I': case 'F': opcode = OPCODE_SPUT; break; case 'J': case 'D': opcode = OPCODE_SPUT_WIDE; break; case 'L': case '[': opcode = OPCODE_SPUT_OBJECT; break; default: always_assert(false); break; } sfield_op(opcode, field, src); }
void MethodBlock::ret(Location loc) { auto ch = type_shorty(loc.type); assert(ch != 'V'); DexOpcode opcode; if (ch == 'L') opcode = OPCODE_RETURN_OBJECT; else if (ch == 'J' || ch == 'D') opcode = OPCODE_RETURN_WIDE; else opcode = OPCODE_RETURN; auto ret = new DexInstruction(opcode); ret->set_src(0, reg_num(loc)); push_instruction(ret); }
std::vector<DexField*> create_merger_fields( const DexType* owner, const std::vector<DexField*>& mergeable_fields) { std::vector<DexField*> res; size_t cnt = 0; for (const auto f : mergeable_fields) { auto type = f->get_type(); std::string name; if (type == get_byte_type() || type == get_char_type() || type == get_short_type() || type == get_int_type()) { type = get_int_type(); name = "i"; } else if (type == get_boolean_type()) { type = get_boolean_type(); name = "z"; } else if (type == get_long_type()) { type = get_long_type(); name = "j"; } else if (type == get_float_type()) { type = get_float_type(); name = "f"; } else if (type == get_double_type()) { type = get_double_type(); name = "d"; } else { static DexType* string_type = DexType::make_type("Ljava/lang/String;"); if (type == string_type) { type = string_type; name = "s"; } else { char t = type_shorty(type); always_assert(t == 'L' || t == '['); type = get_object_type(); name = "l"; } } name = name + std::to_string(cnt); auto field = static_cast<DexField*>( DexField::make_field(owner, DexString::make_string(name), type)); field->make_concrete(ACC_PUBLIC); res.push_back(field); cnt++; } TRACE(TERA, 8, " created merger fields %d \n", res.size()); return res; }
void MethodBlock::move_result(Location& dst, DexType* type) { always_assert(dst.is_compatible(type)); auto ch = type_shorty(type); assert(ch != 'V'); DexOpcode opcode; if (ch == 'L') opcode = OPCODE_MOVE_RESULT_OBJECT; else if (ch == 'J' || ch == 'D') opcode = OPCODE_MOVE_RESULT_WIDE; else opcode = OPCODE_MOVE_RESULT; DexInstruction* mov_res = new DexInstruction(opcode); mov_res->set_dest(reg_num(dst)); dst.type = type; push_instruction(mov_res); }
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); }