Change the BugDriver to store the current module with std::unique_ptr.

While there, change a bunch of helper functions to take references to
avoid adding calls to get().

This should conclude the bugpoint yak shaving.

llvm-svn: 325177
This commit is contained in:
Rafael Espindola 2018-02-14 21:44:34 +00:00
parent d702241c98
commit f6074ed9f6
8 changed files with 185 additions and 207 deletions

View File

@ -55,12 +55,11 @@ cl::opt<std::string> OutputFile("output",
"(for miscompilation detection)"));
}
/// setNewProgram - If we reduce or update the program somehow, call this method
/// to update bugdriver with it. This deletes the old module and sets the
/// specified one as the current program.
void BugDriver::setNewProgram(Module *M) {
delete Program;
Program = M;
/// If we reduce or update the program somehow, call this method to update
/// bugdriver with it. This deletes the old module and sets the specified one
/// as the current program.
void BugDriver::setNewProgram(std::unique_ptr<Module> M) {
Program = std::move(M);
}
/// getPassesString - Turn a list of passes into a string which indicates the
@ -85,7 +84,6 @@ BugDriver::BugDriver(const char *toolname, bool find_bugs, unsigned timeout,
MemoryLimit(memlimit), UseValgrind(use_valgrind) {}
BugDriver::~BugDriver() {
delete Program;
if (Interpreter != SafeInterpreter)
delete Interpreter;
delete SafeInterpreter;
@ -121,6 +119,12 @@ std::unique_ptr<Module> llvm::parseInputFile(StringRef Filename,
return Result;
}
std::unique_ptr<Module> BugDriver::swapProgramIn(std::unique_ptr<Module> M) {
std::unique_ptr<Module> OldProgram = std::move(Program);
Program = std::move(M);
return OldProgram;
}
// This method takes the specified list of LLVM input files, attempts to load
// them, either as assembly or bitcode, then link them together. It returns
// true on failure (if, for example, an input bitcode file could not be
@ -131,7 +135,7 @@ bool BugDriver::addSources(const std::vector<std::string> &Filenames) {
assert(!Filenames.empty() && "Must specify at least on input filename!");
// Load the first input file.
Program = parseInputFile(Filenames[0], Context).release();
Program = parseInputFile(Filenames[0], Context);
if (!Program)
return true;
@ -172,7 +176,7 @@ Error BugDriver::run() {
// miscompilation.
if (!PassesToRun.empty()) {
outs() << "Running selected passes on program to test for crash: ";
if (runPasses(Program, PassesToRun))
if (runPasses(*Program, PassesToRun))
return debugOptimizerCrash();
}
@ -182,7 +186,7 @@ Error BugDriver::run() {
// Test to see if we have a code generator crash.
outs() << "Running the code generator to test for a crash: ";
if (Error E = compileProgram(Program)) {
if (Error E = compileProgram(*Program)) {
outs() << toString(std::move(E));
return debugCodeGeneratorCrash();
}
@ -195,7 +199,7 @@ Error BugDriver::run() {
bool CreatedOutput = false;
if (ReferenceOutputFile.empty()) {
outs() << "Generating reference output from raw program: ";
if (Error E = createReferenceFile(Program)) {
if (Error E = createReferenceFile(*Program)) {
errs() << toString(std::move(E));
return debugCodeGeneratorCrash();
}
@ -211,7 +215,7 @@ Error BugDriver::run() {
// matches, then we assume there is a miscompilation bug and try to
// diagnose it.
outs() << "*** Checking the code generator...\n";
Expected<bool> Diff = diffProgram(Program, "", "", false);
Expected<bool> Diff = diffProgram(*Program, "", "", false);
if (Error E = Diff.takeError()) {
errs() << toString(std::move(E));
return debugCodeGeneratorCrash();

View File

@ -50,7 +50,7 @@ class BugDriver {
LLVMContext &Context;
const char *ToolName; // argv[0] of bugpoint
std::string ReferenceOutputFile; // Name of `good' output file
Module *Program; // The raw program, linked together
std::unique_ptr<Module> Program; // The raw program, linked together
std::vector<std::string> PassesToRun;
AbstractInterpreter *Interpreter; // How to run the program
AbstractInterpreter *SafeInterpreter; // To generate reference output, etc.
@ -128,15 +128,10 @@ public:
///
bool isExecutingJIT();
Module *getProgram() const { return Program; }
Module &getProgram() const { return *Program; }
/// swapProgramIn - Set the current module to the specified module, returning
/// the old one.
Module *swapProgramIn(Module *M) {
Module *OldProgram = Program;
Program = M;
return OldProgram;
}
/// Set the current module to the specified module, returning the old one.
std::unique_ptr<Module> swapProgramIn(std::unique_ptr<Module> M);
AbstractInterpreter *switchToSafeInterpreter() {
AbstractInterpreter *Old = Interpreter;
@ -146,55 +141,47 @@ public:
void switchToInterpreter(AbstractInterpreter *AI) { Interpreter = AI; }
/// setNewProgram - If we reduce or update the program somehow, call this
/// method to update bugdriver with it. This deletes the old module and sets
/// the specified one as the current program.
void setNewProgram(Module *M);
/// If we reduce or update the program somehow, call this method to update
/// bugdriver with it. This deletes the old module and sets the specified one
/// as the current program.
void setNewProgram(std::unique_ptr<Module> M);
/// Try to compile the specified module. This is used for code generation
/// crash testing.
Error compileProgram(Module *M) const;
Error compileProgram(Module &M) const;
/// executeProgram - This method runs "Program", capturing the output of the
/// program to a file. A recommended filename may be optionally specified.
///
Expected<std::string> executeProgram(const Module *Program,
/// This method runs "Program", capturing the output of the program to a file.
/// A recommended filename may be optionally specified.
Expected<std::string> executeProgram(const Module &Program,
std::string OutputFilename,
std::string Bitcode,
const std::string &SharedObjects,
AbstractInterpreter *AI) const;
/// executeProgramSafely - Used to create reference output with the "safe"
/// backend, if reference output is not provided. If there is a problem with
/// the code generator (e.g., llc crashes), this will return false and set
/// Error.
///
/// Used to create reference output with the "safe" backend, if reference
/// output is not provided. If there is a problem with the code generator
/// (e.g., llc crashes), this will return false and set Error.
Expected<std::string>
executeProgramSafely(const Module *Program,
executeProgramSafely(const Module &Program,
const std::string &OutputFile) const;
/// createReferenceFile - calls compileProgram and then records the output
/// into ReferenceOutputFile. Returns true if reference file created, false
/// otherwise. Note: initializeExecutionEnvironment should be called BEFORE
/// this function.
///
Error createReferenceFile(Module *M, const std::string &Filename =
/// Calls compileProgram and then records the output into ReferenceOutputFile.
/// Returns true if reference file created, false otherwise. Note:
/// initializeExecutionEnvironment should be called BEFORE this function.
Error createReferenceFile(Module &M, const std::string &Filename =
"bugpoint.reference.out-%%%%%%%");
/// diffProgram - This method executes the specified module and diffs the
/// output against the file specified by ReferenceOutputFile. If the output
/// is different, 1 is returned. If there is a problem with the code
/// generator (e.g., llc crashes), this will return -1 and set Error.
///
Expected<bool> diffProgram(const Module *Program,
/// This method executes the specified module and diffs the output against the
/// file specified by ReferenceOutputFile. If the output is different, 1 is
/// returned. If there is a problem with the code generator (e.g., llc
/// crashes), this will return -1 and set Error.
Expected<bool> diffProgram(const Module &Program,
const std::string &BitcodeFile = "",
const std::string &SharedObj = "",
bool RemoveBitcode = false) const;
/// EmitProgressBitcode - This function is used to output M to a file named
/// "bugpoint-ID.bc".
///
void EmitProgressBitcode(const Module *M, const std::string &ID,
/// This function is used to output M to a file named "bugpoint-ID.bc".
void EmitProgressBitcode(const Module &M, const std::string &ID,
bool NoFlyer = false) const;
/// This method clones the current Program and deletes the specified
@ -243,7 +230,7 @@ public:
/// or failed, unless Quiet is set. ExtraArgs specifies additional arguments
/// to pass to the child bugpoint instance.
///
bool runPasses(Module *Program, const std::vector<std::string> &PassesToRun,
bool runPasses(Module &Program, const std::vector<std::string> &PassesToRun,
std::string &OutputFilename, bool DeleteOutput = false,
bool Quiet = false, unsigned NumExtraArgs = 0,
const char *const *ExtraArgs = nullptr) const;
@ -252,7 +239,7 @@ public:
/// false indicating whether or not the optimizer crashed on the specified
/// input (true = crashed). Does not produce any output.
///
bool runPasses(Module *M, const std::vector<std::string> &PassesToRun) const {
bool runPasses(Module &M, const std::vector<std::string> &PassesToRun) const {
std::string Filename;
return runPasses(M, PassesToRun, Filename, true);
}
@ -265,13 +252,12 @@ public:
/// failure.
Error runManyPasses(const std::vector<std::string> &AllPasses);
/// writeProgramToFile - This writes the current "Program" to the named
/// bitcode file. If an error occurs, true is returned.
///
bool writeProgramToFile(const std::string &Filename, const Module *M) const;
/// This writes the current "Program" to the named bitcode file. If an error
/// occurs, true is returned.
bool writeProgramToFile(const std::string &Filename, const Module &M) const;
bool writeProgramToFile(const std::string &Filename, int FD,
const Module *M) const;
bool writeProgramToFile(int FD, const Module *M) const;
const Module &M) const;
bool writeProgramToFile(int FD, const Module &M) const;
private:
/// initializeExecutionEnvironment - This method is used to set up the

View File

@ -92,9 +92,9 @@ ReducePassList::doTest(std::vector<std::string> &Prefix,
if (BD.runPasses(BD.getProgram(), Prefix, PrefixOutput))
return KeepPrefix;
OrigProgram.reset(BD.Program);
OrigProgram = std::move(BD.Program);
BD.Program = parseInputFile(PrefixOutput, BD.getContext()).release();
BD.Program = parseInputFile(PrefixOutput, BD.getContext());
if (BD.Program == nullptr) {
errs() << BD.getToolName() << ": Error reading bitcode file '"
<< PrefixOutput << "'!\n";
@ -110,10 +110,8 @@ ReducePassList::doTest(std::vector<std::string> &Prefix,
return KeepSuffix; // The suffix crashes alone...
// Nothing failed, restore state...
if (OrigProgram) {
delete BD.Program;
BD.Program = OrigProgram.release();
}
if (OrigProgram)
BD.Program = std::move(OrigProgram);
return NoFailure;
}
@ -148,7 +146,7 @@ bool ReduceCrashingGlobalInitializers::TestGlobalVariables(
std::vector<GlobalVariable *> &GVs) {
// Clone the program to try hacking it apart...
ValueToValueMapTy VMap;
std::unique_ptr<Module> M = CloneModule(*BD.getProgram(), VMap);
std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
// Convert list to set for fast lookup...
std::set<GlobalVariable *> GVSet;
@ -174,7 +172,7 @@ bool ReduceCrashingGlobalInitializers::TestGlobalVariables(
// Try running the hacked up program...
if (TestFn(BD, M.get())) {
BD.setNewProgram(M.release()); // It crashed, keep the trimmed version...
BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
// Make sure to use global variable pointers that point into the now-current
// module.
@ -237,12 +235,12 @@ static void RemoveFunctionReferences(Module *M, const char *Name) {
bool ReduceCrashingFunctions::TestFuncs(std::vector<Function *> &Funcs) {
// If main isn't present, claim there is no problem.
if (KeepMain && !is_contained(Funcs, BD.getProgram()->getFunction("main")))
if (KeepMain && !is_contained(Funcs, BD.getProgram().getFunction("main")))
return false;
// Clone the program to try hacking it apart...
ValueToValueMapTy VMap;
std::unique_ptr<Module> M = CloneModule(*BD.getProgram(), VMap);
std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
// Convert list to set for fast lookup...
std::set<Function *> Functions;
@ -306,7 +304,7 @@ bool ReduceCrashingFunctions::TestFuncs(std::vector<Function *> &Funcs) {
}
// Try running the hacked up program...
if (TestFn(BD, M.get())) {
BD.setNewProgram(M.release()); // It crashed, keep the trimmed version...
BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
// Make sure to use function pointers that point into the now-current
// module.
@ -385,7 +383,7 @@ public:
bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock *> &BBs) {
// Clone the program to try hacking it apart...
ValueToValueMapTy VMap;
std::unique_ptr<Module> M = CloneModule(*BD.getProgram(), VMap);
std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
// Convert list to set for fast lookup...
SmallPtrSet<BasicBlock *, 8> Blocks;
@ -454,12 +452,12 @@ bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock *> &BBs) {
// Try running on the hacked up program...
if (TestFn(BD, M.get())) {
BD.setNewProgram(M.release()); // It crashed, keep the trimmed version...
BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
// Make sure to use basic block pointers that point into the now-current
// module, and that they don't include any deleted blocks.
BBs.clear();
const ValueSymbolTable &GST = BD.getProgram()->getValueSymbolTable();
const ValueSymbolTable &GST = BD.getProgram().getValueSymbolTable();
for (const auto &BI : BlockInfo) {
Function *F = cast<Function>(GST.lookup(BI.first));
Value *V = F->getValueSymbolTable()->lookup(BI.second);
@ -504,7 +502,7 @@ bool ReduceCrashingConditionals::TestBlocks(
std::vector<const BasicBlock *> &BBs) {
// Clone the program to try hacking it apart...
ValueToValueMapTy VMap;
std::unique_ptr<Module> M = CloneModule(*BD.getProgram(), VMap);
std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
// Convert list to set for fast lookup...
SmallPtrSet<const BasicBlock *, 8> Blocks;
@ -561,12 +559,12 @@ bool ReduceCrashingConditionals::TestBlocks(
// Try running on the hacked up program...
if (TestFn(BD, M.get())) {
BD.setNewProgram(M.release()); // It crashed, keep the trimmed version...
BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
// Make sure to use basic block pointers that point into the now-current
// module, and that they don't include any deleted blocks.
BBs.clear();
const ValueSymbolTable &GST = BD.getProgram()->getValueSymbolTable();
const ValueSymbolTable &GST = BD.getProgram().getValueSymbolTable();
for (auto &BI : BlockInfo) {
auto *F = cast<Function>(GST.lookup(BI.first));
Value *V = F->getValueSymbolTable()->lookup(BI.second);
@ -590,7 +588,7 @@ class ReduceSimplifyCFG : public ListReducer<const BasicBlock *> {
public:
ReduceSimplifyCFG(BugDriver &bd, BugTester testFn)
: BD(bd), TestFn(testFn), TTI(bd.getProgram()->getDataLayout()) {}
: BD(bd), TestFn(testFn), TTI(bd.getProgram().getDataLayout()) {}
Expected<TestResult> doTest(std::vector<const BasicBlock *> &Prefix,
std::vector<const BasicBlock *> &Kept) override {
@ -608,7 +606,7 @@ public:
bool ReduceSimplifyCFG::TestBlocks(std::vector<const BasicBlock *> &BBs) {
// Clone the program to try hacking it apart...
ValueToValueMapTy VMap;
std::unique_ptr<Module> M = CloneModule(*BD.getProgram(), VMap);
std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
// Convert list to set for fast lookup...
SmallPtrSet<const BasicBlock *, 8> Blocks;
@ -653,12 +651,12 @@ bool ReduceSimplifyCFG::TestBlocks(std::vector<const BasicBlock *> &BBs) {
// Try running on the hacked up program...
if (TestFn(BD, M.get())) {
BD.setNewProgram(M.release()); // It crashed, keep the trimmed version...
BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
// Make sure to use basic block pointers that point into the now-current
// module, and that they don't include any deleted blocks.
BBs.clear();
const ValueSymbolTable &GST = BD.getProgram()->getValueSymbolTable();
const ValueSymbolTable &GST = BD.getProgram().getValueSymbolTable();
for (auto &BI : BlockInfo) {
auto *F = cast<Function>(GST.lookup(BI.first));
Value *V = F->getValueSymbolTable()->lookup(BI.second);
@ -700,7 +698,7 @@ bool ReduceCrashingInstructions::TestInsts(
std::vector<const Instruction *> &Insts) {
// Clone the program to try hacking it apart...
ValueToValueMapTy VMap;
std::unique_ptr<Module> M = CloneModule(*BD.getProgram(), VMap);
std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
// Convert list to set for fast lookup...
SmallPtrSet<Instruction *, 32> Instructions;
@ -735,7 +733,7 @@ bool ReduceCrashingInstructions::TestInsts(
// Try running on the hacked up program...
if (TestFn(BD, M.get())) {
BD.setNewProgram(M.release()); // It crashed, keep the trimmed version...
BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
// Make sure to use instruction pointers that point into the now-current
// module, and that they don't include any deleted blocks.
@ -775,7 +773,7 @@ public:
bool ReduceCrashingNamedMD::TestNamedMDs(std::vector<std::string> &NamedMDs) {
ValueToValueMapTy VMap;
std::unique_ptr<Module> M = CloneModule(*BD.getProgram(), VMap);
std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
outs() << "Checking for crash with only these named metadata nodes:";
unsigned NumPrint = std::min<size_t>(NamedMDs.size(), 10);
@ -810,7 +808,7 @@ bool ReduceCrashingNamedMD::TestNamedMDs(std::vector<std::string> &NamedMDs) {
// Try running on the hacked up program...
if (TestFn(BD, M.get())) {
BD.setNewProgram(M.release()); // It crashed, keep the trimmed version...
BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
return true;
}
return false;
@ -854,11 +852,11 @@ bool ReduceCrashingNamedMDOps::TestNamedMDOps(
outs() << " named metadata operands: ";
ValueToValueMapTy VMap;
std::unique_ptr<Module> M = CloneModule(*BD.getProgram(), VMap);
std::unique_ptr<Module> M = CloneModule(BD.getProgram(), VMap);
// This is a little wasteful. In the future it might be good if we could have
// these dropped during cloning.
for (auto &NamedMD : BD.getProgram()->named_metadata()) {
for (auto &NamedMD : BD.getProgram().named_metadata()) {
// Drop the old one and create a new one
M->eraseNamedMetadata(M->getNamedMetadata(NamedMD.getName()));
NamedMDNode *NewNamedMDNode =
@ -881,7 +879,7 @@ bool ReduceCrashingNamedMDOps::TestNamedMDOps(
for (const MDNode *Node : OldMDNodeOps)
NamedMDOps.push_back(cast<MDNode>(*VMap.getMappedMD(Node)));
BD.setNewProgram(M.release()); // It crashed, keep the trimmed version...
BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
return true;
}
// It didn't crash, try something else.
@ -890,13 +888,13 @@ bool ReduceCrashingNamedMDOps::TestNamedMDOps(
/// Attempt to eliminate as many global initializers as possible.
static Error ReduceGlobalInitializers(BugDriver &BD, BugTester TestFn) {
Module *OrigM = BD.getProgram();
if (OrigM->global_empty())
Module &OrigM = BD.getProgram();
if (OrigM.global_empty())
return Error::success();
// Now try to reduce the number of global variable initializers in the
// module to something small.
std::unique_ptr<Module> M = CloneModule(*OrigM);
std::unique_ptr<Module> M = CloneModule(OrigM);
bool DeletedInit = false;
for (GlobalVariable &GV : M->globals()) {
@ -915,7 +913,7 @@ static Error ReduceGlobalInitializers(BugDriver &BD, BugTester TestFn) {
outs() << "\nChecking to see if we can delete global inits: ";
if (TestFn(BD, M.get())) { // Still crashes?
BD.setNewProgram(M.release());
BD.setNewProgram(std::move(M));
outs() << "\n*** Able to remove all global initializers!\n";
return Error::success();
}
@ -924,7 +922,7 @@ static Error ReduceGlobalInitializers(BugDriver &BD, BugTester TestFn) {
outs() << " - Removing all global inits hides problem!\n";
std::vector<GlobalVariable *> GVs;
for (GlobalVariable &GV : OrigM->globals())
for (GlobalVariable &GV : OrigM.globals())
if (GV.hasInitializer())
GVs.push_back(&GV);
@ -949,7 +947,7 @@ static Error ReduceInsts(BugDriver &BD, BugTester TestFn) {
// cases with large basic blocks where the problem is at one end.
if (!BugpointIsInterrupted) {
std::vector<const Instruction *> Insts;
for (const Function &F : *BD.getProgram())
for (const Function &F : BD.getProgram())
for (const BasicBlock &BB : F)
for (const Instruction &I : BB)
if (!isa<TerminatorInst>(&I))
@ -984,8 +982,8 @@ static Error ReduceInsts(BugDriver &BD, BugTester TestFn) {
// Loop over all of the (non-terminator) instructions remaining in the
// function, attempting to delete them.
unsigned CurInstructionNum = 0;
for (Module::const_iterator FI = BD.getProgram()->begin(),
E = BD.getProgram()->end();
for (Module::const_iterator FI = BD.getProgram().begin(),
E = BD.getProgram().end();
FI != E; ++FI)
if (!FI->isDeclaration())
for (Function::const_iterator BI = FI->begin(), E = FI->end(); BI != E;
@ -1011,7 +1009,7 @@ static Error ReduceInsts(BugDriver &BD, BugTester TestFn) {
if (TestFn(BD, M.get())) {
// Yup, it does, we delete the old module, and continue trying
// to reduce the testcase...
BD.setNewProgram(M.release());
BD.setNewProgram(std::move(M));
InstructionsToSkipBeforeDeleting = CurInstructionNum;
goto TryAgain; // I wish I had a multi-level break here!
}
@ -1040,7 +1038,7 @@ static Error DebugACrash(BugDriver &BD, BugTester TestFn) {
// Now try to reduce the number of functions in the module to something small.
std::vector<Function *> Functions;
for (Function &F : *BD.getProgram())
for (Function &F : BD.getProgram())
if (!F.isDeclaration())
Functions.push_back(&F);
@ -1062,7 +1060,7 @@ static Error DebugACrash(BugDriver &BD, BugTester TestFn) {
// eliminate blocks.
if (!DisableSimplifyCFG && !BugpointIsInterrupted) {
std::vector<const BasicBlock *> Blocks;
for (Function &F : *BD.getProgram())
for (Function &F : BD.getProgram())
for (BasicBlock &BB : F)
Blocks.push_back(&BB);
unsigned OldSize = Blocks.size();
@ -1084,7 +1082,7 @@ static Error DebugACrash(BugDriver &BD, BugTester TestFn) {
//
if (!DisableSimplifyCFG && !BugpointIsInterrupted) {
std::vector<const BasicBlock *> Blocks;
for (Function &F : *BD.getProgram())
for (Function &F : BD.getProgram())
for (BasicBlock &BB : F)
Blocks.push_back(&BB);
unsigned OldSize = Blocks.size();
@ -1097,7 +1095,7 @@ static Error DebugACrash(BugDriver &BD, BugTester TestFn) {
if (!DisableSimplifyCFG && !BugpointIsInterrupted) {
std::vector<const BasicBlock *> Blocks;
for (Function &F : *BD.getProgram())
for (Function &F : BD.getProgram())
for (BasicBlock &BB : F)
Blocks.push_back(&BB);
unsigned OldSize = Blocks.size();
@ -1116,10 +1114,10 @@ static Error DebugACrash(BugDriver &BD, BugTester TestFn) {
// Attempt to strip debug info metadata.
auto stripMetadata = [&](std::function<bool(Module &)> strip) {
std::unique_ptr<Module> M = CloneModule(*BD.getProgram());
std::unique_ptr<Module> M = CloneModule(BD.getProgram());
strip(*M);
if (TestFn(BD, M.get()))
BD.setNewProgram(M.release());
BD.setNewProgram(std::move(M));
};
if (!NoStripDebugInfo && !BugpointIsInterrupted) {
outs() << "\n*** Attempting to strip the debug info: ";
@ -1136,7 +1134,7 @@ static Error DebugACrash(BugDriver &BD, BugTester TestFn) {
// by dropping global named metadata that anchors them
outs() << "\n*** Attempting to remove named metadata: ";
std::vector<std::string> NamedMDNames;
for (auto &NamedMD : BD.getProgram()->named_metadata())
for (auto &NamedMD : BD.getProgram().named_metadata())
NamedMDNames.push_back(NamedMD.getName().str());
Expected<bool> Result =
ReduceCrashingNamedMD(BD, TestFn).reduceList(NamedMDNames);
@ -1148,7 +1146,7 @@ static Error DebugACrash(BugDriver &BD, BugTester TestFn) {
// Now that we quickly dropped all the named metadata that doesn't
// contribute to the crash, bisect the operands of the remaining ones
std::vector<const MDNode *> NamedMDOps;
for (auto &NamedMD : BD.getProgram()->named_metadata())
for (auto &NamedMD : BD.getProgram().named_metadata())
for (auto op : NamedMD.operands())
NamedMDOps.push_back(op);
Expected<bool> Result =
@ -1162,12 +1160,13 @@ static Error DebugACrash(BugDriver &BD, BugTester TestFn) {
// Try to clean up the testcase by running funcresolve and globaldce...
if (!BugpointIsInterrupted) {
outs() << "\n*** Attempting to perform final cleanups: ";
std::unique_ptr<Module> M = CloneModule(*BD.getProgram());
std::unique_ptr<Module> M = CloneModule(BD.getProgram());
M = BD.performFinalCleanups(M.release(), true);
// Find out if the pass still crashes on the cleaned up program...
if (M && TestFn(BD, M.get()))
BD.setNewProgram(M.release()); // Yup, it does, keep the reduced version...
BD.setNewProgram(
std::move(M)); // Yup, it does, keep the reduced version...
}
BD.EmitProgressBitcode(BD.getProgram(), "reduced-simplified");
@ -1176,7 +1175,7 @@ static Error DebugACrash(BugDriver &BD, BugTester TestFn) {
}
static bool TestForOptimizerCrash(const BugDriver &BD, Module *M) {
return BD.runPasses(M, BD.getPassesToRun());
return BD.runPasses(*M, BD.getPassesToRun());
}
/// debugOptimizerCrash - This method is called when some pass crashes on input.
@ -1197,13 +1196,13 @@ Error BugDriver::debugOptimizerCrash(const std::string &ID) {
<< (PassesToRun.size() == 1 ? ": " : "es: ")
<< getPassesString(PassesToRun) << '\n';
EmitProgressBitcode(Program, ID);
EmitProgressBitcode(*Program, ID);
return DebugACrash(*this, TestForOptimizerCrash);
}
static bool TestForCodeGenCrash(const BugDriver &BD, Module *M) {
if (Error E = BD.compileProgram(M)) {
if (Error E = BD.compileProgram(*M)) {
if (VerboseErrors)
errs() << toString(std::move(E)) << "\n";
else {

View File

@ -265,11 +265,9 @@ Error BugDriver::initializeExecutionEnvironment() {
return Error::success();
}
/// compileProgram - Try to compile the specified module, returning false and
/// setting Error if an error occurs. This is used for code generation
/// crash testing.
///
Error BugDriver::compileProgram(Module *M) const {
/// Try to compile the specified module, returning false and setting Error if an
/// error occurs. This is used for code generation crash testing.
Error BugDriver::compileProgram(Module &M) const {
// Emit the program to a bitcode file...
auto Temp =
sys::fs::TempFile::create(OutputPrefix + "-test-program-%%%%%%%.bc");
@ -290,11 +288,10 @@ Error BugDriver::compileProgram(Module *M) const {
return Interpreter->compileProgram(Temp->TmpName, Timeout, MemoryLimit);
}
/// executeProgram - This method runs "Program", capturing the output of the
/// program to a file, returning the filename of the file. A recommended
/// filename may be optionally specified.
///
Expected<std::string> BugDriver::executeProgram(const Module *Program,
/// This method runs "Program", capturing the output of the program to a file,
/// returning the filename of the file. A recommended filename may be
/// optionally specified.
Expected<std::string> BugDriver::executeProgram(const Module &Program,
std::string OutputFile,
std::string BitcodeFile,
const std::string &SharedObj,
@ -373,11 +370,10 @@ Expected<std::string> BugDriver::executeProgram(const Module *Program,
return OutputFile;
}
/// executeProgramSafely - Used to create reference output with the "safe"
/// backend, if reference output is not provided.
///
/// Used to create reference output with the "safe" backend, if reference output
/// is not provided.
Expected<std::string>
BugDriver::executeProgramSafely(const Module *Program,
BugDriver::executeProgramSafely(const Module &Program,
const std::string &OutputFile) const {
return executeProgram(Program, OutputFile, "", "", SafeInterpreter);
}
@ -404,16 +400,14 @@ BugDriver::compileSharedObject(const std::string &BitcodeFile) {
return SharedObjectFile;
}
/// createReferenceFile - calls compileProgram and then records the output
/// into ReferenceOutputFile. Returns true if reference file created, false
/// otherwise. Note: initializeExecutionEnvironment should be called BEFORE
/// this function.
///
Error BugDriver::createReferenceFile(Module *M, const std::string &Filename) {
if (Error E = compileProgram(Program))
/// Calls compileProgram and then records the output into ReferenceOutputFile.
/// Returns true if reference file created, false otherwise. Note:
/// initializeExecutionEnvironment should be called BEFORE this function.
Error BugDriver::createReferenceFile(Module &M, const std::string &Filename) {
if (Error E = compileProgram(*Program))
return E;
Expected<std::string> Result = executeProgramSafely(Program, Filename);
Expected<std::string> Result = executeProgramSafely(*Program, Filename);
if (Error E = Result.takeError()) {
if (Interpreter != SafeInterpreter) {
E = joinErrors(
@ -432,12 +426,11 @@ Error BugDriver::createReferenceFile(Module *M, const std::string &Filename) {
return Error::success();
}
/// diffProgram - This method executes the specified module and diffs the
/// output against the file specified by ReferenceOutputFile. If the output
/// is different, 1 is returned. If there is a problem with the code
/// generator (e.g., llc crashes), this will set ErrMsg.
///
Expected<bool> BugDriver::diffProgram(const Module *Program,
/// This method executes the specified module and diffs the output against the
/// file specified by ReferenceOutputFile. If the output is different, 1 is
/// returned. If there is a problem with the code generator (e.g., llc
/// crashes), this will set ErrMsg.
Expected<bool> BugDriver::diffProgram(const Module &Program,
const std::string &BitcodeFile,
const std::string &SharedObject,
bool RemoveBitcode) const {

View File

@ -156,7 +156,7 @@ std::unique_ptr<Module> BugDriver::extractLoop(Module *M) {
std::unique_ptr<Module> NewM = runPassesOn(M, LoopExtractPasses);
if (!NewM) {
outs() << "*** Loop extraction failed: ";
EmitProgressBitcode(M, "loopextraction", true);
EmitProgressBitcode(*M, "loopextraction", true);
outs() << "*** Sorry. :( Please report a bug!\n";
return nullptr;
}
@ -377,7 +377,7 @@ BugDriver::extractMappedBlocksFromModule(const std::vector<BasicBlock *> &BBs,
outs() << "*** Basic Block extraction failed!\n";
errs() << "Error creating temporary file: " << toString(Temp.takeError())
<< "\n";
EmitProgressBitcode(M, "basicblockextractfail", true);
EmitProgressBitcode(*M, "basicblockextractfail", true);
return nullptr;
}
DiscardTemp Discard{*Temp};
@ -401,7 +401,7 @@ BugDriver::extractMappedBlocksFromModule(const std::vector<BasicBlock *> &BBs,
OS.flush();
if (OS.has_error()) {
errs() << "Error writing list of blocks to not extract\n";
EmitProgressBitcode(M, "basicblockextractfail", true);
EmitProgressBitcode(*M, "basicblockextractfail", true);
OS.clear_error();
return nullptr;
}
@ -416,7 +416,7 @@ BugDriver::extractMappedBlocksFromModule(const std::vector<BasicBlock *> &BBs,
if (!Ret) {
outs() << "*** Basic Block extraction failed, please report a bug!\n";
EmitProgressBitcode(M, "basicblockextractfail", true);
EmitProgressBitcode(*M, "basicblockextractfail", true);
}
return Ret;
}

View File

@ -32,7 +32,7 @@ BugDriver::runManyPasses(const std::vector<std::string> &AllPasses) {
outs() << "\n";
if (ReferenceOutputFile.empty()) {
outs() << "Generating reference output from raw program: \n";
if (Error E = createReferenceFile(Program))
if (Error E = createReferenceFile(*Program))
return E;
}
@ -53,7 +53,7 @@ BugDriver::runManyPasses(const std::vector<std::string> &AllPasses) {
}
std::string Filename;
if (runPasses(Program, PassesToRun, Filename, false)) {
if (runPasses(*Program, PassesToRun, Filename, false)) {
outs() << "\n";
outs() << "Optimizer passes caused failure!\n\n";
return debugOptimizerCrash();
@ -65,7 +65,7 @@ BugDriver::runManyPasses(const std::vector<std::string> &AllPasses) {
// Step 3: Compile the optimized code.
//
outs() << "Running the code generator to test for a crash: ";
if (Error E = compileProgram(Program)) {
if (Error E = compileProgram(*Program)) {
outs() << "\n*** compileProgram threw an exception: ";
outs() << toString(std::move(E));
return debugCodeGeneratorCrash();
@ -77,7 +77,7 @@ BugDriver::runManyPasses(const std::vector<std::string> &AllPasses) {
// output (created above).
//
outs() << "*** Checking if passes caused miscompliation:\n";
Expected<bool> Diff = diffProgram(Program, Filename, "", false);
Expected<bool> Diff = diffProgram(*Program, Filename, "", false);
if (Error E = Diff.takeError()) {
errs() << toString(std::move(E));
return debugCodeGeneratorCrash();

View File

@ -152,8 +152,8 @@ ReduceMiscompilingPasses::doTest(std::vector<std::string> &Prefix,
<< "' passes compile correctly after the '" << getPassesString(Prefix)
<< "' passes: ";
std::unique_ptr<Module> OriginalInput(
BD.swapProgramIn(PrefixOutput.release()));
std::unique_ptr<Module> OriginalInput =
BD.swapProgramIn(std::move(PrefixOutput));
if (BD.runPasses(BD.getProgram(), Suffix, BitcodeResult, false /*delete*/,
true /*quiet*/)) {
errs() << " Error running this sequence of passes"
@ -179,7 +179,7 @@ ReduceMiscompilingPasses::doTest(std::vector<std::string> &Prefix,
// Otherwise, we must not be running the bad pass anymore.
outs() << " yup.\n"; // No miscompilation!
// Restore orig program & free test.
delete BD.swapProgramIn(OriginalInput.release());
BD.setNewProgram(std::move(OriginalInput));
return NoFailure;
}
@ -236,7 +236,7 @@ static Expected<std::unique_ptr<Module>> testMergedProgram(const BugDriver &BD,
exit(1);
// Execute the program.
Expected<bool> Diff = BD.diffProgram(Merged.get(), "", "", false);
Expected<bool> Diff = BD.diffProgram(*Merged, "", "", false);
if (Error E = Diff.takeError())
return std::move(E);
Broken = *Diff;
@ -265,8 +265,8 @@ ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function *> &Funcs) {
// 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;
std::unique_ptr<Module> Clone = CloneModule(*BD.getProgram(), VMap);
std::unique_ptr<Module> Orig(BD.swapProgramIn(Clone.release()));
std::unique_ptr<Module> Clone = CloneModule(BD.getProgram(), VMap);
std::unique_ptr<Module> Orig = BD.swapProgramIn(std::move(Clone));
std::vector<Function *> FuncsOnClone;
for (unsigned i = 0, e = Funcs.size(); i != e; ++i) {
@ -276,26 +276,25 @@ ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function *> &Funcs) {
// Split the module into the two halves of the program we want.
VMap.clear();
std::unique_ptr<Module> ToNotOptimize = CloneModule(*BD.getProgram(), VMap);
std::unique_ptr<Module> ToNotOptimize = CloneModule(BD.getProgram(), VMap);
std::unique_ptr<Module> ToOptimize =
SplitFunctionsOutOfModule(ToNotOptimize.get(), FuncsOnClone, VMap);
Expected<bool> Broken =
TestFn(BD, std::move(ToOptimize), std::move(ToNotOptimize));
delete BD.swapProgramIn(Orig.release());
BD.setNewProgram(std::move(Orig));
return Broken;
}
/// DisambiguateGlobalSymbols - Give anonymous global values names.
///
static void DisambiguateGlobalSymbols(Module *M) {
for (Module::global_iterator I = M->global_begin(), E = M->global_end();
I != E; ++I)
/// Give anonymous global values names.
static void DisambiguateGlobalSymbols(Module &M) {
for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E;
++I)
if (!I->hasName())
I->setName("anon_global");
for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
if (!I->hasName())
I->setName("anon_fn");
}
@ -315,7 +314,7 @@ ExtractLoops(BugDriver &BD,
return MadeChange;
ValueToValueMapTy VMap;
std::unique_ptr<Module> ToNotOptimize = CloneModule(*BD.getProgram(), VMap);
std::unique_ptr<Module> ToNotOptimize = CloneModule(BD.getProgram(), VMap);
std::unique_ptr<Module> ToOptimize = SplitFunctionsOutOfModule(
ToNotOptimize.get(), MiscompiledFunctions, VMap);
std::unique_ptr<Module> ToOptimizeLoopExtracted =
@ -342,7 +341,7 @@ ExtractLoops(BugDriver &BD,
return false;
// Delete the original and set the new program.
std::unique_ptr<Module> Old(BD.swapProgramIn(New->release()));
std::unique_ptr<Module> Old = BD.swapProgramIn(std::move(*New));
for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i)
MiscompiledFunctions[i] = cast<Function>(VMap[MiscompiledFunctions[i]]);
@ -355,11 +354,11 @@ ExtractLoops(BugDriver &BD,
errs() << " Continuing on with un-loop-extracted version.\n";
BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-tno.bc",
ToNotOptimize.get());
*ToNotOptimize);
BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to.bc",
ToOptimize.get());
*ToOptimize);
BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to-le.bc",
ToOptimizeLoopExtracted.get());
*ToOptimizeLoopExtracted);
errs() << "Please submit the " << OutputPrefix
<< "-loop-extract-fail-*.bc files.\n";
@ -406,7 +405,7 @@ ExtractLoops(BugDriver &BD,
MiscompiledFunctions.push_back(NewF);
}
BD.setNewProgram(ToNotOptimize.release());
BD.setNewProgram(std::move(ToNotOptimize));
return MadeChange;
}
@ -437,7 +436,7 @@ ExtractLoops(BugDriver &BD,
MiscompiledFunctions.push_back(NewF);
}
BD.setNewProgram(ToNotOptimize.release());
BD.setNewProgram(std::move(ToNotOptimize));
MadeChange = true;
}
}
@ -501,8 +500,8 @@ ReduceMiscompiledBlocks::TestFuncs(const std::vector<BasicBlock *> &BBs) {
// Split the module into the two halves of the program we want.
ValueToValueMapTy VMap;
std::unique_ptr<Module> Clone = CloneModule(*BD.getProgram(), VMap);
std::unique_ptr<Module> Orig(BD.swapProgramIn(Clone.release()));
std::unique_ptr<Module> Clone = CloneModule(BD.getProgram(), VMap);
std::unique_ptr<Module> Orig = BD.swapProgramIn(std::move(Clone));
std::vector<Function *> FuncsOnClone;
std::vector<BasicBlock *> BBsOnClone;
for (unsigned i = 0, e = FunctionsBeingTested.size(); i != e; ++i) {
@ -515,7 +514,7 @@ ReduceMiscompiledBlocks::TestFuncs(const std::vector<BasicBlock *> &BBs) {
}
VMap.clear();
std::unique_ptr<Module> ToNotOptimize = CloneModule(*BD.getProgram(), VMap);
std::unique_ptr<Module> ToNotOptimize = CloneModule(BD.getProgram(), VMap);
std::unique_ptr<Module> ToOptimize =
SplitFunctionsOutOfModule(ToNotOptimize.get(), FuncsOnClone, VMap);
@ -524,10 +523,10 @@ ReduceMiscompiledBlocks::TestFuncs(const std::vector<BasicBlock *> &BBs) {
if (std::unique_ptr<Module> New =
BD.extractMappedBlocksFromModule(BBsOnClone, ToOptimize.get())) {
Expected<bool> Ret = TestFn(BD, std::move(New), std::move(ToNotOptimize));
delete BD.swapProgramIn(Orig.release());
BD.setNewProgram(std::move(Orig));
return Ret;
}
delete BD.swapProgramIn(Orig.release());
BD.setNewProgram(std::move(Orig));
return false;
}
@ -570,7 +569,7 @@ ExtractBlocks(BugDriver &BD,
}
ValueToValueMapTy VMap;
std::unique_ptr<Module> ProgClone = CloneModule(*BD.getProgram(), VMap);
std::unique_ptr<Module> ProgClone = CloneModule(BD.getProgram(), VMap);
std::unique_ptr<Module> ToExtract =
SplitFunctionsOutOfModule(ProgClone.get(), MiscompiledFunctions, VMap);
std::unique_ptr<Module> Extracted =
@ -594,7 +593,7 @@ ExtractBlocks(BugDriver &BD,
exit(1);
// Set the new program and delete the old one.
BD.setNewProgram(ProgClone.release());
BD.setNewProgram(std::move(ProgClone));
// Update the list of miscompiled functions.
MiscompiledFunctions.clear();
@ -620,8 +619,8 @@ static Expected<std::vector<Function *>> DebugAMiscompilation(
// miscompiled... first build a list of all of the non-external functions in
// the program.
std::vector<Function *> MiscompiledFunctions;
Module *Prog = BD.getProgram();
for (Function &F : *Prog)
Module &Prog = BD.getProgram();
for (Function &F : Prog)
if (!F.isDeclaration())
MiscompiledFunctions.push_back(&F);
@ -707,8 +706,8 @@ static Expected<bool> TestOptimizer(BugDriver &BD, std::unique_ptr<Module> Test,
if (!Optimized) {
errs() << " Error running this sequence of passes"
<< " on the input program!\n";
delete BD.swapProgramIn(Test.get());
BD.EmitProgressBitcode(Test.get(), "pass-error", false);
BD.setNewProgram(std::move(Test));
BD.EmitProgressBitcode(*Test, "pass-error", false);
if (Error E = BD.debugOptimizerCrash())
return std::move(E);
return false;
@ -723,7 +722,7 @@ static Expected<bool> TestOptimizer(BugDriver &BD, std::unique_ptr<Module> Test,
if (auto New = std::move(*Result)) {
outs() << (Broken ? " nope.\n" : " yup.\n");
// Delete the original and set the new program.
delete BD.swapProgramIn(New.release());
BD.setNewProgram(std::move(New));
}
return Broken;
}
@ -749,7 +748,7 @@ Error BugDriver::debugMiscompilation() {
outs() << "\n*** Found miscompiling pass"
<< (getPassesToRun().size() == 1 ? "" : "es") << ": "
<< getPassesString(getPassesToRun()) << '\n';
EmitProgressBitcode(Program, "passinput");
EmitProgressBitcode(*Program, "passinput");
Expected<std::vector<Function *>> MiscompiledFunctions =
DebugAMiscompilation(*this, TestOptimizer);
@ -759,17 +758,17 @@ Error BugDriver::debugMiscompilation() {
// 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).release();
Module *ToNotOptimize = CloneModule(getProgram(), VMap).release();
Module *ToOptimize =
SplitFunctionsOutOfModule(ToNotOptimize, *MiscompiledFunctions, VMap)
.release();
outs() << " Non-optimized portion: ";
EmitProgressBitcode(ToNotOptimize, "tonotoptimize", true);
EmitProgressBitcode(*ToNotOptimize, "tonotoptimize", true);
delete ToNotOptimize; // Delete hacked module.
outs() << " Portion that is input to optimizer: ";
EmitProgressBitcode(ToOptimize, "tooptimize");
EmitProgressBitcode(*ToOptimize, "tooptimize");
delete ToOptimize; // Delete hacked module.
return Error::success();
@ -951,7 +950,7 @@ static Expected<bool> TestCodeGenerator(BugDriver &BD,
<< "Error making unique filename: " << EC.message() << "\n";
exit(1);
}
if (BD.writeProgramToFile(TestModuleBC.str(), TestModuleFD, Test.get())) {
if (BD.writeProgramToFile(TestModuleBC.str(), TestModuleFD, *Test)) {
errs() << "Error writing bitcode to `" << TestModuleBC.str()
<< "'\nExiting.";
exit(1);
@ -970,7 +969,7 @@ static Expected<bool> TestCodeGenerator(BugDriver &BD,
exit(1);
}
if (BD.writeProgramToFile(SafeModuleBC.str(), SafeModuleFD, Safe.get())) {
if (BD.writeProgramToFile(SafeModuleBC.str(), SafeModuleFD, *Safe)) {
errs() << "Error writing bitcode to `" << SafeModuleBC << "'\nExiting.";
exit(1);
}
@ -1004,7 +1003,7 @@ static Expected<bool> TestCodeGenerator(BugDriver &BD,
Error BugDriver::debugCodeGenerator() {
if ((void *)SafeInterpreter == (void *)Interpreter) {
Expected<std::string> Result =
executeProgramSafely(Program, "bugpoint.safe.out");
executeProgramSafely(*Program, "bugpoint.safe.out");
if (Result) {
outs() << "\n*** The \"safe\" i.e. 'known good' backend cannot match "
<< "the reference diff. This may be due to a\n front-end "
@ -1017,7 +1016,7 @@ Error BugDriver::debugCodeGenerator() {
return Error::success();
}
DisambiguateGlobalSymbols(Program);
DisambiguateGlobalSymbols(*Program);
Expected<std::vector<Function *>> Funcs =
DebugAMiscompilation(*this, TestCodeGenerator);
@ -1026,7 +1025,7 @@ Error BugDriver::debugCodeGenerator() {
// Split the module into the two halves of the program we want.
ValueToValueMapTy VMap;
std::unique_ptr<Module> ToNotCodeGen = CloneModule(*getProgram(), VMap);
std::unique_ptr<Module> ToNotCodeGen = CloneModule(getProgram(), VMap);
std::unique_ptr<Module> ToCodeGen =
SplitFunctionsOutOfModule(ToNotCodeGen.get(), *Funcs, VMap);
@ -1043,7 +1042,7 @@ Error BugDriver::debugCodeGenerator() {
exit(1);
}
if (writeProgramToFile(TestModuleBC.str(), TestModuleFD, ToCodeGen.get())) {
if (writeProgramToFile(TestModuleBC.str(), TestModuleFD, *ToCodeGen)) {
errs() << "Error writing bitcode to `" << TestModuleBC << "'\nExiting.";
exit(1);
}
@ -1059,8 +1058,7 @@ Error BugDriver::debugCodeGenerator() {
exit(1);
}
if (writeProgramToFile(SafeModuleBC.str(), SafeModuleFD,
ToNotCodeGen.get())) {
if (writeProgramToFile(SafeModuleBC.str(), SafeModuleFD, *ToNotCodeGen)) {
errs() << "Error writing bitcode to `" << SafeModuleBC << "'\nExiting.";
exit(1);
}

View File

@ -48,11 +48,10 @@ static cl::opt<std::string>
cl::desc("Path to opt. (default: search path "
"for 'opt'.)"));
/// writeProgramToFile - This writes the current "Program" to the named bitcode
/// file. If an error occurs, true is returned.
///
static bool writeProgramToFileAux(ToolOutputFile &Out, const Module *M) {
WriteBitcodeToFile(*M, Out.os(), PreserveBitcodeUseListOrder);
/// This writes the current "Program" to the named bitcode file. If an error
/// occurs, true is returned.
static bool writeProgramToFileAux(ToolOutputFile &Out, const Module &M) {
WriteBitcodeToFile(M, Out.os(), PreserveBitcodeUseListOrder);
Out.os().close();
if (!Out.os().has_error()) {
Out.keep();
@ -62,14 +61,14 @@ static bool writeProgramToFileAux(ToolOutputFile &Out, const Module *M) {
}
bool BugDriver::writeProgramToFile(const std::string &Filename, int FD,
const Module *M) const {
const Module &M) const {
ToolOutputFile Out(Filename, FD);
return writeProgramToFileAux(Out, M);
}
bool BugDriver::writeProgramToFile(int FD, const Module *M) const {
bool BugDriver::writeProgramToFile(int FD, const Module &M) const {
raw_fd_ostream OS(FD, /*shouldClose*/ false);
WriteBitcodeToFile(*M, OS, PreserveBitcodeUseListOrder);
WriteBitcodeToFile(M, OS, PreserveBitcodeUseListOrder);
OS.flush();
if (!OS.has_error())
return false;
@ -78,7 +77,7 @@ bool BugDriver::writeProgramToFile(int FD, const Module *M) const {
}
bool BugDriver::writeProgramToFile(const std::string &Filename,
const Module *M) const {
const Module &M) const {
std::error_code EC;
ToolOutputFile Out(Filename, EC, sys::fs::F_None);
if (!EC)
@ -86,10 +85,9 @@ bool BugDriver::writeProgramToFile(const std::string &Filename,
return true;
}
/// EmitProgressBitcode - This function is used to output the current Program
/// to a file named "bugpoint-ID.bc".
///
void BugDriver::EmitProgressBitcode(const Module *M, const std::string &ID,
/// This function is used to output the current Program to a file named
/// "bugpoint-ID.bc".
void BugDriver::EmitProgressBitcode(const Module &M, const std::string &ID,
bool NoFlyer) const {
// Output the input to the current pass to a bitcode file, emit a message
// telling the user how to reproduce it: opt -foo blah.bc
@ -129,7 +127,7 @@ static cl::list<std::string> OptArgs("opt-args", cl::Positional,
/// outs() a single line message indicating whether compilation was successful
/// or failed.
///
bool BugDriver::runPasses(Module *Program,
bool BugDriver::runPasses(Module &Program,
const std::vector<std::string> &Passes,
std::string &OutputFilename, bool DeleteOutput,
bool Quiet, unsigned NumExtraArgs,
@ -158,7 +156,7 @@ bool BugDriver::runPasses(Module *Program,
DiscardTemp Discard{*Temp};
raw_fd_ostream OS(Temp->FD, /*shouldClose*/ false);
WriteBitcodeToFile(*Program, OS, PreserveBitcodeUseListOrder);
WriteBitcodeToFile(Program, OS, PreserveBitcodeUseListOrder);
OS.flush();
if (OS.has_error()) {
errs() << "Error writing bitcode file: " << Temp->TmpName << "\n";
@ -272,7 +270,7 @@ std::unique_ptr<Module>
BugDriver::runPassesOn(Module *M, const std::vector<std::string> &Passes,
unsigned NumExtraArgs, const char *const *ExtraArgs) {
std::string BitcodeResult;
if (runPasses(M, Passes, BitcodeResult, false /*delete*/, true /*quiet*/,
if (runPasses(*M, Passes, BitcodeResult, false /*delete*/, true /*quiet*/,
NumExtraArgs, ExtraArgs)) {
return nullptr;
}