forked from OSchip/llvm-project
Simplify memory management. NFC.
This passes std::unique_ptr to predicates that are expected to delete their argument. llvm-svn: 255086
This commit is contained in:
parent
466d4b006b
commit
bc12cbc359
|
@ -177,12 +177,15 @@ ReduceMiscompilingPasses::doTest(std::vector<std::string> &Prefix,
|
|||
namespace {
|
||||
class ReduceMiscompilingFunctions : public ListReducer<Function*> {
|
||||
BugDriver &BD;
|
||||
bool (*TestFn)(BugDriver &, Module *, Module *, std::string &);
|
||||
bool (*TestFn)(BugDriver &, std::unique_ptr<Module>,
|
||||
std::unique_ptr<Module>, std::string &);
|
||||
|
||||
public:
|
||||
ReduceMiscompilingFunctions(BugDriver &bd,
|
||||
bool (*F)(BugDriver &, Module *, Module *,
|
||||
bool (*F)(BugDriver &, std::unique_ptr<Module>,
|
||||
std::unique_ptr<Module>,
|
||||
std::string &))
|
||||
: BD(bd), TestFn(F) {}
|
||||
: BD(bd), TestFn(F) {}
|
||||
|
||||
TestResult doTest(std::vector<Function*> &Prefix,
|
||||
std::vector<Function*> &Suffix,
|
||||
|
@ -279,12 +282,12 @@ bool ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*> &Funcs,
|
|||
|
||||
// Split the module into the two halves of the program we want.
|
||||
VMap.clear();
|
||||
Module *ToNotOptimize = CloneModule(BD.getProgram(), VMap).release();
|
||||
Module *ToOptimize =
|
||||
SplitFunctionsOutOfModule(ToNotOptimize, FuncsOnClone, VMap).release();
|
||||
std::unique_ptr<Module> ToNotOptimize = CloneModule(BD.getProgram(), VMap);
|
||||
std::unique_ptr<Module> ToOptimize =
|
||||
SplitFunctionsOutOfModule(ToNotOptimize.get(), FuncsOnClone, VMap);
|
||||
|
||||
// Run the predicate, note that the predicate will delete both input modules.
|
||||
bool Broken = TestFn(BD, ToOptimize, ToNotOptimize, Error);
|
||||
bool Broken =
|
||||
TestFn(BD, std::move(ToOptimize), std::move(ToNotOptimize), Error);
|
||||
|
||||
delete BD.swapProgramIn(Orig);
|
||||
|
||||
|
@ -303,14 +306,14 @@ static void DisambiguateGlobalSymbols(Module *M) {
|
|||
I->setName("anon_fn");
|
||||
}
|
||||
|
||||
/// ExtractLoops - Given a reduced list of functions that still exposed the bug,
|
||||
/// check to see if we can extract the loops in the region without obscuring the
|
||||
/// bug. If so, it reduces the amount of code identified.
|
||||
/// Given a reduced list of functions that still exposed the bug, check to see
|
||||
/// if we can extract the loops in the region without obscuring the bug. If so,
|
||||
/// it reduces the amount of code identified.
|
||||
///
|
||||
static bool ExtractLoops(BugDriver &BD,
|
||||
bool (*TestFn)(BugDriver &, Module *, Module *,
|
||||
std::string &),
|
||||
std::vector<Function*> &MiscompiledFunctions,
|
||||
bool (*TestFn)(BugDriver &, std::unique_ptr<Module>,
|
||||
std::unique_ptr<Module>, std::string &),
|
||||
std::vector<Function *> &MiscompiledFunctions,
|
||||
std::string &Error) {
|
||||
bool MadeChange = false;
|
||||
while (1) {
|
||||
|
@ -382,8 +385,8 @@ static bool ExtractLoops(BugDriver &BD,
|
|||
for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i)
|
||||
MiscompiledFunctions[i] = cast<Function>(VMap[MiscompiledFunctions[i]]);
|
||||
|
||||
Failure =
|
||||
TestFn(BD, ToOptimizeLoopExtracted.get(), ToNotOptimize.get(), Error);
|
||||
Failure = TestFn(BD, std::move(ToOptimizeLoopExtracted),
|
||||
std::move(ToNotOptimize), Error);
|
||||
if (!Error.empty())
|
||||
return false;
|
||||
|
||||
|
@ -451,14 +454,15 @@ static bool ExtractLoops(BugDriver &BD,
|
|||
namespace {
|
||||
class ReduceMiscompiledBlocks : public ListReducer<BasicBlock*> {
|
||||
BugDriver &BD;
|
||||
bool (*TestFn)(BugDriver &, Module *, Module *, std::string &);
|
||||
bool (*TestFn)(BugDriver &, std::unique_ptr<Module>,
|
||||
std::unique_ptr<Module>, std::string &);
|
||||
std::vector<Function*> FunctionsBeingTested;
|
||||
public:
|
||||
ReduceMiscompiledBlocks(BugDriver &bd,
|
||||
bool (*F)(BugDriver &, Module *, Module *,
|
||||
std::string &),
|
||||
const std::vector<Function*> &Fns)
|
||||
: BD(bd), TestFn(F), FunctionsBeingTested(Fns) {}
|
||||
bool (*F)(BugDriver &, std::unique_ptr<Module>,
|
||||
std::unique_ptr<Module>, std::string &),
|
||||
const std::vector<Function *> &Fns)
|
||||
: BD(bd), TestFn(F), FunctionsBeingTested(Fns) {}
|
||||
|
||||
TestResult doTest(std::vector<BasicBlock*> &Prefix,
|
||||
std::vector<BasicBlock*> &Suffix,
|
||||
|
@ -518,36 +522,30 @@ bool ReduceMiscompiledBlocks::TestFuncs(const std::vector<BasicBlock*> &BBs,
|
|||
}
|
||||
VMap.clear();
|
||||
|
||||
Module *ToNotOptimize = CloneModule(BD.getProgram(), VMap).release();
|
||||
Module *ToOptimize =
|
||||
SplitFunctionsOutOfModule(ToNotOptimize, FuncsOnClone, VMap).release();
|
||||
std::unique_ptr<Module> ToNotOptimize = CloneModule(BD.getProgram(), VMap);
|
||||
std::unique_ptr<Module> ToOptimize =
|
||||
SplitFunctionsOutOfModule(ToNotOptimize.get(), FuncsOnClone, VMap);
|
||||
|
||||
// Try the extraction. If it doesn't work, then the block extractor crashed
|
||||
// or something, in which case bugpoint can't chase down this possibility.
|
||||
if (std::unique_ptr<Module> New =
|
||||
BD.extractMappedBlocksFromModule(BBsOnClone, ToOptimize)) {
|
||||
delete ToOptimize;
|
||||
// Run the predicate,
|
||||
// note that the predicate will delete both input modules.
|
||||
bool Ret = TestFn(BD, New.get(), ToNotOptimize, Error);
|
||||
BD.extractMappedBlocksFromModule(BBsOnClone, ToOptimize.get())) {
|
||||
bool Ret = TestFn(BD, std::move(New), std::move(ToNotOptimize), Error);
|
||||
delete BD.swapProgramIn(Orig);
|
||||
return Ret;
|
||||
}
|
||||
delete BD.swapProgramIn(Orig);
|
||||
delete ToOptimize;
|
||||
delete ToNotOptimize;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// ExtractBlocks - Given a reduced list of functions that still expose the bug,
|
||||
/// extract as many basic blocks from the region as possible without obscuring
|
||||
/// the bug.
|
||||
/// Given a reduced list of functions that still expose the bug, extract as many
|
||||
/// basic blocks from the region as possible without obscuring the bug.
|
||||
///
|
||||
static bool ExtractBlocks(BugDriver &BD,
|
||||
bool (*TestFn)(BugDriver &, Module *, Module *,
|
||||
bool (*TestFn)(BugDriver &, std::unique_ptr<Module>,
|
||||
std::unique_ptr<Module>,
|
||||
std::string &),
|
||||
std::vector<Function*> &MiscompiledFunctions,
|
||||
std::vector<Function *> &MiscompiledFunctions,
|
||||
std::string &Error) {
|
||||
if (BugpointIsInterrupted) return false;
|
||||
|
||||
|
@ -620,14 +618,13 @@ static bool ExtractBlocks(BugDriver &BD,
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// DebugAMiscompilation - This is a generic driver to narrow down
|
||||
/// miscompilations, either in an optimization or a code generator.
|
||||
/// This is a generic driver to narrow down miscompilations, either in an
|
||||
/// optimization or a code generator.
|
||||
///
|
||||
static std::vector<Function*>
|
||||
static std::vector<Function *>
|
||||
DebugAMiscompilation(BugDriver &BD,
|
||||
bool (*TestFn)(BugDriver &, Module *, Module *,
|
||||
std::string &),
|
||||
bool (*TestFn)(BugDriver &, std::unique_ptr<Module>,
|
||||
std::unique_ptr<Module>, std::string &),
|
||||
std::string &Error) {
|
||||
// Okay, now that we have reduced the list of passes which are causing the
|
||||
// failure, see if we can pin down which functions are being
|
||||
|
@ -706,24 +703,24 @@ DebugAMiscompilation(BugDriver &BD,
|
|||
return MiscompiledFunctions;
|
||||
}
|
||||
|
||||
/// TestOptimizer - This is the predicate function used to check to see if the
|
||||
/// "Test" portion of the program is misoptimized. If so, return true. In any
|
||||
/// case, both module arguments are deleted.
|
||||
/// This is the predicate function used to check to see if the "Test" portion of
|
||||
/// the program is misoptimized. If so, return true. In any case, both module
|
||||
/// arguments are deleted.
|
||||
///
|
||||
static bool TestOptimizer(BugDriver &BD, Module *Test, Module *Safe,
|
||||
std::string &Error) {
|
||||
static bool TestOptimizer(BugDriver &BD, std::unique_ptr<Module> Test,
|
||||
std::unique_ptr<Module> Safe, std::string &Error) {
|
||||
// Run the optimization passes on ToOptimize, producing a transformed version
|
||||
// of the functions being tested.
|
||||
outs() << " Optimizing functions being tested: ";
|
||||
std::unique_ptr<Module> Optimized = BD.runPassesOn(Test, BD.getPassesToRun(),
|
||||
/*AutoDebugCrashes*/ true);
|
||||
std::unique_ptr<Module> Optimized =
|
||||
BD.runPassesOn(Test.get(), BD.getPassesToRun(),
|
||||
/*AutoDebugCrashes*/ true);
|
||||
outs() << "done.\n";
|
||||
delete Test;
|
||||
|
||||
outs() << " Checking to see if the merged program executes correctly: ";
|
||||
bool Broken;
|
||||
Module *New =
|
||||
TestMergedProgram(BD, Optimized.get(), Safe, true, Error, Broken);
|
||||
TestMergedProgram(BD, Optimized.get(), Safe.get(), true, Error, Broken);
|
||||
if (New) {
|
||||
outs() << (Broken ? " nope.\n" : " yup.\n");
|
||||
// Delete the original and set the new program.
|
||||
|
@ -776,13 +773,13 @@ void BugDriver::debugMiscompilation(std::string *Error) {
|
|||
return;
|
||||
}
|
||||
|
||||
/// CleanupAndPrepareModules - Get the specified modules ready for code
|
||||
/// generator testing.
|
||||
/// Get the specified modules ready for code generator testing.
|
||||
///
|
||||
static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test,
|
||||
static void CleanupAndPrepareModules(BugDriver &BD,
|
||||
std::unique_ptr<Module> &Test,
|
||||
Module *Safe) {
|
||||
// Clean up the modules, removing extra cruft that we don't need anymore...
|
||||
Test = BD.performFinalCleanups(Test).release();
|
||||
Test = BD.performFinalCleanups(Test.get());
|
||||
|
||||
// If we are executing the JIT, we have several nasty issues to take care of.
|
||||
if (!BD.isExecutingJIT()) return;
|
||||
|
@ -795,14 +792,14 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test,
|
|||
// Rename it
|
||||
oldMain->setName("llvm_bugpoint_old_main");
|
||||
// Create a NEW `main' function with same type in the test module.
|
||||
Function *newMain = Function::Create(oldMain->getFunctionType(),
|
||||
GlobalValue::ExternalLinkage,
|
||||
"main", Test);
|
||||
Function *newMain =
|
||||
Function::Create(oldMain->getFunctionType(),
|
||||
GlobalValue::ExternalLinkage, "main", Test.get());
|
||||
// Create an `oldmain' prototype in the test module, which will
|
||||
// corresponds to the real main function in the same module.
|
||||
Function *oldMainProto = Function::Create(oldMain->getFunctionType(),
|
||||
GlobalValue::ExternalLinkage,
|
||||
oldMain->getName(), Test);
|
||||
oldMain->getName(), Test.get());
|
||||
// Set up and remember the argument list for the main function.
|
||||
std::vector<Value*> args;
|
||||
for (Function::arg_iterator
|
||||
|
@ -938,15 +935,14 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// 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.
|
||||
/// 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,
|
||||
static bool TestCodeGenerator(BugDriver &BD, std::unique_ptr<Module> Test,
|
||||
std::unique_ptr<Module> Safe,
|
||||
std::string &Error) {
|
||||
CleanupAndPrepareModules(BD, Test, Safe);
|
||||
CleanupAndPrepareModules(BD, Test, Safe.get());
|
||||
|
||||
SmallString<128> TestModuleBC;
|
||||
int TestModuleFD;
|
||||
|
@ -957,12 +953,11 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe,
|
|||
<< EC.message() << "\n";
|
||||
exit(1);
|
||||
}
|
||||
if (BD.writeProgramToFile(TestModuleBC.str(), TestModuleFD, Test)) {
|
||||
if (BD.writeProgramToFile(TestModuleBC.str(), TestModuleFD, Test.get())) {
|
||||
errs() << "Error writing bitcode to `" << TestModuleBC.str()
|
||||
<< "'\nExiting.";
|
||||
exit(1);
|
||||
}
|
||||
delete Test;
|
||||
|
||||
FileRemover TestModuleBCRemover(TestModuleBC.str(), !SaveTemps);
|
||||
|
||||
|
@ -977,7 +972,7 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe,
|
|||
exit(1);
|
||||
}
|
||||
|
||||
if (BD.writeProgramToFile(SafeModuleBC.str(), SafeModuleFD, Safe)) {
|
||||
if (BD.writeProgramToFile(SafeModuleBC.str(), SafeModuleFD, Safe.get())) {
|
||||
errs() << "Error writing bitcode to `" << SafeModuleBC
|
||||
<< "'\nExiting.";
|
||||
exit(1);
|
||||
|
@ -988,7 +983,6 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe,
|
|||
std::string SharedObject = BD.compileSharedObject(SafeModuleBC.str(), Error);
|
||||
if (!Error.empty())
|
||||
return false;
|
||||
delete Safe;
|
||||
|
||||
FileRemover SharedObjectRemover(SharedObject, !SaveTemps);
|
||||
|
||||
|
@ -1036,12 +1030,12 @@ bool BugDriver::debugCodeGenerator(std::string *Error) {
|
|||
|
||||
// Split the module into the two halves of the program we want.
|
||||
ValueToValueMapTy VMap;
|
||||
Module *ToNotCodeGen = CloneModule(getProgram(), VMap).release();
|
||||
Module *ToCodeGen =
|
||||
SplitFunctionsOutOfModule(ToNotCodeGen, Funcs, VMap).release();
|
||||
std::unique_ptr<Module> ToNotCodeGen = CloneModule(getProgram(), VMap);
|
||||
std::unique_ptr<Module> ToCodeGen =
|
||||
SplitFunctionsOutOfModule(ToNotCodeGen.get(), Funcs, VMap);
|
||||
|
||||
// Condition the modules
|
||||
CleanupAndPrepareModules(*this, ToCodeGen, ToNotCodeGen);
|
||||
CleanupAndPrepareModules(*this, ToCodeGen, ToNotCodeGen.get());
|
||||
|
||||
SmallString<128> TestModuleBC;
|
||||
int TestModuleFD;
|
||||
|
@ -1053,12 +1047,11 @@ bool BugDriver::debugCodeGenerator(std::string *Error) {
|
|||
exit(1);
|
||||
}
|
||||
|
||||
if (writeProgramToFile(TestModuleBC.str(), TestModuleFD, ToCodeGen)) {
|
||||
if (writeProgramToFile(TestModuleBC.str(), TestModuleFD, ToCodeGen.get())) {
|
||||
errs() << "Error writing bitcode to `" << TestModuleBC
|
||||
<< "'\nExiting.";
|
||||
exit(1);
|
||||
}
|
||||
delete ToCodeGen;
|
||||
|
||||
// Make the shared library
|
||||
SmallString<128> SafeModuleBC;
|
||||
|
@ -1071,7 +1064,8 @@ bool BugDriver::debugCodeGenerator(std::string *Error) {
|
|||
exit(1);
|
||||
}
|
||||
|
||||
if (writeProgramToFile(SafeModuleBC.str(), SafeModuleFD, ToNotCodeGen)) {
|
||||
if (writeProgramToFile(SafeModuleBC.str(), SafeModuleFD,
|
||||
ToNotCodeGen.get())) {
|
||||
errs() << "Error writing bitcode to `" << SafeModuleBC
|
||||
<< "'\nExiting.";
|
||||
exit(1);
|
||||
|
@ -1079,7 +1073,6 @@ bool BugDriver::debugCodeGenerator(std::string *Error) {
|
|||
std::string SharedObject = compileSharedObject(SafeModuleBC.str(), *Error);
|
||||
if (!Error->empty())
|
||||
return true;
|
||||
delete ToNotCodeGen;
|
||||
|
||||
outs() << "You can reproduce the problem with the command line: \n";
|
||||
if (isExecutingJIT()) {
|
||||
|
|
Loading…
Reference in New Issue