TEST(ConstantPropagationTest1, constantpropagation) { g_redex = new RedexContext(); const char* dexfile = "gen/native/redex/test/integ/constant-propagation-test-dex/constant-propagation.dex"; if (access(dexfile, R_OK) != 0) { dexfile = std::getenv("dexfile"); ASSERT_NE(nullptr, dexfile); } std::vector<DexClasses> dexen; dexen.emplace_back(load_classes_from_dex(dexfile)); DexClasses& classes = dexen.back(); std::cout << "Loaded classes: " << classes.size() << std::endl; TRACE(CONSTP, 2, "Code before:\n"); for(const auto& cls : classes) { TRACE(CONSTP, 2, "Class %s\n", SHOW(cls)); if (filter_test_classes(cls->get_name()) < 2) { TRACE(CONSTP, 2, "Class %s\n", SHOW(cls)); for (const auto& dm : cls->get_dmethods()) { TRACE(CONSTP, 2, "dmethod: %s\n", dm->get_name()->c_str()); if (strcmp(dm->get_name()->c_str(), "propagation_1") == 0 || strcmp(dm->get_name()->c_str(), "propagation_2") == 0 || strcmp(dm->get_name()->c_str(), "propagation_3") == 0) { TRACE(CONSTP, 2, "dmethod: %s\n", SHOW(dm->get_code())); } } } } std::vector<Pass*> passes = { new ConstantPropagationPass(), new LocalDcePass() }; std::vector<KeepRule> null_rules; PassManager manager(passes, null_rules); Json::Value conf_obj = Json::nullValue; ConfigFiles dummy_cfg(conf_obj); dummy_cfg.using_seeds = true; manager.run_passes(dexen, dummy_cfg); TRACE(CONSTP, 2, "Code after:\n"); for(const auto& cls : classes) { TRACE(CONSTP, 2, "Class %s\n", SHOW(cls)); //ASSERT_NE(filter_test_classes(cls->get_name()), REMOVEDCLASS); if (filter_test_classes(cls->get_name()) == MAINCLASS) { for (const auto& dm : cls->get_dmethods()) { TRACE(CONSTP, 2, "dmethod: %s\n", dm->get_name()->c_str()); if (strcmp(dm->get_name()->c_str(), "propagation_1") == 0) { TRACE(CONSTP, 2, "dmethod: %s\n", SHOW(dm->get_code())); for (auto const instruction : dm->get_code()->get_instructions()) { ASSERT_NE(instruction->opcode(), OPCODE_IF_EQZ); ASSERT_NE(instruction->opcode(), OPCODE_NEW_INSTANCE); } } else if (strcmp(dm->get_name()->c_str(), "propagation_2") == 0) { TRACE(CONSTP, 2, "dmethod: %s\n", SHOW(dm->get_code())); for (auto const instruction : dm->get_code()->get_instructions()) { ASSERT_NE(instruction->opcode(), OPCODE_IF_EQZ); ASSERT_NE(instruction->opcode(), OPCODE_INVOKE_STATIC); } } else if(strcmp(dm->get_name()->c_str(), "propagation_3") == 0) { TRACE(CONSTP, 2, "dmethod: %s\n", SHOW(dm->get_code())); for (auto const instruction : dm->get_code()->get_instructions()) { //ASSERT_NE(instruction->opcode(), OPCODE_IF_EQZ); //ASSERT_NE(instruction->opcode(), OPCODE_INVOKE_STATIC); } } } } } }
TEST(ConstantPropagationTest1, constantpropagation) { g_redex = new RedexContext(); const char* dexfile = "gen/native/redex/test/integ/constant-propagation-test-dex/constant-propagation.dex"; if (access(dexfile, R_OK) != 0) { dexfile = std::getenv("dexfile"); ASSERT_NE(nullptr, dexfile); } std::vector<DexClasses> dexen; dexen.emplace_back(load_classes_from_dex(dexfile)); DexClasses& classes = dexen.back(); std::cout << "Loaded classes: " << classes.size() << std::endl; TRACE(CONSTP, 2, "Code before:\n"); for(const auto& cls : classes) { if (filter_test_classes(cls->get_name()) < 2) { TRACE(CONSTP, 2, "Class %s\n", SHOW(cls)); for (const auto& dm : cls->get_dmethods()) { TRACE(CONSTP, 2, "dmethod: %s\n", dm->get_name()->c_str()); if (strcmp(dm->get_name()->c_str(), "propagation_1") == 0 || strcmp(dm->get_name()->c_str(), "propagation_2") == 0) { TRACE(CONSTP, 2, "dmethod: %s\n", SHOW(dm->get_code())); } } } } std::vector<Pass*> passes = { new DelInitPass(), new RemoveEmptyClassesPass(), new ConstantPropagationPass(), new LocalDcePass(), }; std::vector<KeepRule> null_rules; PassManager manager(passes, null_rules); Json::Value conf_obj = Json::nullValue; ConfigFiles dummy_cfg(conf_obj); manager.run_passes(dexen, dummy_cfg); TRACE(CONSTP, 2, "Code after:\n"); for(const auto& cls : classes) { if (filter_test_classes(cls->get_name()) == REMOVEDCLASS) { TRACE(CONSTP, 2, "Class %s\n", SHOW(cls)); // To be reverted: These classes should be removed by future optimization. ASSERT_TRUE(true); } else if (filter_test_classes(cls->get_name()) == MAINCLASS) { TRACE(CONSTP, 2, "Class %s\n", SHOW(cls)); for (const auto& dm : cls->get_dmethods()) { TRACE(CONSTP, 2, "dmethod: %s\n", dm->get_name()->c_str()); if (strcmp(dm->get_name()->c_str(), "propagation_1") == 0) { TRACE(CONSTP, 2, "dmethod: %s\n", SHOW(dm->get_code())); for (auto const instruction : dm->get_code()->get_instructions()) { // The logic will be reverted when the future // development of constant propagation optimization is done, i.e., // The code will be changed to ASSERT_TRUE(false) // if IF_EQZ or New Class Instance instruction is found if (instruction->opcode() == OPCODE_IF_EQZ || instruction->opcode() == OPCODE_NEW_INSTANCE) { ASSERT_TRUE(true); } } } else if (strcmp(dm->get_name()->c_str(), "propagation_2") == 0) { TRACE(CONSTP, 2, "dmethod: %s\n", SHOW(dm->get_code())); for (auto const instruction : dm->get_code()->get_instructions()) { // The logic will be reverted when the future // development of constant propagation optimization is done, i.e., // The code will be changed to ASSERT_TRUE(false) // if IF_EQZ or Invote_Static instruction is found if (instruction->opcode() == OPCODE_IF_EQZ || instruction->opcode() == OPCODE_INVOKE_STATIC) { ASSERT_TRUE(true); } } } else if(strcmp(dm->get_name()->c_str(), "propagation_3") == 0) { TRACE(CONSTP, 2, "dmethod: %s\n", SHOW(dm->get_code())); for (auto const instruction : dm->get_code()->get_instructions()) { // The logic will be reverted when the future // development of constant propagation optimization is done, i.e., // The code will be changed to ASSERT_TRUE(false) // if IF_EQZ or Invote_Static instruction is found if (instruction->opcode() == OPCODE_IF_EQZ || instruction->opcode() == OPCODE_INVOKE_STATIC) { ASSERT_TRUE(true); } } } } } } }