#include "BugDriver.h"
#include "ListReducer.h"
#include "ToolRunner.h"
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Instructions.h"
-#include "llvm/Linker.h"
-#include "llvm/Module.h"
+#include "llvm/Config/config.h" // for HAVE_LINK_R
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/Linker/Linker.h"
#include "llvm/Pass.h"
-#include "llvm/Analysis/Verifier.h"
-#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileUtilities.h"
-#include "llvm/Config/config.h" // for HAVE_LINK_R
+#include "llvm/Transforms/Utils/Cloning.h"
using namespace llvm;
namespace llvm {
public:
ReduceMiscompilingPasses(BugDriver &bd) : BD(bd) {}
- virtual TestResult doTest(std::vector<std::string> &Prefix,
- std::vector<std::string> &Suffix,
- std::string &Error);
+ TestResult doTest(std::vector<std::string> &Prefix,
+ std::vector<std::string> &Suffix,
+ std::string &Error) override;
};
}
return InternalError;
if (Diff) {
outs() << " nope.\n";
- sys::Path(BitcodeResult).eraseFromDisk();
+ sys::fs::remove(BitcodeResult);
return KeepPrefix;
}
outs() << " yup.\n"; // No miscompilation!
// Ok, so now we know that the prefix passes work, try running the suffix
// passes on the result of the prefix passes.
//
- OwningPtr<Module> PrefixOutput(ParseInputFile(BitcodeResult,
- BD.getContext()));
- if (PrefixOutput == 0) {
+ std::unique_ptr<Module> PrefixOutput =
+ parseInputFile(BitcodeResult, BD.getContext());
+ if (!PrefixOutput) {
errs() << BD.getToolName() << ": Error reading bitcode file '"
<< BitcodeResult << "'!\n";
exit(1);
}
- sys::Path(BitcodeResult).eraseFromDisk(); // No longer need the file on disk
+ sys::fs::remove(BitcodeResult);
// Don't check if there are no passes in the suffix.
if (Suffix.empty())
<< "' passes compile correctly after the '"
<< getPassesString(Prefix) << "' passes: ";
- OwningPtr<Module> OriginalInput(BD.swapProgramIn(PrefixOutput.take()));
+ std::unique_ptr<Module> OriginalInput(
+ BD.swapProgramIn(PrefixOutput.release()));
if (BD.runPasses(BD.getProgram(), Suffix, BitcodeResult, false/*delete*/,
true/*quiet*/)) {
errs() << " Error running this sequence of passes"
// Otherwise, we must not be running the bad pass anymore.
outs() << " yup.\n"; // No miscompilation!
// Restore orig program & free test.
- delete BD.swapProgramIn(OriginalInput.take());
+ delete BD.swapProgramIn(OriginalInput.release());
return NoFailure;
}
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) {}
- virtual TestResult doTest(std::vector<Function*> &Prefix,
- std::vector<Function*> &Suffix,
- std::string &Error) {
+ TestResult doTest(std::vector<Function*> &Prefix,
+ std::vector<Function*> &Suffix,
+ std::string &Error) override {
if (!Suffix.empty()) {
bool Ret = TestFuncs(Suffix, Error);
if (!Error.empty())
};
}
-/// TestMergedProgram - 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.
+/// 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 Module *TestMergedProgram(const BugDriver &BD, Module *M1, Module *M2,
- bool DeleteInputs, std::string &Error,
- bool &Broken) {
- // 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';
+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);
- }
- delete M2; // We are done with this module.
// Execute the program.
- Broken = BD.diffProgram(M1, "", "", false, &Error);
- if (!Error.empty()) {
- // Delete the linked module
- delete M1;
- return NULL;
- }
+ Broken = BD.diffProgram(M1.get(), "", "", false, &Error);
+ if (!Error.empty())
+ return nullptr;
return M1;
}
// we can conclude that a function triggers the bug when in fact one
// needs a larger set of original functions to do so.
ValueToValueMapTy VMap;
- Module *Clone = CloneModule(BD.getProgram(), VMap);
+ Module *Clone = CloneModule(BD.getProgram(), VMap).release();
Module *Orig = BD.swapProgramIn(Clone);
std::vector<Function*> FuncsOnClone;
// Split the module into the two halves of the program we want.
VMap.clear();
- Module *ToNotOptimize = CloneModule(BD.getProgram(), VMap);
- Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, FuncsOnClone,
- VMap);
+ 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);
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) {
if (BugpointIsInterrupted) return MadeChange;
ValueToValueMapTy VMap;
- Module *ToNotOptimize = CloneModule(BD.getProgram(), VMap);
- Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize,
- MiscompiledFunctions,
- VMap);
- Module *ToOptimizeLoopExtracted = BD.ExtractLoop(ToOptimize);
+ std::unique_ptr<Module> ToNotOptimize = CloneModule(BD.getProgram(), VMap);
+ Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize.get(),
+ MiscompiledFunctions, VMap)
+ .release();
+ std::unique_ptr<Module> ToOptimizeLoopExtracted =
+ BD.extractLoop(ToOptimize);
if (!ToOptimizeLoopExtracted) {
// If the loop extractor crashed or if there were no extractible loops,
// then this chapter of our odyssey is over with.
- delete ToNotOptimize;
delete ToOptimize;
return MadeChange;
}
// extraction.
AbstractInterpreter *AI = BD.switchToSafeInterpreter();
bool Failure;
- Module *New = TestMergedProgram(BD, ToOptimizeLoopExtracted, ToNotOptimize,
- false, Error, Failure);
+ std::unique_ptr<Module> New =
+ testMergedProgram(BD, std::move(ToOptimizeLoopExtracted),
+ std::move(ToNotOptimize), Error, Failure);
if (!New)
return false;
+
// Delete the original and set the new program.
- delete BD.swapProgramIn(New);
+ Module *Old = BD.swapProgramIn(New.release());
+ for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i)
+ MiscompiledFunctions[i] = cast<Function>(VMap[MiscompiledFunctions[i]]);
+ delete Old;
+
if (Failure) {
BD.switchToInterpreter(AI);
errs() << " Continuing on with un-loop-extracted version.\n";
BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-tno.bc",
- ToNotOptimize);
+ ToNotOptimize.get());
BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to.bc",
ToOptimize);
BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to-le.bc",
- ToOptimizeLoopExtracted);
+ ToOptimizeLoopExtracted.get());
errs() << "Please submit the "
<< OutputPrefix << "-loop-extract-fail-*.bc files.\n";
delete ToOptimize;
- delete ToNotOptimize;
- delete ToOptimizeLoopExtracted;
return MadeChange;
}
delete ToOptimize;
outs() << " Testing after loop extraction:\n";
// Clone modules, the tester function will free them.
- Module *TOLEBackup = CloneModule(ToOptimizeLoopExtracted);
- Module *TNOBackup = CloneModule(ToNotOptimize);
- Failure = TestFn(BD, ToOptimizeLoopExtracted, ToNotOptimize, Error);
+ std::unique_ptr<Module> TOLEBackup =
+ CloneModule(ToOptimizeLoopExtracted.get(), VMap);
+ std::unique_ptr<Module> TNOBackup = CloneModule(ToNotOptimize.get(), VMap);
+
+ for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i)
+ MiscompiledFunctions[i] = cast<Function>(VMap[MiscompiledFunctions[i]]);
+
+ Failure = TestFn(BD, std::move(ToOptimizeLoopExtracted),
+ std::move(ToNotOptimize), Error);
if (!Error.empty())
return false;
+
+ ToOptimizeLoopExtracted = std::move(TOLEBackup);
+ ToNotOptimize = std::move(TNOBackup);
+
if (!Failure) {
outs() << "*** Loop extraction masked the problem. Undoing.\n";
// If the program is not still broken, then loop extraction did something
// that masked the error. Stop loop extraction now.
- delete TOLEBackup;
- delete TNOBackup;
+
+ std::vector<std::pair<std::string, FunctionType*> > MisCompFunctions;
+ for (Function *F : MiscompiledFunctions) {
+ MisCompFunctions.emplace_back(F->getName(), F->getFunctionType());
+ }
+
+ if (Linker::linkModules(*ToNotOptimize, *ToOptimizeLoopExtracted))
+ exit(1);
+
+ MiscompiledFunctions.clear();
+ for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) {
+ Function *NewF = ToNotOptimize->getFunction(MisCompFunctions[i].first);
+
+ assert(NewF && "Function not found??");
+ MiscompiledFunctions.push_back(NewF);
+ }
+
+ BD.setNewProgram(ToNotOptimize.release());
return MadeChange;
}
- ToOptimizeLoopExtracted = TOLEBackup;
- ToNotOptimize = TNOBackup;
outs() << "*** Loop extraction successful!\n";
- std::vector<std::pair<std::string, const FunctionType*> > MisCompFunctions;
+ std::vector<std::pair<std::string, FunctionType*> > MisCompFunctions;
for (Module::iterator I = ToOptimizeLoopExtracted->begin(),
E = ToOptimizeLoopExtracted->end(); I != E; ++I)
if (!I->isDeclaration())
- MisCompFunctions.push_back(std::make_pair(I->getName(),
- I->getFunctionType()));
+ MisCompFunctions.emplace_back(I->getName(), I->getFunctionType());
// Okay, great! Now we know that we extracted a loop and that loop
// extraction both didn't break the program, and didn't mask the problem.
// Replace the current program with the loop extracted version, and try to
// extract another loop.
- std::string ErrorMsg;
- if (Linker::LinkModules(ToNotOptimize, ToOptimizeLoopExtracted, &ErrorMsg)){
- errs() << BD.getToolName() << ": Error linking modules together:"
- << ErrorMsg << '\n';
+ if (Linker::linkModules(*ToNotOptimize, *ToOptimizeLoopExtracted))
exit(1);
- }
- delete ToOptimizeLoopExtracted;
// All of the Function*'s in the MiscompiledFunctions list are in the old
// module. Update this list to include all of the functions in the
Function *NewF = ToNotOptimize->getFunction(MisCompFunctions[i].first);
assert(NewF && "Function not found??");
- assert(NewF->getFunctionType() == MisCompFunctions[i].second &&
- "found wrong function type?");
MiscompiledFunctions.push_back(NewF);
}
- BD.setNewProgram(ToNotOptimize);
+ BD.setNewProgram(ToNotOptimize.release());
MadeChange = true;
}
}
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) {}
-
- virtual TestResult doTest(std::vector<BasicBlock*> &Prefix,
- std::vector<BasicBlock*> &Suffix,
- std::string &Error) {
+ 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,
+ std::string &Error) override {
if (!Suffix.empty()) {
bool Ret = TestFuncs(Suffix, Error);
if (!Error.empty())
// Split the module into the two halves of the program we want.
ValueToValueMapTy VMap;
- Module *Clone = CloneModule(BD.getProgram(), VMap);
+ Module *Clone = CloneModule(BD.getProgram(), VMap).release();
Module *Orig = BD.swapProgramIn(Clone);
std::vector<Function*> FuncsOnClone;
std::vector<BasicBlock*> BBsOnClone;
}
VMap.clear();
- Module *ToNotOptimize = CloneModule(BD.getProgram(), VMap);
- Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize,
- FuncsOnClone,
- VMap);
+ 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 (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, ToNotOptimize, Error);
+ if (std::unique_ptr<Module> New =
+ 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;
std::vector<BasicBlock*> Blocks;
for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i)
- for (Function::iterator I = MiscompiledFunctions[i]->begin(),
- E = MiscompiledFunctions[i]->end(); I != E; ++I)
- Blocks.push_back(I);
+ for (BasicBlock &BB : *MiscompiledFunctions[i])
+ Blocks.push_back(&BB);
// Use the list reducer to identify blocks that can be extracted without
// obscuring the bug. The Blocks list will end up containing blocks that must
}
ValueToValueMapTy VMap;
- Module *ProgClone = CloneModule(BD.getProgram(), VMap);
- Module *ToExtract = SplitFunctionsOutOfModule(ProgClone,
- MiscompiledFunctions,
- VMap);
- Module *Extracted = BD.ExtractMappedBlocksFromModule(Blocks, ToExtract);
- if (Extracted == 0) {
+ Module *ProgClone = CloneModule(BD.getProgram(), VMap).release();
+ Module *ToExtract =
+ SplitFunctionsOutOfModule(ProgClone, MiscompiledFunctions, VMap)
+ .release();
+ std::unique_ptr<Module> Extracted =
+ BD.extractMappedBlocksFromModule(Blocks, ToExtract);
+ if (!Extracted) {
// Weird, extraction should have worked.
errs() << "Nondeterministic problem extracting blocks??\n";
delete ProgClone;
// together.
delete ToExtract;
- std::vector<std::pair<std::string, const FunctionType*> > MisCompFunctions;
+ std::vector<std::pair<std::string, FunctionType*> > MisCompFunctions;
for (Module::iterator I = Extracted->begin(), E = Extracted->end();
I != E; ++I)
if (!I->isDeclaration())
- MisCompFunctions.push_back(std::make_pair(I->getName(),
- I->getFunctionType()));
+ MisCompFunctions.emplace_back(I->getName(), I->getFunctionType());
- std::string ErrorMsg;
- if (Linker::LinkModules(ProgClone, Extracted, &ErrorMsg)) {
- errs() << BD.getToolName() << ": Error linking modules together:"
- << ErrorMsg << '\n';
+ if (Linker::linkModules(*ProgClone, *Extracted))
exit(1);
- }
- delete Extracted;
// Set the new program and delete the old one.
BD.setNewProgram(ProgClone);
for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) {
Function *NewF = ProgClone->getFunction(MisCompFunctions[i].first);
assert(NewF && "Function not found??");
- assert(NewF->getFunctionType() == MisCompFunctions[i].second &&
- "Function has wrong type??");
MiscompiledFunctions.push_back(NewF);
}
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
// the program.
std::vector<Function*> MiscompiledFunctions;
Module *Prog = BD.getProgram();
- for (Module::iterator I = Prog->begin(), E = Prog->end(); I != E; ++I)
- if (!I->isDeclaration())
- MiscompiledFunctions.push_back(I);
+ for (Function &F : *Prog)
+ if (!F.isDeclaration())
+ MiscompiledFunctions.push_back(&F);
// Do the reduction...
if (!BugpointIsInterrupted)
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: ";
- 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, Safe, true, Error, Broken);
+ std::unique_ptr<Module> New = testMergedProgram(
+ BD, std::move(Optimized), std::move(Safe), Error, Broken);
if (New) {
outs() << (Broken ? " nope.\n" : " yup.\n");
// Delete the original and set the new program.
- delete BD.swapProgramIn(New);
+ delete BD.swapProgramIn(New.release());
}
return Broken;
}
// Output a bunch of bitcode files for the user...
outs() << "Outputting reduced bitcode files which expose the problem:\n";
ValueToValueMapTy VMap;
- Module *ToNotOptimize = CloneModule(getProgram(), VMap);
- Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize,
- MiscompiledFunctions,
- VMap);
+ Module *ToNotOptimize = CloneModule(getProgram(), VMap).release();
+ Module *ToOptimize =
+ SplitFunctionsOutOfModule(ToNotOptimize, MiscompiledFunctions, VMap)
+ .release();
outs() << " Non-optimized portion: ";
EmitProgressBitcode(ToNotOptimize, "tonotoptimize", true);
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);
+ Test = BD.performFinalCleanups(Test.get());
// If we are executing the JIT, we have several nasty issues to take care of.
if (!BD.isExecutingJIT()) return;
// 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
I = newMain->arg_begin(), E = newMain->arg_end(),
OI = oldMain->arg_begin(); I != E; ++I, ++OI) {
I->setName(OI->getName()); // Copy argument names from oldMain
- args.push_back(I);
+ args.push_back(&*I);
}
// Call the old main function and return its result
Safe->getOrInsertFunction("getPointerToNamedFunction",
Type::getInt8PtrTy(Safe->getContext()),
Type::getInt8PtrTy(Safe->getContext()),
- (Type *)0);
+ (Type *)nullptr);
// Use the function we just added to get addresses of functions we need.
for (Module::iterator F = Safe->begin(), E = Safe->end(); F != E; ++F) {
// Don't forward functions which are external in the test module too.
if (TestFn && !TestFn->isDeclaration()) {
// 1. Add a string constant with its name to the global file
- Constant *InitArray = ConstantArray::get(F->getContext(), F->getName());
+ Constant *InitArray =
+ ConstantDataArray::getString(F->getContext(), F->getName());
GlobalVariable *funcName =
new GlobalVariable(*Safe, InitArray->getType(), true /*isConstant*/,
GlobalValue::InternalLinkage, InitArray,
// GetElementPtr *funcName, ulong 0, ulong 0
std::vector<Constant*> GEPargs(2,
Constant::getNullValue(Type::getInt32Ty(F->getContext())));
- Value *GEP =
- ConstantExpr::getGetElementPtr(funcName, &GEPargs[0], 2);
+ Value *GEP = ConstantExpr::getGetElementPtr(InitArray->getType(),
+ funcName, GEPargs);
std::vector<Value*> ResolverArgs;
ResolverArgs.push_back(GEP);
NullPtr,F->getName()+".fpcache");
// Construct a new stub function that will re-route calls to F
- const FunctionType *FuncTy = F->getFunctionType();
+ FunctionType *FuncTy = F->getFunctionType();
Function *FuncWrapper = Function::Create(FuncTy,
GlobalValue::InternalLinkage,
F->getName() + "_wrapper",
// Save the argument list.
std::vector<Value*> Args;
- for (Function::arg_iterator i = FuncWrapper->arg_begin(),
- e = FuncWrapper->arg_end(); i != e; ++i)
- Args.push_back(i);
+ for (Argument &A : FuncWrapper->args())
+ Args.push_back(&A);
// Pass on the arguments to the real function, return its result
if (F->getReturnType()->isVoidTy()) {
}
}
-
-
-/// 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());
- sys::Path TestModuleBC("bugpoint.test.bc");
- std::string ErrMsg;
- if (TestModuleBC.makeUnique(true, &ErrMsg)) {
+ 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: "
- << ErrMsg << "\n";
+ << EC.message() << "\n";
exit(1);
}
- if (BD.writeProgramToFile(TestModuleBC.str(), 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);
// Make the shared library
- sys::Path SafeModuleBC("bugpoint.safe.bc");
- if (SafeModuleBC.makeUnique(true, &ErrMsg)) {
+ SmallString<128> SafeModuleBC;
+ int SafeModuleFD;
+ EC = sys::fs::createTemporaryFile("bugpoint.safe", "bc", SafeModuleFD,
+ SafeModuleBC);
+ if (EC) {
errs() << BD.getToolName() << "Error making unique filename: "
- << ErrMsg << "\n";
+ << EC.message() << "\n";
exit(1);
}
- if (BD.writeProgramToFile(SafeModuleBC.str(), Safe)) {
- errs() << "Error writing bitcode to `" << SafeModuleBC.str()
+ if (BD.writeProgramToFile(SafeModuleBC.str(), SafeModuleFD, Safe.get())) {
+ errs() << "Error writing bitcode to `" << SafeModuleBC
<< "'\nExiting.";
exit(1);
}
std::string SharedObject = BD.compileSharedObject(SafeModuleBC.str(), Error);
if (!Error.empty())
return false;
- delete Safe;
FileRemover SharedObjectRemover(SharedObject, !SaveTemps);
// Split the module into the two halves of the program we want.
ValueToValueMapTy VMap;
- Module *ToNotCodeGen = CloneModule(getProgram(), VMap);
- Module *ToCodeGen = SplitFunctionsOutOfModule(ToNotCodeGen, Funcs, VMap);
+ 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());
- sys::Path TestModuleBC("bugpoint.test.bc");
- std::string ErrMsg;
- if (TestModuleBC.makeUnique(true, &ErrMsg)) {
+ SmallString<128> TestModuleBC;
+ int TestModuleFD;
+ std::error_code EC = sys::fs::createTemporaryFile("bugpoint.test", "bc",
+ TestModuleFD, TestModuleBC);
+ if (EC) {
errs() << getToolName() << "Error making unique filename: "
- << ErrMsg << "\n";
+ << EC.message() << "\n";
exit(1);
}
- if (writeProgramToFile(TestModuleBC.str(), ToCodeGen)) {
- errs() << "Error writing bitcode to `" << TestModuleBC.str()
+ if (writeProgramToFile(TestModuleBC.str(), TestModuleFD, ToCodeGen.get())) {
+ errs() << "Error writing bitcode to `" << TestModuleBC
<< "'\nExiting.";
exit(1);
}
- delete ToCodeGen;
// Make the shared library
- sys::Path SafeModuleBC("bugpoint.safe.bc");
- if (SafeModuleBC.makeUnique(true, &ErrMsg)) {
+ SmallString<128> SafeModuleBC;
+ int SafeModuleFD;
+ EC = sys::fs::createTemporaryFile("bugpoint.safe", "bc", SafeModuleFD,
+ SafeModuleBC);
+ if (EC) {
errs() << getToolName() << "Error making unique filename: "
- << ErrMsg << "\n";
+ << EC.message() << "\n";
exit(1);
}
- if (writeProgramToFile(SafeModuleBC.str(), ToNotCodeGen)) {
- errs() << "Error writing bitcode to `" << SafeModuleBC.str()
+ if (writeProgramToFile(SafeModuleBC.str(), SafeModuleFD,
+ ToNotCodeGen.get())) {
+ errs() << "Error writing bitcode to `" << SafeModuleBC
<< "'\nExiting.";
exit(1);
}
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()) {
- outs() << " lli -load " << SharedObject << " " << TestModuleBC.str();
+ outs() << " lli -load " << SharedObject << " " << TestModuleBC;
} else {
- outs() << " llc " << TestModuleBC.str() << " -o " << TestModuleBC.str()
+ outs() << " llc " << TestModuleBC << " -o " << TestModuleBC
<< ".s\n";
- outs() << " gcc " << SharedObject << " " << TestModuleBC.str()
- << ".s -o " << TestModuleBC.str() << ".exe";
+ outs() << " cc " << SharedObject << " " << TestModuleBC.str()
+ << ".s -o " << TestModuleBC << ".exe";
#if defined (HAVE_LINK_R)
outs() << " -Wl,-R.";
#endif
outs() << "\n";
- outs() << " " << TestModuleBC.str() << ".exe";
+ outs() << " " << TestModuleBC << ".exe";
}
for (unsigned i = 0, e = InputArgv.size(); i != e; ++i)
outs() << " " << InputArgv[i];
outs() << '\n';
outs() << "The shared object was created with:\n llc -march=c "
<< SafeModuleBC.str() << " -o temporary.c\n"
- << " gcc -xc temporary.c -O2 -o " << SharedObject;
+ << " cc -xc temporary.c -O2 -o " << SharedObject;
if (TargetTriple.getArch() == Triple::sparc)
outs() << " -G"; // Compile a shared library, `-G' for Sparc
else