summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/bugpoint
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2012-02-05 23:56:22 +0000
committerdim <dim@FreeBSD.org>2012-02-05 23:56:22 +0000
commiteb8951e7f7015d193e6640deb0ebde32f01b72d8 (patch)
tree8052b8010f619e8d40e5e3b37482591f537e0ca0 /contrib/llvm/tools/bugpoint
parent4de4d315e465f872a81f448b1788cc017f2d2033 (diff)
parent07637c87f826cdf411f0673595e9bc92ebd793f2 (diff)
downloadFreeBSD-src-eb8951e7f7015d193e6640deb0ebde32f01b72d8.zip
FreeBSD-src-eb8951e7f7015d193e6640deb0ebde32f01b72d8.tar.gz
Add a WITH_CLANG_EXTRAS option for src.conf(5), disabled by default,
that builds the following additional llvm/clang tools: - bugpoint - llc - lli - llvm-ar - llvm-as - llvm-bcanalyzer - llvm-diff - llvm-dis - llvm-extract - llvm-ld - llvm-link - llvm-mc - llvm-nm - llvm-objdump - llvm-prof - llvm-ranlib - llvm-rtdyld - llvm-stub - macho-dump - opt These tools are mainly useful for people that want to manipulate llvm bitcode (.bc) and llvm assembly language (.ll) files, or want to tinker with llvm and clang themselves. MFC after: 2 weeks
Diffstat (limited to 'contrib/llvm/tools/bugpoint')
-rw-r--r--contrib/llvm/tools/bugpoint/BugDriver.cpp247
-rw-r--r--contrib/llvm/tools/bugpoint/BugDriver.h330
-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.cpp516
-rw-r--r--contrib/llvm/tools/bugpoint/ExtractFunction.cpp370
-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.cpp1078
-rw-r--r--contrib/llvm/tools/bugpoint/OptimizerDriver.cpp265
-rw-r--r--contrib/llvm/tools/bugpoint/ToolRunner.cpp977
-rw-r--r--contrib/llvm/tools/bugpoint/ToolRunner.h247
-rw-r--r--contrib/llvm/tools/bugpoint/bugpoint.cpp209
14 files changed, 5250 insertions, 0 deletions
diff --git a/contrib/llvm/tools/bugpoint/BugDriver.cpp b/contrib/llvm/tools/bugpoint/BugDriver.cpp
new file mode 100644
index 0000000..677d178
--- /dev/null
+++ b/contrib/llvm/tools/bugpoint/BugDriver.cpp
@@ -0,0 +1,247 @@
+//===- 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/Support/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(), Linker::DestroySource,
+ &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.str(), 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
new file mode 100644
index 0000000..cc78489
--- /dev/null
+++ b/contrib/llvm/tools/bugpoint/BugDriver.h
@@ -0,0 +1,330 @@
+//===- 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 "llvm/Transforms/Utils/ValueMapper.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,
+ ValueToValueMapTy &VMap);
+
+} // End llvm namespace
+
+#endif
diff --git a/contrib/llvm/tools/bugpoint/CMakeLists.txt b/contrib/llvm/tools/bugpoint/CMakeLists.txt
new file mode 100644
index 0000000..e06feb1
--- /dev/null
+++ b/contrib/llvm/tools/bugpoint/CMakeLists.txt
@@ -0,0 +1,14 @@
+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
new file mode 100644
index 0000000..f19ef62
--- /dev/null
+++ b/contrib/llvm/tools/bugpoint/CrashDebugger.cpp
@@ -0,0 +1,667 @@
+//===- 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...
+ ValueToValueMapTy 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...
+ ValueToValueMapTy 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...
+ ValueToValueMapTy 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...
+ ValueToValueMapTy 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
new file mode 100644
index 0000000..77c01ac
--- /dev/null
+++ b/contrib/llvm/tools/bugpoint/ExecutionDriver.cpp
@@ -0,0 +1,516 @@
+//===- 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,
+ CompileCustom, 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(CompileCustom, "compile-custom",
+ "Use -compile-command to define a command to "
+ "compile the bitcode. Useful to avoid linking."),
+ 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>
+ CustomCompileCommand("compile-command", cl::init("llc"),
+ cl::desc("Command to compile the bitcode (use with -compile-custom) "
+ "(default: llc)"));
+
+ 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 CompileCustom:
+ Interpreter =
+ AbstractInterpreter::createCustomCompiler(Message, CustomCompileCommand);
+ break;
+ case Custom:
+ Interpreter =
+ AbstractInterpreter::createCustomExecutor(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::createCustomExecutor(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.str(), !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.str(),
+ 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 set ErrMsg.
+///
+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
new file mode 100644
index 0000000..73b65ca
--- /dev/null
+++ b/contrib/llvm/tools/bugpoint/ExtractFunction.cpp
@@ -0,0 +1,370 @@
+//===- 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/ToolOutputFile.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/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");
+
+ 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;
+ Type *Int32Ty = Type::getInt32Ty(TorList[0].first->getContext());
+
+ StructType *STy =
+ StructType::get(Int32Ty, TorList[0].first->getType(), NULL);
+ for (unsigned i = 0, e = TorList.size(); i != e; ++i) {
+ Constant *Elts[] = {
+ ConstantInt::get(Int32Ty, TorList[i].second),
+ TorList[i].first
+ };
+ ArrayElts.push_back(ConstantStruct::get(STy, Elts));
+ }
+ 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,
+ ValueToValueMapTy &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,
+ ValueToValueMapTy &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);
+ }
+
+ ValueToValueMapTy 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
new file mode 100644
index 0000000..a291f9f
--- /dev/null
+++ b/contrib/llvm/tools/bugpoint/FindBugs.cpp
@@ -0,0 +1,113 @@
+//===-- 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
new file mode 100644
index 0000000..bd1c5da
--- /dev/null
+++ b/contrib/llvm/tools/bugpoint/ListReducer.h
@@ -0,0 +1,201 @@
+//===- 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
new file mode 100644
index 0000000..5d287ef
--- /dev/null
+++ b/contrib/llvm/tools/bugpoint/Makefile
@@ -0,0 +1,16 @@
+##===- 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
new file mode 100644
index 0000000..7ff16db
--- /dev/null
+++ b/contrib/llvm/tools/bugpoint/Miscompilation.cpp
@@ -0,0 +1,1078 @@
+//===- 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, Linker::DestroySource, &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.
+ ValueToValueMapTy 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;
+
+ ValueToValueMapTy 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, 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,
+ Linker::DestroySource, &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??");
+ 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.
+ ValueToValueMapTy 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;
+ }
+
+ ValueToValueMapTy 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, 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, Linker::DestroySource,
+ &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??");
+ 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()) {
+ errs() << "\n***Cannot reduce functions: ";
+ 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";
+ ValueToValueMapTy 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, "", 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);
+ 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
+ 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, "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(), 2,
+ "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, "", DoCallBB);
+ ReturnInst::Create(F->getContext(), DoCallBB);
+ } else {
+ CallInst *Call = CallInst::Create(FuncPtr, Args,
+ "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.str(), !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.str(), !SaveTemps);
+
+ std::string SharedObject = BD.compileSharedObject(SafeModuleBC.str(), Error);
+ if (!Error.empty())
+ return false;
+ delete Safe;
+
+ FileRemover SharedObjectRemover(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.
+ ValueToValueMapTy 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
new file mode 100644
index 0000000..336c83d
--- /dev/null
+++ b/contrib/llvm/tools/bugpoint/OptimizerDriver.cpp
@@ -0,0 +1,265 @@
+//===- 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. :)
+//
+//===----------------------------------------------------------------------===//
+
+#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/ToolOutputFile.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/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;
+ }
+
+ sys::Path tool = PrependMainExecutablePath("opt", getToolName(),
+ (void*)"opt");
+ if (tool.empty()) {
+ errs() << "Cannot find `opt' in executable directory!\n";
+ return 1;
+ }
+
+ // Ok, everything that could go wrong before running opt is done.
+ InFile.keep();
+
+ // setup the child process' arguments
+ SmallVector<const char*, 8> Args;
+ 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: " << ErrMsg << "\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
new file mode 100644
index 0000000..0d98262
--- /dev/null
+++ b/contrib/llvm/tools/bugpoint/ToolRunner.cpp
@@ -0,0 +1,977 @@
+//===-- 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/Support/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,
+ std::string *ErrMsg = 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, ErrMsg);
+}
+
+/// 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, Error);
+}
+
+// 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 =
+ PrependMainExecutablePath("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!\n";
+ return 0;
+}
+
+//===---------------------------------------------------------------------===//
+// Custom compiler command implementation of AbstractIntepreter interface
+//
+// Allows using a custom command for compiling the bitcode, thus allows, for
+// example, to compile a bitcode fragment without linking or executing, then
+// using a custom wrapper script to check for compiler errors.
+namespace {
+ class CustomCompiler : public AbstractInterpreter {
+ std::string CompilerCommand;
+ std::vector<std::string> CompilerArgs;
+ public:
+ CustomCompiler(
+ const std::string &CompilerCmd, std::vector<std::string> CompArgs) :
+ CompilerCommand(CompilerCmd), CompilerArgs(CompArgs) {}
+
+ 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) {
+ *Error = "Execution not supported with -compile-custom";
+ return -1;
+ }
+ };
+}
+
+void CustomCompiler::compileProgram(const std::string &Bitcode,
+ std::string *Error,
+ unsigned Timeout,
+ unsigned MemoryLimit) {
+
+ std::vector<const char*> ProgramArgs;
+ ProgramArgs.push_back(CompilerCommand.c_str());
+
+ for (std::size_t i = 0; i < CompilerArgs.size(); ++i)
+ ProgramArgs.push_back(CompilerArgs.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 = CompilerArgs.size(); i != e; ++i)
+ ProgramArgs.push_back(CompilerArgs[i].c_str());
+
+ if (RunProgramWithTimeout( sys::Path(CompilerCommand), &ProgramArgs[0],
+ sys::Path(), sys::Path(), sys::Path(),
+ Timeout, MemoryLimit, Error))
+ *Error = ProcessFailure(sys::Path(CompilerCommand), &ProgramArgs[0],
+ Timeout, MemoryLimit);
+}
+
+//===---------------------------------------------------------------------===//
+// 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, Error);
+}
+
+// Tokenize the CommandLine 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
+static void lexCommand(std::string &Message, const std::string &CommandLine,
+ std::string &CmdPath, std::vector<std::string> Args) {
+
+ std::string Command = "";
+ std::string delimiters = " ";
+
+ std::string::size_type lastPos = CommandLine.find_first_not_of(delimiters, 0);
+ std::string::size_type pos = CommandLine.find_first_of(delimiters, lastPos);
+
+ while (std::string::npos != pos || std::string::npos != lastPos) {
+ std::string token = CommandLine.substr(lastPos, pos - lastPos);
+ if (Command == "")
+ Command = token;
+ else
+ Args.push_back(token);
+ // Skip delimiters. Note the "not_of"
+ lastPos = CommandLine.find_first_not_of(delimiters, pos);
+ // Find next "non-delimiter"
+ pos = CommandLine.find_first_of(delimiters, lastPos);
+ }
+
+ CmdPath = sys::Program::FindProgramByName(Command).str();
+ if (CmdPath.empty()) {
+ Message =
+ std::string("Cannot find '") + Command +
+ "' in PATH!\n";
+ return;
+ }
+
+ Message = "Found command in: " + CmdPath + "\n";
+}
+
+// Custom execution environment create method, takes the execution command
+// as arguments
+AbstractInterpreter *AbstractInterpreter::createCustomCompiler(
+ std::string &Message,
+ const std::string &CompileCommandLine) {
+
+ std::string CmdPath;
+ std::vector<std::string> Args;
+ lexCommand(Message, CompileCommandLine, CmdPath, Args);
+ if (CmdPath.empty())
+ return 0;
+
+ return new CustomCompiler(CmdPath, Args);
+}
+
+// Custom execution environment create method, takes the execution command
+// as arguments
+AbstractInterpreter *AbstractInterpreter::createCustomExecutor(
+ std::string &Message,
+ const std::string &ExecCommandLine) {
+
+
+ std::string CmdPath;
+ std::vector<std::string> Args;
+ lexCommand(Message, ExecCommandLine, CmdPath, Args);
+ if (CmdPath.empty())
+ return 0;
+
+ 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.str(), !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 =
+ PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t)&createLLC).str();
+ if (LLCPath.empty()) {
+ Message = "Cannot find `llc' in executable directory!\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, Error);
+}
+
+/// 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 =
+ PrependMainExecutablePath("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!\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.str(), !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 =
+ PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t)&createCBE);
+ if (LLCPath.isEmpty()) {
+ Message =
+ "Cannot find `llc' in executable directory!\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.isOSDarwin() && !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.str(), !SaveTemps);
+
+ if (RemoteClientPath.isEmpty()) {
+ DEBUG(errs() << "<run locally>");
+ int ExitCode = RunProgramWithTimeout(OutputBinary, &ProgramArgs[0],
+ sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
+ Timeout, MemoryLimit, Error);
+ // Treat a signal (usually SIGSEGV) or timeout as part of the program output
+ // so that crash-causing miscompilation is handled seamlessly.
+ if (ExitCode < -1) {
+ std::ofstream outFile(OutputFile.c_str(), std::ios_base::app);
+ outFile << *Error << '\n';
+ outFile.close();
+ Error->clear();
+ }
+ return ExitCode;
+ } 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.isOSDarwin()) {
+ // 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 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
new file mode 100644
index 0000000..cfa8acf
--- /dev/null
+++ b/contrib/llvm/tools/bugpoint/ToolRunner.h
@@ -0,0 +1,247 @@
+//===-- 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/Support/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*
+ createCustomCompiler(std::string &Message,
+ const std::string &CompileCommandLine);
+
+ static AbstractInterpreter*
+ createCustomExecutor(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
new file mode 100644
index 0000000..6a87521
--- /dev/null
+++ b/contrib/llvm/tools/bugpoint/bugpoint.cpp
@@ -0,0 +1,209 @@
+//===- 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/PassManager.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/Process.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/Valgrind.h"
+#include "llvm/LinkAllVMCore.h"
+#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+
+//Enable this macro to debug bugpoint itself.
+//#define DEBUG_BUGPOINT 1
+
+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<bool>
+OptLevelO1("O1",
+ cl::desc("Optimization level 1. Similar to llvm-gcc -O1"));
+
+static cl::opt<bool>
+OptLevelO2("O2",
+ cl::desc("Optimization level 2. Similar to llvm-gcc -O2"));
+
+static cl::opt<bool>
+OptLevelO3("O3",
+ cl::desc("Optimization level 3. Similar to llvm-gcc -O3"));
+
+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;
+
+#ifndef DEBUG_BUGPOINT
+static void BugpointInterruptFunction() {
+ BugpointIsInterrupted = true;
+}
+#endif
+
+// Hack to capture a pass list.
+namespace {
+ class AddToDriver : public FunctionPassManager {
+ BugDriver &D;
+ public:
+ AddToDriver(BugDriver &_D) : FunctionPassManager(0), 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) {
+#ifndef DEBUG_BUGPOINT
+ llvm::sys::PrintStackTraceOnErrorSignal();
+ llvm::PrettyStackTraceProgram X(argc, argv);
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+#endif
+
+ // Initialize passes
+ PassRegistry &Registry = *PassRegistry::getPassRegistry();
+ initializeCore(Registry);
+ initializeScalarOpts(Registry);
+ initializeIPO(Registry);
+ initializeAnalysis(Registry);
+ initializeIPA(Registry);
+ initializeTransformUtils(Registry);
+ initializeInstCombine(Registry);
+ initializeInstrumentation(Registry);
+ initializeTarget(Registry);
+
+ cl::ParseCommandLineOptions(argc, argv,
+ "LLVM automatic testcase reducer. See\nhttp://"
+ "llvm.org/cmds/bugpoint.html"
+ " for more information.\n");
+#ifndef DEBUG_BUGPOINT
+ sys::SetInterruptFunction(BugpointInterruptFunction);
+#endif
+
+ 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) {
+ PassManagerBuilder Builder;
+ Builder.OptLevel = 3;
+ Builder.Inliner = createFunctionInliningPass();
+ Builder.populateModulePassManager(PM);
+ }
+
+ if (StandardLinkOpts) {
+ PassManagerBuilder Builder;
+ Builder.populateLTOPassManager(PM, /*Internalize=*/true,
+ /*RunInliner=*/true);
+ }
+
+ if (OptLevelO1 || OptLevelO2 || OptLevelO3) {
+ PassManagerBuilder Builder;
+ if (OptLevelO1)
+ Builder.Inliner = createAlwaysInlinerPass();
+ else if (OptLevelO2)
+ Builder.Inliner = createFunctionInliningPass(225);
+ else
+ Builder.Inliner = createFunctionInliningPass(275);
+
+ // Note that although clang/llvm-gcc use two separate passmanagers
+ // here, it shouldn't normally make a difference.
+ Builder.populateFunctionPassManager(PM);
+ Builder.populateModulePassManager(PM);
+ }
+
+ 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
+#ifndef DEBUG_BUGPOINT
+ sys::Process::PreventCoreFiles();
+#endif
+
+ std::string Error;
+ bool Failure = D.run(Error);
+ if (!Error.empty()) {
+ errs() << Error;
+ return 1;
+ }
+ return Failure;
+}
OpenPOWER on IntegriCloud