BugDriver.cpp revision f1b20d8620b05abaa52f40ac6d21f839b265fb00
1afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner//===- BugDriver.cpp - Top-Level BugPoint class implementation ------------===// 23da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman// 37c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell// The LLVM Compiler Infrastructure 47c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell// 57c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell// This file was developed by the LLVM research group and is distributed under 67c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell// the University of Illinois Open Source License. See LICENSE.TXT for details. 73da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman// 87c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell//===----------------------------------------------------------------------===// 9afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner// 10afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner// This class contains all of the shared state and information that is used by 11afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner// the BugPoint tool to track down errors in optimizations. This class is the 12afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner// main driver class that invokes all sub-functionality. 13afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner// 14afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner//===----------------------------------------------------------------------===// 15afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 16afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner#include "BugDriver.h" 17f1b20d8620b05abaa52f40ac6d21f839b265fb00Chris Lattner#include "ToolRunner.h" 18605b9e2c5bd1b0c151a0b15d01e6df3aba93d52fReid Spencer#include "llvm/Linker.h" 19afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner#include "llvm/Module.h" 20e49603d79d220a795bd50684c8b1f503ee40f97fMisha Brukman#include "llvm/Pass.h" 21afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner#include "llvm/Assembly/Parser.h" 22e49603d79d220a795bd50684c8b1f503ee40f97fMisha Brukman#include "llvm/Bytecode/Reader.h" 23551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/Support/CommandLine.h" 24551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/Support/FileUtilities.h" 2586f42bdad93677fa0ca33b27afb0f493028376cbReid Spencer#include <iostream> 26afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner#include <memory> 2786f42bdad93677fa0ca33b27afb0f493028376cbReid Spencer 28d0fde30ce850b78371fd1386338350591f9ff494Brian Gaekeusing namespace llvm; 29d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke 305073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman// Anonymous namespace to define command line options for debugging. 315073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman// 325073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmannamespace { 335073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // Output - The user can specify a file containing the expected output of the 345073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // program. If this filename is set, it is used as the reference diff source, 355073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // otherwise the raw input run through an interpreter is used as the reference 365073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // source. 375073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // 383da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman cl::opt<std::string> 395073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman OutputFile("output", cl::desc("Specify a reference program output " 405073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman "(for miscompilation detection)")); 415073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman} 425073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 4306905db7d2a2b83c1b3236d5552629ada2d8d56dChris Lattner/// setNewProgram - If we reduce or update the program somehow, call this method 4406905db7d2a2b83c1b3236d5552629ada2d8d56dChris Lattner/// to update bugdriver with it. This deletes the old module and sets the 4506905db7d2a2b83c1b3236d5552629ada2d8d56dChris Lattner/// specified one as the current program. 4606905db7d2a2b83c1b3236d5552629ada2d8d56dChris Lattnervoid BugDriver::setNewProgram(Module *M) { 4706905db7d2a2b83c1b3236d5552629ada2d8d56dChris Lattner delete Program; 4806905db7d2a2b83c1b3236d5552629ada2d8d56dChris Lattner Program = M; 4906905db7d2a2b83c1b3236d5552629ada2d8d56dChris Lattner} 5006905db7d2a2b83c1b3236d5552629ada2d8d56dChris Lattner 5106905db7d2a2b83c1b3236d5552629ada2d8d56dChris Lattner 52640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner/// getPassesString - Turn a list of passes into a string which indicates the 53640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner/// command line options that must be passed to add the passes. 54640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner/// 55fa76183e8e28985dfd17b1d6291c939dab4cbe1dChris Lattnerstd::string llvm::getPassesString(const std::vector<const PassInfo*> &Passes) { 56640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner std::string Result; 57640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner for (unsigned i = 0, e = Passes.size(); i != e; ++i) { 58640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner if (i) Result += " "; 59640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner Result += "-"; 60640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner Result += Passes[i]->getPassArgument(); 61640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner } 62640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner return Result; 63640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner} 64640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner 65c4bb052ecccfafa0ffa928d0b061db35734ee2eeReid SpencerBugDriver::BugDriver(const char *toolname, bool as_child) 665073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman : ToolName(toolname), ReferenceOutputFile(OutputFile), 67c4bb052ecccfafa0ffa928d0b061db35734ee2eeReid Spencer Program(0), Interpreter(0), cbe(0), gcc(0), run_as_child(as_child) {} 685073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 695073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 70afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner/// ParseInputFile - Given a bytecode or assembly input filename, parse and 71afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner/// return it, or return null if not possible. 72afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner/// 73efdc0b505712d1ca4460def27e51c430f033d58dChris LattnerModule *llvm::ParseInputFile(const std::string &InputFilename) { 74afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner Module *Result = 0; 75afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner try { 76afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner Result = ParseBytecodeFile(InputFilename); 77afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner if (!Result && !(Result = ParseAssemblyFile(InputFilename))){ 78efdc0b505712d1ca4460def27e51c430f033d58dChris Lattner std::cerr << "bugpoint: could not read input file '" 79afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner << InputFilename << "'!\n"; 80afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner } 81afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner } catch (const ParseException &E) { 82eed80e23751ecc50c1fa5604f67be4b826d5b417Misha Brukman std::cerr << "bugpoint: " << E.getMessage() << '\n'; 83afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner Result = 0; 84afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner } 85afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner return Result; 86afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner} 87afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 88afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner// This method takes the specified list of LLVM input files, attempts to load 89dae7f92366311de2bfaff91f6e66ef3da2f2fcbcBrian Gaeke// them, either as assembly or bytecode, then link them together. It returns 90dae7f92366311de2bfaff91f6e66ef3da2f2fcbcBrian Gaeke// true on failure (if, for example, an input bytecode file could not be 91dae7f92366311de2bfaff91f6e66ef3da2f2fcbcBrian Gaeke// parsed), and false on success. 92afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner// 93afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattnerbool BugDriver::addSources(const std::vector<std::string> &Filenames) { 94afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner assert(Program == 0 && "Cannot call addSources multiple times!"); 95afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner assert(!Filenames.empty() && "Must specify at least on input filename!"); 96afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 9753bd1b9de74247acae27328cef95bd3888f6cd4dChris Lattner try { 9853bd1b9de74247acae27328cef95bd3888f6cd4dChris Lattner // Load the first input file. 9953bd1b9de74247acae27328cef95bd3888f6cd4dChris Lattner Program = ParseInputFile(Filenames[0]); 10053bd1b9de74247acae27328cef95bd3888f6cd4dChris Lattner if (Program == 0) return true; 101c4bb052ecccfafa0ffa928d0b061db35734ee2eeReid Spencer if (!run_as_child) 10253bd1b9de74247acae27328cef95bd3888f6cd4dChris Lattner std::cout << "Read input file : '" << Filenames[0] << "'\n"; 10353bd1b9de74247acae27328cef95bd3888f6cd4dChris Lattner 10453bd1b9de74247acae27328cef95bd3888f6cd4dChris Lattner for (unsigned i = 1, e = Filenames.size(); i != e; ++i) { 10553bd1b9de74247acae27328cef95bd3888f6cd4dChris Lattner std::auto_ptr<Module> M(ParseInputFile(Filenames[i])); 10653bd1b9de74247acae27328cef95bd3888f6cd4dChris Lattner if (M.get() == 0) return true; 10753bd1b9de74247acae27328cef95bd3888f6cd4dChris Lattner 10853bd1b9de74247acae27328cef95bd3888f6cd4dChris Lattner if (!run_as_child) 10953bd1b9de74247acae27328cef95bd3888f6cd4dChris Lattner std::cout << "Linking in input file: '" << Filenames[i] << "'\n"; 11053bd1b9de74247acae27328cef95bd3888f6cd4dChris Lattner std::string ErrorMessage; 11153bd1b9de74247acae27328cef95bd3888f6cd4dChris Lattner if (Linker::LinkModules(Program, M.get(), &ErrorMessage)) { 11253bd1b9de74247acae27328cef95bd3888f6cd4dChris Lattner std::cerr << ToolName << ": error linking in '" << Filenames[i] << "': " 11353bd1b9de74247acae27328cef95bd3888f6cd4dChris Lattner << ErrorMessage << '\n'; 11453bd1b9de74247acae27328cef95bd3888f6cd4dChris Lattner return true; 11553bd1b9de74247acae27328cef95bd3888f6cd4dChris Lattner } 116afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner } 11753bd1b9de74247acae27328cef95bd3888f6cd4dChris Lattner } catch (const std::string &Error) { 11853bd1b9de74247acae27328cef95bd3888f6cd4dChris Lattner std::cerr << ToolName << ": error reading input '" << Error << "'\n"; 11953bd1b9de74247acae27328cef95bd3888f6cd4dChris Lattner return true; 120afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner } 121afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 122c4bb052ecccfafa0ffa928d0b061db35734ee2eeReid Spencer if (!run_as_child) 123c4bb052ecccfafa0ffa928d0b061db35734ee2eeReid Spencer std::cout << "*** All input ok\n"; 124afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 125afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner // All input files read successfully! 126afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner return false; 127afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner} 128afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 129afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 130afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 131afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner/// run - The top level method that is invoked after all of the instance 132afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner/// variables are set up from command line arguments. 133afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner/// 134afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattnerbool BugDriver::run() { 135c4bb052ecccfafa0ffa928d0b061db35734ee2eeReid Spencer // The first thing to do is determine if we're running as a child. If we are, 136c4bb052ecccfafa0ffa928d0b061db35734ee2eeReid Spencer // then what to do is very narrow. This form of invocation is only called 137c4bb052ecccfafa0ffa928d0b061db35734ee2eeReid Spencer // from the runPasses method to actually run those passes in a child process. 138c4bb052ecccfafa0ffa928d0b061db35734ee2eeReid Spencer if (run_as_child) { 139c4bb052ecccfafa0ffa928d0b061db35734ee2eeReid Spencer // Execute the passes 140c4bb052ecccfafa0ffa928d0b061db35734ee2eeReid Spencer return runPassesAsChild(PassesToRun); 141c4bb052ecccfafa0ffa928d0b061db35734ee2eeReid Spencer } 142c4bb052ecccfafa0ffa928d0b061db35734ee2eeReid Spencer 143c4bb052ecccfafa0ffa928d0b061db35734ee2eeReid Spencer // If we're not running as a child, the first thing that we must do is 144c4bb052ecccfafa0ffa928d0b061db35734ee2eeReid Spencer // determine what the problem is. Does the optimization series crash the 145c4bb052ecccfafa0ffa928d0b061db35734ee2eeReid Spencer // compiler, or does it produce illegal code? We make the top-level 146c4bb052ecccfafa0ffa928d0b061db35734ee2eeReid Spencer // decision by trying to run all of the passes on the the input program, 147c4bb052ecccfafa0ffa928d0b061db35734ee2eeReid Spencer // which should generate a bytecode file. If it does generate a bytecode 148c4bb052ecccfafa0ffa928d0b061db35734ee2eeReid Spencer // file, then we know the compiler didn't crash, so try to diagnose a 149c4bb052ecccfafa0ffa928d0b061db35734ee2eeReid Spencer // miscompilation. 15099b85334d70bc5eb110ee5f1af4ff2f63c55f6cbChris Lattner if (!PassesToRun.empty()) { 15199b85334d70bc5eb110ee5f1af4ff2f63c55f6cbChris Lattner std::cout << "Running selected passes on program to test for crash: "; 15299b85334d70bc5eb110ee5f1af4ff2f63c55f6cbChris Lattner if (runPasses(PassesToRun)) 153025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner return debugOptimizerCrash(); 15499b85334d70bc5eb110ee5f1af4ff2f63c55f6cbChris Lattner } 1555073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1565073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // Set up the execution environment, selecting a method to run LLVM bytecode. 1575073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman if (initializeExecutionEnvironment()) return true; 1585073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1597c955fdb446fa0629e1341f88f4541ee9a929942Chris Lattner // Test to see if we have a code generator crash. 1607c955fdb446fa0629e1341f88f4541ee9a929942Chris Lattner std::cout << "Running the code generator to test for a crash: "; 1617c955fdb446fa0629e1341f88f4541ee9a929942Chris Lattner try { 1627c955fdb446fa0629e1341f88f4541ee9a929942Chris Lattner compileProgram(Program); 163eed80e23751ecc50c1fa5604f67be4b826d5b417Misha Brukman std::cout << '\n'; 1647c955fdb446fa0629e1341f88f4541ee9a929942Chris Lattner } catch (ToolExecutionError &TEE) { 1657c955fdb446fa0629e1341f88f4541ee9a929942Chris Lattner std::cout << TEE.what(); 1667c955fdb446fa0629e1341f88f4541ee9a929942Chris Lattner return debugCodeGeneratorCrash(); 1677c955fdb446fa0629e1341f88f4541ee9a929942Chris Lattner } 1687c955fdb446fa0629e1341f88f4541ee9a929942Chris Lattner 1697c955fdb446fa0629e1341f88f4541ee9a929942Chris Lattner 1705073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // Run the raw input to see where we are coming from. If a reference output 1715073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // was specified, make sure that the raw output matches it. If not, it's a 1725073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // problem in the front-end or the code generator. 1735073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // 174c28c1d3cd19bbfcc8eec44f25c5890f8e3ed8bdcChris Lattner bool CreatedOutput = false; 1755073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman if (ReferenceOutputFile.empty()) { 1767d91e49ff7bcc0fd10a54d45a6185bb05adf3d20Chris Lattner std::cout << "Generating reference output from raw program: "; 177025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner try { 178025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner ReferenceOutputFile = executeProgramWithCBE("bugpoint.reference.out"); 179025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner CreatedOutput = true; 180eed80e23751ecc50c1fa5604f67be4b826d5b417Misha Brukman std::cout << "Reference output is: " << ReferenceOutputFile << '\n'; 181025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner } catch (ToolExecutionError &TEE) { 1821d29a6d6c7a7f6203065c003d3d2d002870e38a1Alkis Evlogimenos std::cerr << TEE.what(); 183025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner if (Interpreter != cbe) { 184025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner std::cerr << "*** There is a bug running the C backend. Either debug" 185025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner << " it (use the -run-cbe bugpoint option), or fix the error" 186025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner << " some other way.\n"; 187025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner return 1; 188025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner } 189025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner return debugCodeGeneratorCrash(); 190025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner } 191a5a96a9ed9d90014769ffc86ca48c486cf753ad5Chris Lattner } 1925073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 193a5a96a9ed9d90014769ffc86ca48c486cf753ad5Chris Lattner // Make sure the reference output file gets deleted on exit from this 194a5a96a9ed9d90014769ffc86ca48c486cf753ad5Chris Lattner // function, if appropriate. 1955d282185f517d651d965e86dab1b383e0cb5e919Reid Spencer sys::Path ROF(ReferenceOutputFile); 1965d282185f517d651d965e86dab1b383e0cb5e919Reid Spencer FileRemover RemoverInstance(ROF, CreatedOutput); 197a5a96a9ed9d90014769ffc86ca48c486cf753ad5Chris Lattner 198a5a96a9ed9d90014769ffc86ca48c486cf753ad5Chris Lattner // Diff the output of the raw program against the reference output. If it 199a5a96a9ed9d90014769ffc86ca48c486cf753ad5Chris Lattner // matches, then we have a miscompilation bug. 200a5a96a9ed9d90014769ffc86ca48c486cf753ad5Chris Lattner std::cout << "*** Checking the code generator...\n"; 201025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner try { 202025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner if (!diffProgram()) { 203025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner std::cout << "\n*** Debugging miscompilation!\n"; 204025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner return debugMiscompilation(); 205025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner } 206025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner } catch (ToolExecutionError &TEE) { 2071d29a6d6c7a7f6203065c003d3d2d002870e38a1Alkis Evlogimenos std::cerr << TEE.what(); 208025262692a6710de29a48e2b3905672cd12d13d2Chris Lattner return debugCodeGeneratorCrash(); 2095073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 2105073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 211a5a96a9ed9d90014769ffc86ca48c486cf753ad5Chris Lattner std::cout << "\n*** Input program does not match reference diff!\n"; 212a5a96a9ed9d90014769ffc86ca48c486cf753ad5Chris Lattner std::cout << "Debugging code generator problem!\n"; 2137c955fdb446fa0629e1341f88f4541ee9a929942Chris Lattner try { 2147c955fdb446fa0629e1341f88f4541ee9a929942Chris Lattner return debugCodeGenerator(); 2157c955fdb446fa0629e1341f88f4541ee9a929942Chris Lattner } catch (ToolExecutionError &TEE) { 2167c955fdb446fa0629e1341f88f4541ee9a929942Chris Lattner std::cerr << TEE.what(); 2177c955fdb446fa0629e1341f88f4541ee9a929942Chris Lattner return debugCodeGeneratorCrash(); 2187c955fdb446fa0629e1341f88f4541ee9a929942Chris Lattner } 2195073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman} 2205073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 221efdc0b505712d1ca4460def27e51c430f033d58dChris Lattnervoid llvm::PrintFunctionList(const std::vector<Function*> &Funcs) { 222efdc0b505712d1ca4460def27e51c430f033d58dChris Lattner unsigned NumPrint = Funcs.size(); 223efdc0b505712d1ca4460def27e51c430f033d58dChris Lattner if (NumPrint > 10) NumPrint = 10; 224efdc0b505712d1ca4460def27e51c430f033d58dChris Lattner for (unsigned i = 0; i != NumPrint; ++i) 225efdc0b505712d1ca4460def27e51c430f033d58dChris Lattner std::cout << " " << Funcs[i]->getName(); 226efdc0b505712d1ca4460def27e51c430f033d58dChris Lattner if (NumPrint < Funcs.size()) 227efdc0b505712d1ca4460def27e51c430f033d58dChris Lattner std::cout << "... <" << Funcs.size() << " total>"; 228b6c3a88dc4c749e88fdd68368d74ccfb37d506a3Brian Gaeke std::cout << std::flush; 229afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner} 230