1afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner//===- CrashDebugger.cpp - Debug compilation crashes ----------------------===// 23da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman// 37c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell// The LLVM Compiler Infrastructure 47c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell// 521c62da287237d39d0d95004881ea4baae3be6daChris Lattner// This file is distributed under the University of Illinois Open Source 621c62da287237d39d0d95004881ea4baae3be6daChris Lattner// License. See LICENSE.TXT for details. 73da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman// 87c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell//===----------------------------------------------------------------------===// 9afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner// 10afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner// This file defines the bugpoint internals that narrow down compilation crashes 11afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner// 12afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner//===----------------------------------------------------------------------===// 13afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 14afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner#include "BugDriver.h" 15f1b20d8620b05abaa52f40ac6d21f839b265fb00Chris Lattner#include "ToolRunner.h" 16aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner#include "ListReducer.h" 17e78109eb3a3d177d03cea40b46d9dcfc9bf32210Chris Lattner#include "llvm/Constants.h" 184e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling#include "llvm/DerivedTypes.h" 1947b14a4a6a455c7be169cfd312fcbe796f0ad426Misha Brukman#include "llvm/Instructions.h" 20e49603d79d220a795bd50684c8b1f503ee40f97fMisha Brukman#include "llvm/Module.h" 21e49603d79d220a795bd50684c8b1f503ee40f97fMisha Brukman#include "llvm/Pass.h" 22e49603d79d220a795bd50684c8b1f503ee40f97fMisha Brukman#include "llvm/PassManager.h" 23ef9b9a793949469cdaa4ab6d0173136229dcab7bReid Spencer#include "llvm/ValueSymbolTable.h" 24e032590f58e400ba25e416da5bee10a85ad6d114Nick Lewycky#include "llvm/ADT/SmallPtrSet.h" 25286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner#include "llvm/Analysis/Verifier.h" 26e49603d79d220a795bd50684c8b1f503ee40f97fMisha Brukman#include "llvm/Support/CFG.h" 27286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner#include "llvm/Transforms/Scalar.h" 28aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner#include "llvm/Transforms/Utils/Cloning.h" 29551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/Support/FileUtilities.h" 307c0a93785e283110ff05e4a95062990fd32a8389Andrew Lenharth#include "llvm/Support/CommandLine.h" 31aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner#include <set> 32fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattnerusing namespace llvm; 33afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 347c0a93785e283110ff05e4a95062990fd32a8389Andrew Lenharthnamespace { 357c0a93785e283110ff05e4a95062990fd32a8389Andrew Lenharth cl::opt<bool> 367c0a93785e283110ff05e4a95062990fd32a8389Andrew Lenharth KeepMain("keep-main", 377c0a93785e283110ff05e4a95062990fd32a8389Andrew Lenharth cl::desc("Force function reduction to keep main"), 387c0a93785e283110ff05e4a95062990fd32a8389Andrew Lenharth cl::init(false)); 3923d471f62eed3518fe7737dbccee52faec4ffe75Torok Edwin cl::opt<bool> 4023d471f62eed3518fe7737dbccee52faec4ffe75Torok Edwin NoGlobalRM ("disable-global-remove", 4123d471f62eed3518fe7737dbccee52faec4ffe75Torok Edwin cl::desc("Do not remove global variables"), 4223d471f62eed3518fe7737dbccee52faec4ffe75Torok Edwin cl::init(false)); 437c0a93785e283110ff05e4a95062990fd32a8389Andrew Lenharth} 447c0a93785e283110ff05e4a95062990fd32a8389Andrew Lenharth 45d0fde30ce850b78371fd1386338350591f9ff494Brian Gaekenamespace llvm { 468261dfed05e32302469ef707cc881fed2c31f85fRafael Espindola class ReducePassList : public ListReducer<std::string> { 47fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner BugDriver &BD; 48fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner public: 4906905db7d2a2b83c1b3236d5552629ada2d8d56dChris Lattner ReducePassList(BugDriver &bd) : BD(bd) {} 503da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman 51fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner // doTest - Return true iff running the "removed" passes succeeds, and 52fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner // running the "Kept" passes fail when run on the output of the "removed" 53fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner // passes. If we return true, we update the current module of bugpoint. 54fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner // 558261dfed05e32302469ef707cc881fed2c31f85fRafael Espindola virtual TestResult doTest(std::vector<std::string> &Removed, 568261dfed05e32302469ef707cc881fed2c31f85fRafael Espindola std::vector<std::string> &Kept, 5722ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky std::string &Error); 58fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner }; 59fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner} 60aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner 6106905db7d2a2b83c1b3236d5552629ada2d8d56dChris LattnerReducePassList::TestResult 628261dfed05e32302469ef707cc881fed2c31f85fRafael EspindolaReducePassList::doTest(std::vector<std::string> &Prefix, 638261dfed05e32302469ef707cc881fed2c31f85fRafael Espindola std::vector<std::string> &Suffix, 6422ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky std::string &Error) { 655f76760c880e6d61c229d2058c5699b033caeae1Reid Spencer sys::Path PrefixOutput; 66b417c795d2a8832b5edac321dc0d19eca7e3f2f5Chris Lattner Module *OrigProgram = 0; 67aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner if (!Prefix.empty()) { 68ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman outs() << "Checking to see if these passes crash: " 69ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman << getPassesString(Prefix) << ": "; 705f76760c880e6d61c229d2058c5699b033caeae1Reid Spencer std::string PfxOutput; 71ca356afe09454b3378165ded4eda294bd6341428Rafael Espindola if (BD.runPasses(BD.getProgram(), Prefix, PfxOutput)) 72aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner return KeepPrefix; 73b417c795d2a8832b5edac321dc0d19eca7e3f2f5Chris Lattner 74dd04df0ec33a903ee7fc747701bafde622f77d8bReid Spencer PrefixOutput.set(PfxOutput); 75b417c795d2a8832b5edac321dc0d19eca7e3f2f5Chris Lattner OrigProgram = BD.Program; 76b417c795d2a8832b5edac321dc0d19eca7e3f2f5Chris Lattner 7774382b7c699120fbec5cb5603c9cf4212eb37f06Chris Lattner BD.Program = ParseInputFile(PrefixOutput.str(), BD.getContext()); 78b417c795d2a8832b5edac321dc0d19eca7e3f2f5Chris Lattner if (BD.Program == 0) { 7965f57c233cd4499e2e8b52a503201e64edfd6a9eDan Gohman errs() << BD.getToolName() << ": Error reading bitcode file '" 8074382b7c699120fbec5cb5603c9cf4212eb37f06Chris Lattner << PrefixOutput.str() << "'!\n"; 81b417c795d2a8832b5edac321dc0d19eca7e3f2f5Chris Lattner exit(1); 82b417c795d2a8832b5edac321dc0d19eca7e3f2f5Chris Lattner } 83a229c5cce75209047db32c6039aa0b0fd481f049Reid Spencer PrefixOutput.eraseFromDisk(); 84aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner } 85aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner 86ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman outs() << "Checking to see if these passes crash: " 87ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman << getPassesString(Suffix) << ": "; 883da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman 895d8cace94a71169ce8493baa7f3305a27fe0cd84Rafael Espindola if (BD.runPasses(BD.getProgram(), Suffix)) { 90aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner delete OrigProgram; // The suffix crashes alone... 91aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner return KeepSuffix; 92aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner } 93aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner 94aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner // Nothing failed, restore state... 95b417c795d2a8832b5edac321dc0d19eca7e3f2f5Chris Lattner if (OrigProgram) { 96b417c795d2a8832b5edac321dc0d19eca7e3f2f5Chris Lattner delete BD.Program; 97b417c795d2a8832b5edac321dc0d19eca7e3f2f5Chris Lattner BD.Program = OrigProgram; 98b417c795d2a8832b5edac321dc0d19eca7e3f2f5Chris Lattner } 99aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner return NoFailure; 100aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner} 101aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner 1024e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendlingnamespace { 1034e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling /// ReduceCrashingGlobalVariables - This works by removing the global 1044e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling /// variable's initializer and seeing if the program still crashes. If it 1054e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling /// does, then we keep that program and try again. 1064e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling /// 1074e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling class ReduceCrashingGlobalVariables : public ListReducer<GlobalVariable*> { 1084e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling BugDriver &BD; 109248d1c65f1ce5bc04b892998b2c2061e6a5f8e1cRafael Espindola bool (*TestFn)(const BugDriver &, Module *); 1104e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling public: 1114e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling ReduceCrashingGlobalVariables(BugDriver &bd, 112248d1c65f1ce5bc04b892998b2c2061e6a5f8e1cRafael Espindola bool (*testFn)(const BugDriver &, Module *)) 1134e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling : BD(bd), TestFn(testFn) {} 1144e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling 11522ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky virtual TestResult doTest(std::vector<GlobalVariable*> &Prefix, 11622ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky std::vector<GlobalVariable*> &Kept, 11722ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky std::string &Error) { 1184e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling if (!Kept.empty() && TestGlobalVariables(Kept)) 1194e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling return KeepSuffix; 1204e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling if (!Prefix.empty() && TestGlobalVariables(Prefix)) 1214e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling return KeepPrefix; 1224e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling return NoFailure; 1234e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling } 1244e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling 12522ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky bool TestGlobalVariables(std::vector<GlobalVariable*> &GVs); 1264e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling }; 1274e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling} 1284e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling 1294e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendlingbool 1304e3be89cb5cde6e2df294c64db3bc28133b67594Bill WendlingReduceCrashingGlobalVariables::TestGlobalVariables( 13122ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky std::vector<GlobalVariable*> &GVs) { 1324e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling // Clone the program to try hacking it apart... 1331ed219a9d2279ce5a5bbcf16d9b7ccc05cce638cRafael Espindola ValueToValueMapTy VMap; 134e9916a302f1bacad234d7dafc1df3dc968a6ba0fDevang Patel Module *M = CloneModule(BD.getProgram(), VMap); 1354e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling 1364e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling // Convert list to set for fast lookup... 1374e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling std::set<GlobalVariable*> GVSet; 1384e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling 1394e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling for (unsigned i = 0, e = GVs.size(); i != e; ++i) { 140e9916a302f1bacad234d7dafc1df3dc968a6ba0fDevang Patel GlobalVariable* CMGV = cast<GlobalVariable>(VMap[GVs[i]]); 1414e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling assert(CMGV && "Global Variable not in module?!"); 1424e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling GVSet.insert(CMGV); 1434e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling } 1444e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling 145ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman outs() << "Checking for crash with only these global variables: "; 1464e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling PrintGlobalVariableList(GVs); 147ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman outs() << ": "; 1484e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling 1494e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling // Loop over and delete any global variables which we aren't supposed to be 1504e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling // playing with... 1514e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling for (Module::global_iterator I = M->global_begin(), E = M->global_end(); 1524e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling I != E; ++I) 153028839db09eb47424cd3955471f2c32c68fee74dNick Lewycky if (I->hasInitializer() && !GVSet.count(I)) { 1544e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling I->setInitializer(0); 1554e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling I->setLinkage(GlobalValue::ExternalLinkage); 1564e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling } 1574e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling 1584e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling // Try running the hacked up program... 1594e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling if (TestFn(BD, M)) { 1604e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling BD.setNewProgram(M); // It crashed, keep the trimmed version... 1614e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling 1624e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling // Make sure to use global variable pointers that point into the now-current 1634e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling // module. 1644e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling GVs.assign(GVSet.begin(), GVSet.end()); 1654e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling return true; 1664e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling } 1674e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling 1684e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling delete M; 1694e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling return false; 1704e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling} 1714e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling 1722d24e2a396a1d211baaeedf32148a3b657240170David Blaikienamespace { 1734e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling /// ReduceCrashingFunctions reducer - This works by removing functions and 1744e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling /// seeing if the program still crashes. If it does, then keep the newer, 1754e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling /// smaller program. 1764e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling /// 177efdc0b505712d1ca4460def27e51c430f033d58dChris Lattner class ReduceCrashingFunctions : public ListReducer<Function*> { 178fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner BugDriver &BD; 179248d1c65f1ce5bc04b892998b2c2061e6a5f8e1cRafael Espindola bool (*TestFn)(const BugDriver &, Module *); 180fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner public: 1818b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner ReduceCrashingFunctions(BugDriver &bd, 182248d1c65f1ce5bc04b892998b2c2061e6a5f8e1cRafael Espindola bool (*testFn)(const BugDriver &, Module *)) 1838b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner : BD(bd), TestFn(testFn) {} 1843da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman 185efdc0b505712d1ca4460def27e51c430f033d58dChris Lattner virtual TestResult doTest(std::vector<Function*> &Prefix, 18622ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky std::vector<Function*> &Kept, 18722ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky std::string &Error) { 188fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner if (!Kept.empty() && TestFuncs(Kept)) 189fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner return KeepSuffix; 190fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner if (!Prefix.empty() && TestFuncs(Prefix)) 191fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner return KeepPrefix; 192fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner return NoFailure; 193fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner } 1943da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman 195efdc0b505712d1ca4460def27e51c430f033d58dChris Lattner bool TestFuncs(std::vector<Function*> &Prefix); 196fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner }; 197fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner} 198aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner 199efdc0b505712d1ca4460def27e51c430f033d58dChris Lattnerbool ReduceCrashingFunctions::TestFuncs(std::vector<Function*> &Funcs) { 2007c0a93785e283110ff05e4a95062990fd32a8389Andrew Lenharth 2017c0a93785e283110ff05e4a95062990fd32a8389Andrew Lenharth //if main isn't present, claim there is no problem 2024e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling if (KeepMain && find(Funcs.begin(), Funcs.end(), 203688b0490e22eb67623f5aaa24406209be74efcb2Reid Spencer BD.getProgram()->getFunction("main")) == Funcs.end()) 2047c0a93785e283110ff05e4a95062990fd32a8389Andrew Lenharth return false; 2057c0a93785e283110ff05e4a95062990fd32a8389Andrew Lenharth 206cf00c4ab3ba308d45d98c5ccab87362cf802facbMisha Brukman // Clone the program to try hacking it apart... 2071ed219a9d2279ce5a5bbcf16d9b7ccc05cce638cRafael Espindola ValueToValueMapTy VMap; 208e9916a302f1bacad234d7dafc1df3dc968a6ba0fDevang Patel Module *M = CloneModule(BD.getProgram(), VMap); 2093da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman 210aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner // Convert list to set for fast lookup... 211aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner std::set<Function*> Functions; 212aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner for (unsigned i = 0, e = Funcs.size(); i != e; ++i) { 213e9916a302f1bacad234d7dafc1df3dc968a6ba0fDevang Patel Function *CMF = cast<Function>(VMap[Funcs[i]]); 214aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner assert(CMF && "Function not in module?!"); 215ef9b9a793949469cdaa4ab6d0173136229dcab7bReid Spencer assert(CMF->getFunctionType() == Funcs[i]->getFunctionType() && "wrong ty"); 216f6dd0eb5c4a1c4824d7f83fa39586478da618ffdDan Gohman assert(CMF->getName() == Funcs[i]->getName() && "wrong name"); 217f607b79bc78fcbfd8cda01d2d5dbda6cd8253a40Chris Lattner Functions.insert(CMF); 218aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner } 219aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner 220ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman outs() << "Checking for crash with only these functions: "; 221efdc0b505712d1ca4460def27e51c430f033d58dChris Lattner PrintFunctionList(Funcs); 222ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman outs() << ": "; 223aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner 224aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner // Loop over and delete any functions which we aren't supposed to be playing 225aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner // with... 226aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) 2275cbf985dcbc89fba3208e7baf8b6f488b06d3ec9Reid Spencer if (!I->isDeclaration() && !Functions.count(I)) 228aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner DeleteFunctionBody(I); 229aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner 230aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner // Try running the hacked up program... 2318b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner if (TestFn(BD, M)) { 23206905db7d2a2b83c1b3236d5552629ada2d8d56dChris Lattner BD.setNewProgram(M); // It crashed, keep the trimmed version... 233aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner 234aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner // Make sure to use function pointers that point into the now-current 235aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner // module. 236aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner Funcs.assign(Functions.begin(), Functions.end()); 237aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner return true; 238aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner } 23906905db7d2a2b83c1b3236d5552629ada2d8d56dChris Lattner delete M; 240aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner return false; 241aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner} 242aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner 243640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner 244f913f40be8501738fa4bdcae2015dd196dcbfc50Chris Lattnernamespace { 245fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner /// ReduceCrashingBlocks reducer - This works by setting the terminators of 246fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner /// all terminators except the specified basic blocks to a 'ret' instruction, 247fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner /// then running the simplify-cfg pass. This has the effect of chopping up 248fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner /// the CFG really fast which can reduce large functions quickly. 249fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner /// 2508b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner class ReduceCrashingBlocks : public ListReducer<const BasicBlock*> { 251fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner BugDriver &BD; 252248d1c65f1ce5bc04b892998b2c2061e6a5f8e1cRafael Espindola bool (*TestFn)(const BugDriver &, Module *); 253fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner public: 254248d1c65f1ce5bc04b892998b2c2061e6a5f8e1cRafael Espindola ReduceCrashingBlocks(BugDriver &bd, 255248d1c65f1ce5bc04b892998b2c2061e6a5f8e1cRafael Espindola bool (*testFn)(const BugDriver &, Module *)) 2568b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner : BD(bd), TestFn(testFn) {} 2573da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman 2588b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner virtual TestResult doTest(std::vector<const BasicBlock*> &Prefix, 25922ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky std::vector<const BasicBlock*> &Kept, 26022ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky std::string &Error) { 261fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner if (!Kept.empty() && TestBlocks(Kept)) 262fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner return KeepSuffix; 263fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner if (!Prefix.empty() && TestBlocks(Prefix)) 264fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner return KeepPrefix; 265fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner return NoFailure; 266fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner } 2673da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman 2688b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner bool TestBlocks(std::vector<const BasicBlock*> &Prefix); 269fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner }; 270fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattner} 271286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner 2728b189277bde5f617405dded0bbd6583e6665f4dfChris Lattnerbool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock*> &BBs) { 273cf00c4ab3ba308d45d98c5ccab87362cf802facbMisha Brukman // Clone the program to try hacking it apart... 2741ed219a9d2279ce5a5bbcf16d9b7ccc05cce638cRafael Espindola ValueToValueMapTy VMap; 275e9916a302f1bacad234d7dafc1df3dc968a6ba0fDevang Patel Module *M = CloneModule(BD.getProgram(), VMap); 2763da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman 277286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner // Convert list to set for fast lookup... 278e032590f58e400ba25e416da5bee10a85ad6d114Nick Lewycky SmallPtrSet<BasicBlock*, 8> Blocks; 279e032590f58e400ba25e416da5bee10a85ad6d114Nick Lewycky for (unsigned i = 0, e = BBs.size(); i != e; ++i) 280e9916a302f1bacad234d7dafc1df3dc968a6ba0fDevang Patel Blocks.insert(cast<BasicBlock>(VMap[BBs[i]])); 281286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner 282ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman outs() << "Checking for crash with only these blocks:"; 28373b96bd52d9361d5c947e4fb660a46e498f7b407Chris Lattner unsigned NumPrint = Blocks.size(); 28473b96bd52d9361d5c947e4fb660a46e498f7b407Chris Lattner if (NumPrint > 10) NumPrint = 10; 28573b96bd52d9361d5c947e4fb660a46e498f7b407Chris Lattner for (unsigned i = 0, e = NumPrint; i != e; ++i) 286ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman outs() << " " << BBs[i]->getName(); 28773b96bd52d9361d5c947e4fb660a46e498f7b407Chris Lattner if (NumPrint < Blocks.size()) 288ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman outs() << "... <" << Blocks.size() << " total>"; 289ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman outs() << ": "; 290286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner 291286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner // Loop over and delete any hack up any blocks that are not listed... 292286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) 293286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner for (Function::iterator BB = I->begin(), E = I->end(); BB != E; ++BB) 2948bc098be0cce48dcc08fea746d28011cac79eef6Chris Lattner if (!Blocks.count(BB) && BB->getTerminator()->getNumSuccessors()) { 295286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner // Loop over all of the successors of this block, deleting any PHI nodes 296286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner // that might include it. 297286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner for (succ_iterator SI = succ_begin(BB), E = succ_end(BB); SI != E; ++SI) 298286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner (*SI)->removePredecessor(BB); 299286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner 300e78109eb3a3d177d03cea40b46d9dcfc9bf32210Chris Lattner TerminatorInst *BBTerm = BB->getTerminator(); 301e78109eb3a3d177d03cea40b46d9dcfc9bf32210Chris Lattner 302e49a13e7260b83ce56d01446f2a165cc9f35da7fDan Gohman if (!BB->getTerminator()->getType()->isVoidTy()) 303a7235ea7245028a0723e8ab7fd011386b3900777Owen Anderson BBTerm->replaceAllUsesWith(Constant::getNullValue(BBTerm->getType())); 3048bc098be0cce48dcc08fea746d28011cac79eef6Chris Lattner 305e78109eb3a3d177d03cea40b46d9dcfc9bf32210Chris Lattner // Replace the old terminator instruction. 306286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner BB->getInstList().pop_back(); 3071d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson new UnreachableInst(BB->getContext(), BB); 308286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner } 309286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner 310286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner // The CFG Simplifier pass may delete one of the basic blocks we are 311286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner // interested in. If it does we need to take the block out of the list. Make 312286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner // a "persistent mapping" by turning basic blocks into <function, name> pairs. 313286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner // This won't work well if blocks are unnamed, but that is just the risk we 314286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner // have to take. 315866aa0d742b7bc9811fd1b45507af999c605205aRafael Espindola std::vector<std::pair<std::string, std::string> > BlockInfo; 316286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner 317e032590f58e400ba25e416da5bee10a85ad6d114Nick Lewycky for (SmallPtrSet<BasicBlock*, 8>::iterator I = Blocks.begin(), 318e032590f58e400ba25e416da5bee10a85ad6d114Nick Lewycky E = Blocks.end(); I != E; ++I) 319866aa0d742b7bc9811fd1b45507af999c605205aRafael Espindola BlockInfo.push_back(std::make_pair((*I)->getParent()->getName(), 320866aa0d742b7bc9811fd1b45507af999c605205aRafael Espindola (*I)->getName())); 321286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner 322286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner // Now run the CFG simplify pass on the function... 323866aa0d742b7bc9811fd1b45507af999c605205aRafael Espindola std::vector<std::string> Passes; 324866aa0d742b7bc9811fd1b45507af999c605205aRafael Espindola Passes.push_back("simplifycfg"); 325866aa0d742b7bc9811fd1b45507af999c605205aRafael Espindola Passes.push_back("verify"); 326866aa0d742b7bc9811fd1b45507af999c605205aRafael Espindola Module *New = BD.runPassesOn(M, Passes); 327866aa0d742b7bc9811fd1b45507af999c605205aRafael Espindola delete M; 328866aa0d742b7bc9811fd1b45507af999c605205aRafael Espindola if (!New) { 329866aa0d742b7bc9811fd1b45507af999c605205aRafael Espindola errs() << "simplifycfg failed!\n"; 330866aa0d742b7bc9811fd1b45507af999c605205aRafael Espindola exit(1); 331866aa0d742b7bc9811fd1b45507af999c605205aRafael Espindola } 332866aa0d742b7bc9811fd1b45507af999c605205aRafael Espindola M = New; 333286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner 334286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner // Try running on the hacked up program... 3358b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner if (TestFn(BD, M)) { 33606905db7d2a2b83c1b3236d5552629ada2d8d56dChris Lattner BD.setNewProgram(M); // It crashed, keep the trimmed version... 337286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner 338286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner // Make sure to use basic block pointers that point into the now-current 339286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner // module, and that they don't include any deleted blocks. 340286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner BBs.clear(); 341866aa0d742b7bc9811fd1b45507af999c605205aRafael Espindola const ValueSymbolTable &GST = M->getValueSymbolTable(); 342286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner for (unsigned i = 0, e = BlockInfo.size(); i != e; ++i) { 343866aa0d742b7bc9811fd1b45507af999c605205aRafael Espindola Function *F = cast<Function>(GST.lookup(BlockInfo[i].first)); 344866aa0d742b7bc9811fd1b45507af999c605205aRafael Espindola ValueSymbolTable &ST = F->getValueSymbolTable(); 345ef9b9a793949469cdaa4ab6d0173136229dcab7bReid Spencer Value* V = ST.lookup(BlockInfo[i].second); 3461d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson if (V && V->getType() == Type::getLabelTy(V->getContext())) 347ef9b9a793949469cdaa4ab6d0173136229dcab7bReid Spencer BBs.push_back(cast<BasicBlock>(V)); 348286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner } 349286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner return true; 350286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner } 35106905db7d2a2b83c1b3236d5552629ada2d8d56dChris Lattner delete M; // It didn't crash, try something else. 352286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner return false; 353286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner} 354286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner 3554c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewyckynamespace { 3564c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky /// ReduceCrashingInstructions reducer - This works by removing the specified 3574c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky /// non-terminator instructions and replacing them with undef. 3584c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky /// 3594c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky class ReduceCrashingInstructions : public ListReducer<const Instruction*> { 3604c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky BugDriver &BD; 361248d1c65f1ce5bc04b892998b2c2061e6a5f8e1cRafael Espindola bool (*TestFn)(const BugDriver &, Module *); 3624c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky public: 363248d1c65f1ce5bc04b892998b2c2061e6a5f8e1cRafael Espindola ReduceCrashingInstructions(BugDriver &bd, 364248d1c65f1ce5bc04b892998b2c2061e6a5f8e1cRafael Espindola bool (*testFn)(const BugDriver &, Module *)) 3654c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky : BD(bd), TestFn(testFn) {} 3664c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky 3674c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky virtual TestResult doTest(std::vector<const Instruction*> &Prefix, 36822ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky std::vector<const Instruction*> &Kept, 36922ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky std::string &Error) { 3704c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky if (!Kept.empty() && TestInsts(Kept)) 3714c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky return KeepSuffix; 3724c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky if (!Prefix.empty() && TestInsts(Prefix)) 3734c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky return KeepPrefix; 3744c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky return NoFailure; 3754c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky } 3764c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky 3774c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky bool TestInsts(std::vector<const Instruction*> &Prefix); 3784c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky }; 3794c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky} 3804c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky 3814c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewyckybool ReduceCrashingInstructions::TestInsts(std::vector<const Instruction*> 3824c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky &Insts) { 3834c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky // Clone the program to try hacking it apart... 3841ed219a9d2279ce5a5bbcf16d9b7ccc05cce638cRafael Espindola ValueToValueMapTy VMap; 385e9916a302f1bacad234d7dafc1df3dc968a6ba0fDevang Patel Module *M = CloneModule(BD.getProgram(), VMap); 3864c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky 3874c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky // Convert list to set for fast lookup... 3884c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky SmallPtrSet<Instruction*, 64> Instructions; 3894c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky for (unsigned i = 0, e = Insts.size(); i != e; ++i) { 3904c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky assert(!isa<TerminatorInst>(Insts[i])); 391e9916a302f1bacad234d7dafc1df3dc968a6ba0fDevang Patel Instructions.insert(cast<Instruction>(VMap[Insts[i]])); 3924c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky } 3934c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky 394ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman outs() << "Checking for crash with only " << Instructions.size(); 3954c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky if (Instructions.size() == 1) 396ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman outs() << " instruction: "; 3974c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky else 398ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman outs() << " instructions: "; 3994c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky 4004c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky for (Module::iterator MI = M->begin(), ME = M->end(); MI != ME; ++MI) 4014c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE; ++FI) 4024c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky for (BasicBlock::iterator I = FI->begin(), E = FI->end(); I != E;) { 4034c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky Instruction *Inst = I++; 404597362a54bf4bb8de5538b4a1d97c618b18a023cEli Friedman if (!Instructions.count(Inst) && !isa<TerminatorInst>(Inst) && 405597362a54bf4bb8de5538b4a1d97c618b18a023cEli Friedman !isa<LandingPadInst>(Inst)) { 406e49a13e7260b83ce56d01446f2a165cc9f35da7fDan Gohman if (!Inst->getType()->isVoidTy()) 4074c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky Inst->replaceAllUsesWith(UndefValue::get(Inst->getType())); 4084c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky Inst->eraseFromParent(); 4094c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky } 4104c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky } 4114c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky 4124c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky // Verify that this is still valid. 4134c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky PassManager Passes; 4144c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky Passes.add(createVerifierPass()); 4154c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky Passes.run(*M); 4164c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky 4174c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky // Try running on the hacked up program... 4184c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky if (TestFn(BD, M)) { 4194c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky BD.setNewProgram(M); // It crashed, keep the trimmed version... 4204c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky 4214c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky // Make sure to use instruction pointers that point into the now-current 4224c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky // module, and that they don't include any deleted blocks. 4234c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky Insts.clear(); 4244c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky for (SmallPtrSet<Instruction*, 64>::const_iterator I = Instructions.begin(), 4254c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky E = Instructions.end(); I != E; ++I) 4264c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky Insts.push_back(*I); 4274c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky return true; 4284c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky } 4294c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky delete M; // It didn't crash, try something else. 4304c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky return false; 4314c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky} 4324c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky 4338b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner/// DebugACrash - Given a predicate that determines whether a component crashes 4348b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner/// on a program, try to destructively reduce the program while still keeping 4358b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner/// the predicate true. 436248d1c65f1ce5bc04b892998b2c2061e6a5f8e1cRafael Espindolastatic bool DebugACrash(BugDriver &BD, 437248d1c65f1ce5bc04b892998b2c2061e6a5f8e1cRafael Espindola bool (*TestFn)(const BugDriver &, Module *), 43822ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky std::string &Error) { 4394e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling // See if we can get away with nuking some of the global variable initializers 4405f73e38548c57636ad0ef8c719d040e166761962Chris Lattner // in the program... 44123d471f62eed3518fe7737dbccee52faec4ffe75Torok Edwin if (!NoGlobalRM && 44223d471f62eed3518fe7737dbccee52faec4ffe75Torok Edwin BD.getProgram()->global_begin() != BD.getProgram()->global_end()) { 4434e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling // Now try to reduce the number of global variable initializers in the 4444e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling // module to something small. 445b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling Module *M = CloneModule(BD.getProgram()); 446b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling bool DeletedInit = false; 447b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling 448b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling for (Module::global_iterator I = M->global_begin(), E = M->global_end(); 449b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling I != E; ++I) 450b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling if (I->hasInitializer()) { 451b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling I->setInitializer(0); 452b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling I->setLinkage(GlobalValue::ExternalLinkage); 453b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling DeletedInit = true; 454b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling } 455b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling 456b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling if (!DeletedInit) { 457b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling delete M; // No change made... 458b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling } else { 459b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling // See if the program still causes a crash... 460ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman outs() << "\nChecking to see if we can delete global inits: "; 461b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling 462b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling if (TestFn(BD, M)) { // Still crashes? 463b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling BD.setNewProgram(M); 464ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman outs() << "\n*** Able to remove all global initializers!\n"; 465b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling } else { // No longer crashes? 466ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman outs() << " - Removing all global inits hides problem!\n"; 467b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling delete M; 468b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling 469b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling std::vector<GlobalVariable*> GVs; 4703da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman 471b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling for (Module::global_iterator I = BD.getProgram()->global_begin(), 472b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling E = BD.getProgram()->global_end(); I != E; ++I) 473b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling if (I->hasInitializer()) 474b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling GVs.push_back(I); 4754e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling 476b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling if (GVs.size() > 1 && !BugpointIsInterrupted) { 477ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman outs() << "\n*** Attempting to reduce the number of global " 478b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling << "variables in the testcase\n"; 4794e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling 480b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling unsigned OldSize = GVs.size(); 48122ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky ReduceCrashingGlobalVariables(BD, TestFn).reduceList(GVs, Error); 48222ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky if (!Error.empty()) 48322ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky return true; 4844e3be89cb5cde6e2df294c64db3bc28133b67594Bill Wendling 485b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling if (GVs.size() < OldSize) 486bae1b71cbb930e419df03db209ebc547a0e4ec72Rafael Espindola BD.EmitProgressBitcode(BD.getProgram(), "reduced-global-variables"); 487b3d83a3ed5e99cc858141ee4da61fe9f80ec4b00Bill Wendling } 48822706e82d57fd37150d494881a8f90b4043d42a1Bill Wendling } 4895f73e38548c57636ad0ef8c719d040e166761962Chris Lattner } 4905f73e38548c57636ad0ef8c719d040e166761962Chris Lattner } 4913da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman 492aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner // Now try to reduce the number of functions in the module to something small. 493efdc0b505712d1ca4460def27e51c430f033d58dChris Lattner std::vector<Function*> Functions; 494efdc0b505712d1ca4460def27e51c430f033d58dChris Lattner for (Module::iterator I = BD.getProgram()->begin(), 4958b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner E = BD.getProgram()->end(); I != E; ++I) 4965cbf985dcbc89fba3208e7baf8b6f488b06d3ec9Reid Spencer if (!I->isDeclaration()) 497aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner Functions.push_back(I); 498afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 499f9aaae06cd2109082cda2b09ef3f23e0e1cff47bChris Lattner if (Functions.size() > 1 && !BugpointIsInterrupted) { 500ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman outs() << "\n*** Attempting to reduce the number of functions " 501aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner "in the testcase\n"; 502afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 5038b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner unsigned OldSize = Functions.size(); 50422ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky ReduceCrashingFunctions(BD, TestFn).reduceList(Functions, Error); 505afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 506f9aaae06cd2109082cda2b09ef3f23e0e1cff47bChris Lattner if (Functions.size() < OldSize) 507bae1b71cbb930e419df03db209ebc547a0e4ec72Rafael Espindola BD.EmitProgressBitcode(BD.getProgram(), "reduced-function"); 508218e26ef3583cc3270f5f2a2b9cb1025e5b05ebeChris Lattner } 509218e26ef3583cc3270f5f2a2b9cb1025e5b05ebeChris Lattner 510286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner // Attempt to delete entire basic blocks at a time to speed up 511286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner // convergence... this actually works by setting the terminator of the blocks 512286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner // to a return instruction then running simplifycfg, which can potentially 513286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner // shrinks the code dramatically quickly 514286921e8d21d4f0655905ed278d0e140829c7d1fChris Lattner // 515f9aaae06cd2109082cda2b09ef3f23e0e1cff47bChris Lattner if (!DisableSimplifyCFG && !BugpointIsInterrupted) { 5168b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner std::vector<const BasicBlock*> Blocks; 5178b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner for (Module::const_iterator I = BD.getProgram()->begin(), 5188b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner E = BD.getProgram()->end(); I != E; ++I) 5198b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner for (Function::const_iterator FI = I->begin(), E = I->end(); FI !=E; ++FI) 52047ae4a1cee5eec5767a11403c0fac7c91ec45461Chris Lattner Blocks.push_back(FI); 5212c235010312f72622acd4b7bb70f87cf31a982f6Torok Edwin unsigned OldSize = Blocks.size(); 52222ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky ReduceCrashingBlocks(BD, TestFn).reduceList(Blocks, Error); 5232c235010312f72622acd4b7bb70f87cf31a982f6Torok Edwin if (Blocks.size() < OldSize) 524bae1b71cbb930e419df03db209ebc547a0e4ec72Rafael Espindola BD.EmitProgressBitcode(BD.getProgram(), "reduced-blocks"); 52547ae4a1cee5eec5767a11403c0fac7c91ec45461Chris Lattner } 5266520785dcd22012535934098942d57c07c7631c2Chris Lattner 5274c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky // Attempt to delete instructions using bisection. This should help out nasty 5284c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky // cases with large basic blocks where the problem is at one end. 5294c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky if (!BugpointIsInterrupted) { 5304c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky std::vector<const Instruction*> Insts; 5314c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky for (Module::const_iterator MI = BD.getProgram()->begin(), 5324c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky ME = BD.getProgram()->end(); MI != ME; ++MI) 5334c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky for (Function::const_iterator FI = MI->begin(), FE = MI->end(); FI != FE; 5344c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky ++FI) 5354c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky for (BasicBlock::const_iterator I = FI->begin(), E = FI->end(); 5364c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky I != E; ++I) 5374c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky if (!isa<TerminatorInst>(I)) 5384c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky Insts.push_back(I); 5394c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky 54022ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky ReduceCrashingInstructions(BD, TestFn).reduceList(Insts, Error); 5414c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky } 5424c8f9af6e0c264a99b41817b2ee78c2297930165Nick Lewycky 543aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner // FIXME: This should use the list reducer to converge faster by deleting 544aae33f9137e4a64394d8f9fe66611ae53a0ef4e8Chris Lattner // larger chunks of instructions at a time! 545b2c180f04e4f71a29c8c4a2478179cb1ddd5d859Chris Lattner unsigned Simplification = 2; 5466520785dcd22012535934098942d57c07c7631c2Chris Lattner do { 547f9aaae06cd2109082cda2b09ef3f23e0e1cff47bChris Lattner if (BugpointIsInterrupted) break; 5486520785dcd22012535934098942d57c07c7631c2Chris Lattner --Simplification; 549ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman outs() << "\n*** Attempting to reduce testcase by deleting instruc" 550ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman << "tions: Simplification Level #" << Simplification << '\n'; 5516520785dcd22012535934098942d57c07c7631c2Chris Lattner 5525560c9d49ccae132cabf1155f18aa0480dce3edaMisha Brukman // Now that we have deleted the functions that are unnecessary for the 5535560c9d49ccae132cabf1155f18aa0480dce3edaMisha Brukman // program, try to remove instructions that are not necessary to cause the 5546520785dcd22012535934098942d57c07c7631c2Chris Lattner // crash. To do this, we loop through all of the instructions in the 5556520785dcd22012535934098942d57c07c7631c2Chris Lattner // remaining functions, deleting them (replacing any values produced with 5566520785dcd22012535934098942d57c07c7631c2Chris Lattner // nulls), and then running ADCE and SimplifyCFG. If the transformed input 5576520785dcd22012535934098942d57c07c7631c2Chris Lattner // still triggers failure, keep deleting until we cannot trigger failure 5586520785dcd22012535934098942d57c07c7631c2Chris Lattner // anymore. 5596520785dcd22012535934098942d57c07c7631c2Chris Lattner // 560f66d9069cff9ee8b3658b92d3a13d04d198ada91Chris Lattner unsigned InstructionsToSkipBeforeDeleting = 0; 5616520785dcd22012535934098942d57c07c7631c2Chris Lattner TryAgain: 5623da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman 5636520785dcd22012535934098942d57c07c7631c2Chris Lattner // Loop over all of the (non-terminator) instructions remaining in the 5646520785dcd22012535934098942d57c07c7631c2Chris Lattner // function, attempting to delete them. 565f66d9069cff9ee8b3658b92d3a13d04d198ada91Chris Lattner unsigned CurInstructionNum = 0; 5668b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner for (Module::const_iterator FI = BD.getProgram()->begin(), 5678b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner E = BD.getProgram()->end(); FI != E; ++FI) 5685cbf985dcbc89fba3208e7baf8b6f488b06d3ec9Reid Spencer if (!FI->isDeclaration()) 5698b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner for (Function::const_iterator BI = FI->begin(), E = FI->end(); BI != E; 5708b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner ++BI) 5718b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner for (BasicBlock::const_iterator I = BI->begin(), E = --BI->end(); 572467ef21cafa8be9c62f4adc70a04496607336cd8Bill Wendling I != E; ++I, ++CurInstructionNum) { 573f66d9069cff9ee8b3658b92d3a13d04d198ada91Chris Lattner if (InstructionsToSkipBeforeDeleting) { 574f66d9069cff9ee8b3658b92d3a13d04d198ada91Chris Lattner --InstructionsToSkipBeforeDeleting; 575f66d9069cff9ee8b3658b92d3a13d04d198ada91Chris Lattner } else { 576f9aaae06cd2109082cda2b09ef3f23e0e1cff47bChris Lattner if (BugpointIsInterrupted) goto ExitLoops; 577f9aaae06cd2109082cda2b09ef3f23e0e1cff47bChris Lattner 578597362a54bf4bb8de5538b4a1d97c618b18a023cEli Friedman if (isa<LandingPadInst>(I)) 579597362a54bf4bb8de5538b4a1d97c618b18a023cEli Friedman continue; 580597362a54bf4bb8de5538b4a1d97c618b18a023cEli Friedman 581ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman outs() << "Checking instruction: " << *I; 582f66d9069cff9ee8b3658b92d3a13d04d198ada91Chris Lattner Module *M = BD.deleteInstructionFromProgram(I, Simplification); 5833da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman 584f66d9069cff9ee8b3658b92d3a13d04d198ada91Chris Lattner // Find out if the pass still crashes on this pass... 585f66d9069cff9ee8b3658b92d3a13d04d198ada91Chris Lattner if (TestFn(BD, M)) { 586f66d9069cff9ee8b3658b92d3a13d04d198ada91Chris Lattner // Yup, it does, we delete the old module, and continue trying 587f66d9069cff9ee8b3658b92d3a13d04d198ada91Chris Lattner // to reduce the testcase... 588f66d9069cff9ee8b3658b92d3a13d04d198ada91Chris Lattner BD.setNewProgram(M); 589f66d9069cff9ee8b3658b92d3a13d04d198ada91Chris Lattner InstructionsToSkipBeforeDeleting = CurInstructionNum; 590f66d9069cff9ee8b3658b92d3a13d04d198ada91Chris Lattner goto TryAgain; // I wish I had a multi-level break here! 591f66d9069cff9ee8b3658b92d3a13d04d198ada91Chris Lattner } 5923da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman 593f66d9069cff9ee8b3658b92d3a13d04d198ada91Chris Lattner // This pass didn't crash without this instruction, try the next 594f66d9069cff9ee8b3658b92d3a13d04d198ada91Chris Lattner // one. 595f66d9069cff9ee8b3658b92d3a13d04d198ada91Chris Lattner delete M; 5966520785dcd22012535934098942d57c07c7631c2Chris Lattner } 597467ef21cafa8be9c62f4adc70a04496607336cd8Bill Wendling } 598f66d9069cff9ee8b3658b92d3a13d04d198ada91Chris Lattner 599f66d9069cff9ee8b3658b92d3a13d04d198ada91Chris Lattner if (InstructionsToSkipBeforeDeleting) { 600f66d9069cff9ee8b3658b92d3a13d04d198ada91Chris Lattner InstructionsToSkipBeforeDeleting = 0; 601f66d9069cff9ee8b3658b92d3a13d04d198ada91Chris Lattner goto TryAgain; 602f66d9069cff9ee8b3658b92d3a13d04d198ada91Chris Lattner } 6033da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman 6046520785dcd22012535934098942d57c07c7631c2Chris Lattner } while (Simplification); 605f9aaae06cd2109082cda2b09ef3f23e0e1cff47bChris LattnerExitLoops: 606ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner 607ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner // Try to clean up the testcase by running funcresolve and globaldce... 608f9aaae06cd2109082cda2b09ef3f23e0e1cff47bChris Lattner if (!BugpointIsInterrupted) { 609ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman outs() << "\n*** Attempting to perform final cleanups: "; 610f9aaae06cd2109082cda2b09ef3f23e0e1cff47bChris Lattner Module *M = CloneModule(BD.getProgram()); 611f9aaae06cd2109082cda2b09ef3f23e0e1cff47bChris Lattner M = BD.performFinalCleanups(M, true); 6123da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman 613f9aaae06cd2109082cda2b09ef3f23e0e1cff47bChris Lattner // Find out if the pass still crashes on the cleaned up program... 614f9aaae06cd2109082cda2b09ef3f23e0e1cff47bChris Lattner if (TestFn(BD, M)) { 615f9aaae06cd2109082cda2b09ef3f23e0e1cff47bChris Lattner BD.setNewProgram(M); // Yup, it does, keep the reduced version... 616f9aaae06cd2109082cda2b09ef3f23e0e1cff47bChris Lattner } else { 617f9aaae06cd2109082cda2b09ef3f23e0e1cff47bChris Lattner delete M; 618f9aaae06cd2109082cda2b09ef3f23e0e1cff47bChris Lattner } 619ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner } 620ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner 621bae1b71cbb930e419df03db209ebc547a0e4ec72Rafael Espindola BD.EmitProgressBitcode(BD.getProgram(), "reduced-simplified"); 622ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner 6233da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman return false; 6248b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner} 6258b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner 626248d1c65f1ce5bc04b892998b2c2061e6a5f8e1cRafael Espindolastatic bool TestForOptimizerCrash(const BugDriver &BD, Module *M) { 6278b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner return BD.runPasses(M); 628afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner} 629d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke 6308b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner/// debugOptimizerCrash - This method is called when some pass crashes on input. 6318b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner/// It attempts to prune down the testcase to something reasonable, and figure 6328b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner/// out exactly which pass is crashing. 6338b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner/// 6346a3f31cb707972ebde1e45a61fa8f5bcff132ebaPatrick Jenkinsbool BugDriver::debugOptimizerCrash(const std::string &ID) { 635ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman outs() << "\n*** Debugging optimizer crash!\n"; 6368b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner 63722ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky std::string Error; 6388b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner // Reduce the list of passes which causes the optimizer to crash... 639f9aaae06cd2109082cda2b09ef3f23e0e1cff47bChris Lattner if (!BugpointIsInterrupted) 64022ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky ReducePassList(*this).reduceList(PassesToRun, Error); 64122ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky assert(Error.empty()); 6428b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner 643ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman outs() << "\n*** Found crashing pass" 644ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman << (PassesToRun.size() == 1 ? ": " : "es: ") 645ac95cc79ac0b899d566cc29c0f646f39c2fa35c0Dan Gohman << getPassesString(PassesToRun) << '\n'; 646025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner 647bae1b71cbb930e419df03db209ebc547a0e4ec72Rafael Espindola EmitProgressBitcode(Program, ID); 6488b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner 64922ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky bool Success = DebugACrash(*this, TestForOptimizerCrash, Error); 65022ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky assert(Error.empty()); 65122ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky return Success; 6528b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner} 6538b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner 654248d1c65f1ce5bc04b892998b2c2061e6a5f8e1cRafael Espindolastatic bool TestForCodeGenCrash(const BugDriver &BD, Module *M) { 65522ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky std::string Error; 65622ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky BD.compileProgram(M, &Error); 65722ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky if (!Error.empty()) { 65865f57c233cd4499e2e8b52a503201e64edfd6a9eDan Gohman errs() << "<crash>\n"; 6598b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner return true; // Tool is still crashing. 6608b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner } 66122ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky errs() << '\n'; 66222ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky return false; 6638b189277bde5f617405dded0bbd6583e6665f4dfChris Lattner} 664025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner 665025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner/// debugCodeGeneratorCrash - This method is called when the code generator 666025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner/// crashes on an input. It attempts to reduce the input as much as possible 667025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner/// while still causing the code generator to crash. 66822ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewyckybool BugDriver::debugCodeGeneratorCrash(std::string &Error) { 66965f57c233cd4499e2e8b52a503201e64edfd6a9eDan Gohman errs() << "*** Debugging code generator crash!\n"; 670025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner 67122ff748712b348300e51248339b6e8cf9b59e2c6Nick Lewycky return DebugACrash(*this, TestForCodeGenCrash, Error); 672025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner} 673