/// TestMergedProgram - Given two modules, link them together and run the /// program, checking to see if the program matches the diff. If the diff /// matches, return false, otherwise return true. If the DeleteInputs argument /// is set to true then this function deletes both input modules before it /// returns. /// static bool TestMergedProgram(BugDriver &BD, Module *M1, Module *M2, bool DeleteInputs, std::string &Error) { // Link the two portions of the program back to together. std::string ErrorMsg; if (!DeleteInputs) { M1 = CloneModule(M1); M2 = CloneModule(M2); } if (Linker::LinkModules(M1, M2, &ErrorMsg)) { errs() << BD.getToolName() << ": Error linking modules together:" << ErrorMsg << '\n'; exit(1); } delete M2; // We are done with this module. OwningPtr<Module> OldProgram(BD.swapProgramIn(M1)); // Execute the program. If it does not match the expected output, we must // return true. bool Broken = BD.diffProgram("", "", false, &Error); if (!Error.empty()) { // Delete the linked module & restore the original delete BD.swapProgramIn(OldProgram.take()); } return Broken; }
/// TestCodeGenerator - This is the predicate function used to check to see if /// the "Test" portion of the program is miscompiled by the code generator under /// test. If so, return true. In any case, both module arguments are deleted. /// static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe, std::string &Error) { CleanupAndPrepareModules(BD, Test, Safe); sys::Path TestModuleBC("bugpoint.test.bc"); std::string ErrMsg; if (TestModuleBC.makeUnique(true, &ErrMsg)) { errs() << BD.getToolName() << "Error making unique filename: " << ErrMsg << "\n"; exit(1); } if (BD.writeProgramToFile(TestModuleBC.str(), Test)) { errs() << "Error writing bitcode to `" << TestModuleBC.str() << "'\nExiting."; exit(1); } delete Test; FileRemover TestModuleBCRemover(TestModuleBC, !SaveTemps); // Make the shared library sys::Path SafeModuleBC("bugpoint.safe.bc"); if (SafeModuleBC.makeUnique(true, &ErrMsg)) { errs() << BD.getToolName() << "Error making unique filename: " << ErrMsg << "\n"; exit(1); } if (BD.writeProgramToFile(SafeModuleBC.str(), Safe)) { errs() << "Error writing bitcode to `" << SafeModuleBC.str() << "'\nExiting."; exit(1); } FileRemover SafeModuleBCRemover(SafeModuleBC, !SaveTemps); std::string SharedObject = BD.compileSharedObject(SafeModuleBC.str(), Error); if (!Error.empty()) return false; delete Safe; FileRemover SharedObjectRemover(sys::Path(SharedObject), !SaveTemps); // Run the code generator on the `Test' code, loading the shared library. // The function returns whether or not the new output differs from reference. bool Result = BD.diffProgram(BD.getProgram(), TestModuleBC.str(), SharedObject, false, &Error); if (!Error.empty()) return false; if (Result) errs() << ": still failing!\n"; else errs() << ": didn't fail.\n"; return Result; }
/// Given two modules, link them together and run the program, checking to see /// if the program matches the diff. If there is an error, return NULL. If not, /// return the merged module. The Broken argument will be set to true if the /// output is different. If the DeleteInputs argument is set to true then this /// function deletes both input modules before it returns. /// static std::unique_ptr<Module> testMergedProgram(const BugDriver &BD, std::unique_ptr<Module> M1, std::unique_ptr<Module> M2, std::string &Error, bool &Broken) { if (Linker::linkModules(*M1, *M2)) exit(1); // Execute the program. Broken = BD.diffProgram(M1.get(), "", "", false, &Error); if (!Error.empty()) return nullptr; return M1; }
/// TestCodeGenerator - This is the predicate function used to check to see if /// the "Test" portion of the program is miscompiled by the code generator under /// test. If so, return true. In any case, both module arguments are deleted. /// static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe) { CleanupAndPrepareModules(BD, Test, Safe); sys::Path TestModuleBC("bugpoint.test.bc"); std::string ErrMsg; if (TestModuleBC.makeUnique(true, &ErrMsg)) { std::cerr << BD.getToolName() << "Error making unique filename: " << ErrMsg << "\n"; exit(1); } if (BD.writeProgramToFile(TestModuleBC.toString(), Test)) { std::cerr << "Error writing bitcode to `" << TestModuleBC << "'\nExiting."; exit(1); } delete Test; // Make the shared library sys::Path SafeModuleBC("bugpoint.safe.bc"); if (SafeModuleBC.makeUnique(true, &ErrMsg)) { std::cerr << BD.getToolName() << "Error making unique filename: " << ErrMsg << "\n"; exit(1); } if (BD.writeProgramToFile(SafeModuleBC.toString(), Safe)) { std::cerr << "Error writing bitcode to `" << SafeModuleBC << "'\nExiting."; exit(1); } std::string SharedObject = BD.compileSharedObject(SafeModuleBC.toString()); delete Safe; // Run the code generator on the `Test' code, loading the shared library. // The function returns whether or not the new output differs from reference. int Result = BD.diffProgram(TestModuleBC.toString(), SharedObject, false); if (Result) std::cerr << ": still failing!\n"; else std::cerr << ": didn't fail.\n"; TestModuleBC.eraseFromDisk(); SafeModuleBC.eraseFromDisk(); sys::Path(SharedObject).eraseFromDisk(); return Result; }
/// TestCodeGenerator - This is the predicate function used to check to see if /// the "Test" portion of the program is miscompiled by the code generator under /// test. If so, return true. In any case, both module arguments are deleted. /// static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe, std::string &Error) { CleanupAndPrepareModules(BD, Test, Safe); SmallString<128> TestModuleBC; int TestModuleFD; std::error_code EC = sys::fs::createTemporaryFile("bugpoint.test", "bc", TestModuleFD, TestModuleBC); if (EC) { errs() << BD.getToolName() << "Error making unique filename: " << EC.message() << "\n"; exit(1); } if (BD.writeProgramToFile(TestModuleBC.str(), TestModuleFD, Test)) { errs() << "Error writing bitcode to `" << TestModuleBC.str() << "'\nExiting."; exit(1); } delete Test; FileRemover TestModuleBCRemover(TestModuleBC.str(), !SaveTemps); // Make the shared library SmallString<128> SafeModuleBC; int SafeModuleFD; EC = sys::fs::createTemporaryFile("bugpoint.safe", "bc", SafeModuleFD, SafeModuleBC); if (EC) { errs() << BD.getToolName() << "Error making unique filename: " << EC.message() << "\n"; exit(1); } if (BD.writeProgramToFile(SafeModuleBC.str(), SafeModuleFD, Safe)) { errs() << "Error writing bitcode to `" << SafeModuleBC << "'\nExiting."; exit(1); } FileRemover SafeModuleBCRemover(SafeModuleBC.str(), !SaveTemps); std::string SharedObject = BD.compileSharedObject(SafeModuleBC.str(), Error); if (!Error.empty()) return false; delete Safe; FileRemover SharedObjectRemover(SharedObject, !SaveTemps); // Run the code generator on the `Test' code, loading the shared library. // The function returns whether or not the new output differs from reference. bool Result = BD.diffProgram(BD.getProgram(), TestModuleBC.str(), SharedObject, false, &Error); if (!Error.empty()) return false; if (Result) errs() << ": still failing!\n"; else errs() << ": didn't fail.\n"; return Result; }