std::vector get_replacements()

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;
  }