mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
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:
parent
503af7c700
commit
829dbc0aeb
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user