// passes. If we return true, we update the current module of bugpoint.
//
virtual TestResult doTest(std::vector<const PassInfo*> &Removed,
- std::vector<const PassInfo*> &Kept);
+ std::vector<const PassInfo*> &Kept,
+ std::string &Error);
};
}
ReducePassList::TestResult
ReducePassList::doTest(std::vector<const PassInfo*> &Prefix,
- std::vector<const PassInfo*> &Suffix) {
+ std::vector<const PassInfo*> &Suffix,
+ std::string &Error) {
sys::Path PrefixOutput;
Module *OrigProgram = 0;
if (!Prefix.empty()) {
PrefixOutput.set(PfxOutput);
OrigProgram = BD.Program;
- BD.Program = ParseInputFile(PrefixOutput.toString(), BD.getContext());
+ BD.Program = ParseInputFile(PrefixOutput.str(), BD.getContext());
if (BD.Program == 0) {
errs() << BD.getToolName() << ": Error reading bitcode file '"
- << PrefixOutput << "'!\n";
+ << PrefixOutput.str() << "'!\n";
exit(1);
}
PrefixOutput.eraseFromDisk();
bool (*TestFn)(BugDriver &, Module *);
public:
ReduceCrashingGlobalVariables(BugDriver &bd,
- bool (*testFn)(BugDriver&, Module*))
+ bool (*testFn)(BugDriver &, Module *))
: BD(bd), TestFn(testFn) {}
- virtual TestResult doTest(std::vector<GlobalVariable*>& Prefix,
- std::vector<GlobalVariable*>& Kept) {
+ virtual TestResult doTest(std::vector<GlobalVariable*> &Prefix,
+ std::vector<GlobalVariable*> &Kept,
+ std::string &Error) {
if (!Kept.empty() && TestGlobalVariables(Kept))
return KeepSuffix;
-
if (!Prefix.empty() && TestGlobalVariables(Prefix))
return KeepPrefix;
-
return NoFailure;
}
- bool TestGlobalVariables(std::vector<GlobalVariable*>& GVs);
+ bool TestGlobalVariables(std::vector<GlobalVariable*> &GVs);
};
}
bool
ReduceCrashingGlobalVariables::TestGlobalVariables(
- std::vector<GlobalVariable*>& GVs) {
+ std::vector<GlobalVariable*> &GVs) {
// Clone the program to try hacking it apart...
- DenseMap<const Value*, Value*> ValueMap;
- Module *M = CloneModule(BD.getProgram(), ValueMap);
+ ValueMap<const Value*, Value*> VMap;
+ Module *M = CloneModule(BD.getProgram(), VMap);
// Convert list to set for fast lookup...
std::set<GlobalVariable*> GVSet;
for (unsigned i = 0, e = GVs.size(); i != e; ++i) {
- GlobalVariable* CMGV = cast<GlobalVariable>(ValueMap[GVs[i]]);
+ GlobalVariable* CMGV = cast<GlobalVariable>(VMap[GVs[i]]);
assert(CMGV && "Global Variable not in module?!");
GVSet.insert(CMGV);
}
: BD(bd), TestFn(testFn) {}
virtual TestResult doTest(std::vector<Function*> &Prefix,
- std::vector<Function*> &Kept) {
+ std::vector<Function*> &Kept,
+ std::string &Error) {
if (!Kept.empty() && TestFuncs(Kept))
return KeepSuffix;
if (!Prefix.empty() && TestFuncs(Prefix))
return false;
// Clone the program to try hacking it apart...
- DenseMap<const Value*, Value*> ValueMap;
- Module *M = CloneModule(BD.getProgram(), ValueMap);
+ ValueMap<const Value*, Value*> VMap;
+ Module *M = CloneModule(BD.getProgram(), VMap);
// Convert list to set for fast lookup...
std::set<Function*> Functions;
for (unsigned i = 0, e = Funcs.size(); i != e; ++i) {
- Function *CMF = cast<Function>(ValueMap[Funcs[i]]);
+ Function *CMF = cast<Function>(VMap[Funcs[i]]);
assert(CMF && "Function not in module?!");
assert(CMF->getFunctionType() == Funcs[i]->getFunctionType() && "wrong ty");
assert(CMF->getName() == Funcs[i]->getName() && "wrong name");
: BD(bd), TestFn(testFn) {}
virtual TestResult doTest(std::vector<const BasicBlock*> &Prefix,
- std::vector<const BasicBlock*> &Kept) {
+ std::vector<const BasicBlock*> &Kept,
+ std::string &Error) {
if (!Kept.empty() && TestBlocks(Kept))
return KeepSuffix;
if (!Prefix.empty() && TestBlocks(Prefix))
bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock*> &BBs) {
// Clone the program to try hacking it apart...
- DenseMap<const Value*, Value*> ValueMap;
- Module *M = CloneModule(BD.getProgram(), ValueMap);
+ ValueMap<const Value*, Value*> VMap;
+ Module *M = CloneModule(BD.getProgram(), VMap);
// Convert list to set for fast lookup...
SmallPtrSet<BasicBlock*, 8> Blocks;
for (unsigned i = 0, e = BBs.size(); i != e; ++i)
- Blocks.insert(cast<BasicBlock>(ValueMap[BBs[i]]));
+ Blocks.insert(cast<BasicBlock>(VMap[BBs[i]]));
outs() << "Checking for crash with only these blocks:";
unsigned NumPrint = Blocks.size();
TerminatorInst *BBTerm = BB->getTerminator();
- if (isa<StructType>(BBTerm->getType()))
- BBTerm->replaceAllUsesWith(UndefValue::get(BBTerm->getType()));
- else if (BB->getTerminator()->getType() != Type::VoidTy)
+ if (!BB->getTerminator()->getType()->isVoidTy())
BBTerm->replaceAllUsesWith(Constant::getNullValue(BBTerm->getType()));
// Replace the old terminator instruction.
BB->getInstList().pop_back();
- new UnreachableInst(BB);
+ new UnreachableInst(BB->getContext(), BB);
}
// The CFG Simplifier pass may delete one of the basic blocks we are
for (unsigned i = 0, e = BlockInfo.size(); i != e; ++i) {
ValueSymbolTable &ST = BlockInfo[i].first->getValueSymbolTable();
Value* V = ST.lookup(BlockInfo[i].second);
- if (V && V->getType() == Type::LabelTy)
+ if (V && V->getType() == Type::getLabelTy(V->getContext()))
BBs.push_back(cast<BasicBlock>(V));
}
return true;
: BD(bd), TestFn(testFn) {}
virtual TestResult doTest(std::vector<const Instruction*> &Prefix,
- std::vector<const Instruction*> &Kept) {
+ std::vector<const Instruction*> &Kept,
+ std::string &Error) {
if (!Kept.empty() && TestInsts(Kept))
return KeepSuffix;
if (!Prefix.empty() && TestInsts(Prefix))
bool ReduceCrashingInstructions::TestInsts(std::vector<const Instruction*>
&Insts) {
// Clone the program to try hacking it apart...
- DenseMap<const Value*, Value*> ValueMap;
- Module *M = CloneModule(BD.getProgram(), ValueMap);
+ ValueMap<const Value*, Value*> VMap;
+ Module *M = CloneModule(BD.getProgram(), VMap);
// Convert list to set for fast lookup...
SmallPtrSet<Instruction*, 64> Instructions;
for (unsigned i = 0, e = Insts.size(); i != e; ++i) {
assert(!isa<TerminatorInst>(Insts[i]));
- Instructions.insert(cast<Instruction>(ValueMap[Insts[i]]));
+ Instructions.insert(cast<Instruction>(VMap[Insts[i]]));
}
outs() << "Checking for crash with only " << Instructions.size();
for (BasicBlock::iterator I = FI->begin(), E = FI->end(); I != E;) {
Instruction *Inst = I++;
if (!Instructions.count(Inst) && !isa<TerminatorInst>(Inst)) {
- if (Inst->getType() != Type::VoidTy)
+ if (!Inst->getType()->isVoidTy())
Inst->replaceAllUsesWith(UndefValue::get(Inst->getType()));
Inst->eraseFromParent();
}
/// DebugACrash - Given a predicate that determines whether a component crashes
/// on a program, try to destructively reduce the program while still keeping
/// the predicate true.
-static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) {
+static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *),
+ std::string &Error) {
// See if we can get away with nuking some of the global variable initializers
// in the program...
if (!NoGlobalRM &&
<< "variables in the testcase\n";
unsigned OldSize = GVs.size();
- ReduceCrashingGlobalVariables(BD, TestFn).reduceList(GVs);
+ ReduceCrashingGlobalVariables(BD, TestFn).reduceList(GVs, Error);
+ if (!Error.empty())
+ return true;
if (GVs.size() < OldSize)
BD.EmitProgressBitcode("reduced-global-variables");
"in the testcase\n";
unsigned OldSize = Functions.size();
- ReduceCrashingFunctions(BD, TestFn).reduceList(Functions);
+ ReduceCrashingFunctions(BD, TestFn).reduceList(Functions, Error);
if (Functions.size() < OldSize)
BD.EmitProgressBitcode("reduced-function");
for (Function::const_iterator FI = I->begin(), E = I->end(); FI !=E; ++FI)
Blocks.push_back(FI);
unsigned OldSize = Blocks.size();
- ReduceCrashingBlocks(BD, TestFn).reduceList(Blocks);
+ ReduceCrashingBlocks(BD, TestFn).reduceList(Blocks, Error);
if (Blocks.size() < OldSize)
BD.EmitProgressBitcode("reduced-blocks");
}
if (!isa<TerminatorInst>(I))
Insts.push_back(I);
- ReduceCrashingInstructions(BD, TestFn).reduceList(Insts);
+ ReduceCrashingInstructions(BD, TestFn).reduceList(Insts, Error);
}
// FIXME: This should use the list reducer to converge faster by deleting
bool BugDriver::debugOptimizerCrash(const std::string &ID) {
outs() << "\n*** Debugging optimizer crash!\n";
+ std::string Error;
// Reduce the list of passes which causes the optimizer to crash...
if (!BugpointIsInterrupted)
- ReducePassList(*this).reduceList(PassesToRun);
+ ReducePassList(*this).reduceList(PassesToRun, Error);
+ assert(Error.empty());
outs() << "\n*** Found crashing pass"
<< (PassesToRun.size() == 1 ? ": " : "es: ")
EmitProgressBitcode(ID);
- return DebugACrash(*this, TestForOptimizerCrash);
+ bool Success = DebugACrash(*this, TestForOptimizerCrash, Error);
+ assert(Error.empty());
+ return Success;
}
static bool TestForCodeGenCrash(BugDriver &BD, Module *M) {
- try {
- BD.compileProgram(M);
- errs() << '\n';
- return false;
- } catch (ToolExecutionError &) {
+ std::string Error;
+ BD.compileProgram(M, &Error);
+ if (!Error.empty()) {
errs() << "<crash>\n";
return true; // Tool is still crashing.
}
+ errs() << '\n';
+ return false;
}
/// debugCodeGeneratorCrash - This method is called when the code generator
/// crashes on an input. It attempts to reduce the input as much as possible
/// while still causing the code generator to crash.
-bool BugDriver::debugCodeGeneratorCrash() {
+bool BugDriver::debugCodeGeneratorCrash(std::string &Error) {
errs() << "*** Debugging code generator crash!\n";
- return DebugACrash(*this, TestForCodeGenCrash);
+ return DebugACrash(*this, TestForCodeGenCrash, Error);
}