CrashDebugger.cpp revision 640f22e66d90439857a97a83896ee68c4f7128c9
1afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner//===- CrashDebugger.cpp - Debug compilation crashes ----------------------===// 2afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner// 3afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner// This file defines the bugpoint internals that narrow down compilation crashes 4afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner// 5afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner//===----------------------------------------------------------------------===// 6afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 7afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner#include "BugDriver.h" 8218e26ef3583cc3270f5f2a2b9cb1025e5b05ebeChris Lattner#include "SystemUtils.h" 9afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner#include "llvm/Module.h" 10afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner#include "llvm/Bytecode/Writer.h" 11afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner#include "llvm/Pass.h" 12afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner#include <fstream> 13afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 14640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner#if 0 15640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattnerclass DebugCrashes : public ListReducer<const PassInfo*> { 16640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner BugDriver &BD; 17640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattnerpublic: 18640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner DebugCrashes(BugDriver &bd) : BD(bd) {} 19640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner 20640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner // doTest - Return true iff running the "removed" passes succeeds, and running 21640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner // the "Kept" passes fail when run on the output of the "removed" passes. If 22640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner // we return true, we update the current module of bugpoint. 23640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner // 24640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner virtual bool doTest(const std::vector<ElTy> &Removed, 25640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner const std::vector<ElTy> &Kept) { 26640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner return BD.runPasses(Kept); 27640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner } 28640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner}; 29640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner#endif 30640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner 31afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner/// debugCrash - This method is called when some pass crashes on input. It 32afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner/// attempts to prune down the testcase to something reasonable, and figure 33afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner/// out exactly which pass is crashing. 34afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner/// 35afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattnerbool BugDriver::debugCrash() { 36afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner std::cout << "\n*** Debugging optimizer crash!\n"; 37afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 38640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner#if 0 39640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner // Reduce the list of passes which causes the optimizer to crash... 40640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner DebugCrashes(*this).reduceList(PassesToRun); 41640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner#endif 42640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner 43afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner unsigned LastToPass = 0, LastToCrash = PassesToRun.size(); 44afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner while (LastToPass != LastToCrash) { 45afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner unsigned Mid = (LastToCrash+LastToPass+1) / 2; 46afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner std::vector<const PassInfo*> P(PassesToRun.begin(), 47afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner PassesToRun.begin()+Mid); 48afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner std::cout << "Checking to see if the first " << Mid << " passes crash: "; 49afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 50afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner if (runPasses(P)) 51afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner LastToCrash = Mid-1; 52afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner else 53afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner LastToPass = Mid; 54afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner } 55afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 56afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner // Make sure something crashed. :) 57afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner if (LastToCrash >= PassesToRun.size()) { 58afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner std::cerr << "ERROR: No passes crashed!\n"; 59afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner return true; 60afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner } 61afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 62afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner // Calculate which pass it is that crashes... 63afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner const PassInfo *CrashingPass = PassesToRun[LastToCrash]; 64afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 65afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner std::cout << "\n*** Found crashing pass '-" << CrashingPass->getPassArgument() 66afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner << "': " << CrashingPass->getPassName() << "\n"; 67afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 68afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner // Compile the program with just the passes that don't crash. 69218e26ef3583cc3270f5f2a2b9cb1025e5b05ebeChris Lattner if (LastToPass != 0) { // Don't bother doing this if the first pass crashes... 70afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner std::vector<const PassInfo*> P(PassesToRun.begin(), 71afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner PassesToRun.begin()+LastToPass); 72afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner std::string Filename; 73afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner std::cout << "Running passes that don't crash to get input for pass: "; 74afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner if (runPasses(P, Filename)) { 75afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner std::cerr << "ERROR: Running the first " << LastToPass 76afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner << " passes crashed this time!\n"; 77afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner return true; 78afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner } 79afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 80afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner // Assuming everything was successful, we now have a valid bytecode file in 81afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner // OutputName. Use it for "Program" Instead. 82afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner delete Program; 83afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner Program = ParseInputFile(Filename); 84afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 85afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner // Delete the file now. 86afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner removeFile(Filename); 87afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner } 88afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 89640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner PassesToRun.clear(); 90640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner PassesToRun.push_back(CrashingPass); 91640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner 92afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner return debugPassCrash(CrashingPass); 93afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner} 94afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 95afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner/// CountFunctions - return the number of non-external functions defined in the 96afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner/// module. 97afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattnerstatic unsigned CountFunctions(Module *M) { 98afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner unsigned N = 0; 99afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) 100afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner if (!I->isExternal()) 101afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner ++N; 102afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner return N; 103afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner} 104afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 105afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner/// debugPassCrash - This method is called when the specified pass crashes on 106afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner/// Program as input. It tries to reduce the testcase to something that still 107afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner/// crashes, but it smaller. 108afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner/// 109afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattnerbool BugDriver::debugPassCrash(const PassInfo *Pass) { 110640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner EmitProgressBytecode("passinput"); 111ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner bool Reduced = false, AnyReduction = false; 112afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 113afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner if (CountFunctions(Program) > 1) { 114afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner // Attempt to reduce the input program down to a single function that still 115218e26ef3583cc3270f5f2a2b9cb1025e5b05ebeChris Lattner // crashes. Do this by removing everything except for that one function... 116afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner // 117afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner std::cout << "\n*** Attempting to reduce the testcase to one function\n"; 118afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 119afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner for (Module::iterator I = Program->begin(), E = Program->end(); I != E; ++I) 120afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner if (!I->isExternal()) { 121afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner // Extract one function from the module... 122afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner Module *M = extractFunctionFromModule(I); 123afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 124afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner // Make the function the current program... 125afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner std::swap(Program, M); 126afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 127afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner // Find out if the pass still crashes on this pass... 128afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner std::cout << "Checking function '" << I->getName() << "': "; 129afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner if (runPass(Pass)) { 130afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner // Yup, it does, we delete the old module, and continue trying to 131afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner // reduce the testcase... 132afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner delete M; 133afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 134ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner Reduced = AnyReduction = true; 135afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner break; 136afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner } 137afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 138afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner // This pass didn't crash on this function, try the next one. 139afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner delete Program; 140afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner Program = M; 141afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner } 142afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 1436520785dcd22012535934098942d57c07c7631c2Chris Lattner if (CountFunctions(Program) > 1) { 1446520785dcd22012535934098942d57c07c7631c2Chris Lattner std::cout << "\n*** Couldn't reduce testcase to one function.\n" 1456520785dcd22012535934098942d57c07c7631c2Chris Lattner << " Attempting to remove individual functions.\n"; 1466520785dcd22012535934098942d57c07c7631c2Chris Lattner std::cout << "XXX Individual function removal unimplemented!\n"; 1476520785dcd22012535934098942d57c07c7631c2Chris Lattner } 148218e26ef3583cc3270f5f2a2b9cb1025e5b05ebeChris Lattner } 149218e26ef3583cc3270f5f2a2b9cb1025e5b05ebeChris Lattner 150ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner if (Reduced) { 151640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner EmitProgressBytecode("reduced-function"); 152ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner Reduced = false; 153ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner } 154ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner 1556520785dcd22012535934098942d57c07c7631c2Chris Lattner // FIXME: This should attempt to delete entire basic blocks at a time to speed 1566520785dcd22012535934098942d57c07c7631c2Chris Lattner // up convergence... 1576520785dcd22012535934098942d57c07c7631c2Chris Lattner 1586520785dcd22012535934098942d57c07c7631c2Chris Lattner unsigned Simplification = 4; 1596520785dcd22012535934098942d57c07c7631c2Chris Lattner do { 1606520785dcd22012535934098942d57c07c7631c2Chris Lattner --Simplification; 1616520785dcd22012535934098942d57c07c7631c2Chris Lattner std::cout << "\n*** Attempting to reduce testcase by deleting instruc" 1626520785dcd22012535934098942d57c07c7631c2Chris Lattner << "tions: Simplification Level #" << Simplification << "\n"; 1636520785dcd22012535934098942d57c07c7631c2Chris Lattner 1646520785dcd22012535934098942d57c07c7631c2Chris Lattner // Now that we have deleted the functions that are unneccesary for the 1656520785dcd22012535934098942d57c07c7631c2Chris Lattner // program, try to remove instructions that are not neccesary to cause the 1666520785dcd22012535934098942d57c07c7631c2Chris Lattner // crash. To do this, we loop through all of the instructions in the 1676520785dcd22012535934098942d57c07c7631c2Chris Lattner // remaining functions, deleting them (replacing any values produced with 1686520785dcd22012535934098942d57c07c7631c2Chris Lattner // nulls), and then running ADCE and SimplifyCFG. If the transformed input 1696520785dcd22012535934098942d57c07c7631c2Chris Lattner // still triggers failure, keep deleting until we cannot trigger failure 1706520785dcd22012535934098942d57c07c7631c2Chris Lattner // anymore. 1716520785dcd22012535934098942d57c07c7631c2Chris Lattner // 1726520785dcd22012535934098942d57c07c7631c2Chris Lattner TryAgain: 1736520785dcd22012535934098942d57c07c7631c2Chris Lattner 1746520785dcd22012535934098942d57c07c7631c2Chris Lattner // Loop over all of the (non-terminator) instructions remaining in the 1756520785dcd22012535934098942d57c07c7631c2Chris Lattner // function, attempting to delete them. 1766520785dcd22012535934098942d57c07c7631c2Chris Lattner for (Module::iterator FI = Program->begin(), E = Program->end(); 1776520785dcd22012535934098942d57c07c7631c2Chris Lattner FI != E; ++FI) 1786520785dcd22012535934098942d57c07c7631c2Chris Lattner if (!FI->isExternal()) { 1796520785dcd22012535934098942d57c07c7631c2Chris Lattner for (Function::iterator BI = FI->begin(), E = FI->end(); BI != E; ++BI) 1806520785dcd22012535934098942d57c07c7631c2Chris Lattner for (BasicBlock::iterator I = BI->begin(), E = --BI->end(); 1816520785dcd22012535934098942d57c07c7631c2Chris Lattner I != E; ++I) { 1826520785dcd22012535934098942d57c07c7631c2Chris Lattner Module *M = deleteInstructionFromProgram(I, Simplification); 1836520785dcd22012535934098942d57c07c7631c2Chris Lattner 1846520785dcd22012535934098942d57c07c7631c2Chris Lattner // Make the function the current program... 1856520785dcd22012535934098942d57c07c7631c2Chris Lattner std::swap(Program, M); 1866520785dcd22012535934098942d57c07c7631c2Chris Lattner 1876520785dcd22012535934098942d57c07c7631c2Chris Lattner // Find out if the pass still crashes on this pass... 1886520785dcd22012535934098942d57c07c7631c2Chris Lattner std::cout << "Checking instruction '" << I->getName() << "': "; 1896520785dcd22012535934098942d57c07c7631c2Chris Lattner if (runPass(Pass)) { 1906520785dcd22012535934098942d57c07c7631c2Chris Lattner // Yup, it does, we delete the old module, and continue trying to 1916520785dcd22012535934098942d57c07c7631c2Chris Lattner // reduce the testcase... 1926520785dcd22012535934098942d57c07c7631c2Chris Lattner delete M; 193ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner Reduced = AnyReduction = true; 1946520785dcd22012535934098942d57c07c7631c2Chris Lattner goto TryAgain; // I wish I had a multi-level break here! 1956520785dcd22012535934098942d57c07c7631c2Chris Lattner } 1966520785dcd22012535934098942d57c07c7631c2Chris Lattner 1976520785dcd22012535934098942d57c07c7631c2Chris Lattner // This pass didn't crash without this instruction, try the next 1986520785dcd22012535934098942d57c07c7631c2Chris Lattner // one. 1996520785dcd22012535934098942d57c07c7631c2Chris Lattner delete Program; 2006520785dcd22012535934098942d57c07c7631c2Chris Lattner Program = M; 2016520785dcd22012535934098942d57c07c7631c2Chris Lattner } 2026520785dcd22012535934098942d57c07c7631c2Chris Lattner } 2036520785dcd22012535934098942d57c07c7631c2Chris Lattner } while (Simplification); 204ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner 205ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner // Try to clean up the testcase by running funcresolve and globaldce... 206ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner if (AnyReduction) { 207ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner std::cout << "\n*** Attempting to perform final cleanups: "; 208ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner Module *M = performFinalCleanups(); 209ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner std::swap(Program, M); 210ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner 211ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner // Find out if the pass still crashes on the cleaned up program... 212ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner if (runPass(Pass)) { 213ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner // Yup, it does, keep the reduced version... 214ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner delete M; 215ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner Reduced = AnyReduction = true; 216ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner } else { 217ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner delete Program; // Otherwise, restore the original module... 218ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner Program = M; 219ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner } 220ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner } 221ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner 222ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner if (Reduced) { 223640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner EmitProgressBytecode("reduced-simplified"); 224ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner Reduced = false; 225ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner } 226ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner 227afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner return false; 228afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner} 229