diff options
Diffstat (limited to 'contrib/llvm/tools/bugpoint')
-rw-r--r-- | contrib/llvm/tools/bugpoint/BugDriver.cpp | 246 | ||||
-rw-r--r-- | contrib/llvm/tools/bugpoint/BugDriver.h | 329 | ||||
-rw-r--r-- | contrib/llvm/tools/bugpoint/CMakeLists.txt | 14 | ||||
-rw-r--r-- | contrib/llvm/tools/bugpoint/CrashDebugger.cpp | 667 | ||||
-rw-r--r-- | contrib/llvm/tools/bugpoint/ExecutionDriver.cpp | 501 | ||||
-rw-r--r-- | contrib/llvm/tools/bugpoint/ExtractFunction.cpp | 369 | ||||
-rw-r--r-- | contrib/llvm/tools/bugpoint/FindBugs.cpp | 113 | ||||
-rw-r--r-- | contrib/llvm/tools/bugpoint/ListReducer.h | 201 | ||||
-rw-r--r-- | contrib/llvm/tools/bugpoint/Makefile | 16 | ||||
-rw-r--r-- | contrib/llvm/tools/bugpoint/Miscompilation.cpp | 1082 | ||||
-rw-r--r-- | contrib/llvm/tools/bugpoint/OptimizerDriver.cpp | 260 | ||||
-rw-r--r-- | contrib/llvm/tools/bugpoint/ToolRunner.cpp | 883 | ||||
-rw-r--r-- | contrib/llvm/tools/bugpoint/ToolRunner.h | 242 | ||||
-rw-r--r-- | contrib/llvm/tools/bugpoint/bugpoint.cpp | 159 |
14 files changed, 0 insertions, 5082 deletions
diff --git a/contrib/llvm/tools/bugpoint/BugDriver.cpp b/contrib/llvm/tools/bugpoint/BugDriver.cpp deleted file mode 100644 index 6966671..0000000 --- a/contrib/llvm/tools/bugpoint/BugDriver.cpp +++ /dev/null @@ -1,246 +0,0 @@ -//===- BugDriver.cpp - Top-Level BugPoint class implementation ------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This class contains all of the shared state and information that is used by -// the BugPoint tool to track down errors in optimizations. This class is the -// main driver class that invokes all sub-functionality. -// -//===----------------------------------------------------------------------===// - -#include "BugDriver.h" -#include "ToolRunner.h" -#include "llvm/Linker.h" -#include "llvm/Module.h" -#include "llvm/Pass.h" -#include "llvm/Support/IRReader.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/FileUtilities.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/System/Host.h" -#include <memory> -using namespace llvm; - -namespace llvm { - Triple TargetTriple; -} - -// Anonymous namespace to define command line options for debugging. -// -namespace { - // Output - The user can specify a file containing the expected output of the - // program. If this filename is set, it is used as the reference diff source, - // otherwise the raw input run through an interpreter is used as the reference - // source. - // - cl::opt<std::string> - OutputFile("output", cl::desc("Specify a reference program output " - "(for miscompilation detection)")); -} - -/// setNewProgram - If we reduce or update the program somehow, call this method -/// to update bugdriver with it. This deletes the old module and sets the -/// specified one as the current program. -void BugDriver::setNewProgram(Module *M) { - delete Program; - Program = M; -} - - -/// getPassesString - Turn a list of passes into a string which indicates the -/// command line options that must be passed to add the passes. -/// -std::string llvm::getPassesString(const std::vector<std::string> &Passes) { - std::string Result; - for (unsigned i = 0, e = Passes.size(); i != e; ++i) { - if (i) Result += " "; - Result += "-"; - Result += Passes[i]; - } - return Result; -} - -BugDriver::BugDriver(const char *toolname, bool find_bugs, - unsigned timeout, unsigned memlimit, bool use_valgrind, - LLVMContext& ctxt) - : Context(ctxt), ToolName(toolname), ReferenceOutputFile(OutputFile), - Program(0), Interpreter(0), SafeInterpreter(0), gcc(0), - run_find_bugs(find_bugs), Timeout(timeout), - MemoryLimit(memlimit), UseValgrind(use_valgrind) {} - -BugDriver::~BugDriver() { - delete Program; -} - - -/// ParseInputFile - Given a bitcode or assembly input filename, parse and -/// return it, or return null if not possible. -/// -Module *llvm::ParseInputFile(const std::string &Filename, - LLVMContext& Ctxt) { - SMDiagnostic Err; - Module *Result = ParseIRFile(Filename, Err, Ctxt); - if (!Result) - Err.Print("bugpoint", errs()); - - // If we don't have an override triple, use the first one to configure - // bugpoint, or use the host triple if none provided. - if (Result) { - if (TargetTriple.getTriple().empty()) { - Triple TheTriple(Result->getTargetTriple()); - - if (TheTriple.getTriple().empty()) - TheTriple.setTriple(sys::getHostTriple()); - - TargetTriple.setTriple(TheTriple.getTriple()); - } - - Result->setTargetTriple(TargetTriple.getTriple()); // override the triple - } - return Result; -} - -// This method takes the specified list of LLVM input files, attempts to load -// them, either as assembly or bitcode, then link them together. It returns -// true on failure (if, for example, an input bitcode file could not be -// parsed), and false on success. -// -bool BugDriver::addSources(const std::vector<std::string> &Filenames) { - assert(Program == 0 && "Cannot call addSources multiple times!"); - assert(!Filenames.empty() && "Must specify at least on input filename!"); - - // Load the first input file. - Program = ParseInputFile(Filenames[0], Context); - if (Program == 0) return true; - - outs() << "Read input file : '" << Filenames[0] << "'\n"; - - for (unsigned i = 1, e = Filenames.size(); i != e; ++i) { - std::auto_ptr<Module> M(ParseInputFile(Filenames[i], Context)); - if (M.get() == 0) return true; - - outs() << "Linking in input file: '" << Filenames[i] << "'\n"; - std::string ErrorMessage; - if (Linker::LinkModules(Program, M.get(), &ErrorMessage)) { - errs() << ToolName << ": error linking in '" << Filenames[i] << "': " - << ErrorMessage << '\n'; - return true; - } - } - - outs() << "*** All input ok\n"; - - // All input files read successfully! - return false; -} - - - -/// run - The top level method that is invoked after all of the instance -/// variables are set up from command line arguments. -/// -bool BugDriver::run(std::string &ErrMsg) { - if (run_find_bugs) { - // Rearrange the passes and apply them to the program. Repeat this process - // until the user kills the program or we find a bug. - return runManyPasses(PassesToRun, ErrMsg); - } - - // If we're not running as a child, the first thing that we must do is - // determine what the problem is. Does the optimization series crash the - // compiler, or does it produce illegal code? We make the top-level - // decision by trying to run all of the passes on the the input program, - // which should generate a bitcode file. If it does generate a bitcode - // file, then we know the compiler didn't crash, so try to diagnose a - // miscompilation. - if (!PassesToRun.empty()) { - outs() << "Running selected passes on program to test for crash: "; - if (runPasses(Program, PassesToRun)) - return debugOptimizerCrash(); - } - - // Set up the execution environment, selecting a method to run LLVM bitcode. - if (initializeExecutionEnvironment()) return true; - - // Test to see if we have a code generator crash. - outs() << "Running the code generator to test for a crash: "; - std::string Error; - compileProgram(Program, &Error); - if (!Error.empty()) { - outs() << Error; - return debugCodeGeneratorCrash(ErrMsg); - } - outs() << '\n'; - - // Run the raw input to see where we are coming from. If a reference output - // was specified, make sure that the raw output matches it. If not, it's a - // problem in the front-end or the code generator. - // - bool CreatedOutput = false; - if (ReferenceOutputFile.empty()) { - outs() << "Generating reference output from raw program: "; - if (!createReferenceFile(Program)) { - return debugCodeGeneratorCrash(ErrMsg); - } - CreatedOutput = true; - } - - // Make sure the reference output file gets deleted on exit from this - // function, if appropriate. - sys::Path ROF(ReferenceOutputFile); - FileRemover RemoverInstance(ROF, CreatedOutput && !SaveTemps); - - // Diff the output of the raw program against the reference output. If it - // matches, then we assume there is a miscompilation bug and try to - // diagnose it. - outs() << "*** Checking the code generator...\n"; - bool Diff = diffProgram(Program, "", "", false, &Error); - if (!Error.empty()) { - errs() << Error; - return debugCodeGeneratorCrash(ErrMsg); - } - if (!Diff) { - outs() << "\n*** Output matches: Debugging miscompilation!\n"; - debugMiscompilation(&Error); - if (!Error.empty()) { - errs() << Error; - return debugCodeGeneratorCrash(ErrMsg); - } - return false; - } - - outs() << "\n*** Input program does not match reference diff!\n"; - outs() << "Debugging code generator problem!\n"; - bool Failure = debugCodeGenerator(&Error); - if (!Error.empty()) { - errs() << Error; - return debugCodeGeneratorCrash(ErrMsg); - } - return Failure; -} - -void llvm::PrintFunctionList(const std::vector<Function*> &Funcs) { - unsigned NumPrint = Funcs.size(); - if (NumPrint > 10) NumPrint = 10; - for (unsigned i = 0; i != NumPrint; ++i) - outs() << " " << Funcs[i]->getName(); - if (NumPrint < Funcs.size()) - outs() << "... <" << Funcs.size() << " total>"; - outs().flush(); -} - -void llvm::PrintGlobalVariableList(const std::vector<GlobalVariable*> &GVs) { - unsigned NumPrint = GVs.size(); - if (NumPrint > 10) NumPrint = 10; - for (unsigned i = 0; i != NumPrint; ++i) - outs() << " " << GVs[i]->getName(); - if (NumPrint < GVs.size()) - outs() << "... <" << GVs.size() << " total>"; - outs().flush(); -} diff --git a/contrib/llvm/tools/bugpoint/BugDriver.h b/contrib/llvm/tools/bugpoint/BugDriver.h deleted file mode 100644 index e48806a..0000000 --- a/contrib/llvm/tools/bugpoint/BugDriver.h +++ /dev/null @@ -1,329 +0,0 @@ -//===- BugDriver.h - Top-Level BugPoint class -------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This class contains all of the shared state and information that is used by -// the BugPoint tool to track down errors in optimizations. This class is the -// main driver class that invokes all sub-functionality. -// -//===----------------------------------------------------------------------===// - -#ifndef BUGDRIVER_H -#define BUGDRIVER_H - -#include "llvm/ADT/ValueMap.h" -#include <vector> -#include <string> - -namespace llvm { - -class Value; -class PassInfo; -class Module; -class GlobalVariable; -class Function; -class BasicBlock; -class AbstractInterpreter; -class Instruction; -class LLVMContext; - -class DebugCrashes; - -class GCC; - -extern bool DisableSimplifyCFG; - -/// BugpointIsInterrupted - Set to true when the user presses ctrl-c. -/// -extern bool BugpointIsInterrupted; - -class BugDriver { - LLVMContext& Context; - const char *ToolName; // argv[0] of bugpoint - std::string ReferenceOutputFile; // Name of `good' output file - Module *Program; // The raw program, linked together - std::vector<std::string> PassesToRun; - AbstractInterpreter *Interpreter; // How to run the program - AbstractInterpreter *SafeInterpreter; // To generate reference output, etc. - GCC *gcc; - bool run_find_bugs; - unsigned Timeout; - unsigned MemoryLimit; - bool UseValgrind; - - // FIXME: sort out public/private distinctions... - friend class ReducePassList; - friend class ReduceMisCodegenFunctions; - -public: - BugDriver(const char *toolname, bool find_bugs, - unsigned timeout, unsigned memlimit, bool use_valgrind, - LLVMContext& ctxt); - ~BugDriver(); - - const char *getToolName() const { return ToolName; } - - LLVMContext& getContext() const { return Context; } - - // Set up methods... these methods are used to copy information about the - // command line arguments into instance variables of BugDriver. - // - bool addSources(const std::vector<std::string> &FileNames); - void addPass(std::string p) { PassesToRun.push_back(p); } - void setPassesToRun(const std::vector<std::string> &PTR) { - PassesToRun = PTR; - } - const std::vector<std::string> &getPassesToRun() const { - return PassesToRun; - } - - /// run - The top level method that is invoked after all of the instance - /// variables are set up from command line arguments. The \p as_child argument - /// indicates whether the driver is to run in parent mode or child mode. - /// - bool run(std::string &ErrMsg); - - /// debugOptimizerCrash - This method is called when some optimizer pass - /// crashes on input. It attempts to prune down the testcase to something - /// reasonable, and figure out exactly which pass is crashing. - /// - bool debugOptimizerCrash(const std::string &ID = "passes"); - - /// debugCodeGeneratorCrash - This method is called when the code generator - /// crashes on an input. It attempts to reduce the input as much as possible - /// while still causing the code generator to crash. - bool debugCodeGeneratorCrash(std::string &Error); - - /// debugMiscompilation - This method is used when the passes selected are not - /// crashing, but the generated output is semantically different from the - /// input. - void debugMiscompilation(std::string *Error); - - /// debugPassMiscompilation - This method is called when the specified pass - /// miscompiles Program as input. It tries to reduce the testcase to - /// something that smaller that still miscompiles the program. - /// ReferenceOutput contains the filename of the file containing the output we - /// are to match. - /// - bool debugPassMiscompilation(const PassInfo *ThePass, - const std::string &ReferenceOutput); - - /// compileSharedObject - This method creates a SharedObject from a given - /// BitcodeFile for debugging a code generator. - /// - std::string compileSharedObject(const std::string &BitcodeFile, - std::string &Error); - - /// debugCodeGenerator - This method narrows down a module to a function or - /// set of functions, using the CBE as a ``safe'' code generator for other - /// functions that are not under consideration. - bool debugCodeGenerator(std::string *Error); - - /// isExecutingJIT - Returns true if bugpoint is currently testing the JIT - /// - bool isExecutingJIT(); - - /// runPasses - Run all of the passes in the "PassesToRun" list, discard the - /// output, and return true if any of the passes crashed. - bool runPasses(Module *M) const { - return runPasses(M, PassesToRun); - } - - Module *getProgram() const { return Program; } - - /// swapProgramIn - Set the current module to the specified module, returning - /// the old one. - Module *swapProgramIn(Module *M) { - Module *OldProgram = Program; - Program = M; - return OldProgram; - } - - AbstractInterpreter *switchToSafeInterpreter() { - AbstractInterpreter *Old = Interpreter; - Interpreter = (AbstractInterpreter*)SafeInterpreter; - return Old; - } - - void switchToInterpreter(AbstractInterpreter *AI) { - Interpreter = AI; - } - - /// setNewProgram - If we reduce or update the program somehow, call this - /// method to update bugdriver with it. This deletes the old module and sets - /// the specified one as the current program. - void setNewProgram(Module *M); - - /// compileProgram - Try to compile the specified module, returning false and - /// setting Error if an error occurs. This is used for code generation - /// crash testing. - /// - void compileProgram(Module *M, std::string *Error) const; - - /// executeProgram - This method runs "Program", capturing the output of the - /// program to a file. A recommended filename may be optionally specified. - /// - std::string executeProgram(const Module *Program, - std::string OutputFilename, - std::string Bitcode, - const std::string &SharedObjects, - AbstractInterpreter *AI, - std::string *Error) const; - - /// executeProgramSafely - Used to create reference output with the "safe" - /// backend, if reference output is not provided. If there is a problem with - /// the code generator (e.g., llc crashes), this will return false and set - /// Error. - /// - std::string executeProgramSafely(const Module *Program, - std::string OutputFile, - std::string *Error) const; - - /// createReferenceFile - calls compileProgram and then records the output - /// into ReferenceOutputFile. Returns true if reference file created, false - /// otherwise. Note: initializeExecutionEnvironment should be called BEFORE - /// this function. - /// - bool createReferenceFile(Module *M, const std::string &Filename - = "bugpoint.reference.out"); - - /// diffProgram - This method executes the specified module and diffs the - /// output against the file specified by ReferenceOutputFile. If the output - /// is different, 1 is returned. If there is a problem with the code - /// generator (e.g., llc crashes), this will return -1 and set Error. - /// - bool diffProgram(const Module *Program, - const std::string &BitcodeFile = "", - const std::string &SharedObj = "", - bool RemoveBitcode = false, - std::string *Error = 0) const; - - /// EmitProgressBitcode - This function is used to output M to a file named - /// "bugpoint-ID.bc". - /// - void EmitProgressBitcode(const Module *M, const std::string &ID, - bool NoFlyer = false) const; - - /// deleteInstructionFromProgram - This method clones the current Program and - /// deletes the specified instruction from the cloned module. It then runs a - /// series of cleanup passes (ADCE and SimplifyCFG) to eliminate any code - /// which depends on the value. The modified module is then returned. - /// - Module *deleteInstructionFromProgram(const Instruction *I, unsigned Simp); - - /// performFinalCleanups - This method clones the current Program and performs - /// a series of cleanups intended to get rid of extra cruft on the module. If - /// the MayModifySemantics argument is true, then the cleanups is allowed to - /// modify how the code behaves. - /// - Module *performFinalCleanups(Module *M, bool MayModifySemantics = false); - - /// ExtractLoop - Given a module, extract up to one loop from it into a new - /// function. This returns null if there are no extractable loops in the - /// program or if the loop extractor crashes. - Module *ExtractLoop(Module *M); - - /// ExtractMappedBlocksFromModule - Extract all but the specified basic blocks - /// into their own functions. The only detail is that M is actually a module - /// cloned from the one the BBs are in, so some mapping needs to be performed. - /// If this operation fails for some reason (ie the implementation is buggy), - /// this function should return null, otherwise it returns a new Module. - Module *ExtractMappedBlocksFromModule(const std::vector<BasicBlock*> &BBs, - Module *M); - - /// runPassesOn - Carefully run the specified set of pass on the specified - /// module, returning the transformed module on success, or a null pointer on - /// failure. If AutoDebugCrashes is set to true, then bugpoint will - /// automatically attempt to track down a crashing pass if one exists, and - /// this method will never return null. - Module *runPassesOn(Module *M, const std::vector<std::string> &Passes, - bool AutoDebugCrashes = false, unsigned NumExtraArgs = 0, - const char * const *ExtraArgs = NULL); - - /// runPasses - Run the specified passes on Program, outputting a bitcode - /// file and writting the filename into OutputFile if successful. If the - /// optimizations fail for some reason (optimizer crashes), return true, - /// otherwise return false. If DeleteOutput is set to true, the bitcode is - /// deleted on success, and the filename string is undefined. This prints to - /// outs() a single line message indicating whether compilation was successful - /// or failed, unless Quiet is set. ExtraArgs specifies additional arguments - /// to pass to the child bugpoint instance. - /// - bool runPasses(Module *Program, - const std::vector<std::string> &PassesToRun, - std::string &OutputFilename, bool DeleteOutput = false, - bool Quiet = false, unsigned NumExtraArgs = 0, - const char * const *ExtraArgs = NULL) const; - - /// runManyPasses - Take the specified pass list and create different - /// combinations of passes to compile the program with. Compile the program with - /// each set and mark test to see if it compiled correctly. If the passes - /// compiled correctly output nothing and rearrange the passes into a new order. - /// If the passes did not compile correctly, output the command required to - /// recreate the failure. This returns true if a compiler error is found. - /// - bool runManyPasses(const std::vector<std::string> &AllPasses, - std::string &ErrMsg); - - /// writeProgramToFile - This writes the current "Program" to the named - /// bitcode file. If an error occurs, true is returned. - /// - bool writeProgramToFile(const std::string &Filename, const Module *M) const; - -private: - /// runPasses - Just like the method above, but this just returns true or - /// false indicating whether or not the optimizer crashed on the specified - /// input (true = crashed). - /// - bool runPasses(Module *M, - const std::vector<std::string> &PassesToRun, - bool DeleteOutput = true) const { - std::string Filename; - return runPasses(M, PassesToRun, Filename, DeleteOutput); - } - - /// initializeExecutionEnvironment - This method is used to set up the - /// environment for executing LLVM programs. - /// - bool initializeExecutionEnvironment(); -}; - -/// ParseInputFile - Given a bitcode or assembly input filename, parse and -/// return it, or return null if not possible. -/// -Module *ParseInputFile(const std::string &InputFilename, - LLVMContext& ctxt); - - -/// getPassesString - Turn a list of passes into a string which indicates the -/// command line options that must be passed to add the passes. -/// -std::string getPassesString(const std::vector<std::string> &Passes); - -/// PrintFunctionList - prints out list of problematic functions -/// -void PrintFunctionList(const std::vector<Function*> &Funcs); - -/// PrintGlobalVariableList - prints out list of problematic global variables -/// -void PrintGlobalVariableList(const std::vector<GlobalVariable*> &GVs); - -// DeleteFunctionBody - "Remove" the function by deleting all of it's basic -// blocks, making it external. -// -void DeleteFunctionBody(Function *F); - -/// SplitFunctionsOutOfModule - Given a module and a list of functions in the -/// module, split the functions OUT of the specified module, and place them in -/// the new module. -Module *SplitFunctionsOutOfModule(Module *M, const std::vector<Function*> &F, - ValueMap<const Value*, Value*> &VMap); - -} // End llvm namespace - -#endif diff --git a/contrib/llvm/tools/bugpoint/CMakeLists.txt b/contrib/llvm/tools/bugpoint/CMakeLists.txt deleted file mode 100644 index e06feb1..0000000 --- a/contrib/llvm/tools/bugpoint/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -set(LLVM_LINK_COMPONENTS asmparser instrumentation scalaropts ipo - linker bitreader bitwriter) - -add_llvm_tool(bugpoint - BugDriver.cpp - CrashDebugger.cpp - ExecutionDriver.cpp - ExtractFunction.cpp - FindBugs.cpp - Miscompilation.cpp - OptimizerDriver.cpp - ToolRunner.cpp - bugpoint.cpp - ) diff --git a/contrib/llvm/tools/bugpoint/CrashDebugger.cpp b/contrib/llvm/tools/bugpoint/CrashDebugger.cpp deleted file mode 100644 index 57dc1c8..0000000 --- a/contrib/llvm/tools/bugpoint/CrashDebugger.cpp +++ /dev/null @@ -1,667 +0,0 @@ -//===- CrashDebugger.cpp - Debug compilation crashes ----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the bugpoint internals that narrow down compilation crashes -// -//===----------------------------------------------------------------------===// - -#include "BugDriver.h" -#include "ToolRunner.h" -#include "ListReducer.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Instructions.h" -#include "llvm/Module.h" -#include "llvm/Pass.h" -#include "llvm/PassManager.h" -#include "llvm/ValueSymbolTable.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/Analysis/Verifier.h" -#include "llvm/Support/CFG.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/Utils/Cloning.h" -#include "llvm/Support/FileUtilities.h" -#include "llvm/Support/CommandLine.h" -#include <set> -using namespace llvm; - -namespace { - cl::opt<bool> - KeepMain("keep-main", - cl::desc("Force function reduction to keep main"), - cl::init(false)); - cl::opt<bool> - NoGlobalRM ("disable-global-remove", - cl::desc("Do not remove global variables"), - cl::init(false)); -} - -namespace llvm { - class ReducePassList : public ListReducer<std::string> { - BugDriver &BD; - public: - ReducePassList(BugDriver &bd) : BD(bd) {} - - // doTest - Return true iff running the "removed" passes succeeds, and - // running the "Kept" passes fail when run on the output of the "removed" - // passes. If we return true, we update the current module of bugpoint. - // - virtual TestResult doTest(std::vector<std::string> &Removed, - std::vector<std::string> &Kept, - std::string &Error); - }; -} - -ReducePassList::TestResult -ReducePassList::doTest(std::vector<std::string> &Prefix, - std::vector<std::string> &Suffix, - std::string &Error) { - sys::Path PrefixOutput; - Module *OrigProgram = 0; - if (!Prefix.empty()) { - outs() << "Checking to see if these passes crash: " - << getPassesString(Prefix) << ": "; - std::string PfxOutput; - if (BD.runPasses(BD.getProgram(), Prefix, PfxOutput)) - return KeepPrefix; - - PrefixOutput.set(PfxOutput); - OrigProgram = BD.Program; - - BD.Program = ParseInputFile(PrefixOutput.str(), BD.getContext()); - if (BD.Program == 0) { - errs() << BD.getToolName() << ": Error reading bitcode file '" - << PrefixOutput.str() << "'!\n"; - exit(1); - } - PrefixOutput.eraseFromDisk(); - } - - outs() << "Checking to see if these passes crash: " - << getPassesString(Suffix) << ": "; - - if (BD.runPasses(BD.getProgram(), Suffix)) { - delete OrigProgram; // The suffix crashes alone... - return KeepSuffix; - } - - // Nothing failed, restore state... - if (OrigProgram) { - delete BD.Program; - BD.Program = OrigProgram; - } - return NoFailure; -} - -namespace { - /// ReduceCrashingGlobalVariables - This works by removing the global - /// variable's initializer and seeing if the program still crashes. If it - /// does, then we keep that program and try again. - /// - class ReduceCrashingGlobalVariables : public ListReducer<GlobalVariable*> { - BugDriver &BD; - bool (*TestFn)(const BugDriver &, Module *); - public: - ReduceCrashingGlobalVariables(BugDriver &bd, - bool (*testFn)(const BugDriver &, Module *)) - : BD(bd), TestFn(testFn) {} - - virtual TestResult doTest(std::vector<GlobalVariable*> &Prefix, - std::vector<GlobalVariable*> &Kept, - std::string &Error) { - if (!Kept.empty() && TestGlobalVariables(Kept)) - return KeepSuffix; - if (!Prefix.empty() && TestGlobalVariables(Prefix)) - return KeepPrefix; - return NoFailure; - } - - bool TestGlobalVariables(std::vector<GlobalVariable*> &GVs); - }; -} - -bool -ReduceCrashingGlobalVariables::TestGlobalVariables( - std::vector<GlobalVariable*> &GVs) { - // Clone the program to try hacking it apart... - ValueMap<const Value*, Value*> VMap; - Module *M = CloneModule(BD.getProgram(), VMap); - - // Convert list to set for fast lookup... - std::set<GlobalVariable*> GVSet; - - for (unsigned i = 0, e = GVs.size(); i != e; ++i) { - GlobalVariable* CMGV = cast<GlobalVariable>(VMap[GVs[i]]); - assert(CMGV && "Global Variable not in module?!"); - GVSet.insert(CMGV); - } - - outs() << "Checking for crash with only these global variables: "; - PrintGlobalVariableList(GVs); - outs() << ": "; - - // Loop over and delete any global variables which we aren't supposed to be - // playing with... - for (Module::global_iterator I = M->global_begin(), E = M->global_end(); - I != E; ++I) - if (I->hasInitializer() && !GVSet.count(I)) { - I->setInitializer(0); - I->setLinkage(GlobalValue::ExternalLinkage); - } - - // Try running the hacked up program... - if (TestFn(BD, M)) { - BD.setNewProgram(M); // It crashed, keep the trimmed version... - - // Make sure to use global variable pointers that point into the now-current - // module. - GVs.assign(GVSet.begin(), GVSet.end()); - return true; - } - - delete M; - return false; -} - -namespace llvm { - /// ReduceCrashingFunctions reducer - This works by removing functions and - /// seeing if the program still crashes. If it does, then keep the newer, - /// smaller program. - /// - class ReduceCrashingFunctions : public ListReducer<Function*> { - BugDriver &BD; - bool (*TestFn)(const BugDriver &, Module *); - public: - ReduceCrashingFunctions(BugDriver &bd, - bool (*testFn)(const BugDriver &, Module *)) - : BD(bd), TestFn(testFn) {} - - virtual TestResult doTest(std::vector<Function*> &Prefix, - std::vector<Function*> &Kept, - std::string &Error) { - if (!Kept.empty() && TestFuncs(Kept)) - return KeepSuffix; - if (!Prefix.empty() && TestFuncs(Prefix)) - return KeepPrefix; - return NoFailure; - } - - bool TestFuncs(std::vector<Function*> &Prefix); - }; -} - -bool ReduceCrashingFunctions::TestFuncs(std::vector<Function*> &Funcs) { - - //if main isn't present, claim there is no problem - if (KeepMain && find(Funcs.begin(), Funcs.end(), - BD.getProgram()->getFunction("main")) == Funcs.end()) - return false; - - // Clone the program to try hacking it apart... - ValueMap<const Value*, Value*> VMap; - Module *M = CloneModule(BD.getProgram(), VMap); - - // Convert list to set for fast lookup... - std::set<Function*> Functions; - for (unsigned i = 0, e = Funcs.size(); i != e; ++i) { - Function *CMF = cast<Function>(VMap[Funcs[i]]); - assert(CMF && "Function not in module?!"); - assert(CMF->getFunctionType() == Funcs[i]->getFunctionType() && "wrong ty"); - assert(CMF->getName() == Funcs[i]->getName() && "wrong name"); - Functions.insert(CMF); - } - - outs() << "Checking for crash with only these functions: "; - PrintFunctionList(Funcs); - outs() << ": "; - - // Loop over and delete any functions which we aren't supposed to be playing - // with... - for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) - if (!I->isDeclaration() && !Functions.count(I)) - DeleteFunctionBody(I); - - // Try running the hacked up program... - if (TestFn(BD, M)) { - BD.setNewProgram(M); // It crashed, keep the trimmed version... - - // Make sure to use function pointers that point into the now-current - // module. - Funcs.assign(Functions.begin(), Functions.end()); - return true; - } - delete M; - return false; -} - - -namespace { - /// ReduceCrashingBlocks reducer - This works by setting the terminators of - /// all terminators except the specified basic blocks to a 'ret' instruction, - /// then running the simplify-cfg pass. This has the effect of chopping up - /// the CFG really fast which can reduce large functions quickly. - /// - class ReduceCrashingBlocks : public ListReducer<const BasicBlock*> { - BugDriver &BD; - bool (*TestFn)(const BugDriver &, Module *); - public: - ReduceCrashingBlocks(BugDriver &bd, - bool (*testFn)(const BugDriver &, Module *)) - : BD(bd), TestFn(testFn) {} - - virtual TestResult doTest(std::vector<const BasicBlock*> &Prefix, - std::vector<const BasicBlock*> &Kept, - std::string &Error) { - if (!Kept.empty() && TestBlocks(Kept)) - return KeepSuffix; - if (!Prefix.empty() && TestBlocks(Prefix)) - return KeepPrefix; - return NoFailure; - } - - bool TestBlocks(std::vector<const BasicBlock*> &Prefix); - }; -} - -bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock*> &BBs) { - // Clone the program to try hacking it apart... - ValueMap<const Value*, Value*> VMap; - Module *M = CloneModule(BD.getProgram(), VMap); - - // Convert list to set for fast lookup... - SmallPtrSet<BasicBlock*, 8> Blocks; - for (unsigned i = 0, e = BBs.size(); i != e; ++i) - Blocks.insert(cast<BasicBlock>(VMap[BBs[i]])); - - outs() << "Checking for crash with only these blocks:"; - unsigned NumPrint = Blocks.size(); - if (NumPrint > 10) NumPrint = 10; - for (unsigned i = 0, e = NumPrint; i != e; ++i) - outs() << " " << BBs[i]->getName(); - if (NumPrint < Blocks.size()) - outs() << "... <" << Blocks.size() << " total>"; - outs() << ": "; - - // Loop over and delete any hack up any blocks that are not listed... - for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) - for (Function::iterator BB = I->begin(), E = I->end(); BB != E; ++BB) - if (!Blocks.count(BB) && BB->getTerminator()->getNumSuccessors()) { - // Loop over all of the successors of this block, deleting any PHI nodes - // that might include it. - for (succ_iterator SI = succ_begin(BB), E = succ_end(BB); SI != E; ++SI) - (*SI)->removePredecessor(BB); - - TerminatorInst *BBTerm = BB->getTerminator(); - - if (!BB->getTerminator()->getType()->isVoidTy()) - BBTerm->replaceAllUsesWith(Constant::getNullValue(BBTerm->getType())); - - // Replace the old terminator instruction. - BB->getInstList().pop_back(); - new UnreachableInst(BB->getContext(), BB); - } - - // The CFG Simplifier pass may delete one of the basic blocks we are - // interested in. If it does we need to take the block out of the list. Make - // a "persistent mapping" by turning basic blocks into <function, name> pairs. - // This won't work well if blocks are unnamed, but that is just the risk we - // have to take. - std::vector<std::pair<std::string, std::string> > BlockInfo; - - for (SmallPtrSet<BasicBlock*, 8>::iterator I = Blocks.begin(), - E = Blocks.end(); I != E; ++I) - BlockInfo.push_back(std::make_pair((*I)->getParent()->getName(), - (*I)->getName())); - - // Now run the CFG simplify pass on the function... - std::vector<std::string> Passes; - Passes.push_back("simplifycfg"); - Passes.push_back("verify"); - Module *New = BD.runPassesOn(M, Passes); - delete M; - if (!New) { - errs() << "simplifycfg failed!\n"; - exit(1); - } - M = New; - - // Try running on the hacked up program... - if (TestFn(BD, M)) { - BD.setNewProgram(M); // It crashed, keep the trimmed version... - - // Make sure to use basic block pointers that point into the now-current - // module, and that they don't include any deleted blocks. - BBs.clear(); - const ValueSymbolTable &GST = M->getValueSymbolTable(); - for (unsigned i = 0, e = BlockInfo.size(); i != e; ++i) { - Function *F = cast<Function>(GST.lookup(BlockInfo[i].first)); - ValueSymbolTable &ST = F->getValueSymbolTable(); - Value* V = ST.lookup(BlockInfo[i].second); - if (V && V->getType() == Type::getLabelTy(V->getContext())) - BBs.push_back(cast<BasicBlock>(V)); - } - return true; - } - delete M; // It didn't crash, try something else. - return false; -} - -namespace { - /// ReduceCrashingInstructions reducer - This works by removing the specified - /// non-terminator instructions and replacing them with undef. - /// - class ReduceCrashingInstructions : public ListReducer<const Instruction*> { - BugDriver &BD; - bool (*TestFn)(const BugDriver &, Module *); - public: - ReduceCrashingInstructions(BugDriver &bd, - bool (*testFn)(const BugDriver &, Module *)) - : BD(bd), TestFn(testFn) {} - - virtual TestResult doTest(std::vector<const Instruction*> &Prefix, - std::vector<const Instruction*> &Kept, - std::string &Error) { - if (!Kept.empty() && TestInsts(Kept)) - return KeepSuffix; - if (!Prefix.empty() && TestInsts(Prefix)) - return KeepPrefix; - return NoFailure; - } - - bool TestInsts(std::vector<const Instruction*> &Prefix); - }; -} - -bool ReduceCrashingInstructions::TestInsts(std::vector<const Instruction*> - &Insts) { - // Clone the program to try hacking it apart... - ValueMap<const Value*, Value*> VMap; - Module *M = CloneModule(BD.getProgram(), VMap); - - // Convert list to set for fast lookup... - SmallPtrSet<Instruction*, 64> Instructions; - for (unsigned i = 0, e = Insts.size(); i != e; ++i) { - assert(!isa<TerminatorInst>(Insts[i])); - Instructions.insert(cast<Instruction>(VMap[Insts[i]])); - } - - outs() << "Checking for crash with only " << Instructions.size(); - if (Instructions.size() == 1) - outs() << " instruction: "; - else - outs() << " instructions: "; - - for (Module::iterator MI = M->begin(), ME = M->end(); MI != ME; ++MI) - for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE; ++FI) - for (BasicBlock::iterator I = FI->begin(), E = FI->end(); I != E;) { - Instruction *Inst = I++; - if (!Instructions.count(Inst) && !isa<TerminatorInst>(Inst)) { - if (!Inst->getType()->isVoidTy()) - Inst->replaceAllUsesWith(UndefValue::get(Inst->getType())); - Inst->eraseFromParent(); - } - } - - // Verify that this is still valid. - PassManager Passes; - Passes.add(createVerifierPass()); - Passes.run(*M); - - // Try running on the hacked up program... - if (TestFn(BD, M)) { - BD.setNewProgram(M); // It crashed, keep the trimmed version... - - // Make sure to use instruction pointers that point into the now-current - // module, and that they don't include any deleted blocks. - Insts.clear(); - for (SmallPtrSet<Instruction*, 64>::const_iterator I = Instructions.begin(), - E = Instructions.end(); I != E; ++I) - Insts.push_back(*I); - return true; - } - delete M; // It didn't crash, try something else. - return false; -} - -/// DebugACrash - Given a predicate that determines whether a component crashes -/// on a program, try to destructively reduce the program while still keeping -/// the predicate true. -static bool DebugACrash(BugDriver &BD, - bool (*TestFn)(const BugDriver &, Module *), - std::string &Error) { - // See if we can get away with nuking some of the global variable initializers - // in the program... - if (!NoGlobalRM && - BD.getProgram()->global_begin() != BD.getProgram()->global_end()) { - // Now try to reduce the number of global variable initializers in the - // module to something small. - Module *M = CloneModule(BD.getProgram()); - bool DeletedInit = false; - - for (Module::global_iterator I = M->global_begin(), E = M->global_end(); - I != E; ++I) - if (I->hasInitializer()) { - I->setInitializer(0); - I->setLinkage(GlobalValue::ExternalLinkage); - DeletedInit = true; - } - - if (!DeletedInit) { - delete M; // No change made... - } else { - // See if the program still causes a crash... - outs() << "\nChecking to see if we can delete global inits: "; - - if (TestFn(BD, M)) { // Still crashes? - BD.setNewProgram(M); - outs() << "\n*** Able to remove all global initializers!\n"; - } else { // No longer crashes? - outs() << " - Removing all global inits hides problem!\n"; - delete M; - - std::vector<GlobalVariable*> GVs; - - for (Module::global_iterator I = BD.getProgram()->global_begin(), - E = BD.getProgram()->global_end(); I != E; ++I) - if (I->hasInitializer()) - GVs.push_back(I); - - if (GVs.size() > 1 && !BugpointIsInterrupted) { - outs() << "\n*** Attempting to reduce the number of global " - << "variables in the testcase\n"; - - unsigned OldSize = GVs.size(); - ReduceCrashingGlobalVariables(BD, TestFn).reduceList(GVs, Error); - if (!Error.empty()) - return true; - - if (GVs.size() < OldSize) - BD.EmitProgressBitcode(BD.getProgram(), "reduced-global-variables"); - } - } - } - } - - // Now try to reduce the number of functions in the module to something small. - std::vector<Function*> Functions; - for (Module::iterator I = BD.getProgram()->begin(), - E = BD.getProgram()->end(); I != E; ++I) - if (!I->isDeclaration()) - Functions.push_back(I); - - if (Functions.size() > 1 && !BugpointIsInterrupted) { - outs() << "\n*** Attempting to reduce the number of functions " - "in the testcase\n"; - - unsigned OldSize = Functions.size(); - ReduceCrashingFunctions(BD, TestFn).reduceList(Functions, Error); - - if (Functions.size() < OldSize) - BD.EmitProgressBitcode(BD.getProgram(), "reduced-function"); - } - - // Attempt to delete entire basic blocks at a time to speed up - // convergence... this actually works by setting the terminator of the blocks - // to a return instruction then running simplifycfg, which can potentially - // shrinks the code dramatically quickly - // - if (!DisableSimplifyCFG && !BugpointIsInterrupted) { - std::vector<const BasicBlock*> Blocks; - for (Module::const_iterator I = BD.getProgram()->begin(), - E = BD.getProgram()->end(); I != E; ++I) - for (Function::const_iterator FI = I->begin(), E = I->end(); FI !=E; ++FI) - Blocks.push_back(FI); - unsigned OldSize = Blocks.size(); - ReduceCrashingBlocks(BD, TestFn).reduceList(Blocks, Error); - if (Blocks.size() < OldSize) - BD.EmitProgressBitcode(BD.getProgram(), "reduced-blocks"); - } - - // Attempt to delete instructions using bisection. This should help out nasty - // cases with large basic blocks where the problem is at one end. - if (!BugpointIsInterrupted) { - std::vector<const Instruction*> Insts; - for (Module::const_iterator MI = BD.getProgram()->begin(), - ME = BD.getProgram()->end(); MI != ME; ++MI) - for (Function::const_iterator FI = MI->begin(), FE = MI->end(); FI != FE; - ++FI) - for (BasicBlock::const_iterator I = FI->begin(), E = FI->end(); - I != E; ++I) - if (!isa<TerminatorInst>(I)) - Insts.push_back(I); - - ReduceCrashingInstructions(BD, TestFn).reduceList(Insts, Error); - } - - // FIXME: This should use the list reducer to converge faster by deleting - // larger chunks of instructions at a time! - unsigned Simplification = 2; - do { - if (BugpointIsInterrupted) break; - --Simplification; - outs() << "\n*** Attempting to reduce testcase by deleting instruc" - << "tions: Simplification Level #" << Simplification << '\n'; - - // Now that we have deleted the functions that are unnecessary for the - // program, try to remove instructions that are not necessary to cause the - // crash. To do this, we loop through all of the instructions in the - // remaining functions, deleting them (replacing any values produced with - // nulls), and then running ADCE and SimplifyCFG. If the transformed input - // still triggers failure, keep deleting until we cannot trigger failure - // anymore. - // - unsigned InstructionsToSkipBeforeDeleting = 0; - TryAgain: - - // Loop over all of the (non-terminator) instructions remaining in the - // function, attempting to delete them. - unsigned CurInstructionNum = 0; - for (Module::const_iterator FI = BD.getProgram()->begin(), - E = BD.getProgram()->end(); FI != E; ++FI) - if (!FI->isDeclaration()) - for (Function::const_iterator BI = FI->begin(), E = FI->end(); BI != E; - ++BI) - for (BasicBlock::const_iterator I = BI->begin(), E = --BI->end(); - I != E; ++I, ++CurInstructionNum) - if (InstructionsToSkipBeforeDeleting) { - --InstructionsToSkipBeforeDeleting; - } else { - if (BugpointIsInterrupted) goto ExitLoops; - - outs() << "Checking instruction: " << *I; - Module *M = BD.deleteInstructionFromProgram(I, Simplification); - - // Find out if the pass still crashes on this pass... - if (TestFn(BD, M)) { - // Yup, it does, we delete the old module, and continue trying - // to reduce the testcase... - BD.setNewProgram(M); - InstructionsToSkipBeforeDeleting = CurInstructionNum; - goto TryAgain; // I wish I had a multi-level break here! - } - - // This pass didn't crash without this instruction, try the next - // one. - delete M; - } - - if (InstructionsToSkipBeforeDeleting) { - InstructionsToSkipBeforeDeleting = 0; - goto TryAgain; - } - - } while (Simplification); -ExitLoops: - - // Try to clean up the testcase by running funcresolve and globaldce... - if (!BugpointIsInterrupted) { - outs() << "\n*** Attempting to perform final cleanups: "; - Module *M = CloneModule(BD.getProgram()); - M = BD.performFinalCleanups(M, true); - - // Find out if the pass still crashes on the cleaned up program... - if (TestFn(BD, M)) { - BD.setNewProgram(M); // Yup, it does, keep the reduced version... - } else { - delete M; - } - } - - BD.EmitProgressBitcode(BD.getProgram(), "reduced-simplified"); - - return false; -} - -static bool TestForOptimizerCrash(const BugDriver &BD, Module *M) { - return BD.runPasses(M); -} - -/// debugOptimizerCrash - This method is called when some pass crashes on input. -/// It attempts to prune down the testcase to something reasonable, and figure -/// out exactly which pass is crashing. -/// -bool BugDriver::debugOptimizerCrash(const std::string &ID) { - outs() << "\n*** Debugging optimizer crash!\n"; - - std::string Error; - // Reduce the list of passes which causes the optimizer to crash... - if (!BugpointIsInterrupted) - ReducePassList(*this).reduceList(PassesToRun, Error); - assert(Error.empty()); - - outs() << "\n*** Found crashing pass" - << (PassesToRun.size() == 1 ? ": " : "es: ") - << getPassesString(PassesToRun) << '\n'; - - EmitProgressBitcode(Program, ID); - - bool Success = DebugACrash(*this, TestForOptimizerCrash, Error); - assert(Error.empty()); - return Success; -} - -static bool TestForCodeGenCrash(const BugDriver &BD, Module *M) { - std::string Error; - BD.compileProgram(M, &Error); - if (!Error.empty()) { - errs() << "<crash>\n"; - return true; // Tool is still crashing. - } - errs() << '\n'; - return false; -} - -/// debugCodeGeneratorCrash - This method is called when the code generator -/// crashes on an input. It attempts to reduce the input as much as possible -/// while still causing the code generator to crash. -bool BugDriver::debugCodeGeneratorCrash(std::string &Error) { - errs() << "*** Debugging code generator crash!\n"; - - return DebugACrash(*this, TestForCodeGenCrash, Error); -} diff --git a/contrib/llvm/tools/bugpoint/ExecutionDriver.cpp b/contrib/llvm/tools/bugpoint/ExecutionDriver.cpp deleted file mode 100644 index 7312484..0000000 --- a/contrib/llvm/tools/bugpoint/ExecutionDriver.cpp +++ /dev/null @@ -1,501 +0,0 @@ -//===- ExecutionDriver.cpp - Allow execution of LLVM program --------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains code used to execute the program utilizing one of the -// various ways of running LLVM bitcode. -// -//===----------------------------------------------------------------------===// - -#include "BugDriver.h" -#include "ToolRunner.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/FileUtilities.h" -#include "llvm/Support/SystemUtils.h" -#include "llvm/Support/raw_ostream.h" -#include <fstream> - -using namespace llvm; - -namespace { - // OutputType - Allow the user to specify the way code should be run, to test - // for miscompilation. - // - enum OutputType { - AutoPick, RunLLI, RunJIT, RunLLC, RunLLCIA, RunCBE, CBE_bug, LLC_Safe,Custom - }; - - cl::opt<double> - AbsTolerance("abs-tolerance", cl::desc("Absolute error tolerated"), - cl::init(0.0)); - cl::opt<double> - RelTolerance("rel-tolerance", cl::desc("Relative error tolerated"), - cl::init(0.0)); - - cl::opt<OutputType> - InterpreterSel(cl::desc("Specify the \"test\" i.e. suspect back-end:"), - cl::values(clEnumValN(AutoPick, "auto", "Use best guess"), - clEnumValN(RunLLI, "run-int", - "Execute with the interpreter"), - clEnumValN(RunJIT, "run-jit", "Execute with JIT"), - clEnumValN(RunLLC, "run-llc", "Compile with LLC"), - clEnumValN(RunLLCIA, "run-llc-ia", - "Compile with LLC with integrated assembler"), - clEnumValN(RunCBE, "run-cbe", "Compile with CBE"), - clEnumValN(CBE_bug,"cbe-bug", "Find CBE bugs"), - clEnumValN(LLC_Safe, "llc-safe", "Use LLC for all"), - clEnumValN(Custom, "run-custom", - "Use -exec-command to define a command to execute " - "the bitcode. Useful for cross-compilation."), - clEnumValEnd), - cl::init(AutoPick)); - - cl::opt<OutputType> - SafeInterpreterSel(cl::desc("Specify \"safe\" i.e. known-good backend:"), - cl::values(clEnumValN(AutoPick, "safe-auto", "Use best guess"), - clEnumValN(RunLLC, "safe-run-llc", "Compile with LLC"), - clEnumValN(RunCBE, "safe-run-cbe", "Compile with CBE"), - clEnumValN(Custom, "safe-run-custom", - "Use -exec-command to define a command to execute " - "the bitcode. Useful for cross-compilation."), - clEnumValEnd), - cl::init(AutoPick)); - - cl::opt<std::string> - SafeInterpreterPath("safe-path", - cl::desc("Specify the path to the \"safe\" backend program"), - cl::init("")); - - cl::opt<bool> - AppendProgramExitCode("append-exit-code", - cl::desc("Append the exit code to the output so it gets diff'd too"), - cl::init(false)); - - cl::opt<std::string> - InputFile("input", cl::init("/dev/null"), - cl::desc("Filename to pipe in as stdin (default: /dev/null)")); - - cl::list<std::string> - AdditionalSOs("additional-so", - cl::desc("Additional shared objects to load " - "into executing programs")); - - cl::list<std::string> - AdditionalLinkerArgs("Xlinker", - cl::desc("Additional arguments to pass to the linker")); - - cl::opt<std::string> - CustomExecCommand("exec-command", cl::init("simulate"), - cl::desc("Command to execute the bitcode (use with -run-custom) " - "(default: simulate)")); -} - -namespace llvm { - // Anything specified after the --args option are taken as arguments to the - // program being debugged. - cl::list<std::string> - InputArgv("args", cl::Positional, cl::desc("<program arguments>..."), - cl::ZeroOrMore, cl::PositionalEatsArgs); - - cl::opt<std::string> - OutputPrefix("output-prefix", cl::init("bugpoint"), - cl::desc("Prefix to use for outputs (default: 'bugpoint')")); -} - -namespace { - cl::list<std::string> - ToolArgv("tool-args", cl::Positional, cl::desc("<tool arguments>..."), - cl::ZeroOrMore, cl::PositionalEatsArgs); - - cl::list<std::string> - SafeToolArgv("safe-tool-args", cl::Positional, - cl::desc("<safe-tool arguments>..."), - cl::ZeroOrMore, cl::PositionalEatsArgs); - - cl::opt<std::string> - GCCBinary("gcc", cl::init("gcc"), - cl::desc("The gcc binary to use. (default 'gcc')")); - - cl::list<std::string> - GCCToolArgv("gcc-tool-args", cl::Positional, - cl::desc("<gcc-tool arguments>..."), - cl::ZeroOrMore, cl::PositionalEatsArgs); -} - -//===----------------------------------------------------------------------===// -// BugDriver method implementation -// - -/// initializeExecutionEnvironment - This method is used to set up the -/// environment for executing LLVM programs. -/// -bool BugDriver::initializeExecutionEnvironment() { - outs() << "Initializing execution environment: "; - - // Create an instance of the AbstractInterpreter interface as specified on - // the command line - SafeInterpreter = 0; - std::string Message; - - switch (InterpreterSel) { - case AutoPick: - InterpreterSel = RunCBE; - Interpreter = - AbstractInterpreter::createCBE(getToolName(), Message, GCCBinary, - &ToolArgv, &GCCToolArgv); - if (!Interpreter) { - InterpreterSel = RunJIT; - Interpreter = AbstractInterpreter::createJIT(getToolName(), Message, - &ToolArgv); - } - if (!Interpreter) { - InterpreterSel = RunLLC; - Interpreter = AbstractInterpreter::createLLC(getToolName(), Message, - GCCBinary, &ToolArgv, - &GCCToolArgv); - } - if (!Interpreter) { - InterpreterSel = RunLLI; - Interpreter = AbstractInterpreter::createLLI(getToolName(), Message, - &ToolArgv); - } - if (!Interpreter) { - InterpreterSel = AutoPick; - Message = "Sorry, I can't automatically select an interpreter!\n"; - } - break; - case RunLLI: - Interpreter = AbstractInterpreter::createLLI(getToolName(), Message, - &ToolArgv); - break; - case RunLLC: - case RunLLCIA: - case LLC_Safe: - Interpreter = AbstractInterpreter::createLLC(getToolName(), Message, - GCCBinary, &ToolArgv, - &GCCToolArgv, - InterpreterSel == RunLLCIA); - break; - case RunJIT: - Interpreter = AbstractInterpreter::createJIT(getToolName(), Message, - &ToolArgv); - break; - case RunCBE: - case CBE_bug: - Interpreter = AbstractInterpreter::createCBE(getToolName(), Message, - GCCBinary, &ToolArgv, - &GCCToolArgv); - break; - case Custom: - Interpreter = AbstractInterpreter::createCustom(Message, CustomExecCommand); - break; - default: - Message = "Sorry, this back-end is not supported by bugpoint right now!\n"; - break; - } - if (!Interpreter) - errs() << Message; - else // Display informational messages on stdout instead of stderr - outs() << Message; - - std::string Path = SafeInterpreterPath; - if (Path.empty()) - Path = getToolName(); - std::vector<std::string> SafeToolArgs = SafeToolArgv; - switch (SafeInterpreterSel) { - case AutoPick: - // In "cbe-bug" mode, default to using LLC as the "safe" backend. - if (!SafeInterpreter && - InterpreterSel == CBE_bug) { - SafeInterpreterSel = RunLLC; - SafeToolArgs.push_back("--relocation-model=pic"); - SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, - GCCBinary, - &SafeToolArgs, - &GCCToolArgv); - } - - // In "llc-safe" mode, default to using LLC as the "safe" backend. - if (!SafeInterpreter && - InterpreterSel == LLC_Safe) { - SafeInterpreterSel = RunLLC; - SafeToolArgs.push_back("--relocation-model=pic"); - SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, - GCCBinary, - &SafeToolArgs, - &GCCToolArgv); - } - - // Pick a backend that's different from the test backend. The JIT and - // LLC backends share a lot of code, so prefer to use the CBE as the - // safe back-end when testing them. - if (!SafeInterpreter && - InterpreterSel != RunCBE) { - SafeInterpreterSel = RunCBE; - SafeInterpreter = AbstractInterpreter::createCBE(Path.c_str(), Message, - GCCBinary, - &SafeToolArgs, - &GCCToolArgv); - } - if (!SafeInterpreter && - InterpreterSel != RunLLC && - InterpreterSel != RunJIT) { - SafeInterpreterSel = RunLLC; - SafeToolArgs.push_back("--relocation-model=pic"); - SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, - GCCBinary, - &SafeToolArgs, - &GCCToolArgv); - } - if (!SafeInterpreter) { - SafeInterpreterSel = AutoPick; - Message = "Sorry, I can't automatically select an interpreter!\n"; - } - break; - case RunLLC: - case RunLLCIA: - SafeToolArgs.push_back("--relocation-model=pic"); - SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, - GCCBinary, &SafeToolArgs, - &GCCToolArgv, - SafeInterpreterSel == RunLLCIA); - break; - case RunCBE: - SafeInterpreter = AbstractInterpreter::createCBE(Path.c_str(), Message, - GCCBinary, &SafeToolArgs, - &GCCToolArgv); - break; - case Custom: - SafeInterpreter = AbstractInterpreter::createCustom(Message, - CustomExecCommand); - break; - default: - Message = "Sorry, this back-end is not supported by bugpoint as the " - "\"safe\" backend right now!\n"; - break; - } - if (!SafeInterpreter) { outs() << Message << "\nExiting.\n"; exit(1); } - - gcc = GCC::create(Message, GCCBinary, &GCCToolArgv); - if (!gcc) { outs() << Message << "\nExiting.\n"; exit(1); } - - // If there was an error creating the selected interpreter, quit with error. - return Interpreter == 0; -} - -/// compileProgram - Try to compile the specified module, returning false and -/// setting Error if an error occurs. This is used for code generation -/// crash testing. -/// -void BugDriver::compileProgram(Module *M, std::string *Error) const { - // Emit the program to a bitcode file... - sys::Path BitcodeFile (OutputPrefix + "-test-program.bc"); - std::string ErrMsg; - if (BitcodeFile.makeUnique(true, &ErrMsg)) { - errs() << ToolName << ": Error making unique filename: " << ErrMsg - << "\n"; - exit(1); - } - if (writeProgramToFile(BitcodeFile.str(), M)) { - errs() << ToolName << ": Error emitting bitcode to file '" - << BitcodeFile.str() << "'!\n"; - exit(1); - } - - // Remove the temporary bitcode file when we are done. - FileRemover BitcodeFileRemover(BitcodeFile, !SaveTemps); - - // Actually compile the program! - Interpreter->compileProgram(BitcodeFile.str(), Error, Timeout, MemoryLimit); -} - - -/// executeProgram - This method runs "Program", capturing the output of the -/// program to a file, returning the filename of the file. A recommended -/// filename may be optionally specified. -/// -std::string BugDriver::executeProgram(const Module *Program, - std::string OutputFile, - std::string BitcodeFile, - const std::string &SharedObj, - AbstractInterpreter *AI, - std::string *Error) const { - if (AI == 0) AI = Interpreter; - assert(AI && "Interpreter should have been created already!"); - bool CreatedBitcode = false; - std::string ErrMsg; - if (BitcodeFile.empty()) { - // Emit the program to a bitcode file... - sys::Path uniqueFilename(OutputPrefix + "-test-program.bc"); - if (uniqueFilename.makeUnique(true, &ErrMsg)) { - errs() << ToolName << ": Error making unique filename: " - << ErrMsg << "!\n"; - exit(1); - } - BitcodeFile = uniqueFilename.str(); - - if (writeProgramToFile(BitcodeFile, Program)) { - errs() << ToolName << ": Error emitting bitcode to file '" - << BitcodeFile << "'!\n"; - exit(1); - } - CreatedBitcode = true; - } - - // Remove the temporary bitcode file when we are done. - sys::Path BitcodePath(BitcodeFile); - FileRemover BitcodeFileRemover(BitcodePath, CreatedBitcode && !SaveTemps); - - if (OutputFile.empty()) OutputFile = OutputPrefix + "-execution-output"; - - // Check to see if this is a valid output filename... - sys::Path uniqueFile(OutputFile); - if (uniqueFile.makeUnique(true, &ErrMsg)) { - errs() << ToolName << ": Error making unique filename: " - << ErrMsg << "\n"; - exit(1); - } - OutputFile = uniqueFile.str(); - - // Figure out which shared objects to run, if any. - std::vector<std::string> SharedObjs(AdditionalSOs); - if (!SharedObj.empty()) - SharedObjs.push_back(SharedObj); - - int RetVal = AI->ExecuteProgram(BitcodeFile, InputArgv, InputFile, OutputFile, - Error, AdditionalLinkerArgs, SharedObjs, - Timeout, MemoryLimit); - if (!Error->empty()) - return OutputFile; - - if (RetVal == -1) { - errs() << "<timeout>"; - static bool FirstTimeout = true; - if (FirstTimeout) { - outs() << "\n" - "*** Program execution timed out! This mechanism is designed to handle\n" - " programs stuck in infinite loops gracefully. The -timeout option\n" - " can be used to change the timeout threshold or disable it completely\n" - " (with -timeout=0). This message is only displayed once.\n"; - FirstTimeout = false; - } - } - - if (AppendProgramExitCode) { - std::ofstream outFile(OutputFile.c_str(), std::ios_base::app); - outFile << "exit " << RetVal << '\n'; - outFile.close(); - } - - // Return the filename we captured the output to. - return OutputFile; -} - -/// executeProgramSafely - Used to create reference output with the "safe" -/// backend, if reference output is not provided. -/// -std::string BugDriver::executeProgramSafely(const Module *Program, - std::string OutputFile, - std::string *Error) const { - return executeProgram(Program, OutputFile, "", "", SafeInterpreter, Error); -} - -std::string BugDriver::compileSharedObject(const std::string &BitcodeFile, - std::string &Error) { - assert(Interpreter && "Interpreter should have been created already!"); - sys::Path OutputFile; - - // Using the known-good backend. - GCC::FileType FT = SafeInterpreter->OutputCode(BitcodeFile, OutputFile, - Error); - if (!Error.empty()) - return ""; - - std::string SharedObjectFile; - bool Failure = gcc->MakeSharedObject(OutputFile.str(), FT, SharedObjectFile, - AdditionalLinkerArgs, Error); - if (!Error.empty()) - return ""; - if (Failure) - exit(1); - - // Remove the intermediate C file - OutputFile.eraseFromDisk(); - - return "./" + SharedObjectFile; -} - -/// createReferenceFile - calls compileProgram and then records the output -/// into ReferenceOutputFile. Returns true if reference file created, false -/// otherwise. Note: initializeExecutionEnvironment should be called BEFORE -/// this function. -/// -bool BugDriver::createReferenceFile(Module *M, const std::string &Filename) { - std::string Error; - compileProgram(Program, &Error); - if (!Error.empty()) - return false; - - ReferenceOutputFile = executeProgramSafely(Program, Filename, &Error); - if (!Error.empty()) { - errs() << Error; - if (Interpreter != SafeInterpreter) { - errs() << "*** There is a bug running the \"safe\" backend. Either" - << " debug it (for example with the -run-cbe bugpoint option," - << " if CBE is being used as the \"safe\" backend), or fix the" - << " error some other way.\n"; - } - return false; - } - outs() << "\nReference output is: " << ReferenceOutputFile << "\n\n"; - return true; -} - -/// diffProgram - This method executes the specified module and diffs the -/// output against the file specified by ReferenceOutputFile. If the output -/// is different, 1 is returned. If there is a problem with the code -/// generator (e.g., llc crashes), this will return -1 and set Error. -/// -bool BugDriver::diffProgram(const Module *Program, - const std::string &BitcodeFile, - const std::string &SharedObject, - bool RemoveBitcode, - std::string *ErrMsg) const { - // Execute the program, generating an output file... - sys::Path Output(executeProgram(Program, "", BitcodeFile, SharedObject, 0, - ErrMsg)); - if (!ErrMsg->empty()) - return false; - - std::string Error; - bool FilesDifferent = false; - if (int Diff = DiffFilesWithTolerance(sys::Path(ReferenceOutputFile), - sys::Path(Output.str()), - AbsTolerance, RelTolerance, &Error)) { - if (Diff == 2) { - errs() << "While diffing output: " << Error << '\n'; - exit(1); - } - FilesDifferent = true; - } - else { - // Remove the generated output if there are no differences. - Output.eraseFromDisk(); - } - - // Remove the bitcode file if we are supposed to. - if (RemoveBitcode) - sys::Path(BitcodeFile).eraseFromDisk(); - return FilesDifferent; -} - -bool BugDriver::isExecutingJIT() { - return InterpreterSel == RunJIT; -} - diff --git a/contrib/llvm/tools/bugpoint/ExtractFunction.cpp b/contrib/llvm/tools/bugpoint/ExtractFunction.cpp deleted file mode 100644 index 524f130..0000000 --- a/contrib/llvm/tools/bugpoint/ExtractFunction.cpp +++ /dev/null @@ -1,369 +0,0 @@ -//===- ExtractFunction.cpp - Extract a function from Program --------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements several methods that are used to extract functions, -// loops, or portions of a module from the rest of the module. -// -//===----------------------------------------------------------------------===// - -#include "BugDriver.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" -#include "llvm/PassManager.h" -#include "llvm/Pass.h" -#include "llvm/Analysis/Verifier.h" -#include "llvm/Assembly/Writer.h" -#include "llvm/Transforms/IPO.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/Utils/Cloning.h" -#include "llvm/Transforms/Utils/FunctionUtils.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/FileUtilities.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/System/Path.h" -#include "llvm/System/Signals.h" -#include <set> -using namespace llvm; - -namespace llvm { - bool DisableSimplifyCFG = false; - extern cl::opt<std::string> OutputPrefix; -} // End llvm namespace - -namespace { - cl::opt<bool> - NoDCE ("disable-dce", - cl::desc("Do not use the -dce pass to reduce testcases")); - cl::opt<bool, true> - NoSCFG("disable-simplifycfg", cl::location(DisableSimplifyCFG), - cl::desc("Do not use the -simplifycfg pass to reduce testcases")); -} - -/// deleteInstructionFromProgram - This method clones the current Program and -/// deletes the specified instruction from the cloned module. It then runs a -/// series of cleanup passes (ADCE and SimplifyCFG) to eliminate any code which -/// depends on the value. The modified module is then returned. -/// -Module *BugDriver::deleteInstructionFromProgram(const Instruction *I, - unsigned Simplification) { - // FIXME, use vmap? - Module *Clone = CloneModule(Program); - - const BasicBlock *PBB = I->getParent(); - const Function *PF = PBB->getParent(); - - Module::iterator RFI = Clone->begin(); // Get iterator to corresponding fn - std::advance(RFI, std::distance(PF->getParent()->begin(), - Module::const_iterator(PF))); - - Function::iterator RBI = RFI->begin(); // Get iterator to corresponding BB - std::advance(RBI, std::distance(PF->begin(), Function::const_iterator(PBB))); - - BasicBlock::iterator RI = RBI->begin(); // Get iterator to corresponding inst - std::advance(RI, std::distance(PBB->begin(), BasicBlock::const_iterator(I))); - Instruction *TheInst = RI; // Got the corresponding instruction! - - // If this instruction produces a value, replace any users with null values - if (!TheInst->getType()->isVoidTy()) - TheInst->replaceAllUsesWith(Constant::getNullValue(TheInst->getType())); - - // Remove the instruction from the program. - TheInst->getParent()->getInstList().erase(TheInst); - - // Spiff up the output a little bit. - std::vector<std::string> Passes; - - /// Can we get rid of the -disable-* options? - if (Simplification > 1 && !NoDCE) - Passes.push_back("dce"); - if (Simplification && !DisableSimplifyCFG) - Passes.push_back("simplifycfg"); // Delete dead control flow - - Passes.push_back("verify"); - Module *New = runPassesOn(Clone, Passes); - delete Clone; - if (!New) { - errs() << "Instruction removal failed. Sorry. :( Please report a bug!\n"; - exit(1); - } - return New; -} - -/// performFinalCleanups - This method clones the current Program and performs -/// a series of cleanups intended to get rid of extra cruft on the module -/// before handing it to the user. -/// -Module *BugDriver::performFinalCleanups(Module *M, bool MayModifySemantics) { - // Make all functions external, so GlobalDCE doesn't delete them... - for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) - I->setLinkage(GlobalValue::ExternalLinkage); - - std::vector<std::string> CleanupPasses; - CleanupPasses.push_back("globaldce"); - - if (MayModifySemantics) - CleanupPasses.push_back("deadarghaX0r"); - else - CleanupPasses.push_back("deadargelim"); - - CleanupPasses.push_back("deadtypeelim"); - - Module *New = runPassesOn(M, CleanupPasses); - if (New == 0) { - errs() << "Final cleanups failed. Sorry. :( Please report a bug!\n"; - return M; - } - delete M; - return New; -} - - -/// ExtractLoop - Given a module, extract up to one loop from it into a new -/// function. This returns null if there are no extractable loops in the -/// program or if the loop extractor crashes. -Module *BugDriver::ExtractLoop(Module *M) { - std::vector<std::string> LoopExtractPasses; - LoopExtractPasses.push_back("loop-extract-single"); - - Module *NewM = runPassesOn(M, LoopExtractPasses); - if (NewM == 0) { - outs() << "*** Loop extraction failed: "; - EmitProgressBitcode(M, "loopextraction", true); - outs() << "*** Sorry. :( Please report a bug!\n"; - return 0; - } - - // Check to see if we created any new functions. If not, no loops were - // extracted and we should return null. Limit the number of loops we extract - // to avoid taking forever. - static unsigned NumExtracted = 32; - if (M->size() == NewM->size() || --NumExtracted == 0) { - delete NewM; - return 0; - } else { - assert(M->size() < NewM->size() && "Loop extract removed functions?"); - Module::iterator MI = NewM->begin(); - for (unsigned i = 0, e = M->size(); i != e; ++i) - ++MI; - } - - return NewM; -} - - -// DeleteFunctionBody - "Remove" the function by deleting all of its basic -// blocks, making it external. -// -void llvm::DeleteFunctionBody(Function *F) { - // delete the body of the function... - F->deleteBody(); - assert(F->isDeclaration() && "This didn't make the function external!"); -} - -/// GetTorInit - Given a list of entries for static ctors/dtors, return them -/// as a constant array. -static Constant *GetTorInit(std::vector<std::pair<Function*, int> > &TorList) { - assert(!TorList.empty() && "Don't create empty tor list!"); - std::vector<Constant*> ArrayElts; - for (unsigned i = 0, e = TorList.size(); i != e; ++i) { - std::vector<Constant*> Elts; - Elts.push_back(ConstantInt::get( - Type::getInt32Ty(TorList[i].first->getContext()), TorList[i].second)); - Elts.push_back(TorList[i].first); - ArrayElts.push_back(ConstantStruct::get(TorList[i].first->getContext(), - Elts, false)); - } - return ConstantArray::get(ArrayType::get(ArrayElts[0]->getType(), - ArrayElts.size()), - ArrayElts); -} - -/// SplitStaticCtorDtor - A module was recently split into two parts, M1/M2, and -/// M1 has all of the global variables. If M2 contains any functions that are -/// static ctors/dtors, we need to add an llvm.global_[cd]tors global to M2, and -/// prune appropriate entries out of M1s list. -static void SplitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2, - ValueMap<const Value*, Value*> &VMap) { - GlobalVariable *GV = M1->getNamedGlobal(GlobalName); - if (!GV || GV->isDeclaration() || GV->hasLocalLinkage() || - !GV->use_empty()) return; - - std::vector<std::pair<Function*, int> > M1Tors, M2Tors; - ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer()); - if (!InitList) return; - - for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { - if (ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(i))){ - if (CS->getNumOperands() != 2) return; // Not array of 2-element structs. - - if (CS->getOperand(1)->isNullValue()) - break; // Found a null terminator, stop here. - - ConstantInt *CI = dyn_cast<ConstantInt>(CS->getOperand(0)); - int Priority = CI ? CI->getSExtValue() : 0; - - Constant *FP = CS->getOperand(1); - if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP)) - if (CE->isCast()) - FP = CE->getOperand(0); - if (Function *F = dyn_cast<Function>(FP)) { - if (!F->isDeclaration()) - M1Tors.push_back(std::make_pair(F, Priority)); - else { - // Map to M2's version of the function. - F = cast<Function>(VMap[F]); - M2Tors.push_back(std::make_pair(F, Priority)); - } - } - } - } - - GV->eraseFromParent(); - if (!M1Tors.empty()) { - Constant *M1Init = GetTorInit(M1Tors); - new GlobalVariable(*M1, M1Init->getType(), false, - GlobalValue::AppendingLinkage, - M1Init, GlobalName); - } - - GV = M2->getNamedGlobal(GlobalName); - assert(GV && "Not a clone of M1?"); - assert(GV->use_empty() && "llvm.ctors shouldn't have uses!"); - - GV->eraseFromParent(); - if (!M2Tors.empty()) { - Constant *M2Init = GetTorInit(M2Tors); - new GlobalVariable(*M2, M2Init->getType(), false, - GlobalValue::AppendingLinkage, - M2Init, GlobalName); - } -} - - -/// SplitFunctionsOutOfModule - Given a module and a list of functions in the -/// module, split the functions OUT of the specified module, and place them in -/// the new module. -Module * -llvm::SplitFunctionsOutOfModule(Module *M, - const std::vector<Function*> &F, - ValueMap<const Value*, Value*> &VMap) { - // Make sure functions & globals are all external so that linkage - // between the two modules will work. - for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) - I->setLinkage(GlobalValue::ExternalLinkage); - for (Module::global_iterator I = M->global_begin(), E = M->global_end(); - I != E; ++I) { - if (I->hasName() && I->getName()[0] == '\01') - I->setName(I->getName().substr(1)); - I->setLinkage(GlobalValue::ExternalLinkage); - } - - ValueMap<const Value*, Value*> NewVMap; - Module *New = CloneModule(M, NewVMap); - - // Make sure global initializers exist only in the safe module (CBE->.so) - for (Module::global_iterator I = New->global_begin(), E = New->global_end(); - I != E; ++I) - I->setInitializer(0); // Delete the initializer to make it external - - // Remove the Test functions from the Safe module - std::set<Function *> TestFunctions; - for (unsigned i = 0, e = F.size(); i != e; ++i) { - Function *TNOF = cast<Function>(VMap[F[i]]); - DEBUG(errs() << "Removing function "); - DEBUG(WriteAsOperand(errs(), TNOF, false)); - DEBUG(errs() << "\n"); - TestFunctions.insert(cast<Function>(NewVMap[TNOF])); - DeleteFunctionBody(TNOF); // Function is now external in this module! - } - - - // Remove the Safe functions from the Test module - for (Module::iterator I = New->begin(), E = New->end(); I != E; ++I) - if (!TestFunctions.count(I)) - DeleteFunctionBody(I); - - - // Make sure that there is a global ctor/dtor array in both halves of the - // module if they both have static ctor/dtor functions. - SplitStaticCtorDtor("llvm.global_ctors", M, New, NewVMap); - SplitStaticCtorDtor("llvm.global_dtors", M, New, NewVMap); - - return New; -} - -//===----------------------------------------------------------------------===// -// Basic Block Extraction Code -//===----------------------------------------------------------------------===// - -/// ExtractMappedBlocksFromModule - Extract all but the specified basic blocks -/// into their own functions. The only detail is that M is actually a module -/// cloned from the one the BBs are in, so some mapping needs to be performed. -/// If this operation fails for some reason (ie the implementation is buggy), -/// this function should return null, otherwise it returns a new Module. -Module *BugDriver::ExtractMappedBlocksFromModule(const - std::vector<BasicBlock*> &BBs, - Module *M) { - sys::Path uniqueFilename(OutputPrefix + "-extractblocks"); - std::string ErrMsg; - if (uniqueFilename.createTemporaryFileOnDisk(true, &ErrMsg)) { - outs() << "*** Basic Block extraction failed!\n"; - errs() << "Error creating temporary file: " << ErrMsg << "\n"; - EmitProgressBitcode(M, "basicblockextractfail", true); - return 0; - } - sys::RemoveFileOnSignal(uniqueFilename); - - std::string ErrorInfo; - tool_output_file BlocksToNotExtractFile(uniqueFilename.c_str(), ErrorInfo); - if (!ErrorInfo.empty()) { - outs() << "*** Basic Block extraction failed!\n"; - errs() << "Error writing list of blocks to not extract: " << ErrorInfo - << "\n"; - EmitProgressBitcode(M, "basicblockextractfail", true); - return 0; - } - for (std::vector<BasicBlock*>::const_iterator I = BBs.begin(), E = BBs.end(); - I != E; ++I) { - BasicBlock *BB = *I; - // If the BB doesn't have a name, give it one so we have something to key - // off of. - if (!BB->hasName()) BB->setName("tmpbb"); - BlocksToNotExtractFile.os() << BB->getParent()->getNameStr() << " " - << BB->getName() << "\n"; - } - BlocksToNotExtractFile.os().close(); - if (BlocksToNotExtractFile.os().has_error()) { - errs() << "Error writing list of blocks to not extract: " << ErrorInfo - << "\n"; - EmitProgressBitcode(M, "basicblockextractfail", true); - BlocksToNotExtractFile.os().clear_error(); - return 0; - } - BlocksToNotExtractFile.keep(); - - std::string uniqueFN = "--extract-blocks-file=" + uniqueFilename.str(); - const char *ExtraArg = uniqueFN.c_str(); - - std::vector<std::string> PI; - PI.push_back("extract-blocks"); - Module *Ret = runPassesOn(M, PI, false, 1, &ExtraArg); - - uniqueFilename.eraseFromDisk(); // Free disk space - - if (Ret == 0) { - outs() << "*** Basic Block extraction failed, please report a bug!\n"; - EmitProgressBitcode(M, "basicblockextractfail", true); - } - return Ret; -} diff --git a/contrib/llvm/tools/bugpoint/FindBugs.cpp b/contrib/llvm/tools/bugpoint/FindBugs.cpp deleted file mode 100644 index a291f9f..0000000 --- a/contrib/llvm/tools/bugpoint/FindBugs.cpp +++ /dev/null @@ -1,113 +0,0 @@ -//===-- FindBugs.cpp - Run Many Different Optimizations -------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines an interface that allows bugpoint to choose different -// combinations of optimizations to run on the selected input. Bugpoint will -// run these optimizations and record the success/failure of each. This way -// we can hopefully spot bugs in the optimizations. -// -//===----------------------------------------------------------------------===// - -#include "BugDriver.h" -#include "ToolRunner.h" -#include "llvm/Pass.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <ctime> -using namespace llvm; - -/// runManyPasses - Take the specified pass list and create different -/// combinations of passes to compile the program with. Compile the program with -/// each set and mark test to see if it compiled correctly. If the passes -/// compiled correctly output nothing and rearrange the passes into a new order. -/// If the passes did not compile correctly, output the command required to -/// recreate the failure. This returns true if a compiler error is found. -/// -bool BugDriver::runManyPasses(const std::vector<std::string> &AllPasses, - std::string &ErrMsg) { - setPassesToRun(AllPasses); - outs() << "Starting bug finding procedure...\n\n"; - - // Creating a reference output if necessary - if (initializeExecutionEnvironment()) return false; - - outs() << "\n"; - if (ReferenceOutputFile.empty()) { - outs() << "Generating reference output from raw program: \n"; - if (!createReferenceFile(Program)) - return false; - } - - srand(time(NULL)); - - unsigned num = 1; - while(1) { - // - // Step 1: Randomize the order of the optimizer passes. - // - std::random_shuffle(PassesToRun.begin(), PassesToRun.end()); - - // - // Step 2: Run optimizer passes on the program and check for success. - // - outs() << "Running selected passes on program to test for crash: "; - for(int i = 0, e = PassesToRun.size(); i != e; i++) { - outs() << "-" << PassesToRun[i] << " "; - } - - std::string Filename; - if(runPasses(Program, PassesToRun, Filename, false)) { - outs() << "\n"; - outs() << "Optimizer passes caused failure!\n\n"; - debugOptimizerCrash(); - return true; - } else { - outs() << "Combination " << num << " optimized successfully!\n"; - } - - // - // Step 3: Compile the optimized code. - // - outs() << "Running the code generator to test for a crash: "; - std::string Error; - compileProgram(Program, &Error); - if (!Error.empty()) { - outs() << "\n*** compileProgram threw an exception: "; - outs() << Error; - return debugCodeGeneratorCrash(ErrMsg); - } - outs() << '\n'; - - // - // Step 4: Run the program and compare its output to the reference - // output (created above). - // - outs() << "*** Checking if passes caused miscompliation:\n"; - bool Diff = diffProgram(Program, Filename, "", false, &Error); - if (Error.empty() && Diff) { - outs() << "\n*** diffProgram returned true!\n"; - debugMiscompilation(&Error); - if (Error.empty()) - return true; - } - if (!Error.empty()) { - errs() << Error; - debugCodeGeneratorCrash(ErrMsg); - return true; - } - outs() << "\n*** diff'd output matches!\n"; - - sys::Path(Filename).eraseFromDisk(); - - outs() << "\n\n"; - num++; - } //end while - - // Unreachable. -} diff --git a/contrib/llvm/tools/bugpoint/ListReducer.h b/contrib/llvm/tools/bugpoint/ListReducer.h deleted file mode 100644 index bd1c5da..0000000 --- a/contrib/llvm/tools/bugpoint/ListReducer.h +++ /dev/null @@ -1,201 +0,0 @@ -//===- ListReducer.h - Trim down list while retaining property --*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This class is to be used as a base class for operations that want to zero in -// on a subset of the input which still causes the bug we are tracking. -// -//===----------------------------------------------------------------------===// - -#ifndef BUGPOINT_LIST_REDUCER_H -#define BUGPOINT_LIST_REDUCER_H - -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/ErrorHandling.h" -#include <vector> -#include <cstdlib> -#include <algorithm> - -namespace llvm { - - extern bool BugpointIsInterrupted; - -template<typename ElTy> -struct ListReducer { - enum TestResult { - NoFailure, // No failure of the predicate was detected - KeepSuffix, // The suffix alone satisfies the predicate - KeepPrefix, // The prefix alone satisfies the predicate - InternalError // Encountered an error trying to run the predicate - }; - - virtual ~ListReducer() {} - - // doTest - This virtual function should be overriden by subclasses to - // implement the test desired. The testcase is only required to test to see - // if the Kept list still satisfies the property, but if it is going to check - // the prefix anyway, it can. - // - virtual TestResult doTest(std::vector<ElTy> &Prefix, - std::vector<ElTy> &Kept, - std::string &Error) = 0; - - // reduceList - This function attempts to reduce the length of the specified - // list while still maintaining the "test" property. This is the core of the - // "work" that bugpoint does. - // - bool reduceList(std::vector<ElTy> &TheList, std::string &Error) { - std::vector<ElTy> empty; - std::srand(0x6e5ea738); // Seed the random number generator - switch (doTest(TheList, empty, Error)) { - case KeepPrefix: - if (TheList.size() == 1) // we are done, it's the base case and it fails - return true; - else - break; // there's definitely an error, but we need to narrow it down - - case KeepSuffix: - // cannot be reached! - llvm_unreachable("bugpoint ListReducer internal error: " - "selected empty set."); - - case NoFailure: - return false; // there is no failure with the full set of passes/funcs! - - case InternalError: - assert(!Error.empty()); - return true; - } - - // Maximal number of allowed splitting iterations, - // before the elements are randomly shuffled. - const unsigned MaxIterationsWithoutProgress = 3; - bool ShufflingEnabled = true; - -Backjump: - unsigned MidTop = TheList.size(); - unsigned MaxIterations = MaxIterationsWithoutProgress; - unsigned NumOfIterationsWithoutProgress = 0; - while (MidTop > 1) { // Binary split reduction loop - // Halt if the user presses ctrl-c. - if (BugpointIsInterrupted) { - errs() << "\n\n*** Reduction Interrupted, cleaning up...\n\n"; - return true; - } - - // If the loop doesn't make satisfying progress, try shuffling. - // The purpose of shuffling is to avoid the heavy tails of the - // distribution (improving the speed of convergence). - if (ShufflingEnabled && - NumOfIterationsWithoutProgress > MaxIterations) { - std::vector<ElTy> ShuffledList(TheList); - std::random_shuffle(ShuffledList.begin(), ShuffledList.end()); - errs() << "\n\n*** Testing shuffled set...\n\n"; - // Check that random shuffle doesn't loose the bug - if (doTest(ShuffledList, empty, Error) == KeepPrefix) { - // If the bug is still here, use the shuffled list. - TheList.swap(ShuffledList); - MidTop = TheList.size(); - // Must increase the shuffling treshold to avoid the small - // probability of inifinite looping without making progress. - MaxIterations += 2; - errs() << "\n\n*** Shuffling does not hide the bug...\n\n"; - } else { - ShufflingEnabled = false; // Disable shuffling further on - errs() << "\n\n*** Shuffling hides the bug...\n\n"; - } - NumOfIterationsWithoutProgress = 0; - } - - unsigned Mid = MidTop / 2; - std::vector<ElTy> Prefix(TheList.begin(), TheList.begin()+Mid); - std::vector<ElTy> Suffix(TheList.begin()+Mid, TheList.end()); - - switch (doTest(Prefix, Suffix, Error)) { - case KeepSuffix: - // The property still holds. We can just drop the prefix elements, and - // shorten the list to the "kept" elements. - TheList.swap(Suffix); - MidTop = TheList.size(); - // Reset progress treshold and progress counter - MaxIterations = MaxIterationsWithoutProgress; - NumOfIterationsWithoutProgress = 0; - break; - case KeepPrefix: - // The predicate still holds, shorten the list to the prefix elements. - TheList.swap(Prefix); - MidTop = TheList.size(); - // Reset progress treshold and progress counter - MaxIterations = MaxIterationsWithoutProgress; - NumOfIterationsWithoutProgress = 0; - break; - case NoFailure: - // Otherwise the property doesn't hold. Some of the elements we removed - // must be necessary to maintain the property. - MidTop = Mid; - NumOfIterationsWithoutProgress++; - break; - case InternalError: - return true; // Error was set by doTest. - } - assert(Error.empty() && "doTest did not return InternalError for error"); - } - - // Probability of backjumping from the trimming loop back to the binary - // split reduction loop. - const int BackjumpProbability = 10; - - // Okay, we trimmed as much off the top and the bottom of the list as we - // could. If there is more than two elements in the list, try deleting - // interior elements and testing that. - // - if (TheList.size() > 2) { - bool Changed = true; - std::vector<ElTy> EmptyList; - while (Changed) { // Trimming loop. - Changed = false; - - // If the binary split reduction loop made an unfortunate sequence of - // splits, the trimming loop might be left off with a huge number of - // remaining elements (large search space). Backjumping out of that - // search space and attempting a different split can significantly - // improve the convergence speed. - if (std::rand() % 100 < BackjumpProbability) - goto Backjump; - - for (unsigned i = 1; i < TheList.size()-1; ++i) { // Check interior elts - if (BugpointIsInterrupted) { - errs() << "\n\n*** Reduction Interrupted, cleaning up...\n\n"; - return true; - } - - std::vector<ElTy> TestList(TheList); - TestList.erase(TestList.begin()+i); - - if (doTest(EmptyList, TestList, Error) == KeepSuffix) { - // We can trim down the list! - TheList.swap(TestList); - --i; // Don't skip an element of the list - Changed = true; - } - if (!Error.empty()) - return true; - } - // This can take a long time if left uncontrolled. For now, don't - // iterate. - break; - } - } - - return true; // there are some failure and we've narrowed them down - } -}; - -} // End llvm namespace - -#endif diff --git a/contrib/llvm/tools/bugpoint/Makefile b/contrib/llvm/tools/bugpoint/Makefile deleted file mode 100644 index 5d287ef..0000000 --- a/contrib/llvm/tools/bugpoint/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- tools/bugpoint/Makefile -----------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../.. - -TOOLNAME = bugpoint - -LINK_COMPONENTS := asmparser instrumentation scalaropts ipo \ - linker bitreader bitwriter - -include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/tools/bugpoint/Miscompilation.cpp b/contrib/llvm/tools/bugpoint/Miscompilation.cpp deleted file mode 100644 index 3f2b696..0000000 --- a/contrib/llvm/tools/bugpoint/Miscompilation.cpp +++ /dev/null @@ -1,1082 +0,0 @@ -//===- Miscompilation.cpp - Debug program miscompilations -----------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements optimizer and code generation miscompilation debugging -// support. -// -//===----------------------------------------------------------------------===// - -#include "BugDriver.h" -#include "ListReducer.h" -#include "ToolRunner.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Instructions.h" -#include "llvm/Linker.h" -#include "llvm/Module.h" -#include "llvm/Pass.h" -#include "llvm/Analysis/Verifier.h" -#include "llvm/Transforms/Utils/Cloning.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/FileUtilities.h" -#include "llvm/Config/config.h" // for HAVE_LINK_R -using namespace llvm; - -namespace llvm { - extern cl::opt<std::string> OutputPrefix; - extern cl::list<std::string> InputArgv; -} - -namespace { - static llvm::cl::opt<bool> - DisableLoopExtraction("disable-loop-extraction", - cl::desc("Don't extract loops when searching for miscompilations"), - cl::init(false)); - static llvm::cl::opt<bool> - DisableBlockExtraction("disable-block-extraction", - cl::desc("Don't extract blocks when searching for miscompilations"), - cl::init(false)); - - class ReduceMiscompilingPasses : public ListReducer<std::string> { - BugDriver &BD; - public: - ReduceMiscompilingPasses(BugDriver &bd) : BD(bd) {} - - virtual TestResult doTest(std::vector<std::string> &Prefix, - std::vector<std::string> &Suffix, - std::string &Error); - }; -} - -/// TestResult - After passes have been split into a test group and a control -/// group, see if they still break the program. -/// -ReduceMiscompilingPasses::TestResult -ReduceMiscompilingPasses::doTest(std::vector<std::string> &Prefix, - std::vector<std::string> &Suffix, - std::string &Error) { - // First, run the program with just the Suffix passes. If it is still broken - // with JUST the kept passes, discard the prefix passes. - outs() << "Checking to see if '" << getPassesString(Suffix) - << "' compiles correctly: "; - - std::string BitcodeResult; - if (BD.runPasses(BD.getProgram(), Suffix, BitcodeResult, false/*delete*/, - true/*quiet*/)) { - errs() << " Error running this sequence of passes" - << " on the input program!\n"; - BD.setPassesToRun(Suffix); - BD.EmitProgressBitcode(BD.getProgram(), "pass-error", false); - exit(BD.debugOptimizerCrash()); - } - - // Check to see if the finished program matches the reference output... - bool Diff = BD.diffProgram(BD.getProgram(), BitcodeResult, "", - true /*delete bitcode*/, &Error); - if (!Error.empty()) - return InternalError; - if (Diff) { - outs() << " nope.\n"; - if (Suffix.empty()) { - errs() << BD.getToolName() << ": I'm confused: the test fails when " - << "no passes are run, nondeterministic program?\n"; - exit(1); - } - return KeepSuffix; // Miscompilation detected! - } - outs() << " yup.\n"; // No miscompilation! - - if (Prefix.empty()) return NoFailure; - - // Next, see if the program is broken if we run the "prefix" passes first, - // then separately run the "kept" passes. - outs() << "Checking to see if '" << getPassesString(Prefix) - << "' compiles correctly: "; - - // If it is not broken with the kept passes, it's possible that the prefix - // passes must be run before the kept passes to break it. If the program - // WORKS after the prefix passes, but then fails if running the prefix AND - // kept passes, we can update our bitcode file to include the result of the - // prefix passes, then discard the prefix passes. - // - if (BD.runPasses(BD.getProgram(), Prefix, BitcodeResult, false/*delete*/, - true/*quiet*/)) { - errs() << " Error running this sequence of passes" - << " on the input program!\n"; - BD.setPassesToRun(Prefix); - BD.EmitProgressBitcode(BD.getProgram(), "pass-error", false); - exit(BD.debugOptimizerCrash()); - } - - // If the prefix maintains the predicate by itself, only keep the prefix! - Diff = BD.diffProgram(BD.getProgram(), BitcodeResult, "", false, &Error); - if (!Error.empty()) - return InternalError; - if (Diff) { - outs() << " nope.\n"; - sys::Path(BitcodeResult).eraseFromDisk(); - return KeepPrefix; - } - outs() << " yup.\n"; // No miscompilation! - - // Ok, so now we know that the prefix passes work, try running the suffix - // passes on the result of the prefix passes. - // - OwningPtr<Module> PrefixOutput(ParseInputFile(BitcodeResult, - BD.getContext())); - if (PrefixOutput == 0) { - errs() << BD.getToolName() << ": Error reading bitcode file '" - << BitcodeResult << "'!\n"; - exit(1); - } - sys::Path(BitcodeResult).eraseFromDisk(); // No longer need the file on disk - - // Don't check if there are no passes in the suffix. - if (Suffix.empty()) - return NoFailure; - - outs() << "Checking to see if '" << getPassesString(Suffix) - << "' passes compile correctly after the '" - << getPassesString(Prefix) << "' passes: "; - - OwningPtr<Module> OriginalInput(BD.swapProgramIn(PrefixOutput.take())); - if (BD.runPasses(BD.getProgram(), Suffix, BitcodeResult, false/*delete*/, - true/*quiet*/)) { - errs() << " Error running this sequence of passes" - << " on the input program!\n"; - BD.setPassesToRun(Suffix); - BD.EmitProgressBitcode(BD.getProgram(), "pass-error", false); - exit(BD.debugOptimizerCrash()); - } - - // Run the result... - Diff = BD.diffProgram(BD.getProgram(), BitcodeResult, "", - true /*delete bitcode*/, &Error); - if (!Error.empty()) - return InternalError; - if (Diff) { - outs() << " nope.\n"; - return KeepSuffix; - } - - // Otherwise, we must not be running the bad pass anymore. - outs() << " yup.\n"; // No miscompilation! - // Restore orig program & free test. - delete BD.swapProgramIn(OriginalInput.take()); - return NoFailure; -} - -namespace { - class ReduceMiscompilingFunctions : public ListReducer<Function*> { - BugDriver &BD; - bool (*TestFn)(BugDriver &, Module *, Module *, std::string &); - public: - ReduceMiscompilingFunctions(BugDriver &bd, - bool (*F)(BugDriver &, Module *, Module *, - std::string &)) - : BD(bd), TestFn(F) {} - - virtual TestResult doTest(std::vector<Function*> &Prefix, - std::vector<Function*> &Suffix, - std::string &Error) { - if (!Suffix.empty()) { - bool Ret = TestFuncs(Suffix, Error); - if (!Error.empty()) - return InternalError; - if (Ret) - return KeepSuffix; - } - if (!Prefix.empty()) { - bool Ret = TestFuncs(Prefix, Error); - if (!Error.empty()) - return InternalError; - if (Ret) - return KeepPrefix; - } - return NoFailure; - } - - bool TestFuncs(const std::vector<Function*> &Prefix, std::string &Error); - }; -} - -/// TestMergedProgram - Given two modules, link them together and run the -/// program, checking to see if the program matches the diff. If there is -/// an error, return NULL. If not, return the merged module. The Broken argument -/// will be set to true if the output is different. If the DeleteInputs -/// argument is set to true then this function deletes both input -/// modules before it returns. -/// -static Module *TestMergedProgram(const BugDriver &BD, Module *M1, Module *M2, - bool DeleteInputs, std::string &Error, - bool &Broken) { - // Link the two portions of the program back to together. - std::string ErrorMsg; - if (!DeleteInputs) { - M1 = CloneModule(M1); - M2 = CloneModule(M2); - } - if (Linker::LinkModules(M1, M2, &ErrorMsg)) { - errs() << BD.getToolName() << ": Error linking modules together:" - << ErrorMsg << '\n'; - exit(1); - } - delete M2; // We are done with this module. - - // Execute the program. - Broken = BD.diffProgram(M1, "", "", false, &Error); - if (!Error.empty()) { - // Delete the linked module - delete M1; - return NULL; - } - return M1; -} - -/// TestFuncs - split functions in a Module into two groups: those that are -/// under consideration for miscompilation vs. those that are not, and test -/// accordingly. Each group of functions becomes a separate Module. -/// -bool ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*> &Funcs, - std::string &Error) { - // Test to see if the function is misoptimized if we ONLY run it on the - // functions listed in Funcs. - outs() << "Checking to see if the program is misoptimized when " - << (Funcs.size()==1 ? "this function is" : "these functions are") - << " run through the pass" - << (BD.getPassesToRun().size() == 1 ? "" : "es") << ":"; - PrintFunctionList(Funcs); - outs() << '\n'; - - // Create a clone for two reasons: - // * If the optimization passes delete any function, the deleted function - // will be in the clone and Funcs will still point to valid memory - // * If the optimization passes use interprocedural information to break - // a function, we want to continue with the original function. Otherwise - // we can conclude that a function triggers the bug when in fact one - // needs a larger set of original functions to do so. - ValueMap<const Value*, Value*> VMap; - Module *Clone = CloneModule(BD.getProgram(), VMap); - Module *Orig = BD.swapProgramIn(Clone); - - std::vector<Function*> FuncsOnClone; - for (unsigned i = 0, e = Funcs.size(); i != e; ++i) { - Function *F = cast<Function>(VMap[Funcs[i]]); - FuncsOnClone.push_back(F); - } - - // Split the module into the two halves of the program we want. - VMap.clear(); - Module *ToNotOptimize = CloneModule(BD.getProgram(), VMap); - Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, FuncsOnClone, - VMap); - - // Run the predicate, note that the predicate will delete both input modules. - bool Broken = TestFn(BD, ToOptimize, ToNotOptimize, Error); - - delete BD.swapProgramIn(Orig); - - return Broken; -} - -/// DisambiguateGlobalSymbols - Give anonymous global values names. -/// -static void DisambiguateGlobalSymbols(Module *M) { - for (Module::global_iterator I = M->global_begin(), E = M->global_end(); - I != E; ++I) - if (!I->hasName()) - I->setName("anon_global"); - for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) - if (!I->hasName()) - I->setName("anon_fn"); -} - -/// ExtractLoops - Given a reduced list of functions that still exposed the bug, -/// check to see if we can extract the loops in the region without obscuring the -/// bug. If so, it reduces the amount of code identified. -/// -static bool ExtractLoops(BugDriver &BD, - bool (*TestFn)(BugDriver &, Module *, Module *, - std::string &), - std::vector<Function*> &MiscompiledFunctions, - std::string &Error) { - bool MadeChange = false; - while (1) { - if (BugpointIsInterrupted) return MadeChange; - - ValueMap<const Value*, Value*> VMap; - Module *ToNotOptimize = CloneModule(BD.getProgram(), VMap); - Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, - MiscompiledFunctions, - VMap); - Module *ToOptimizeLoopExtracted = BD.ExtractLoop(ToOptimize); - if (!ToOptimizeLoopExtracted) { - // If the loop extractor crashed or if there were no extractible loops, - // then this chapter of our odyssey is over with. - delete ToNotOptimize; - delete ToOptimize; - return MadeChange; - } - - errs() << "Extracted a loop from the breaking portion of the program.\n"; - - // Bugpoint is intentionally not very trusting of LLVM transformations. In - // particular, we're not going to assume that the loop extractor works, so - // we're going to test the newly loop extracted program to make sure nothing - // has broken. If something broke, then we'll inform the user and stop - // extraction. - AbstractInterpreter *AI = BD.switchToSafeInterpreter(); - bool Failure; - Module *New = TestMergedProgram(BD, ToOptimizeLoopExtracted, ToNotOptimize, - false, Error, Failure); - if (!New) - return false; - // Delete the original and set the new program. - delete BD.swapProgramIn(New); - if (Failure) { - BD.switchToInterpreter(AI); - - // Merged program doesn't work anymore! - errs() << " *** ERROR: Loop extraction broke the program. :(" - << " Please report a bug!\n"; - errs() << " Continuing on with un-loop-extracted version.\n"; - - BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-tno.bc", - ToNotOptimize); - BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to.bc", - ToOptimize); - BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to-le.bc", - ToOptimizeLoopExtracted); - - errs() << "Please submit the " - << OutputPrefix << "-loop-extract-fail-*.bc files.\n"; - delete ToOptimize; - delete ToNotOptimize; - delete ToOptimizeLoopExtracted; - return MadeChange; - } - delete ToOptimize; - BD.switchToInterpreter(AI); - - outs() << " Testing after loop extraction:\n"; - // Clone modules, the tester function will free them. - Module *TOLEBackup = CloneModule(ToOptimizeLoopExtracted); - Module *TNOBackup = CloneModule(ToNotOptimize); - Failure = TestFn(BD, ToOptimizeLoopExtracted, ToNotOptimize, Error); - if (!Error.empty()) - return false; - if (!Failure) { - outs() << "*** Loop extraction masked the problem. Undoing.\n"; - // If the program is not still broken, then loop extraction did something - // that masked the error. Stop loop extraction now. - delete TOLEBackup; - delete TNOBackup; - return MadeChange; - } - ToOptimizeLoopExtracted = TOLEBackup; - ToNotOptimize = TNOBackup; - - outs() << "*** Loop extraction successful!\n"; - - std::vector<std::pair<std::string, const FunctionType*> > MisCompFunctions; - for (Module::iterator I = ToOptimizeLoopExtracted->begin(), - E = ToOptimizeLoopExtracted->end(); I != E; ++I) - if (!I->isDeclaration()) - MisCompFunctions.push_back(std::make_pair(I->getName(), - I->getFunctionType())); - - // Okay, great! Now we know that we extracted a loop and that loop - // extraction both didn't break the program, and didn't mask the problem. - // Replace the current program with the loop extracted version, and try to - // extract another loop. - std::string ErrorMsg; - if (Linker::LinkModules(ToNotOptimize, ToOptimizeLoopExtracted, &ErrorMsg)){ - errs() << BD.getToolName() << ": Error linking modules together:" - << ErrorMsg << '\n'; - exit(1); - } - delete ToOptimizeLoopExtracted; - - // All of the Function*'s in the MiscompiledFunctions list are in the old - // module. Update this list to include all of the functions in the - // optimized and loop extracted module. - MiscompiledFunctions.clear(); - for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) { - Function *NewF = ToNotOptimize->getFunction(MisCompFunctions[i].first); - - assert(NewF && "Function not found??"); - assert(NewF->getFunctionType() == MisCompFunctions[i].second && - "found wrong function type?"); - MiscompiledFunctions.push_back(NewF); - } - - BD.setNewProgram(ToNotOptimize); - MadeChange = true; - } -} - -namespace { - class ReduceMiscompiledBlocks : public ListReducer<BasicBlock*> { - BugDriver &BD; - bool (*TestFn)(BugDriver &, Module *, Module *, std::string &); - std::vector<Function*> FunctionsBeingTested; - public: - ReduceMiscompiledBlocks(BugDriver &bd, - bool (*F)(BugDriver &, Module *, Module *, - std::string &), - const std::vector<Function*> &Fns) - : BD(bd), TestFn(F), FunctionsBeingTested(Fns) {} - - virtual TestResult doTest(std::vector<BasicBlock*> &Prefix, - std::vector<BasicBlock*> &Suffix, - std::string &Error) { - if (!Suffix.empty()) { - bool Ret = TestFuncs(Suffix, Error); - if (!Error.empty()) - return InternalError; - if (Ret) - return KeepSuffix; - } - if (!Prefix.empty()) { - bool Ret = TestFuncs(Prefix, Error); - if (!Error.empty()) - return InternalError; - if (Ret) - return KeepPrefix; - } - return NoFailure; - } - - bool TestFuncs(const std::vector<BasicBlock*> &BBs, std::string &Error); - }; -} - -/// TestFuncs - Extract all blocks for the miscompiled functions except for the -/// specified blocks. If the problem still exists, return true. -/// -bool ReduceMiscompiledBlocks::TestFuncs(const std::vector<BasicBlock*> &BBs, - std::string &Error) { - // Test to see if the function is misoptimized if we ONLY run it on the - // functions listed in Funcs. - outs() << "Checking to see if the program is misoptimized when all "; - if (!BBs.empty()) { - outs() << "but these " << BBs.size() << " blocks are extracted: "; - for (unsigned i = 0, e = BBs.size() < 10 ? BBs.size() : 10; i != e; ++i) - outs() << BBs[i]->getName() << " "; - if (BBs.size() > 10) outs() << "..."; - } else { - outs() << "blocks are extracted."; - } - outs() << '\n'; - - // Split the module into the two halves of the program we want. - ValueMap<const Value*, Value*> VMap; - Module *Clone = CloneModule(BD.getProgram(), VMap); - Module *Orig = BD.swapProgramIn(Clone); - std::vector<Function*> FuncsOnClone; - std::vector<BasicBlock*> BBsOnClone; - for (unsigned i = 0, e = FunctionsBeingTested.size(); i != e; ++i) { - Function *F = cast<Function>(VMap[FunctionsBeingTested[i]]); - FuncsOnClone.push_back(F); - } - for (unsigned i = 0, e = BBs.size(); i != e; ++i) { - BasicBlock *BB = cast<BasicBlock>(VMap[BBs[i]]); - BBsOnClone.push_back(BB); - } - VMap.clear(); - - Module *ToNotOptimize = CloneModule(BD.getProgram(), VMap); - Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, - FuncsOnClone, - VMap); - - // Try the extraction. If it doesn't work, then the block extractor crashed - // or something, in which case bugpoint can't chase down this possibility. - if (Module *New = BD.ExtractMappedBlocksFromModule(BBsOnClone, ToOptimize)) { - delete ToOptimize; - // Run the predicate, - // note that the predicate will delete both input modules. - bool Ret = TestFn(BD, New, ToNotOptimize, Error); - delete BD.swapProgramIn(Orig); - return Ret; - } - delete BD.swapProgramIn(Orig); - delete ToOptimize; - delete ToNotOptimize; - return false; -} - - -/// ExtractBlocks - Given a reduced list of functions that still expose the bug, -/// extract as many basic blocks from the region as possible without obscuring -/// the bug. -/// -static bool ExtractBlocks(BugDriver &BD, - bool (*TestFn)(BugDriver &, Module *, Module *, - std::string &), - std::vector<Function*> &MiscompiledFunctions, - std::string &Error) { - if (BugpointIsInterrupted) return false; - - std::vector<BasicBlock*> Blocks; - for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i) - for (Function::iterator I = MiscompiledFunctions[i]->begin(), - E = MiscompiledFunctions[i]->end(); I != E; ++I) - Blocks.push_back(I); - - // Use the list reducer to identify blocks that can be extracted without - // obscuring the bug. The Blocks list will end up containing blocks that must - // be retained from the original program. - unsigned OldSize = Blocks.size(); - - // Check to see if all blocks are extractible first. - bool Ret = ReduceMiscompiledBlocks(BD, TestFn, MiscompiledFunctions) - .TestFuncs(std::vector<BasicBlock*>(), Error); - if (!Error.empty()) - return false; - if (Ret) { - Blocks.clear(); - } else { - ReduceMiscompiledBlocks(BD, TestFn, - MiscompiledFunctions).reduceList(Blocks, Error); - if (!Error.empty()) - return false; - if (Blocks.size() == OldSize) - return false; - } - - ValueMap<const Value*, Value*> VMap; - Module *ProgClone = CloneModule(BD.getProgram(), VMap); - Module *ToExtract = SplitFunctionsOutOfModule(ProgClone, - MiscompiledFunctions, - VMap); - Module *Extracted = BD.ExtractMappedBlocksFromModule(Blocks, ToExtract); - if (Extracted == 0) { - // Weird, extraction should have worked. - errs() << "Nondeterministic problem extracting blocks??\n"; - delete ProgClone; - delete ToExtract; - return false; - } - - // Otherwise, block extraction succeeded. Link the two program fragments back - // together. - delete ToExtract; - - std::vector<std::pair<std::string, const FunctionType*> > MisCompFunctions; - for (Module::iterator I = Extracted->begin(), E = Extracted->end(); - I != E; ++I) - if (!I->isDeclaration()) - MisCompFunctions.push_back(std::make_pair(I->getName(), - I->getFunctionType())); - - std::string ErrorMsg; - if (Linker::LinkModules(ProgClone, Extracted, &ErrorMsg)) { - errs() << BD.getToolName() << ": Error linking modules together:" - << ErrorMsg << '\n'; - exit(1); - } - delete Extracted; - - // Set the new program and delete the old one. - BD.setNewProgram(ProgClone); - - // Update the list of miscompiled functions. - MiscompiledFunctions.clear(); - - for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) { - Function *NewF = ProgClone->getFunction(MisCompFunctions[i].first); - assert(NewF && "Function not found??"); - assert(NewF->getFunctionType() == MisCompFunctions[i].second && - "Function has wrong type??"); - MiscompiledFunctions.push_back(NewF); - } - - return true; -} - - -/// DebugAMiscompilation - This is a generic driver to narrow down -/// miscompilations, either in an optimization or a code generator. -/// -static std::vector<Function*> -DebugAMiscompilation(BugDriver &BD, - bool (*TestFn)(BugDriver &, Module *, Module *, - std::string &), - std::string &Error) { - // Okay, now that we have reduced the list of passes which are causing the - // failure, see if we can pin down which functions are being - // miscompiled... first build a list of all of the non-external functions in - // the program. - std::vector<Function*> MiscompiledFunctions; - Module *Prog = BD.getProgram(); - for (Module::iterator I = Prog->begin(), E = Prog->end(); I != E; ++I) - if (!I->isDeclaration()) - MiscompiledFunctions.push_back(I); - - // Do the reduction... - if (!BugpointIsInterrupted) - ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions, - Error); - if (!Error.empty()) - return MiscompiledFunctions; - - outs() << "\n*** The following function" - << (MiscompiledFunctions.size() == 1 ? " is" : "s are") - << " being miscompiled: "; - PrintFunctionList(MiscompiledFunctions); - outs() << '\n'; - - // See if we can rip any loops out of the miscompiled functions and still - // trigger the problem. - - if (!BugpointIsInterrupted && !DisableLoopExtraction) { - bool Ret = ExtractLoops(BD, TestFn, MiscompiledFunctions, Error); - if (!Error.empty()) - return MiscompiledFunctions; - if (Ret) { - // Okay, we extracted some loops and the problem still appears. See if - // we can eliminate some of the created functions from being candidates. - DisambiguateGlobalSymbols(BD.getProgram()); - - // Do the reduction... - if (!BugpointIsInterrupted) - ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions, - Error); - if (!Error.empty()) - return MiscompiledFunctions; - - outs() << "\n*** The following function" - << (MiscompiledFunctions.size() == 1 ? " is" : "s are") - << " being miscompiled: "; - PrintFunctionList(MiscompiledFunctions); - outs() << '\n'; - } - } - - if (!BugpointIsInterrupted && !DisableBlockExtraction) { - bool Ret = ExtractBlocks(BD, TestFn, MiscompiledFunctions, Error); - if (!Error.empty()) - return MiscompiledFunctions; - if (Ret) { - // Okay, we extracted some blocks and the problem still appears. See if - // we can eliminate some of the created functions from being candidates. - DisambiguateGlobalSymbols(BD.getProgram()); - - // Do the reduction... - ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions, - Error); - if (!Error.empty()) - return MiscompiledFunctions; - - outs() << "\n*** The following function" - << (MiscompiledFunctions.size() == 1 ? " is" : "s are") - << " being miscompiled: "; - PrintFunctionList(MiscompiledFunctions); - outs() << '\n'; - } - } - - return MiscompiledFunctions; -} - -/// TestOptimizer - This is the predicate function used to check to see if the -/// "Test" portion of the program is misoptimized. If so, return true. In any -/// case, both module arguments are deleted. -/// -static bool TestOptimizer(BugDriver &BD, Module *Test, Module *Safe, - std::string &Error) { - // Run the optimization passes on ToOptimize, producing a transformed version - // of the functions being tested. - outs() << " Optimizing functions being tested: "; - Module *Optimized = BD.runPassesOn(Test, BD.getPassesToRun(), - /*AutoDebugCrashes*/true); - outs() << "done.\n"; - delete Test; - - outs() << " Checking to see if the merged program executes correctly: "; - bool Broken; - Module *New = TestMergedProgram(BD, Optimized, Safe, true, Error, Broken); - if (New) { - outs() << (Broken ? " nope.\n" : " yup.\n"); - // Delete the original and set the new program. - delete BD.swapProgramIn(New); - } - return Broken; -} - - -/// debugMiscompilation - This method is used when the passes selected are not -/// crashing, but the generated output is semantically different from the -/// input. -/// -void BugDriver::debugMiscompilation(std::string *Error) { - // Make sure something was miscompiled... - if (!BugpointIsInterrupted) - if (!ReduceMiscompilingPasses(*this).reduceList(PassesToRun, *Error)) { - if (Error->empty()) - errs() << "*** Optimized program matches reference output! No problem" - << " detected...\nbugpoint can't help you with your problem!\n"; - return; - } - - outs() << "\n*** Found miscompiling pass" - << (getPassesToRun().size() == 1 ? "" : "es") << ": " - << getPassesString(getPassesToRun()) << '\n'; - EmitProgressBitcode(Program, "passinput"); - - std::vector<Function *> MiscompiledFunctions = - DebugAMiscompilation(*this, TestOptimizer, *Error); - if (!Error->empty()) - return; - - // Output a bunch of bitcode files for the user... - outs() << "Outputting reduced bitcode files which expose the problem:\n"; - ValueMap<const Value*, Value*> VMap; - Module *ToNotOptimize = CloneModule(getProgram(), VMap); - Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, - MiscompiledFunctions, - VMap); - - outs() << " Non-optimized portion: "; - EmitProgressBitcode(ToNotOptimize, "tonotoptimize", true); - delete ToNotOptimize; // Delete hacked module. - - outs() << " Portion that is input to optimizer: "; - EmitProgressBitcode(ToOptimize, "tooptimize"); - delete ToOptimize; // Delete hacked module. - - return; -} - -/// CleanupAndPrepareModules - Get the specified modules ready for code -/// generator testing. -/// -static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, - Module *Safe) { - // Clean up the modules, removing extra cruft that we don't need anymore... - Test = BD.performFinalCleanups(Test); - - // If we are executing the JIT, we have several nasty issues to take care of. - if (!BD.isExecutingJIT()) return; - - // First, if the main function is in the Safe module, we must add a stub to - // the Test module to call into it. Thus, we create a new function `main' - // which just calls the old one. - if (Function *oldMain = Safe->getFunction("main")) - if (!oldMain->isDeclaration()) { - // Rename it - oldMain->setName("llvm_bugpoint_old_main"); - // Create a NEW `main' function with same type in the test module. - Function *newMain = Function::Create(oldMain->getFunctionType(), - GlobalValue::ExternalLinkage, - "main", Test); - // Create an `oldmain' prototype in the test module, which will - // corresponds to the real main function in the same module. - Function *oldMainProto = Function::Create(oldMain->getFunctionType(), - GlobalValue::ExternalLinkage, - oldMain->getName(), Test); - // Set up and remember the argument list for the main function. - std::vector<Value*> args; - for (Function::arg_iterator - I = newMain->arg_begin(), E = newMain->arg_end(), - OI = oldMain->arg_begin(); I != E; ++I, ++OI) { - I->setName(OI->getName()); // Copy argument names from oldMain - args.push_back(I); - } - - // Call the old main function and return its result - BasicBlock *BB = BasicBlock::Create(Safe->getContext(), "entry", newMain); - CallInst *call = CallInst::Create(oldMainProto, args.begin(), args.end(), - "", BB); - - // If the type of old function wasn't void, return value of call - ReturnInst::Create(Safe->getContext(), call, BB); - } - - // The second nasty issue we must deal with in the JIT is that the Safe - // module cannot directly reference any functions defined in the test - // module. Instead, we use a JIT API call to dynamically resolve the - // symbol. - - // Add the resolver to the Safe module. - // Prototype: void *getPointerToNamedFunction(const char* Name) - Constant *resolverFunc = - Safe->getOrInsertFunction("getPointerToNamedFunction", - Type::getInt8PtrTy(Safe->getContext()), - Type::getInt8PtrTy(Safe->getContext()), - (Type *)0); - - // Use the function we just added to get addresses of functions we need. - for (Module::iterator F = Safe->begin(), E = Safe->end(); F != E; ++F) { - if (F->isDeclaration() && !F->use_empty() && &*F != resolverFunc && - !F->isIntrinsic() /* ignore intrinsics */) { - Function *TestFn = Test->getFunction(F->getName()); - - // Don't forward functions which are external in the test module too. - if (TestFn && !TestFn->isDeclaration()) { - // 1. Add a string constant with its name to the global file - Constant *InitArray = ConstantArray::get(F->getContext(), F->getName()); - GlobalVariable *funcName = - new GlobalVariable(*Safe, InitArray->getType(), true /*isConstant*/, - GlobalValue::InternalLinkage, InitArray, - F->getName() + "_name"); - - // 2. Use `GetElementPtr *funcName, 0, 0' to convert the string to an - // sbyte* so it matches the signature of the resolver function. - - // GetElementPtr *funcName, ulong 0, ulong 0 - std::vector<Constant*> GEPargs(2, - Constant::getNullValue(Type::getInt32Ty(F->getContext()))); - Value *GEP = - ConstantExpr::getGetElementPtr(funcName, &GEPargs[0], 2); - std::vector<Value*> ResolverArgs; - ResolverArgs.push_back(GEP); - - // Rewrite uses of F in global initializers, etc. to uses of a wrapper - // function that dynamically resolves the calls to F via our JIT API - if (!F->use_empty()) { - // Create a new global to hold the cached function pointer. - Constant *NullPtr = ConstantPointerNull::get(F->getType()); - GlobalVariable *Cache = - new GlobalVariable(*F->getParent(), F->getType(), - false, GlobalValue::InternalLinkage, - NullPtr,F->getName()+".fpcache"); - - // Construct a new stub function that will re-route calls to F - const FunctionType *FuncTy = F->getFunctionType(); - Function *FuncWrapper = Function::Create(FuncTy, - GlobalValue::InternalLinkage, - F->getName() + "_wrapper", - F->getParent()); - BasicBlock *EntryBB = BasicBlock::Create(F->getContext(), - "entry", FuncWrapper); - BasicBlock *DoCallBB = BasicBlock::Create(F->getContext(), - "usecache", FuncWrapper); - BasicBlock *LookupBB = BasicBlock::Create(F->getContext(), - "lookupfp", FuncWrapper); - - // Check to see if we already looked up the value. - Value *CachedVal = new LoadInst(Cache, "fpcache", EntryBB); - Value *IsNull = new ICmpInst(*EntryBB, ICmpInst::ICMP_EQ, CachedVal, - NullPtr, "isNull"); - BranchInst::Create(LookupBB, DoCallBB, IsNull, EntryBB); - - // Resolve the call to function F via the JIT API: - // - // call resolver(GetElementPtr...) - CallInst *Resolver = - CallInst::Create(resolverFunc, ResolverArgs.begin(), - ResolverArgs.end(), "resolver", LookupBB); - - // Cast the result from the resolver to correctly-typed function. - CastInst *CastedResolver = - new BitCastInst(Resolver, - PointerType::getUnqual(F->getFunctionType()), - "resolverCast", LookupBB); - - // Save the value in our cache. - new StoreInst(CastedResolver, Cache, LookupBB); - BranchInst::Create(DoCallBB, LookupBB); - - PHINode *FuncPtr = PHINode::Create(NullPtr->getType(), - "fp", DoCallBB); - FuncPtr->addIncoming(CastedResolver, LookupBB); - FuncPtr->addIncoming(CachedVal, EntryBB); - - // Save the argument list. - std::vector<Value*> Args; - for (Function::arg_iterator i = FuncWrapper->arg_begin(), - e = FuncWrapper->arg_end(); i != e; ++i) - Args.push_back(i); - - // Pass on the arguments to the real function, return its result - if (F->getReturnType()->isVoidTy()) { - CallInst::Create(FuncPtr, Args.begin(), Args.end(), "", DoCallBB); - ReturnInst::Create(F->getContext(), DoCallBB); - } else { - CallInst *Call = CallInst::Create(FuncPtr, Args.begin(), Args.end(), - "retval", DoCallBB); - ReturnInst::Create(F->getContext(),Call, DoCallBB); - } - - // Use the wrapper function instead of the old function - F->replaceAllUsesWith(FuncWrapper); - } - } - } - } - - if (verifyModule(*Test) || verifyModule(*Safe)) { - errs() << "Bugpoint has a bug, which corrupted a module!!\n"; - abort(); - } -} - - - -/// TestCodeGenerator - This is the predicate function used to check to see if -/// the "Test" portion of the program is miscompiled by the code generator under -/// test. If so, return true. In any case, both module arguments are deleted. -/// -static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe, - std::string &Error) { - CleanupAndPrepareModules(BD, Test, Safe); - - sys::Path TestModuleBC("bugpoint.test.bc"); - std::string ErrMsg; - if (TestModuleBC.makeUnique(true, &ErrMsg)) { - errs() << BD.getToolName() << "Error making unique filename: " - << ErrMsg << "\n"; - exit(1); - } - if (BD.writeProgramToFile(TestModuleBC.str(), Test)) { - errs() << "Error writing bitcode to `" << TestModuleBC.str() - << "'\nExiting."; - exit(1); - } - delete Test; - - FileRemover TestModuleBCRemover(TestModuleBC, !SaveTemps); - - // Make the shared library - sys::Path SafeModuleBC("bugpoint.safe.bc"); - if (SafeModuleBC.makeUnique(true, &ErrMsg)) { - errs() << BD.getToolName() << "Error making unique filename: " - << ErrMsg << "\n"; - exit(1); - } - - if (BD.writeProgramToFile(SafeModuleBC.str(), Safe)) { - errs() << "Error writing bitcode to `" << SafeModuleBC.str() - << "'\nExiting."; - exit(1); - } - - FileRemover SafeModuleBCRemover(SafeModuleBC, !SaveTemps); - - std::string SharedObject = BD.compileSharedObject(SafeModuleBC.str(), Error); - if (!Error.empty()) - return false; - delete Safe; - - FileRemover SharedObjectRemover(sys::Path(SharedObject), !SaveTemps); - - // Run the code generator on the `Test' code, loading the shared library. - // The function returns whether or not the new output differs from reference. - bool Result = BD.diffProgram(BD.getProgram(), TestModuleBC.str(), - SharedObject, false, &Error); - if (!Error.empty()) - return false; - - if (Result) - errs() << ": still failing!\n"; - else - errs() << ": didn't fail.\n"; - - return Result; -} - - -/// debugCodeGenerator - debug errors in LLC, LLI, or CBE. -/// -bool BugDriver::debugCodeGenerator(std::string *Error) { - if ((void*)SafeInterpreter == (void*)Interpreter) { - std::string Result = executeProgramSafely(Program, "bugpoint.safe.out", - Error); - if (Error->empty()) { - outs() << "\n*** The \"safe\" i.e. 'known good' backend cannot match " - << "the reference diff. This may be due to a\n front-end " - << "bug or a bug in the original program, but this can also " - << "happen if bugpoint isn't running the program with the " - << "right flags or input.\n I left the result of executing " - << "the program with the \"safe\" backend in this file for " - << "you: '" - << Result << "'.\n"; - } - return true; - } - - DisambiguateGlobalSymbols(Program); - - std::vector<Function*> Funcs = DebugAMiscompilation(*this, TestCodeGenerator, - *Error); - if (!Error->empty()) - return true; - - // Split the module into the two halves of the program we want. - ValueMap<const Value*, Value*> VMap; - Module *ToNotCodeGen = CloneModule(getProgram(), VMap); - Module *ToCodeGen = SplitFunctionsOutOfModule(ToNotCodeGen, Funcs, VMap); - - // Condition the modules - CleanupAndPrepareModules(*this, ToCodeGen, ToNotCodeGen); - - sys::Path TestModuleBC("bugpoint.test.bc"); - std::string ErrMsg; - if (TestModuleBC.makeUnique(true, &ErrMsg)) { - errs() << getToolName() << "Error making unique filename: " - << ErrMsg << "\n"; - exit(1); - } - - if (writeProgramToFile(TestModuleBC.str(), ToCodeGen)) { - errs() << "Error writing bitcode to `" << TestModuleBC.str() - << "'\nExiting."; - exit(1); - } - delete ToCodeGen; - - // Make the shared library - sys::Path SafeModuleBC("bugpoint.safe.bc"); - if (SafeModuleBC.makeUnique(true, &ErrMsg)) { - errs() << getToolName() << "Error making unique filename: " - << ErrMsg << "\n"; - exit(1); - } - - if (writeProgramToFile(SafeModuleBC.str(), ToNotCodeGen)) { - errs() << "Error writing bitcode to `" << SafeModuleBC.str() - << "'\nExiting."; - exit(1); - } - std::string SharedObject = compileSharedObject(SafeModuleBC.str(), *Error); - if (!Error->empty()) - return true; - delete ToNotCodeGen; - - outs() << "You can reproduce the problem with the command line: \n"; - if (isExecutingJIT()) { - outs() << " lli -load " << SharedObject << " " << TestModuleBC.str(); - } else { - outs() << " llc " << TestModuleBC.str() << " -o " << TestModuleBC.str() - << ".s\n"; - outs() << " gcc " << SharedObject << " " << TestModuleBC.str() - << ".s -o " << TestModuleBC.str() << ".exe"; -#if defined (HAVE_LINK_R) - outs() << " -Wl,-R."; -#endif - outs() << "\n"; - outs() << " " << TestModuleBC.str() << ".exe"; - } - for (unsigned i = 0, e = InputArgv.size(); i != e; ++i) - outs() << " " << InputArgv[i]; - outs() << '\n'; - outs() << "The shared object was created with:\n llc -march=c " - << SafeModuleBC.str() << " -o temporary.c\n" - << " gcc -xc temporary.c -O2 -o " << SharedObject; - if (TargetTriple.getArch() == Triple::sparc) - outs() << " -G"; // Compile a shared library, `-G' for Sparc - else - outs() << " -fPIC -shared"; // `-shared' for Linux/X86, maybe others - - outs() << " -fno-strict-aliasing\n"; - - return false; -} diff --git a/contrib/llvm/tools/bugpoint/OptimizerDriver.cpp b/contrib/llvm/tools/bugpoint/OptimizerDriver.cpp deleted file mode 100644 index 3600ca6..0000000 --- a/contrib/llvm/tools/bugpoint/OptimizerDriver.cpp +++ /dev/null @@ -1,260 +0,0 @@ -//===- OptimizerDriver.cpp - Allow BugPoint to run passes safely ----------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines an interface that allows bugpoint to run various passes -// without the threat of a buggy pass corrupting bugpoint (of course, bugpoint -// may have its own bugs, but that's another story...). It achieves this by -// forking a copy of itself and having the child process do the optimizations. -// If this client dies, we can always fork a new one. :) -// -//===----------------------------------------------------------------------===// - -// Note: as a short term hack, the old Unix-specific code and platform- -// independent code co-exist via conditional compilation until it is verified -// that the new code works correctly on Unix. - -#include "BugDriver.h" -#include "llvm/Module.h" -#include "llvm/PassManager.h" -#include "llvm/Analysis/Verifier.h" -#include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Support/FileUtilities.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/SystemUtils.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/System/Path.h" -#include "llvm/System/Program.h" - -#define DONT_GET_PLUGIN_LOADER_OPTION -#include "llvm/Support/PluginLoader.h" - -#include <fstream> -using namespace llvm; - -namespace llvm { - extern cl::opt<std::string> OutputPrefix; -} - -namespace { - // ChildOutput - This option captures the name of the child output file that - // is set up by the parent bugpoint process - cl::opt<std::string> ChildOutput("child-output", cl::ReallyHidden); -} - -/// writeProgramToFile - This writes the current "Program" to the named bitcode -/// file. If an error occurs, true is returned. -/// -bool BugDriver::writeProgramToFile(const std::string &Filename, - const Module *M) const { - std::string ErrInfo; - tool_output_file Out(Filename.c_str(), ErrInfo, - raw_fd_ostream::F_Binary); - if (ErrInfo.empty()) { - WriteBitcodeToFile(M, Out.os()); - Out.os().close(); - if (!Out.os().has_error()) { - Out.keep(); - return false; - } - } - Out.os().clear_error(); - return true; -} - - -/// EmitProgressBitcode - This function is used to output the current Program -/// to a file named "bugpoint-ID.bc". -/// -void BugDriver::EmitProgressBitcode(const Module *M, - const std::string &ID, - bool NoFlyer) const { - // Output the input to the current pass to a bitcode file, emit a message - // telling the user how to reproduce it: opt -foo blah.bc - // - std::string Filename = OutputPrefix + "-" + ID + ".bc"; - if (writeProgramToFile(Filename, M)) { - errs() << "Error opening file '" << Filename << "' for writing!\n"; - return; - } - - outs() << "Emitted bitcode to '" << Filename << "'\n"; - if (NoFlyer || PassesToRun.empty()) return; - outs() << "\n*** You can reproduce the problem with: "; - if (UseValgrind) outs() << "valgrind "; - outs() << "opt " << Filename << " "; - outs() << getPassesString(PassesToRun) << "\n"; -} - -cl::opt<bool> SilencePasses("silence-passes", cl::desc("Suppress output of running passes (both stdout and stderr)")); - -static cl::list<std::string> OptArgs("opt-args", cl::Positional, - cl::desc("<opt arguments>..."), - cl::ZeroOrMore, cl::PositionalEatsArgs); - -/// runPasses - Run the specified passes on Program, outputting a bitcode file -/// and writing the filename into OutputFile if successful. If the -/// optimizations fail for some reason (optimizer crashes), return true, -/// otherwise return false. If DeleteOutput is set to true, the bitcode is -/// deleted on success, and the filename string is undefined. This prints to -/// outs() a single line message indicating whether compilation was successful -/// or failed. -/// -bool BugDriver::runPasses(Module *Program, - const std::vector<std::string> &Passes, - std::string &OutputFilename, bool DeleteOutput, - bool Quiet, unsigned NumExtraArgs, - const char * const *ExtraArgs) const { - // setup the output file name - outs().flush(); - sys::Path uniqueFilename(OutputPrefix + "-output.bc"); - std::string ErrMsg; - if (uniqueFilename.makeUnique(true, &ErrMsg)) { - errs() << getToolName() << ": Error making unique filename: " - << ErrMsg << "\n"; - return(1); - } - OutputFilename = uniqueFilename.str(); - - // set up the input file name - sys::Path inputFilename(OutputPrefix + "-input.bc"); - if (inputFilename.makeUnique(true, &ErrMsg)) { - errs() << getToolName() << ": Error making unique filename: " - << ErrMsg << "\n"; - return(1); - } - - std::string ErrInfo; - tool_output_file InFile(inputFilename.c_str(), ErrInfo, - raw_fd_ostream::F_Binary); - - - if (!ErrInfo.empty()) { - errs() << "Error opening bitcode file: " << inputFilename.str() << "\n"; - return 1; - } - WriteBitcodeToFile(Program, InFile.os()); - InFile.os().close(); - if (InFile.os().has_error()) { - errs() << "Error writing bitcode file: " << inputFilename.str() << "\n"; - InFile.os().clear_error(); - return 1; - } - InFile.keep(); - - // setup the child process' arguments - SmallVector<const char*, 8> Args; - sys::Path tool = FindExecutable("opt", getToolName(), (void*)"opt"); - std::string Opt = tool.str(); - if (UseValgrind) { - Args.push_back("valgrind"); - Args.push_back("--error-exitcode=1"); - Args.push_back("-q"); - Args.push_back(tool.c_str()); - } else - Args.push_back(Opt.c_str()); - - Args.push_back("-o"); - Args.push_back(OutputFilename.c_str()); - for (unsigned i = 0, e = OptArgs.size(); i != e; ++i) - Args.push_back(OptArgs[i].c_str()); - std::vector<std::string> pass_args; - for (unsigned i = 0, e = PluginLoader::getNumPlugins(); i != e; ++i) { - pass_args.push_back( std::string("-load")); - pass_args.push_back( PluginLoader::getPlugin(i)); - } - for (std::vector<std::string>::const_iterator I = Passes.begin(), - E = Passes.end(); I != E; ++I ) - pass_args.push_back( std::string("-") + (*I) ); - for (std::vector<std::string>::const_iterator I = pass_args.begin(), - E = pass_args.end(); I != E; ++I ) - Args.push_back(I->c_str()); - Args.push_back(inputFilename.c_str()); - for (unsigned i = 0; i < NumExtraArgs; ++i) - Args.push_back(*ExtraArgs); - Args.push_back(0); - - DEBUG(errs() << "\nAbout to run:\t"; - for (unsigned i = 0, e = Args.size()-1; i != e; ++i) - errs() << " " << Args[i]; - errs() << "\n"; - ); - - sys::Path prog; - if (UseValgrind) - prog = sys::Program::FindProgramByName("valgrind"); - else - prog = tool; - - // Redirect stdout and stderr to nowhere if SilencePasses is given - sys::Path Nowhere; - const sys::Path *Redirects[3] = {0, &Nowhere, &Nowhere}; - - int result = sys::Program::ExecuteAndWait(prog, Args.data(), 0, - (SilencePasses ? Redirects : 0), - Timeout, MemoryLimit, &ErrMsg); - - // If we are supposed to delete the bitcode file or if the passes crashed, - // remove it now. This may fail if the file was never created, but that's ok. - if (DeleteOutput || result != 0) - sys::Path(OutputFilename).eraseFromDisk(); - - // Remove the temporary input file as well - inputFilename.eraseFromDisk(); - - if (!Quiet) { - if (result == 0) - outs() << "Success!\n"; - else if (result > 0) - outs() << "Exited with error code '" << result << "'\n"; - else if (result < 0) { - if (result == -1) - outs() << "Execute failed: " << ErrMsg << "\n"; - else - outs() << "Crashed with signal #" << abs(result) << "\n"; - } - if (result & 0x01000000) - outs() << "Dumped core\n"; - } - - // Was the child successful? - return result != 0; -} - - -/// runPassesOn - Carefully run the specified set of pass on the specified -/// module, returning the transformed module on success, or a null pointer on -/// failure. -Module *BugDriver::runPassesOn(Module *M, - const std::vector<std::string> &Passes, - bool AutoDebugCrashes, unsigned NumExtraArgs, - const char * const *ExtraArgs) { - std::string BitcodeResult; - if (runPasses(M, Passes, BitcodeResult, false/*delete*/, true/*quiet*/, - NumExtraArgs, ExtraArgs)) { - if (AutoDebugCrashes) { - errs() << " Error running this sequence of passes" - << " on the input program!\n"; - delete swapProgramIn(M); - EmitProgressBitcode(M, "pass-error", false); - exit(debugOptimizerCrash()); - } - return 0; - } - - Module *Ret = ParseInputFile(BitcodeResult, Context); - if (Ret == 0) { - errs() << getToolName() << ": Error reading bitcode file '" - << BitcodeResult << "'!\n"; - exit(1); - } - sys::Path(BitcodeResult).eraseFromDisk(); // No longer need the file on disk - return Ret; -} diff --git a/contrib/llvm/tools/bugpoint/ToolRunner.cpp b/contrib/llvm/tools/bugpoint/ToolRunner.cpp deleted file mode 100644 index 36dbe14..0000000 --- a/contrib/llvm/tools/bugpoint/ToolRunner.cpp +++ /dev/null @@ -1,883 +0,0 @@ -//===-- ToolRunner.cpp ----------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the interfaces described in the ToolRunner.h file. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "toolrunner" -#include "ToolRunner.h" -#include "llvm/System/Program.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/FileUtilities.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Config/config.h" // for HAVE_LINK_R -#include <fstream> -#include <sstream> -using namespace llvm; - -namespace llvm { - cl::opt<bool> - SaveTemps("save-temps", cl::init(false), cl::desc("Save temporary files")); -} - -namespace { - cl::opt<std::string> - RemoteClient("remote-client", - cl::desc("Remote execution client (rsh/ssh)")); - - cl::opt<std::string> - RemoteHost("remote-host", - cl::desc("Remote execution (rsh/ssh) host")); - - cl::opt<std::string> - RemotePort("remote-port", - cl::desc("Remote execution (rsh/ssh) port")); - - cl::opt<std::string> - RemoteUser("remote-user", - cl::desc("Remote execution (rsh/ssh) user id")); - - cl::opt<std::string> - RemoteExtra("remote-extra-options", - cl::desc("Remote execution (rsh/ssh) extra options")); -} - -/// RunProgramWithTimeout - This function provides an alternate interface -/// to the sys::Program::ExecuteAndWait interface. -/// @see sys::Program::ExecuteAndWait -static int RunProgramWithTimeout(const sys::Path &ProgramPath, - const char **Args, - const sys::Path &StdInFile, - const sys::Path &StdOutFile, - const sys::Path &StdErrFile, - unsigned NumSeconds = 0, - unsigned MemoryLimit = 0) { - const sys::Path* redirects[3]; - redirects[0] = &StdInFile; - redirects[1] = &StdOutFile; - redirects[2] = &StdErrFile; - -#if 0 // For debug purposes - { - errs() << "RUN:"; - for (unsigned i = 0; Args[i]; ++i) - errs() << " " << Args[i]; - errs() << "\n"; - } -#endif - - return - sys::Program::ExecuteAndWait(ProgramPath, Args, 0, redirects, - NumSeconds, MemoryLimit); -} - -/// RunProgramRemotelyWithTimeout - This function runs the given program -/// remotely using the given remote client and the sys::Program::ExecuteAndWait. -/// Returns the remote program exit code or reports a remote client error if it -/// fails. Remote client is required to return 255 if it failed or program exit -/// code otherwise. -/// @see sys::Program::ExecuteAndWait -static int RunProgramRemotelyWithTimeout(const sys::Path &RemoteClientPath, - const char **Args, - const sys::Path &StdInFile, - const sys::Path &StdOutFile, - const sys::Path &StdErrFile, - unsigned NumSeconds = 0, - unsigned MemoryLimit = 0) { - const sys::Path* redirects[3]; - redirects[0] = &StdInFile; - redirects[1] = &StdOutFile; - redirects[2] = &StdErrFile; - -#if 0 // For debug purposes - { - errs() << "RUN:"; - for (unsigned i = 0; Args[i]; ++i) - errs() << " " << Args[i]; - errs() << "\n"; - } -#endif - - // Run the program remotely with the remote client - int ReturnCode = sys::Program::ExecuteAndWait(RemoteClientPath, Args, - 0, redirects, NumSeconds, MemoryLimit); - - // Has the remote client fail? - if (255 == ReturnCode) { - std::ostringstream OS; - OS << "\nError running remote client:\n "; - for (const char **Arg = Args; *Arg; ++Arg) - OS << " " << *Arg; - OS << "\n"; - - // The error message is in the output file, let's print it out from there. - std::ifstream ErrorFile(StdOutFile.c_str()); - if (ErrorFile) { - std::copy(std::istreambuf_iterator<char>(ErrorFile), - std::istreambuf_iterator<char>(), - std::ostreambuf_iterator<char>(OS)); - ErrorFile.close(); - } - - errs() << OS; - } - - return ReturnCode; -} - -static std::string ProcessFailure(sys::Path ProgPath, const char** Args, - unsigned Timeout = 0, - unsigned MemoryLimit = 0) { - std::ostringstream OS; - OS << "\nError running tool:\n "; - for (const char **Arg = Args; *Arg; ++Arg) - OS << " " << *Arg; - OS << "\n"; - - // Rerun the compiler, capturing any error messages to print them. - sys::Path ErrorFilename("bugpoint.program_error_messages"); - std::string ErrMsg; - if (ErrorFilename.makeUnique(true, &ErrMsg)) { - errs() << "Error making unique filename: " << ErrMsg << "\n"; - exit(1); - } - RunProgramWithTimeout(ProgPath, Args, sys::Path(""), ErrorFilename, - ErrorFilename, Timeout, MemoryLimit); - // FIXME: check return code ? - - // Print out the error messages generated by GCC if possible... - std::ifstream ErrorFile(ErrorFilename.c_str()); - if (ErrorFile) { - std::copy(std::istreambuf_iterator<char>(ErrorFile), - std::istreambuf_iterator<char>(), - std::ostreambuf_iterator<char>(OS)); - ErrorFile.close(); - } - - ErrorFilename.eraseFromDisk(); - return OS.str(); -} - -//===---------------------------------------------------------------------===// -// LLI Implementation of AbstractIntepreter interface -// -namespace { - class LLI : public AbstractInterpreter { - std::string LLIPath; // The path to the LLI executable - std::vector<std::string> ToolArgs; // Args to pass to LLI - public: - LLI(const std::string &Path, const std::vector<std::string> *Args) - : LLIPath(Path) { - ToolArgs.clear (); - if (Args) { ToolArgs = *Args; } - } - - virtual int ExecuteProgram(const std::string &Bitcode, - const std::vector<std::string> &Args, - const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, - const std::vector<std::string> &GCCArgs, - const std::vector<std::string> &SharedLibs = - std::vector<std::string>(), - unsigned Timeout = 0, - unsigned MemoryLimit = 0); - }; -} - -int LLI::ExecuteProgram(const std::string &Bitcode, - const std::vector<std::string> &Args, - const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, - const std::vector<std::string> &GCCArgs, - const std::vector<std::string> &SharedLibs, - unsigned Timeout, - unsigned MemoryLimit) { - std::vector<const char*> LLIArgs; - LLIArgs.push_back(LLIPath.c_str()); - LLIArgs.push_back("-force-interpreter=true"); - - for (std::vector<std::string>::const_iterator i = SharedLibs.begin(), e = SharedLibs.end(); i != e; ++i) { - LLIArgs.push_back("-load"); - LLIArgs.push_back((*i).c_str()); - } - - // Add any extra LLI args. - for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) - LLIArgs.push_back(ToolArgs[i].c_str()); - - LLIArgs.push_back(Bitcode.c_str()); - // Add optional parameters to the running program from Argv - for (unsigned i=0, e = Args.size(); i != e; ++i) - LLIArgs.push_back(Args[i].c_str()); - LLIArgs.push_back(0); - - outs() << "<lli>"; outs().flush(); - DEBUG(errs() << "\nAbout to run:\t"; - for (unsigned i=0, e = LLIArgs.size()-1; i != e; ++i) - errs() << " " << LLIArgs[i]; - errs() << "\n"; - ); - return RunProgramWithTimeout(sys::Path(LLIPath), &LLIArgs[0], - sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), - Timeout, MemoryLimit); -} - -// LLI create method - Try to find the LLI executable -AbstractInterpreter *AbstractInterpreter::createLLI(const char *Argv0, - std::string &Message, - const std::vector<std::string> *ToolArgs) { - std::string LLIPath = - FindExecutable("lli", Argv0, (void *)(intptr_t)&createLLI).str(); - if (!LLIPath.empty()) { - Message = "Found lli: " + LLIPath + "\n"; - return new LLI(LLIPath, ToolArgs); - } - - Message = "Cannot find `lli' in executable directory or PATH!\n"; - return 0; -} - -//===---------------------------------------------------------------------===// -// Custom execution command implementation of AbstractIntepreter interface -// -// Allows using a custom command for executing the bitcode, thus allows, -// for example, to invoke a cross compiler for code generation followed by -// a simulator that executes the generated binary. -namespace { - class CustomExecutor : public AbstractInterpreter { - std::string ExecutionCommand; - std::vector<std::string> ExecutorArgs; - public: - CustomExecutor( - const std::string &ExecutionCmd, std::vector<std::string> ExecArgs) : - ExecutionCommand(ExecutionCmd), ExecutorArgs(ExecArgs) {} - - virtual int ExecuteProgram(const std::string &Bitcode, - const std::vector<std::string> &Args, - const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, - const std::vector<std::string> &GCCArgs, - const std::vector<std::string> &SharedLibs = - std::vector<std::string>(), - unsigned Timeout = 0, - unsigned MemoryLimit = 0); - }; -} - -int CustomExecutor::ExecuteProgram(const std::string &Bitcode, - const std::vector<std::string> &Args, - const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, - const std::vector<std::string> &GCCArgs, - const std::vector<std::string> &SharedLibs, - unsigned Timeout, - unsigned MemoryLimit) { - - std::vector<const char*> ProgramArgs; - ProgramArgs.push_back(ExecutionCommand.c_str()); - - for (std::size_t i = 0; i < ExecutorArgs.size(); ++i) - ProgramArgs.push_back(ExecutorArgs.at(i).c_str()); - ProgramArgs.push_back(Bitcode.c_str()); - ProgramArgs.push_back(0); - - // Add optional parameters to the running program from Argv - for (unsigned i = 0, e = Args.size(); i != e; ++i) - ProgramArgs.push_back(Args[i].c_str()); - - return RunProgramWithTimeout( - sys::Path(ExecutionCommand), - &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), - sys::Path(OutputFile), Timeout, MemoryLimit); -} - -// Custom execution environment create method, takes the execution command -// as arguments -AbstractInterpreter *AbstractInterpreter::createCustom( - std::string &Message, - const std::string &ExecCommandLine) { - - std::string Command = ""; - std::vector<std::string> Args; - std::string delimiters = " "; - - // Tokenize the ExecCommandLine to the command and the args to allow - // defining a full command line as the command instead of just the - // executed program. We cannot just pass the whole string after the command - // as a single argument because then program sees only a single - // command line argument (with spaces in it: "foo bar" instead - // of "foo" and "bar"). - - // code borrowed from: - // http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html - std::string::size_type lastPos = - ExecCommandLine.find_first_not_of(delimiters, 0); - std::string::size_type pos = - ExecCommandLine.find_first_of(delimiters, lastPos); - - while (std::string::npos != pos || std::string::npos != lastPos) { - std::string token = ExecCommandLine.substr(lastPos, pos - lastPos); - if (Command == "") - Command = token; - else - Args.push_back(token); - // Skip delimiters. Note the "not_of" - lastPos = ExecCommandLine.find_first_not_of(delimiters, pos); - // Find next "non-delimiter" - pos = ExecCommandLine.find_first_of(delimiters, lastPos); - } - - std::string CmdPath = sys::Program::FindProgramByName(Command).str(); - if (CmdPath.empty()) { - Message = - std::string("Cannot find '") + Command + - "' in executable directory or PATH!\n"; - return 0; - } - - Message = "Found command in: " + CmdPath + "\n"; - - return new CustomExecutor(CmdPath, Args); -} - -//===----------------------------------------------------------------------===// -// LLC Implementation of AbstractIntepreter interface -// -GCC::FileType LLC::OutputCode(const std::string &Bitcode, - sys::Path &OutputAsmFile, std::string &Error, - unsigned Timeout, unsigned MemoryLimit) { - const char *Suffix = (UseIntegratedAssembler ? ".llc.o" : ".llc.s"); - sys::Path uniqueFile(Bitcode + Suffix); - std::string ErrMsg; - if (uniqueFile.makeUnique(true, &ErrMsg)) { - errs() << "Error making unique filename: " << ErrMsg << "\n"; - exit(1); - } - OutputAsmFile = uniqueFile; - std::vector<const char *> LLCArgs; - LLCArgs.push_back(LLCPath.c_str()); - - // Add any extra LLC args. - for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) - LLCArgs.push_back(ToolArgs[i].c_str()); - - LLCArgs.push_back("-o"); - LLCArgs.push_back(OutputAsmFile.c_str()); // Output to the Asm file - LLCArgs.push_back(Bitcode.c_str()); // This is the input bitcode - - if (UseIntegratedAssembler) - LLCArgs.push_back("-filetype=obj"); - - LLCArgs.push_back (0); - - outs() << (UseIntegratedAssembler ? "<llc-ia>" : "<llc>"); - outs().flush(); - DEBUG(errs() << "\nAbout to run:\t"; - for (unsigned i = 0, e = LLCArgs.size()-1; i != e; ++i) - errs() << " " << LLCArgs[i]; - errs() << "\n"; - ); - if (RunProgramWithTimeout(sys::Path(LLCPath), &LLCArgs[0], - sys::Path(), sys::Path(), sys::Path(), - Timeout, MemoryLimit)) - Error = ProcessFailure(sys::Path(LLCPath), &LLCArgs[0], - Timeout, MemoryLimit); - return UseIntegratedAssembler ? GCC::ObjectFile : GCC::AsmFile; -} - -void LLC::compileProgram(const std::string &Bitcode, std::string *Error, - unsigned Timeout, unsigned MemoryLimit) { - sys::Path OutputAsmFile; - OutputCode(Bitcode, OutputAsmFile, *Error, Timeout, MemoryLimit); - OutputAsmFile.eraseFromDisk(); -} - -int LLC::ExecuteProgram(const std::string &Bitcode, - const std::vector<std::string> &Args, - const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, - const std::vector<std::string> &ArgsForGCC, - const std::vector<std::string> &SharedLibs, - unsigned Timeout, - unsigned MemoryLimit) { - - sys::Path OutputAsmFile; - GCC::FileType FileKind = OutputCode(Bitcode, OutputAsmFile, *Error, Timeout, - MemoryLimit); - FileRemover OutFileRemover(OutputAsmFile, !SaveTemps); - - std::vector<std::string> GCCArgs(ArgsForGCC); - GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); - - // Assuming LLC worked, compile the result with GCC and run it. - return gcc->ExecuteProgram(OutputAsmFile.str(), Args, FileKind, - InputFile, OutputFile, Error, GCCArgs, - Timeout, MemoryLimit); -} - -/// createLLC - Try to find the LLC executable -/// -LLC *AbstractInterpreter::createLLC(const char *Argv0, - std::string &Message, - const std::string &GCCBinary, - const std::vector<std::string> *Args, - const std::vector<std::string> *GCCArgs, - bool UseIntegratedAssembler) { - std::string LLCPath = - FindExecutable("llc", Argv0, (void *)(intptr_t)&createLLC).str(); - if (LLCPath.empty()) { - Message = "Cannot find `llc' in executable directory or PATH!\n"; - return 0; - } - - Message = "Found llc: " + LLCPath + "\n"; - GCC *gcc = GCC::create(Message, GCCBinary, GCCArgs); - if (!gcc) { - errs() << Message << "\n"; - exit(1); - } - return new LLC(LLCPath, gcc, Args, UseIntegratedAssembler); -} - -//===---------------------------------------------------------------------===// -// JIT Implementation of AbstractIntepreter interface -// -namespace { - class JIT : public AbstractInterpreter { - std::string LLIPath; // The path to the LLI executable - std::vector<std::string> ToolArgs; // Args to pass to LLI - public: - JIT(const std::string &Path, const std::vector<std::string> *Args) - : LLIPath(Path) { - ToolArgs.clear (); - if (Args) { ToolArgs = *Args; } - } - - virtual int ExecuteProgram(const std::string &Bitcode, - const std::vector<std::string> &Args, - const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, - const std::vector<std::string> &GCCArgs = - std::vector<std::string>(), - const std::vector<std::string> &SharedLibs = - std::vector<std::string>(), - unsigned Timeout = 0, - unsigned MemoryLimit = 0); - }; -} - -int JIT::ExecuteProgram(const std::string &Bitcode, - const std::vector<std::string> &Args, - const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, - const std::vector<std::string> &GCCArgs, - const std::vector<std::string> &SharedLibs, - unsigned Timeout, - unsigned MemoryLimit) { - // Construct a vector of parameters, incorporating those from the command-line - std::vector<const char*> JITArgs; - JITArgs.push_back(LLIPath.c_str()); - JITArgs.push_back("-force-interpreter=false"); - - // Add any extra LLI args. - for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) - JITArgs.push_back(ToolArgs[i].c_str()); - - for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i) { - JITArgs.push_back("-load"); - JITArgs.push_back(SharedLibs[i].c_str()); - } - JITArgs.push_back(Bitcode.c_str()); - // Add optional parameters to the running program from Argv - for (unsigned i=0, e = Args.size(); i != e; ++i) - JITArgs.push_back(Args[i].c_str()); - JITArgs.push_back(0); - - outs() << "<jit>"; outs().flush(); - DEBUG(errs() << "\nAbout to run:\t"; - for (unsigned i=0, e = JITArgs.size()-1; i != e; ++i) - errs() << " " << JITArgs[i]; - errs() << "\n"; - ); - DEBUG(errs() << "\nSending output to " << OutputFile << "\n"); - return RunProgramWithTimeout(sys::Path(LLIPath), &JITArgs[0], - sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), - Timeout, MemoryLimit); -} - -/// createJIT - Try to find the LLI executable -/// -AbstractInterpreter *AbstractInterpreter::createJIT(const char *Argv0, - std::string &Message, const std::vector<std::string> *Args) { - std::string LLIPath = - FindExecutable("lli", Argv0, (void *)(intptr_t)&createJIT).str(); - if (!LLIPath.empty()) { - Message = "Found lli: " + LLIPath + "\n"; - return new JIT(LLIPath, Args); - } - - Message = "Cannot find `lli' in executable directory or PATH!\n"; - return 0; -} - -GCC::FileType CBE::OutputCode(const std::string &Bitcode, - sys::Path &OutputCFile, std::string &Error, - unsigned Timeout, unsigned MemoryLimit) { - sys::Path uniqueFile(Bitcode+".cbe.c"); - std::string ErrMsg; - if (uniqueFile.makeUnique(true, &ErrMsg)) { - errs() << "Error making unique filename: " << ErrMsg << "\n"; - exit(1); - } - OutputCFile = uniqueFile; - std::vector<const char *> LLCArgs; - LLCArgs.push_back(LLCPath.c_str()); - - // Add any extra LLC args. - for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) - LLCArgs.push_back(ToolArgs[i].c_str()); - - LLCArgs.push_back("-o"); - LLCArgs.push_back(OutputCFile.c_str()); // Output to the C file - LLCArgs.push_back("-march=c"); // Output C language - LLCArgs.push_back(Bitcode.c_str()); // This is the input bitcode - LLCArgs.push_back(0); - - outs() << "<cbe>"; outs().flush(); - DEBUG(errs() << "\nAbout to run:\t"; - for (unsigned i = 0, e = LLCArgs.size()-1; i != e; ++i) - errs() << " " << LLCArgs[i]; - errs() << "\n"; - ); - if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], sys::Path(), sys::Path(), - sys::Path(), Timeout, MemoryLimit)) - Error = ProcessFailure(LLCPath, &LLCArgs[0], Timeout, MemoryLimit); - return GCC::CFile; -} - -void CBE::compileProgram(const std::string &Bitcode, std::string *Error, - unsigned Timeout, unsigned MemoryLimit) { - sys::Path OutputCFile; - OutputCode(Bitcode, OutputCFile, *Error, Timeout, MemoryLimit); - OutputCFile.eraseFromDisk(); -} - -int CBE::ExecuteProgram(const std::string &Bitcode, - const std::vector<std::string> &Args, - const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, - const std::vector<std::string> &ArgsForGCC, - const std::vector<std::string> &SharedLibs, - unsigned Timeout, - unsigned MemoryLimit) { - sys::Path OutputCFile; - OutputCode(Bitcode, OutputCFile, *Error, Timeout, MemoryLimit); - - FileRemover CFileRemove(OutputCFile, !SaveTemps); - - std::vector<std::string> GCCArgs(ArgsForGCC); - GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); - - return gcc->ExecuteProgram(OutputCFile.str(), Args, GCC::CFile, - InputFile, OutputFile, Error, GCCArgs, - Timeout, MemoryLimit); -} - -/// createCBE - Try to find the 'llc' executable -/// -CBE *AbstractInterpreter::createCBE(const char *Argv0, - std::string &Message, - const std::string &GCCBinary, - const std::vector<std::string> *Args, - const std::vector<std::string> *GCCArgs) { - sys::Path LLCPath = - FindExecutable("llc", Argv0, (void *)(intptr_t)&createCBE); - if (LLCPath.isEmpty()) { - Message = - "Cannot find `llc' in executable directory or PATH!\n"; - return 0; - } - - Message = "Found llc: " + LLCPath.str() + "\n"; - GCC *gcc = GCC::create(Message, GCCBinary, GCCArgs); - if (!gcc) { - errs() << Message << "\n"; - exit(1); - } - return new CBE(LLCPath, gcc, Args); -} - -//===---------------------------------------------------------------------===// -// GCC abstraction -// - -static bool IsARMArchitecture(std::vector<const char*> Args) { - for (std::vector<const char*>::const_iterator - I = Args.begin(), E = Args.end(); I != E; ++I) { - if (StringRef(*I).equals_lower("-arch")) { - ++I; - if (I != E && StringRef(*I).substr(0, strlen("arm")).equals_lower("arm")) - return true; - } - } - - return false; -} - -int GCC::ExecuteProgram(const std::string &ProgramFile, - const std::vector<std::string> &Args, - FileType fileType, - const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, - const std::vector<std::string> &ArgsForGCC, - unsigned Timeout, - unsigned MemoryLimit) { - std::vector<const char*> GCCArgs; - - GCCArgs.push_back(GCCPath.c_str()); - - if (TargetTriple.getArch() == Triple::x86) - GCCArgs.push_back("-m32"); - - for (std::vector<std::string>::const_iterator - I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I) - GCCArgs.push_back(I->c_str()); - - // Specify -x explicitly in case the extension is wonky - if (fileType != ObjectFile) { - GCCArgs.push_back("-x"); - if (fileType == CFile) { - GCCArgs.push_back("c"); - GCCArgs.push_back("-fno-strict-aliasing"); - } else { - GCCArgs.push_back("assembler"); - - // For ARM architectures we don't want this flag. bugpoint isn't - // explicitly told what architecture it is working on, so we get - // it from gcc flags - if ((TargetTriple.getOS() == Triple::Darwin) && - !IsARMArchitecture(GCCArgs)) - GCCArgs.push_back("-force_cpusubtype_ALL"); - } - } - - GCCArgs.push_back(ProgramFile.c_str()); // Specify the input filename. - - GCCArgs.push_back("-x"); - GCCArgs.push_back("none"); - GCCArgs.push_back("-o"); - sys::Path OutputBinary (ProgramFile+".gcc.exe"); - std::string ErrMsg; - if (OutputBinary.makeUnique(true, &ErrMsg)) { - errs() << "Error making unique filename: " << ErrMsg << "\n"; - exit(1); - } - GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file... - - // Add any arguments intended for GCC. We locate them here because this is - // most likely -L and -l options that need to come before other libraries but - // after the source. Other options won't be sensitive to placement on the - // command line, so this should be safe. - for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i) - GCCArgs.push_back(ArgsForGCC[i].c_str()); - - GCCArgs.push_back("-lm"); // Hard-code the math library... - GCCArgs.push_back("-O2"); // Optimize the program a bit... -#if defined (HAVE_LINK_R) - GCCArgs.push_back("-Wl,-R."); // Search this dir for .so files -#endif - if (TargetTriple.getArch() == Triple::sparc) - GCCArgs.push_back("-mcpu=v9"); - GCCArgs.push_back(0); // NULL terminator - - outs() << "<gcc>"; outs().flush(); - DEBUG(errs() << "\nAbout to run:\t"; - for (unsigned i = 0, e = GCCArgs.size()-1; i != e; ++i) - errs() << " " << GCCArgs[i]; - errs() << "\n"; - ); - if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(), - sys::Path())) { - *Error = ProcessFailure(GCCPath, &GCCArgs[0]); - return -1; - } - - std::vector<const char*> ProgramArgs; - - // Declared here so that the destructor only runs after - // ProgramArgs is used. - std::string Exec; - - if (RemoteClientPath.isEmpty()) - ProgramArgs.push_back(OutputBinary.c_str()); - else { - ProgramArgs.push_back(RemoteClientPath.c_str()); - ProgramArgs.push_back(RemoteHost.c_str()); - if (!RemoteUser.empty()) { - ProgramArgs.push_back("-l"); - ProgramArgs.push_back(RemoteUser.c_str()); - } - if (!RemotePort.empty()) { - ProgramArgs.push_back("-p"); - ProgramArgs.push_back(RemotePort.c_str()); - } - if (!RemoteExtra.empty()) { - ProgramArgs.push_back(RemoteExtra.c_str()); - } - - // Full path to the binary. We need to cd to the exec directory because - // there is a dylib there that the exec expects to find in the CWD - char* env_pwd = getenv("PWD"); - Exec = "cd "; - Exec += env_pwd; - Exec += "; ./"; - Exec += OutputBinary.c_str(); - ProgramArgs.push_back(Exec.c_str()); - } - - // Add optional parameters to the running program from Argv - for (unsigned i = 0, e = Args.size(); i != e; ++i) - ProgramArgs.push_back(Args[i].c_str()); - ProgramArgs.push_back(0); // NULL terminator - - // Now that we have a binary, run it! - outs() << "<program>"; outs().flush(); - DEBUG(errs() << "\nAbout to run:\t"; - for (unsigned i = 0, e = ProgramArgs.size()-1; i != e; ++i) - errs() << " " << ProgramArgs[i]; - errs() << "\n"; - ); - - FileRemover OutputBinaryRemover(OutputBinary, !SaveTemps); - - if (RemoteClientPath.isEmpty()) { - DEBUG(errs() << "<run locally>"); - return RunProgramWithTimeout(OutputBinary, &ProgramArgs[0], - sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), - Timeout, MemoryLimit); - } else { - outs() << "<run remotely>"; outs().flush(); - return RunProgramRemotelyWithTimeout(sys::Path(RemoteClientPath), - &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), - sys::Path(OutputFile), Timeout, MemoryLimit); - } -} - -int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, - std::string &OutputFile, - const std::vector<std::string> &ArgsForGCC, - std::string &Error) { - sys::Path uniqueFilename(InputFile+LTDL_SHLIB_EXT); - std::string ErrMsg; - if (uniqueFilename.makeUnique(true, &ErrMsg)) { - errs() << "Error making unique filename: " << ErrMsg << "\n"; - exit(1); - } - OutputFile = uniqueFilename.str(); - - std::vector<const char*> GCCArgs; - - GCCArgs.push_back(GCCPath.c_str()); - - if (TargetTriple.getArch() == Triple::x86) - GCCArgs.push_back("-m32"); - - for (std::vector<std::string>::const_iterator - I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I) - GCCArgs.push_back(I->c_str()); - - // Compile the C/asm file into a shared object - if (fileType != ObjectFile) { - GCCArgs.push_back("-x"); - GCCArgs.push_back(fileType == AsmFile ? "assembler" : "c"); - } - GCCArgs.push_back("-fno-strict-aliasing"); - GCCArgs.push_back(InputFile.c_str()); // Specify the input filename. - GCCArgs.push_back("-x"); - GCCArgs.push_back("none"); - if (TargetTriple.getArch() == Triple::sparc) - GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc - else if (TargetTriple.getOS() == Triple::Darwin) { - // link all source files into a single module in data segment, rather than - // generating blocks. dynamic_lookup requires that you set - // MACOSX_DEPLOYMENT_TARGET=10.3 in your env. FIXME: it would be better for - // bugpoint to just pass that in the environment of GCC. - GCCArgs.push_back("-single_module"); - GCCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC - GCCArgs.push_back("-undefined"); - GCCArgs.push_back("dynamic_lookup"); - } else - GCCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others - - if ((TargetTriple.getArch() == Triple::alpha) || - (TargetTriple.getArch() == Triple::x86_64)) - GCCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC - - if (TargetTriple.getArch() == Triple::sparc) - GCCArgs.push_back("-mcpu=v9"); - - GCCArgs.push_back("-o"); - GCCArgs.push_back(OutputFile.c_str()); // Output to the right filename. - GCCArgs.push_back("-O2"); // Optimize the program a bit. - - - - // Add any arguments intended for GCC. We locate them here because this is - // most likely -L and -l options that need to come before other libraries but - // after the source. Other options won't be sensitive to placement on the - // command line, so this should be safe. - for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i) - GCCArgs.push_back(ArgsForGCC[i].c_str()); - GCCArgs.push_back(0); // NULL terminator - - - - outs() << "<gcc>"; outs().flush(); - DEBUG(errs() << "\nAbout to run:\t"; - for (unsigned i = 0, e = GCCArgs.size()-1; i != e; ++i) - errs() << " " << GCCArgs[i]; - errs() << "\n"; - ); - if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(), - sys::Path())) { - Error = ProcessFailure(GCCPath, &GCCArgs[0]); - return 1; - } - return 0; -} - -/// create - Try to find the `gcc' executable -/// -GCC *GCC::create(std::string &Message, - const std::string &GCCBinary, - const std::vector<std::string> *Args) { - sys::Path GCCPath = sys::Program::FindProgramByName(GCCBinary); - if (GCCPath.isEmpty()) { - Message = "Cannot find `"+ GCCBinary +"' in executable directory or PATH!\n"; - return 0; - } - - sys::Path RemoteClientPath; - if (!RemoteClient.empty()) - RemoteClientPath = sys::Program::FindProgramByName(RemoteClient); - - Message = "Found gcc: " + GCCPath.str() + "\n"; - return new GCC(GCCPath, RemoteClientPath, Args); -} diff --git a/contrib/llvm/tools/bugpoint/ToolRunner.h b/contrib/llvm/tools/bugpoint/ToolRunner.h deleted file mode 100644 index cda0ddf..0000000 --- a/contrib/llvm/tools/bugpoint/ToolRunner.h +++ /dev/null @@ -1,242 +0,0 @@ -//===-- tools/bugpoint/ToolRunner.h -----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file exposes an abstraction around a platform C compiler, used to -// compile C and assembly code. It also exposes an "AbstractIntepreter" -// interface, which is used to execute code using one of the LLVM execution -// engines. -// -//===----------------------------------------------------------------------===// - -#ifndef BUGPOINT_TOOLRUNNER_H -#define BUGPOINT_TOOLRUNNER_H - -#include "llvm/ADT/Triple.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/SystemUtils.h" -#include "llvm/System/Path.h" -#include <exception> -#include <vector> - -namespace llvm { - -extern cl::opt<bool> SaveTemps; -extern Triple TargetTriple; - -class CBE; -class LLC; - -//===---------------------------------------------------------------------===// -// GCC abstraction -// -class GCC { - sys::Path GCCPath; // The path to the gcc executable. - sys::Path RemoteClientPath; // The path to the rsh / ssh executable. - std::vector<std::string> gccArgs; // GCC-specific arguments. - GCC(const sys::Path &gccPath, const sys::Path &RemotePath, - const std::vector<std::string> *GCCArgs) - : GCCPath(gccPath), RemoteClientPath(RemotePath) { - if (GCCArgs) gccArgs = *GCCArgs; - } -public: - enum FileType { AsmFile, ObjectFile, CFile }; - - static GCC *create(std::string &Message, - const std::string &GCCBinary, - const std::vector<std::string> *Args); - - /// ExecuteProgram - Execute the program specified by "ProgramFile" (which is - /// either a .s file, or a .c file, specified by FileType), with the specified - /// arguments. Standard input is specified with InputFile, and standard - /// Output is captured to the specified OutputFile location. The SharedLibs - /// option specifies optional native shared objects that can be loaded into - /// the program for execution. - /// - int ExecuteProgram(const std::string &ProgramFile, - const std::vector<std::string> &Args, - FileType fileType, - const std::string &InputFile, - const std::string &OutputFile, - std::string *Error = 0, - const std::vector<std::string> &GCCArgs = - std::vector<std::string>(), - unsigned Timeout = 0, - unsigned MemoryLimit = 0); - - /// MakeSharedObject - This compiles the specified file (which is either a .c - /// file or a .s file) into a shared object. - /// - int MakeSharedObject(const std::string &InputFile, FileType fileType, - std::string &OutputFile, - const std::vector<std::string> &ArgsForGCC, - std::string &Error); -}; - - -//===---------------------------------------------------------------------===// -/// AbstractInterpreter Class - Subclasses of this class are used to execute -/// LLVM bitcode in a variety of ways. This abstract interface hides this -/// complexity behind a simple interface. -/// -class AbstractInterpreter { -public: - static CBE *createCBE(const char *Argv0, std::string &Message, - const std::string &GCCBinary, - const std::vector<std::string> *Args = 0, - const std::vector<std::string> *GCCArgs = 0); - static LLC *createLLC(const char *Argv0, std::string &Message, - const std::string &GCCBinary, - const std::vector<std::string> *Args = 0, - const std::vector<std::string> *GCCArgs = 0, - bool UseIntegratedAssembler = false); - - static AbstractInterpreter* createLLI(const char *Argv0, std::string &Message, - const std::vector<std::string> *Args=0); - - static AbstractInterpreter* createJIT(const char *Argv0, std::string &Message, - const std::vector<std::string> *Args=0); - - static AbstractInterpreter* createCustom(std::string &Message, - const std::string &ExecCommandLine); - - - virtual ~AbstractInterpreter() {} - - /// compileProgram - Compile the specified program from bitcode to executable - /// code. This does not produce any output, it is only used when debugging - /// the code generator. It returns false if the code generator fails. - virtual void compileProgram(const std::string &Bitcode, std::string *Error, - unsigned Timeout = 0, unsigned MemoryLimit = 0) {} - - /// OutputCode - Compile the specified program from bitcode to code - /// understood by the GCC driver (either C or asm). If the code generator - /// fails, it sets Error, otherwise, this function returns the type of code - /// emitted. - virtual GCC::FileType OutputCode(const std::string &Bitcode, - sys::Path &OutFile, std::string &Error, - unsigned Timeout = 0, - unsigned MemoryLimit = 0) { - Error = "OutputCode not supported by this AbstractInterpreter!"; - return GCC::AsmFile; - } - - /// ExecuteProgram - Run the specified bitcode file, emitting output to the - /// specified filename. This sets RetVal to the exit code of the program or - /// returns false if a problem was encountered that prevented execution of - /// the program. - /// - virtual int ExecuteProgram(const std::string &Bitcode, - const std::vector<std::string> &Args, - const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, - const std::vector<std::string> &GCCArgs = - std::vector<std::string>(), - const std::vector<std::string> &SharedLibs = - std::vector<std::string>(), - unsigned Timeout = 0, - unsigned MemoryLimit = 0) = 0; -}; - -//===---------------------------------------------------------------------===// -// CBE Implementation of AbstractIntepreter interface -// -class CBE : public AbstractInterpreter { - sys::Path LLCPath; // The path to the `llc' executable. - std::vector<std::string> ToolArgs; // Extra args to pass to LLC. - GCC *gcc; -public: - CBE(const sys::Path &llcPath, GCC *Gcc, - const std::vector<std::string> *Args) - : LLCPath(llcPath), gcc(Gcc) { - ToolArgs.clear (); - if (Args) ToolArgs = *Args; - } - ~CBE() { delete gcc; } - - /// compileProgram - Compile the specified program from bitcode to executable - /// code. This does not produce any output, it is only used when debugging - /// the code generator. Returns false if the code generator fails. - virtual void compileProgram(const std::string &Bitcode, std::string *Error, - unsigned Timeout = 0, unsigned MemoryLimit = 0); - - virtual int ExecuteProgram(const std::string &Bitcode, - const std::vector<std::string> &Args, - const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, - const std::vector<std::string> &GCCArgs = - std::vector<std::string>(), - const std::vector<std::string> &SharedLibs = - std::vector<std::string>(), - unsigned Timeout = 0, - unsigned MemoryLimit = 0); - - /// OutputCode - Compile the specified program from bitcode to code - /// understood by the GCC driver (either C or asm). If the code generator - /// fails, it sets Error, otherwise, this function returns the type of code - /// emitted. - virtual GCC::FileType OutputCode(const std::string &Bitcode, - sys::Path &OutFile, std::string &Error, - unsigned Timeout = 0, - unsigned MemoryLimit = 0); -}; - - -//===---------------------------------------------------------------------===// -// LLC Implementation of AbstractIntepreter interface -// -class LLC : public AbstractInterpreter { - std::string LLCPath; // The path to the LLC executable. - std::vector<std::string> ToolArgs; // Extra args to pass to LLC. - GCC *gcc; - bool UseIntegratedAssembler; -public: - LLC(const std::string &llcPath, GCC *Gcc, - const std::vector<std::string> *Args, - bool useIntegratedAssembler) - : LLCPath(llcPath), gcc(Gcc), - UseIntegratedAssembler(useIntegratedAssembler) { - ToolArgs.clear(); - if (Args) ToolArgs = *Args; - } - ~LLC() { delete gcc; } - - /// compileProgram - Compile the specified program from bitcode to executable - /// code. This does not produce any output, it is only used when debugging - /// the code generator. Returns false if the code generator fails. - virtual void compileProgram(const std::string &Bitcode, std::string *Error, - unsigned Timeout = 0, unsigned MemoryLimit = 0); - - virtual int ExecuteProgram(const std::string &Bitcode, - const std::vector<std::string> &Args, - const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, - const std::vector<std::string> &GCCArgs = - std::vector<std::string>(), - const std::vector<std::string> &SharedLibs = - std::vector<std::string>(), - unsigned Timeout = 0, - unsigned MemoryLimit = 0); - - /// OutputCode - Compile the specified program from bitcode to code - /// understood by the GCC driver (either C or asm). If the code generator - /// fails, it sets Error, otherwise, this function returns the type of code - /// emitted. - virtual GCC::FileType OutputCode(const std::string &Bitcode, - sys::Path &OutFile, std::string &Error, - unsigned Timeout = 0, - unsigned MemoryLimit = 0); -}; - -} // End llvm namespace - -#endif diff --git a/contrib/llvm/tools/bugpoint/bugpoint.cpp b/contrib/llvm/tools/bugpoint/bugpoint.cpp deleted file mode 100644 index 79cf563..0000000 --- a/contrib/llvm/tools/bugpoint/bugpoint.cpp +++ /dev/null @@ -1,159 +0,0 @@ -//===- bugpoint.cpp - The LLVM Bugpoint utility ---------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This program is an automated compiler debugger tool. It is used to narrow -// down miscompilations and crash problems to a specific pass in the compiler, -// and the specific Module or Function input that is causing the problem. -// -//===----------------------------------------------------------------------===// - -#include "BugDriver.h" -#include "ToolRunner.h" -#include "llvm/LinkAllPasses.h" -#include "llvm/LLVMContext.h" -#include "llvm/Support/PassNameParser.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/PluginLoader.h" -#include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/StandardPasses.h" -#include "llvm/System/Process.h" -#include "llvm/System/Signals.h" -#include "llvm/System/Valgrind.h" -#include "llvm/LinkAllVMCore.h" -using namespace llvm; - -static cl::opt<bool> -FindBugs("find-bugs", cl::desc("Run many different optimization sequences " - "on program to find bugs"), cl::init(false)); - -static cl::list<std::string> -InputFilenames(cl::Positional, cl::OneOrMore, - cl::desc("<input llvm ll/bc files>")); - -static cl::opt<unsigned> -TimeoutValue("timeout", cl::init(300), cl::value_desc("seconds"), - cl::desc("Number of seconds program is allowed to run before it " - "is killed (default is 300s), 0 disables timeout")); - -static cl::opt<int> -MemoryLimit("mlimit", cl::init(-1), cl::value_desc("MBytes"), - cl::desc("Maximum amount of memory to use. 0 disables check." - " Defaults to 100MB (800MB under valgrind).")); - -static cl::opt<bool> -UseValgrind("enable-valgrind", - cl::desc("Run optimizations through valgrind")); - -// The AnalysesList is automatically populated with registered Passes by the -// PassNameParser. -// -static cl::list<const PassInfo*, bool, PassNameParser> -PassList(cl::desc("Passes available:"), cl::ZeroOrMore); - -static cl::opt<bool> -StandardCompileOpts("std-compile-opts", - cl::desc("Include the standard compile time optimizations")); - -static cl::opt<bool> -StandardLinkOpts("std-link-opts", - cl::desc("Include the standard link time optimizations")); - -static cl::opt<std::string> -OverrideTriple("mtriple", cl::desc("Override target triple for module")); - -/// BugpointIsInterrupted - Set to true when the user presses ctrl-c. -bool llvm::BugpointIsInterrupted = false; - -static void BugpointInterruptFunction() { - BugpointIsInterrupted = true; -} - -// Hack to capture a pass list. -namespace { - class AddToDriver : public PassManager { - BugDriver &D; - public: - AddToDriver(BugDriver &_D) : D(_D) {} - - virtual void add(Pass *P) { - const void *ID = P->getPassID(); - const PassInfo *PI = PassRegistry::getPassRegistry()->getPassInfo(ID); - D.addPass(PI->getPassArgument()); - } - }; -} - -int main(int argc, char **argv) { - llvm::sys::PrintStackTraceOnErrorSignal(); - llvm::PrettyStackTraceProgram X(argc, argv); - llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. - cl::ParseCommandLineOptions(argc, argv, - "LLVM automatic testcase reducer. See\nhttp://" - "llvm.org/cmds/bugpoint.html" - " for more information.\n"); - sys::SetInterruptFunction(BugpointInterruptFunction); - - LLVMContext& Context = getGlobalContext(); - // If we have an override, set it and then track the triple we want Modules - // to use. - if (!OverrideTriple.empty()) { - TargetTriple.setTriple(Triple::normalize(OverrideTriple)); - outs() << "Override triple set to '" << TargetTriple.getTriple() << "'\n"; - } - - if (MemoryLimit < 0) { - // Set the default MemoryLimit. Be sure to update the flag's description if - // you change this. - if (sys::RunningOnValgrind() || UseValgrind) - MemoryLimit = 800; - else - MemoryLimit = 100; - } - - BugDriver D(argv[0], FindBugs, TimeoutValue, MemoryLimit, - UseValgrind, Context); - if (D.addSources(InputFilenames)) return 1; - - AddToDriver PM(D); - if (StandardCompileOpts) { - createStandardModulePasses(&PM, 3, - /*OptimizeSize=*/ false, - /*UnitAtATime=*/ true, - /*UnrollLoops=*/ true, - /*SimplifyLibCalls=*/ true, - /*HaveExceptions=*/ true, - createFunctionInliningPass()); - } - - if (StandardLinkOpts) - createStandardLTOPasses(&PM, /*Internalize=*/true, - /*RunInliner=*/true, - /*VerifyEach=*/false); - - - for (std::vector<const PassInfo*>::iterator I = PassList.begin(), - E = PassList.end(); - I != E; ++I) { - const PassInfo* PI = *I; - D.addPass(PI->getPassArgument()); - } - - // Bugpoint has the ability of generating a plethora of core files, so to - // avoid filling up the disk, we prevent it - sys::Process::PreventCoreFiles(); - - std::string Error; - bool Failure = D.run(Error); - if (!Error.empty()) { - errs() << Error; - return 1; - } - return Failure; -} |