summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/bugpoint
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/bugpoint')
-rw-r--r--contrib/llvm/tools/bugpoint/BugDriver.cpp246
-rw-r--r--contrib/llvm/tools/bugpoint/BugDriver.h329
-rw-r--r--contrib/llvm/tools/bugpoint/CMakeLists.txt14
-rw-r--r--contrib/llvm/tools/bugpoint/CrashDebugger.cpp667
-rw-r--r--contrib/llvm/tools/bugpoint/ExecutionDriver.cpp501
-rw-r--r--contrib/llvm/tools/bugpoint/ExtractFunction.cpp369
-rw-r--r--contrib/llvm/tools/bugpoint/FindBugs.cpp113
-rw-r--r--contrib/llvm/tools/bugpoint/ListReducer.h201
-rw-r--r--contrib/llvm/tools/bugpoint/Makefile16
-rw-r--r--contrib/llvm/tools/bugpoint/Miscompilation.cpp1082
-rw-r--r--contrib/llvm/tools/bugpoint/OptimizerDriver.cpp260
-rw-r--r--contrib/llvm/tools/bugpoint/ToolRunner.cpp883
-rw-r--r--contrib/llvm/tools/bugpoint/ToolRunner.h242
-rw-r--r--contrib/llvm/tools/bugpoint/bugpoint.cpp159
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;
-}
OpenPOWER on IntegriCloud