in opt/peephole/Peephole.cpp [516:708]
std::vector<IRInstruction*> get_replacements() {
always_assert(pattern.match.size() == match_index);
std::vector<IRInstruction*> replacements;
for (const auto& replace_info : pattern.replace) {
// First, generate the instruction object.
if (replace_info.kind == DexPattern::Kind::copy) {
always_assert(matched_instructions.size() > replace_info.copy_index);
replacements.push_back(
new IRInstruction(*matched_instructions[replace_info.copy_index]));
continue;
}
auto replace = generate_dex_instruction(replace_info);
replacements.push_back(replace);
// Fill the arguments appropriately.
if (!replace_info.dests.empty()) {
redex_assert(replace_info.dests.size() == 1);
const Register dest = replace_info.dests[0];
always_assert(matched_regs.find(dest) != end(matched_regs));
replace->set_dest(matched_regs.at(dest));
}
for (size_t i = 0; i < replace_info.srcs.size(); ++i) {
const Register reg = replace_info.srcs[i];
always_assert(matched_regs.find(reg) != end(matched_regs));
replace->set_src(i, matched_regs.at(reg));
}
if (replace_info.kind == DexPattern::Kind::string) {
switch (replace_info.string) {
case String::A: {
auto a = matched_strings.at(String::A);
replace->set_string(a);
break;
}
case String::B: {
auto b = matched_strings.at(String::B);
replace->set_string(b);
break;
}
case String::empty: {
auto empty = DexString::make_string("");
replace->set_string(empty);
break;
}
case String::boolean_A_to_string: {
bool a = matched_literals.at(Literal::A);
replace->set_string(
DexString::make_string(a == true ? "true" : "false"));
break;
}
case String::char_A_to_string: {
int a = matched_literals.at(Literal::A);
auto achar = encode_utf8_char_to_mutf8_string(a);
replace->set_string(DexString::make_string(achar));
break;
}
case String::int_A_to_string: {
int a = matched_literals.at(Literal::A);
replace->set_string(DexString::make_string(std::to_string(a)));
break;
}
case String::long_int_A_to_string: {
int64_t a = matched_literals.at(Literal::A);
replace->set_string(DexString::make_string(std::to_string(a)));
break;
}
case String::float_A_to_string: {
union {
int32_t i;
float f;
} a;
a.i = static_cast<int32_t>(matched_literals.at(Literal::A));
replace->set_string(DexString::make_string(std::to_string(a.f)));
break;
}
case String::double_A_to_string: {
union {
int64_t i;
double d;
} a;
a.i = matched_literals.at(Literal::A);
replace->set_string(DexString::make_string(std::to_string(a.d)));
break;
}
case String::concat_A_B_strings: {
auto a = matched_strings.at(String::A)->c_str();
auto b = matched_strings.at(String::B)->c_str();
replace->set_string(
DexString::make_string(std::string(a) + std::string(b)));
break;
}
case String::concat_string_A_int_A: {
auto a = matched_strings.at(String::A)->c_str();
int b = matched_literals.at(Literal::A);
replace->set_string(
DexString::make_string(std::string(a) + std::to_string(b)));
break;
}
case String::concat_string_A_boolean_A: {
auto a = matched_strings.at(String::A)->c_str();
bool b = matched_literals.at(Literal::A);
replace->set_string(DexString::make_string(
std::string(a) + (b == true ? "true" : "false")));
break;
}
case String::concat_string_A_long_int_A: {
auto a = matched_strings.at(String::A)->c_str();
int64_t b = matched_literals.at(Literal::A);
replace->set_string(
DexString::make_string(std::string(a) + std::to_string(b)));
break;
}
case String::concat_string_A_char_A: {
auto a = matched_strings.at(String::A)->c_str();
int b = matched_literals.at(Literal::A);
auto bchar = encode_utf8_char_to_mutf8_string(b);
replace->set_string(DexString::make_string(std::string(a) + bchar));
break;
}
case String::Type_A_get_simple_name: {
DexType* a = matched_types.at(Type::A);
std::string simple = type::get_simple_name(a);
replace->set_string(DexString::make_string(simple));
break;
}
default:
not_reached_log("Unexpected string directive: 0x%x",
replace_info.string);
}
} else if (replace_info.kind == DexPattern::Kind::literal) {
switch (replace_info.literal) {
case Literal::Compare_Strings_A_B: {
auto a = matched_strings.at(String::A);
auto b = matched_strings.at(String::B);
// Just DexString* pointer comparison! DexString has uniqueness.
replace->set_literal((a == b) ? 1L : 0L);
break;
}
case Literal::Length_String_A: {
auto a = matched_strings.at(String::A);
replace->set_literal(a->length());
break;
}
case Literal::HashCode_String_A: {
auto a = matched_strings.at(String::A);
replace->set_literal(static_cast<int64_t>(a->java_hashcode()));
break;
}
case Literal::A: {
auto a = matched_literals.at(Literal::A);
replace->set_literal(a);
break;
}
case Literal::Mul_Div_To_Shift_Log2: {
auto a = matched_literals.at(Literal::Mul_Div_To_Shift_Log2);
redex_assert(a > 0);
replace->set_literal(static_cast<uint64_t>(log2(a)));
break;
}
case Literal::Zero: {
replace->set_literal(0);
break;
}
}
} else if (replace_info.kind == DexPattern::Kind::type) {
switch (replace_info.type) {
case Type::A:
replace->set_type(matched_types.at(Type::A));
break;
case Type::B:
replace->set_type(matched_types.at(Type::B));
break;
default:
not_reached_log("Unexpected type directive 0x%x", replace_info.type);
}
} else if (replace_info.kind == DexPattern::Kind::field) {
switch (replace_info.field) {
case Field::A:
replace->set_field(matched_fields.at(Field::A));
break;
case Field::B:
replace->set_field(matched_fields.at(Field::B));
break;
default:
not_reached_log("Unexpected field directive 0x%x",
replace_info.field);
}
}
}
return replacements;
}