summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/CMakeLists.txt36
-rw-r--r--tools/Makefile45
-rw-r--r--tools/bugpoint/BugDriver.cpp241
-rw-r--r--tools/bugpoint/BugDriver.h322
-rw-r--r--tools/bugpoint/CMakeLists.txt16
-rw-r--r--tools/bugpoint/CrashDebugger.cpp648
-rw-r--r--tools/bugpoint/ExecutionDriver.cpp473
-rw-r--r--tools/bugpoint/ExtractFunction.cpp375
-rw-r--r--tools/bugpoint/FindBugs.cpp112
-rw-r--r--tools/bugpoint/ListReducer.h189
-rw-r--r--tools/bugpoint/Makefile17
-rw-r--r--tools/bugpoint/Miscompilation.cpp932
-rw-r--r--tools/bugpoint/OptimizerDriver.cpp266
-rw-r--r--tools/bugpoint/TestPasses.cpp75
-rw-r--r--tools/bugpoint/ToolRunner.cpp748
-rw-r--r--tools/bugpoint/ToolRunner.h230
-rw-r--r--tools/bugpoint/bugpoint.cpp104
-rw-r--r--tools/gccas/Makefile28
-rw-r--r--tools/gccas/gccas.sh64
-rw-r--r--tools/gccld/Makefile29
-rw-r--r--tools/gccld/gccld.sh23
-rw-r--r--tools/gold/Makefile30
-rw-r--r--tools/gold/README.txt21
-rw-r--r--tools/gold/gold-plugin.cpp394
-rw-r--r--tools/llc/CMakeLists.txt5
-rw-r--r--tools/llc/Makefile21
-rw-r--r--tools/llc/llc.cpp349
-rw-r--r--tools/lli/CMakeLists.txt5
-rw-r--r--tools/lli/Makefile15
-rw-r--r--tools/lli/lli.cpp214
-rw-r--r--tools/llvm-ar/CMakeLists.txt8
-rw-r--r--tools/llvm-ar/Makefile25
-rw-r--r--tools/llvm-ar/llvm-ar.cpp776
-rw-r--r--tools/llvm-as/CMakeLists.txt6
-rw-r--r--tools/llvm-as/Makefile18
-rw-r--r--tools/llvm-as/llvm-as.cpp149
-rw-r--r--tools/llvm-bcanalyzer/CMakeLists.txt6
-rw-r--r--tools/llvm-bcanalyzer/Makefile18
-rw-r--r--tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp600
-rw-r--r--tools/llvm-config/CMakeLists.txt120
-rw-r--r--tools/llvm-config/Makefile92
-rwxr-xr-xtools/llvm-config/find-cycles.pl165
-rw-r--r--tools/llvm-config/llvm-config.in.in460
-rw-r--r--tools/llvm-db/CLICommand.h111
-rw-r--r--tools/llvm-db/CLIDebugger.cpp308
-rw-r--r--tools/llvm-db/CLIDebugger.h205
-rw-r--r--tools/llvm-db/CMakeLists.txt8
-rw-r--r--tools/llvm-db/Commands.cpp865
-rw-r--r--tools/llvm-db/Makefile15
-rw-r--r--tools/llvm-db/llvm-db.cpp100
-rw-r--r--tools/llvm-dis/CMakeLists.txt6
-rw-r--r--tools/llvm-dis/Makefile18
-rw-r--r--tools/llvm-dis/llvm-dis.cpp143
-rw-r--r--tools/llvm-extract/CMakeLists.txt5
-rw-r--r--tools/llvm-extract/Makefile18
-rw-r--r--tools/llvm-extract/llvm-extract.cpp136
-rw-r--r--tools/llvm-ld/CMakeLists.txt7
-rw-r--r--tools/llvm-ld/Makefile16
-rw-r--r--tools/llvm-ld/Optimize.cpp194
-rw-r--r--tools/llvm-ld/llvm-ld.cpp708
-rw-r--r--tools/llvm-link/CMakeLists.txt5
-rw-r--r--tools/llvm-link/Makefile17
-rw-r--r--tools/llvm-link/llvm-link.cpp154
-rw-r--r--tools/llvm-nm/CMakeLists.txt5
-rw-r--r--tools/llvm-nm/Makefile17
-rw-r--r--tools/llvm-nm/llvm-nm.cpp192
-rw-r--r--tools/llvm-prof/CMakeLists.txt6
-rw-r--r--tools/llvm-prof/Makefile18
-rw-r--r--tools/llvm-prof/llvm-prof.cpp256
-rw-r--r--tools/llvm-ranlib/CMakeLists.txt6
-rw-r--r--tools/llvm-ranlib/Makefile18
-rw-r--r--tools/llvm-ranlib/llvm-ranlib.cpp98
-rw-r--r--tools/llvm-stub/CMakeLists.txt3
-rw-r--r--tools/llvm-stub/Makefile13
-rw-r--r--tools/llvm-stub/llvm-stub.c74
-rw-r--r--tools/llvmc/CMakeLists.txt4
-rw-r--r--tools/llvmc/Makefile17
-rw-r--r--tools/llvmc/doc/LLVMC-Reference.rst667
-rw-r--r--tools/llvmc/doc/LLVMC-Tutorial.rst124
-rw-r--r--tools/llvmc/doc/Makefile27
-rw-r--r--tools/llvmc/doc/img/lines.gifbin0 -> 91 bytes
-rw-r--r--tools/llvmc/driver/Main.cpp14
-rw-r--r--tools/llvmc/driver/Makefile22
-rw-r--r--tools/llvmc/example/Hello/Hello.cpp30
-rw-r--r--tools/llvmc/example/Hello/Makefile14
-rw-r--r--tools/llvmc/example/Simple/Makefile15
-rw-r--r--tools/llvmc/example/Simple/PluginMain.cpp1
-rw-r--r--tools/llvmc/example/Simple/Simple.td37
-rw-r--r--tools/llvmc/example/Skeleton/Makefile24
-rw-r--r--tools/llvmc/example/Skeleton/README6
-rw-r--r--tools/llvmc/example/Skeleton/driver/Main.cpp14
-rw-r--r--tools/llvmc/example/Skeleton/driver/Makefile22
-rw-r--r--tools/llvmc/example/Skeleton/plugins/Makefile18
-rw-r--r--tools/llvmc/example/Skeleton/plugins/Plugin/Makefile17
-rw-r--r--tools/llvmc/example/Skeleton/plugins/Plugin/Plugin.td7
-rw-r--r--tools/llvmc/example/Skeleton/plugins/Plugin/PluginMain.cpp1
-rw-r--r--tools/llvmc/plugins/Base/Base.td.in202
-rw-r--r--tools/llvmc/plugins/Base/Makefile15
-rw-r--r--tools/llvmc/plugins/Base/PluginMain.cpp1
-rw-r--r--tools/llvmc/plugins/Clang/Clang.td116
-rw-r--r--tools/llvmc/plugins/Clang/Makefile15
-rw-r--r--tools/llvmc/plugins/Clang/PluginMain.cpp1
-rw-r--r--tools/llvmc/plugins/Makefile18
-rw-r--r--tools/lto/LTOCodeGenerator.cpp506
-rw-r--r--tools/lto/LTOCodeGenerator.h67
-rw-r--r--tools/lto/LTOModule.cpp538
-rw-r--r--tools/lto/LTOModule.h112
-rw-r--r--tools/lto/Makefile47
-rw-r--r--tools/lto/lto.cpp259
-rw-r--r--tools/lto/lto.exports23
-rw-r--r--tools/opt/AnalysisWrappers.cpp88
-rw-r--r--tools/opt/CMakeLists.txt9
-rw-r--r--tools/opt/GraphPrinters.cpp115
-rw-r--r--tools/opt/Makefile15
-rw-r--r--tools/opt/PrintSCC.cpp112
-rw-r--r--tools/opt/opt.cpp602
116 files changed, 16157 insertions, 0 deletions
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
new file mode 100644
index 0000000..113d987
--- /dev/null
+++ b/tools/CMakeLists.txt
@@ -0,0 +1,36 @@
+# NOTE: The tools are organized into five groups of four consisting of one
+# large and three small executables. This is done to minimize memory load
+# in parallel builds. Please retain this ordering.
+
+if( NOT MSVC )
+ add_subdirectory(llvm-config)
+endif( NOT MSVC )
+
+add_subdirectory(opt)
+add_subdirectory(llvm-as)
+add_subdirectory(llvm-dis)
+
+add_subdirectory(llc)
+add_subdirectory(llvm-ranlib)
+add_subdirectory(llvm-ar)
+add_subdirectory(llvm-nm)
+
+add_subdirectory(llvm-ld)
+add_subdirectory(llvm-prof)
+add_subdirectory(llvm-link)
+add_subdirectory(lli)
+
+# gccas and gccld are deprecated:
+# add_subdirectory(gccas)
+# add_subdirectory(gccld)
+add_subdirectory(llvm-extract)
+add_subdirectory(llvm-db)
+
+add_subdirectory(bugpoint)
+add_subdirectory(llvm-bcanalyzer)
+add_subdirectory(llvm-stub)
+add_subdirectory(llvmc)
+
+if( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/clang/CMakeLists.txt )
+ add_subdirectory( ${CMAKE_CURRENT_SOURCE_DIR}/clang )
+endif( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/clang/CMakeLists.txt )
diff --git a/tools/Makefile b/tools/Makefile
new file mode 100644
index 0000000..b3c015f
--- /dev/null
+++ b/tools/Makefile
@@ -0,0 +1,45 @@
+##===- tools/Makefile --------------------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL := ..
+
+# Build clang if present.
+OPTIONAL_PARALLEL_DIRS := clang
+
+# NOTE: The tools are organized into five groups of four consisting of one
+# large and three small executables. This is done to minimize memory load
+# in parallel builds. Please retain this ordering.
+DIRS := llvm-config
+PARALLEL_DIRS := opt llvm-as llvm-dis \
+ llc llvm-ranlib llvm-ar llvm-nm \
+ llvm-ld llvm-prof llvm-link \
+ lli gccas gccld llvm-extract llvm-db \
+ bugpoint llvm-bcanalyzer llvm-stub llvmc
+
+# Let users override the set of tools to build from the command line.
+ifdef ONLY_TOOLS
+ OPTIONAL_PARALLEL_DIRS :=
+ PARALLEL_DIRS := $(ONLY_TOOLS)
+endif
+
+include $(LEVEL)/Makefile.config
+
+ifeq ($(ENABLE_PIC),1)
+ DIRS += lto
+ ifdef BINUTILS_INCDIR
+ DIRS += gold
+ endif
+endif
+
+# No support for lto / gold on windows targets
+ifeq ($(OS), $(filter $(OS), Cygwin MingW))
+ DIRS := $(filter-out lto gold, $(DIRS))
+endif
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/bugpoint/BugDriver.cpp b/tools/bugpoint/BugDriver.cpp
new file mode 100644
index 0000000..d050b59
--- /dev/null
+++ b/tools/bugpoint/BugDriver.cpp
@@ -0,0 +1,241 @@
+//===- 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/Assembly/Parser.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include <iostream>
+#include <memory>
+using namespace llvm;
+
+// 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<const PassInfo*> &Passes) {
+ std::string Result;
+ for (unsigned i = 0, e = Passes.size(); i != e; ++i) {
+ if (i) Result += " ";
+ Result += "-";
+ Result += Passes[i]->getPassArgument();
+ }
+ return Result;
+}
+
+BugDriver::BugDriver(const char *toolname, bool as_child, bool find_bugs,
+ unsigned timeout, unsigned memlimit)
+ : ToolName(toolname), ReferenceOutputFile(OutputFile),
+ Program(0), Interpreter(0), SafeInterpreter(0), gcc(0),
+ run_as_child(as_child),
+ run_find_bugs(find_bugs), Timeout(timeout), MemoryLimit(memlimit) {}
+
+
+/// 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) {
+ std::auto_ptr<MemoryBuffer> Buffer(MemoryBuffer::getFileOrSTDIN(Filename));
+ Module *Result = 0;
+ if (Buffer.get())
+ Result = ParseBitcodeFile(Buffer.get());
+
+ ParseError Err;
+ if (!Result && !(Result = ParseAssemblyFile(Filename, Err))) {
+ Err.PrintError("bugpoint", errs());
+ Result = 0;
+ }
+
+ 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!");
+
+ try {
+ // Load the first input file.
+ Program = ParseInputFile(Filenames[0]);
+ if (Program == 0) return true;
+
+ if (!run_as_child)
+ std::cout << "Read input file : '" << Filenames[0] << "'\n";
+
+ for (unsigned i = 1, e = Filenames.size(); i != e; ++i) {
+ std::auto_ptr<Module> M(ParseInputFile(Filenames[i]));
+ if (M.get() == 0) return true;
+
+ if (!run_as_child)
+ std::cout << "Linking in input file: '" << Filenames[i] << "'\n";
+ std::string ErrorMessage;
+ if (Linker::LinkModules(Program, M.get(), &ErrorMessage)) {
+ std::cerr << ToolName << ": error linking in '" << Filenames[i] << "': "
+ << ErrorMessage << '\n';
+ return true;
+ }
+ }
+ } catch (const std::string &Error) {
+ std::cerr << ToolName << ": error reading input '" << Error << "'\n";
+ return true;
+ }
+
+ if (!run_as_child)
+ std::cout << "*** 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() {
+ // The first thing to do is determine if we're running as a child. If we are,
+ // then what to do is very narrow. This form of invocation is only called
+ // from the runPasses method to actually run those passes in a child process.
+ if (run_as_child) {
+ // Execute the passes
+ return runPassesAsChild(PassesToRun);
+ }
+
+ 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);
+ }
+
+ // 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()) {
+ std::cout << "Running selected passes on program to test for crash: ";
+ if (runPasses(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.
+ std::cout << "Running the code generator to test for a crash: ";
+ try {
+ compileProgram(Program);
+ std::cout << '\n';
+ } catch (ToolExecutionError &TEE) {
+ std::cout << TEE.what();
+ return debugCodeGeneratorCrash();
+ }
+
+
+ // 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()) {
+ std::cout << "Generating reference output from raw program: ";
+ if(!createReferenceFile(Program)){
+ return debugCodeGeneratorCrash();
+ }
+ CreatedOutput = true;
+ }
+
+ // Make sure the reference output file gets deleted on exit from this
+ // function, if appropriate.
+ sys::Path ROF(ReferenceOutputFile);
+ FileRemover RemoverInstance(ROF, CreatedOutput);
+
+ // 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.
+ std::cout << "*** Checking the code generator...\n";
+ try {
+ if (!diffProgram()) {
+ std::cout << "\n*** Debugging miscompilation!\n";
+ return debugMiscompilation();
+ }
+ } catch (ToolExecutionError &TEE) {
+ std::cerr << TEE.what();
+ return debugCodeGeneratorCrash();
+ }
+
+ std::cout << "\n*** Input program does not match reference diff!\n";
+ std::cout << "Debugging code generator problem!\n";
+ try {
+ return debugCodeGenerator();
+ } catch (ToolExecutionError &TEE) {
+ std::cerr << TEE.what();
+ return debugCodeGeneratorCrash();
+ }
+}
+
+void llvm::PrintFunctionList(const std::vector<Function*> &Funcs) {
+ unsigned NumPrint = Funcs.size();
+ if (NumPrint > 10) NumPrint = 10;
+ for (unsigned i = 0; i != NumPrint; ++i)
+ std::cout << " " << Funcs[i]->getName();
+ if (NumPrint < Funcs.size())
+ std::cout << "... <" << Funcs.size() << " total>";
+ std::cout << std::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)
+ std::cout << " " << GVs[i]->getName();
+ if (NumPrint < GVs.size())
+ std::cout << "... <" << GVs.size() << " total>";
+ std::cout << std::flush;
+}
diff --git a/tools/bugpoint/BugDriver.h b/tools/bugpoint/BugDriver.h
new file mode 100644
index 0000000..96e9fb9
--- /dev/null
+++ b/tools/bugpoint/BugDriver.h
@@ -0,0 +1,322 @@
+//===- 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/DenseMap.h"
+#include <vector>
+#include <string>
+
+namespace llvm {
+
+class Value;
+class PassInfo;
+class Module;
+class GlobalVariable;
+class Function;
+class BasicBlock;
+class AbstractInterpreter;
+class Instruction;
+
+class DebugCrashes;
+
+class GCC;
+
+extern bool DisableSimplifyCFG;
+
+/// BugpointIsInterrupted - Set to true when the user presses ctrl-c.
+///
+extern bool BugpointIsInterrupted;
+
+class BugDriver {
+ const std::string ToolName; // Name of bugpoint
+ std::string ReferenceOutputFile; // Name of `good' output file
+ Module *Program; // The raw program, linked together
+ std::vector<const PassInfo*> PassesToRun;
+ AbstractInterpreter *Interpreter; // How to run the program
+ AbstractInterpreter *SafeInterpreter; // To generate reference output, etc.
+ GCC *gcc;
+ bool run_as_child;
+ bool run_find_bugs;
+ unsigned Timeout;
+ unsigned MemoryLimit;
+
+ // FIXME: sort out public/private distinctions...
+ friend class ReducePassList;
+ friend class ReduceMisCodegenFunctions;
+
+public:
+ BugDriver(const char *toolname, bool as_child, bool find_bugs,
+ unsigned timeout, unsigned memlimit);
+
+ const std::string &getToolName() const { return ToolName; }
+
+ // 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);
+ template<class It>
+ void addPasses(It I, It E) { PassesToRun.insert(PassesToRun.end(), I, E); }
+ void setPassesToRun(const std::vector<const PassInfo*> &PTR) {
+ PassesToRun = PTR;
+ }
+ const std::vector<const PassInfo*> &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();
+
+ /// 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();
+
+ /// debugMiscompilation - This method is used when the passes selected are not
+ /// crashing, but the generated output is semantically different from the
+ /// input.
+ bool debugMiscompilation();
+
+ /// 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);
+
+ /// 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();
+
+ /// 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 = 0) {
+ if (M == 0) M = Program;
+ std::swap(M, Program);
+ bool Result = runPasses(PassesToRun);
+ std::swap(M, Program);
+ return Result;
+ }
+
+ 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, throwing an
+ /// exception if an error occurs, or returning normally if not. This is used
+ /// for code generation crash testing.
+ ///
+ void compileProgram(Module *M);
+
+ /// 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. If there is a problem with the code
+ /// generator (e.g., llc crashes), this will throw an exception.
+ ///
+ std::string executeProgram(std::string RequestedOutputFilename = "",
+ std::string Bitcode = "",
+ const std::string &SharedObjects = "",
+ AbstractInterpreter *AI = 0,
+ bool *ProgramExitedNonzero = 0);
+
+ /// 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 throw an exception.
+ ///
+ std::string executeProgramSafely(std::string OutputFile = "");
+
+ /// 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, true is returned. If there is a problem with the code
+ /// generator (e.g., llc crashes), this will throw an exception.
+ ///
+ bool diffProgram(const std::string &BitcodeFile = "",
+ const std::string &SharedObj = "",
+ bool RemoveBitcode = false);
+
+ /// EmitProgressBitcode - This function is used to output the current Program
+ /// to a file named "bugpoint-ID.bc".
+ ///
+ void EmitProgressBitcode(const std::string &ID, bool NoFlyer = false);
+
+ /// 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)
+ const;
+
+ /// 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<const PassInfo*> &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
+ /// cout 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(const std::vector<const PassInfo*> &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<const PassInfo*> &AllPasses);
+
+ /// writeProgramToFile - This writes the current "Program" to the named
+ /// bitcode file. If an error occurs, true is returned.
+ ///
+ bool writeProgramToFile(const std::string &Filename, Module *M = 0) 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(const std::vector<const PassInfo*> &PassesToRun,
+ bool DeleteOutput = true) const {
+ std::string Filename;
+ return runPasses(PassesToRun, Filename, DeleteOutput);
+ }
+
+ /// runAsChild - The actual "runPasses" guts that runs in a child process.
+ int runPassesAsChild(const std::vector<const PassInfo*> &PassesToRun);
+
+ /// 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);
+
+
+/// 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<const PassInfo*> &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,
+ DenseMap<const Value*, Value*> &ValueMap);
+
+} // End llvm namespace
+
+#endif
diff --git a/tools/bugpoint/CMakeLists.txt b/tools/bugpoint/CMakeLists.txt
new file mode 100644
index 0000000..90f24ba
--- /dev/null
+++ b/tools/bugpoint/CMakeLists.txt
@@ -0,0 +1,16 @@
+set(LLVM_LINK_COMPONENTS asmparser instrumentation scalaropts ipo
+ linker bitreader bitwriter)
+set(LLVM_REQUIRES_EH 1)
+
+add_llvm_tool(bugpoint
+ BugDriver.cpp
+ CrashDebugger.cpp
+ ExecutionDriver.cpp
+ ExtractFunction.cpp
+ FindBugs.cpp
+ Miscompilation.cpp
+ OptimizerDriver.cpp
+ TestPasses.cpp
+ ToolRunner.cpp
+ bugpoint.cpp
+ )
diff --git a/tools/bugpoint/CrashDebugger.cpp b/tools/bugpoint/CrashDebugger.cpp
new file mode 100644
index 0000000..7daf57c
--- /dev/null
+++ b/tools/bugpoint/CrashDebugger.cpp
@@ -0,0 +1,648 @@
+//===- 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 <fstream>
+#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<const PassInfo*> {
+ 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<const PassInfo*> &Removed,
+ std::vector<const PassInfo*> &Kept);
+ };
+}
+
+ReducePassList::TestResult
+ReducePassList::doTest(std::vector<const PassInfo*> &Prefix,
+ std::vector<const PassInfo*> &Suffix) {
+ sys::Path PrefixOutput;
+ Module *OrigProgram = 0;
+ if (!Prefix.empty()) {
+ std::cout << "Checking to see if these passes crash: "
+ << getPassesString(Prefix) << ": ";
+ std::string PfxOutput;
+ if (BD.runPasses(Prefix, PfxOutput))
+ return KeepPrefix;
+
+ PrefixOutput.set(PfxOutput);
+ OrigProgram = BD.Program;
+
+ BD.Program = ParseInputFile(PrefixOutput.toString());
+ if (BD.Program == 0) {
+ std::cerr << BD.getToolName() << ": Error reading bitcode file '"
+ << PrefixOutput << "'!\n";
+ exit(1);
+ }
+ PrefixOutput.eraseFromDisk();
+ }
+
+ std::cout << "Checking to see if these passes crash: "
+ << getPassesString(Suffix) << ": ";
+
+ if (BD.runPasses(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)(BugDriver &, Module *);
+ public:
+ ReduceCrashingGlobalVariables(BugDriver &bd,
+ bool (*testFn)(BugDriver&, Module*))
+ : BD(bd), TestFn(testFn) {}
+
+ virtual TestResult doTest(std::vector<GlobalVariable*>& Prefix,
+ std::vector<GlobalVariable*>& Kept) {
+ 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...
+ DenseMap<const Value*, Value*> ValueMap;
+ Module *M = CloneModule(BD.getProgram(), ValueMap);
+
+ // 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>(ValueMap[GVs[i]]);
+ assert(CMGV && "Global Variable not in module?!");
+ GVSet.insert(CMGV);
+ }
+
+ std::cout << "Checking for crash with only these global variables: ";
+ PrintGlobalVariableList(GVs);
+ std::cout << ": ";
+
+ // 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)(BugDriver &, Module *);
+ public:
+ ReduceCrashingFunctions(BugDriver &bd,
+ bool (*testFn)(BugDriver &, Module *))
+ : BD(bd), TestFn(testFn) {}
+
+ virtual TestResult doTest(std::vector<Function*> &Prefix,
+ std::vector<Function*> &Kept) {
+ 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...
+ DenseMap<const Value*, Value*> ValueMap;
+ Module *M = CloneModule(BD.getProgram(), ValueMap);
+
+ // 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>(ValueMap[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);
+ }
+
+ std::cout << "Checking for crash with only these functions: ";
+ PrintFunctionList(Funcs);
+ std::cout << ": ";
+
+ // 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)(BugDriver &, Module *);
+ public:
+ ReduceCrashingBlocks(BugDriver &bd, bool (*testFn)(BugDriver &, Module *))
+ : BD(bd), TestFn(testFn) {}
+
+ virtual TestResult doTest(std::vector<const BasicBlock*> &Prefix,
+ std::vector<const BasicBlock*> &Kept) {
+ 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...
+ DenseMap<const Value*, Value*> ValueMap;
+ Module *M = CloneModule(BD.getProgram(), ValueMap);
+
+ // 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>(ValueMap[BBs[i]]));
+
+ std::cout << "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)
+ std::cout << " " << BBs[i]->getName();
+ if (NumPrint < Blocks.size())
+ std::cout << "... <" << Blocks.size() << " total>";
+ std::cout << ": ";
+
+ // 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 (isa<StructType>(BBTerm->getType()))
+ BBTerm->replaceAllUsesWith(UndefValue::get(BBTerm->getType()));
+ else if (BB->getTerminator()->getType() != Type::VoidTy)
+ BBTerm->replaceAllUsesWith(Constant::getNullValue(BBTerm->getType()));
+
+ // Replace the old terminator instruction.
+ BB->getInstList().pop_back();
+ new UnreachableInst(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<Function*, 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(), (*I)->getName()));
+
+ // Now run the CFG simplify pass on the function...
+ PassManager Passes;
+ Passes.add(createCFGSimplificationPass());
+ 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 basic block pointers that point into the now-current
+ // module, and that they don't include any deleted blocks.
+ BBs.clear();
+ for (unsigned i = 0, e = BlockInfo.size(); i != e; ++i) {
+ ValueSymbolTable &ST = BlockInfo[i].first->getValueSymbolTable();
+ Value* V = ST.lookup(BlockInfo[i].second);
+ if (V && V->getType() == Type::LabelTy)
+ 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)(BugDriver &, Module *);
+ public:
+ ReduceCrashingInstructions(BugDriver &bd, bool (*testFn)(BugDriver &,
+ Module *))
+ : BD(bd), TestFn(testFn) {}
+
+ virtual TestResult doTest(std::vector<const Instruction*> &Prefix,
+ std::vector<const Instruction*> &Kept) {
+ 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...
+ DenseMap<const Value*, Value*> ValueMap;
+ Module *M = CloneModule(BD.getProgram(), ValueMap);
+
+ // 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>(ValueMap[Insts[i]]));
+ }
+
+ std::cout << "Checking for crash with only " << Instructions.size();
+ if (Instructions.size() == 1)
+ std::cout << " instruction: ";
+ else
+ std::cout << " 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() != Type::VoidTy)
+ 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)(BugDriver &, Module *)) {
+ // 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...
+ std::cout << "\nChecking to see if we can delete global inits: ";
+
+ if (TestFn(BD, M)) { // Still crashes?
+ BD.setNewProgram(M);
+ std::cout << "\n*** Able to remove all global initializers!\n";
+ } else { // No longer crashes?
+ std::cout << " - 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) {
+ std::cout << "\n*** Attempting to reduce the number of global "
+ << "variables in the testcase\n";
+
+ unsigned OldSize = GVs.size();
+ ReduceCrashingGlobalVariables(BD, TestFn).reduceList(GVs);
+
+ if (GVs.size() < OldSize)
+ BD.EmitProgressBitcode("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) {
+ std::cout << "\n*** Attempting to reduce the number of functions "
+ "in the testcase\n";
+
+ unsigned OldSize = Functions.size();
+ ReduceCrashingFunctions(BD, TestFn).reduceList(Functions);
+
+ if (Functions.size() < OldSize)
+ BD.EmitProgressBitcode("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);
+ if (Blocks.size() < OldSize)
+ BD.EmitProgressBitcode("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);
+ }
+
+ // 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;
+ std::cout << "\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;
+
+ std::cout << "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) {
+ std::cout << "\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("reduced-simplified");
+
+ return false;
+}
+
+static bool TestForOptimizerCrash(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) {
+ std::cout << "\n*** Debugging optimizer crash!\n";
+
+ // Reduce the list of passes which causes the optimizer to crash...
+ if (!BugpointIsInterrupted)
+ ReducePassList(*this).reduceList(PassesToRun);
+
+ std::cout << "\n*** Found crashing pass"
+ << (PassesToRun.size() == 1 ? ": " : "es: ")
+ << getPassesString(PassesToRun) << '\n';
+
+ EmitProgressBitcode(ID);
+
+ return DebugACrash(*this, TestForOptimizerCrash);
+}
+
+static bool TestForCodeGenCrash(BugDriver &BD, Module *M) {
+ try {
+ BD.compileProgram(M);
+ std::cerr << '\n';
+ return false;
+ } catch (ToolExecutionError &) {
+ std::cerr << "<crash>\n";
+ return true; // Tool is still crashing.
+ }
+}
+
+/// 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::cerr << "*** Debugging code generator crash!\n";
+
+ return DebugACrash(*this, TestForCodeGenCrash);
+}
diff --git a/tools/bugpoint/ExecutionDriver.cpp b/tools/bugpoint/ExecutionDriver.cpp
new file mode 100644
index 0000000..640fe28
--- /dev/null
+++ b/tools/bugpoint/ExecutionDriver.cpp
@@ -0,0 +1,473 @@
+//===- 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 <fstream>
+#include <iostream>
+
+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, RunCBE, CBE_bug, LLC_Safe, Custom
+ };
+
+ cl::opt<double>
+ AbsTolerance("abs-tolerance", cl::desc("Absolute error tolerated"),
+ cl::init(0.0));
+ cl::opt<double>
+ RelTolerance("rel-tolerance", cl::desc("Relative error tolerated"),
+ cl::init(0.0));
+
+ cl::opt<OutputType>
+ InterpreterSel(cl::desc("Specify the \"test\" i.e. suspect back-end:"),
+ cl::values(clEnumValN(AutoPick, "auto", "Use best guess"),
+ clEnumValN(RunLLI, "run-int",
+ "Execute with the interpreter"),
+ clEnumValN(RunJIT, "run-jit", "Execute with JIT"),
+ clEnumValN(RunLLC, "run-llc", "Compile with LLC"),
+ clEnumValN(RunCBE, "run-cbe", "Compile with CBE"),
+ clEnumValN(CBE_bug,"cbe-bug", "Find CBE bugs"),
+ clEnumValN(LLC_Safe, "llc-safe", "Use LLC for all"),
+ clEnumValN(Custom, "run-custom",
+ "Use -exec-command to define a command to execute "
+ "the bitcode. Useful for cross-compilation."),
+ clEnumValEnd),
+ cl::init(AutoPick));
+
+ cl::opt<OutputType>
+ SafeInterpreterSel(cl::desc("Specify \"safe\" i.e. known-good backend:"),
+ cl::values(clEnumValN(AutoPick, "safe-auto", "Use best guess"),
+ clEnumValN(RunLLC, "safe-run-llc", "Compile with LLC"),
+ clEnumValN(RunCBE, "safe-run-cbe", "Compile with CBE"),
+ clEnumValN(Custom, "safe-run-custom",
+ "Use -exec-command to define a command to execute "
+ "the bitcode. Useful for cross-compilation."),
+ clEnumValEnd),
+ cl::init(AutoPick));
+
+ cl::opt<std::string>
+ SafeInterpreterPath("safe-path",
+ cl::desc("Specify the path to the \"safe\" backend program"),
+ cl::init(""));
+
+ cl::opt<bool>
+ AppendProgramExitCode("append-exit-code",
+ cl::desc("Append the exit code to the output so it gets diff'd too"),
+ cl::init(false));
+
+ cl::opt<std::string>
+ InputFile("input", cl::init("/dev/null"),
+ cl::desc("Filename to pipe in as stdin (default: /dev/null)"));
+
+ cl::list<std::string>
+ AdditionalSOs("additional-so",
+ cl::desc("Additional shared objects to load "
+ "into executing programs"));
+
+ cl::list<std::string>
+ AdditionalLinkerArgs("Xlinker",
+ cl::desc("Additional arguments to pass to the linker"));
+
+ cl::opt<std::string>
+ CustomExecCommand("exec-command", cl::init("simulate"),
+ cl::desc("Command to execute the bitcode (use with -run-custom) "
+ "(default: simulate)"));
+}
+
+namespace llvm {
+ // Anything specified after the --args option are taken as arguments to the
+ // program being debugged.
+ cl::list<std::string>
+ InputArgv("args", cl::Positional, cl::desc("<program arguments>..."),
+ cl::ZeroOrMore, cl::PositionalEatsArgs);
+}
+
+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::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() {
+ std::cout << "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, &ToolArgv,
+ &GCCToolArgv);
+ if (!Interpreter) {
+ InterpreterSel = RunJIT;
+ Interpreter = AbstractInterpreter::createJIT(getToolName(), Message,
+ &ToolArgv);
+ }
+ if (!Interpreter) {
+ InterpreterSel = RunLLC;
+ Interpreter = AbstractInterpreter::createLLC(getToolName(), Message,
+ &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 LLC_Safe:
+ Interpreter = AbstractInterpreter::createLLC(getToolName(), Message,
+ &ToolArgv, &GCCToolArgv);
+ break;
+ case RunJIT:
+ Interpreter = AbstractInterpreter::createJIT(getToolName(), Message,
+ &ToolArgv);
+ break;
+ case RunCBE:
+ case CBE_bug:
+ Interpreter = AbstractInterpreter::createCBE(getToolName(), Message,
+ &ToolArgv, &GCCToolArgv);
+ break;
+ case Custom:
+ Interpreter = AbstractInterpreter::createCustom(getToolName(), Message,
+ CustomExecCommand);
+ break;
+ default:
+ Message = "Sorry, this back-end is not supported by bugpoint right now!\n";
+ break;
+ }
+ if (!Interpreter)
+ std::cerr << Message;
+ else // Display informational messages on stdout instead of stderr
+ std::cout << 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, Message,
+ &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, Message,
+ &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, Message,
+ &SafeToolArgs,
+ &GCCToolArgv);
+ }
+ if (!SafeInterpreter &&
+ InterpreterSel != RunLLC &&
+ InterpreterSel != RunJIT) {
+ SafeInterpreterSel = RunLLC;
+ SafeToolArgs.push_back("--relocation-model=pic");
+ SafeInterpreter = AbstractInterpreter::createLLC(Path, Message,
+ &SafeToolArgs,
+ &GCCToolArgv);
+ }
+ if (!SafeInterpreter) {
+ SafeInterpreterSel = AutoPick;
+ Message = "Sorry, I can't automatically select an interpreter!\n";
+ }
+ break;
+ case RunLLC:
+ SafeToolArgs.push_back("--relocation-model=pic");
+ SafeInterpreter = AbstractInterpreter::createLLC(Path, Message,
+ &SafeToolArgs,
+ &GCCToolArgv);
+ break;
+ case RunCBE:
+ SafeInterpreter = AbstractInterpreter::createCBE(Path, Message,
+ &SafeToolArgs,
+ &GCCToolArgv);
+ break;
+ case Custom:
+ SafeInterpreter = AbstractInterpreter::createCustom(Path, Message,
+ CustomExecCommand);
+ break;
+ default:
+ Message = "Sorry, this back-end is not supported by bugpoint as the "
+ "\"safe\" backend right now!\n";
+ break;
+ }
+ if (!SafeInterpreter) { std::cout << Message << "\nExiting.\n"; exit(1); }
+
+ gcc = GCC::create(getToolName(), Message, &GCCToolArgv);
+ if (!gcc) { std::cout << 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, throwing an exception
+/// if an error occurs, or returning normally if not. This is used for code
+/// generation crash testing.
+///
+void BugDriver::compileProgram(Module *M) {
+ // Emit the program to a bitcode file...
+ sys::Path BitcodeFile ("bugpoint-test-program.bc");
+ std::string ErrMsg;
+ if (BitcodeFile.makeUnique(true,&ErrMsg)) {
+ std::cerr << ToolName << ": Error making unique filename: " << ErrMsg
+ << "\n";
+ exit(1);
+ }
+ if (writeProgramToFile(BitcodeFile.toString(), M)) {
+ std::cerr << ToolName << ": Error emitting bitcode to file '"
+ << BitcodeFile << "'!\n";
+ exit(1);
+ }
+
+ // Remove the temporary bitcode file when we are done.
+ FileRemover BitcodeFileRemover(BitcodeFile);
+
+ // Actually compile the program!
+ Interpreter->compileProgram(BitcodeFile.toString());
+}
+
+
+/// 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(std::string OutputFile,
+ std::string BitcodeFile,
+ const std::string &SharedObj,
+ AbstractInterpreter *AI,
+ bool *ProgramExitedNonzero) {
+ 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("bugpoint-test-program.bc");
+ if (uniqueFilename.makeUnique(true, &ErrMsg)) {
+ std::cerr << ToolName << ": Error making unique filename: "
+ << ErrMsg << "!\n";
+ exit(1);
+ }
+ BitcodeFile = uniqueFilename.toString();
+
+ if (writeProgramToFile(BitcodeFile, Program)) {
+ std::cerr << ToolName << ": Error emitting bitcode to file '"
+ << BitcodeFile << "'!\n";
+ exit(1);
+ }
+ CreatedBitcode = true;
+ }
+
+ // Remove the temporary bitcode file when we are done.
+ sys::Path BitcodePath (BitcodeFile);
+ FileRemover BitcodeFileRemover(BitcodePath, CreatedBitcode);
+
+ if (OutputFile.empty()) OutputFile = "bugpoint-execution-output";
+
+ // Check to see if this is a valid output filename...
+ sys::Path uniqueFile(OutputFile);
+ if (uniqueFile.makeUnique(true, &ErrMsg)) {
+ std::cerr << ToolName << ": Error making unique filename: "
+ << ErrMsg << "\n";
+ exit(1);
+ }
+ OutputFile = uniqueFile.toString();
+
+ // 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, AdditionalLinkerArgs, SharedObjs,
+ Timeout, MemoryLimit);
+
+ if (RetVal == -1) {
+ std::cerr << "<timeout>";
+ static bool FirstTimeout = true;
+ if (FirstTimeout) {
+ std::cout << "\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();
+ }
+
+ if (ProgramExitedNonzero != 0)
+ *ProgramExitedNonzero = (RetVal != 0);
+
+ // 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(std::string OutputFile) {
+ bool ProgramExitedNonzero;
+ std::string outFN = executeProgram(OutputFile, "", "", SafeInterpreter,
+ &ProgramExitedNonzero);
+ return outFN;
+}
+
+std::string BugDriver::compileSharedObject(const std::string &BitcodeFile) {
+ assert(Interpreter && "Interpreter should have been created already!");
+ sys::Path OutputFile;
+
+ // Using the known-good backend.
+ GCC::FileType FT = SafeInterpreter->OutputCode(BitcodeFile, OutputFile);
+
+ std::string SharedObjectFile;
+ if (gcc->MakeSharedObject(OutputFile.toString(), FT,
+ SharedObjectFile, AdditionalLinkerArgs))
+ 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) {
+ try {
+ compileProgram(Program);
+ } catch (ToolExecutionError &) {
+ return false;
+ }
+ try {
+ ReferenceOutputFile = executeProgramSafely(Filename);
+ std::cout << "\nReference output is: " << ReferenceOutputFile << "\n\n";
+ } catch (ToolExecutionError &TEE) {
+ std::cerr << TEE.what();
+ if (Interpreter != SafeInterpreter) {
+ std::cerr << "*** 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;
+ }
+ return true;
+}
+
+/// diffProgram - This method executes the specified module and diffs the
+/// output against the file specified by ReferenceOutputFile. If the output
+/// is different, true is returned. If there is a problem with the code
+/// generator (e.g., llc crashes), this will throw an exception.
+///
+bool BugDriver::diffProgram(const std::string &BitcodeFile,
+ const std::string &SharedObject,
+ bool RemoveBitcode) {
+ bool ProgramExitedNonzero;
+
+ // Execute the program, generating an output file...
+ sys::Path Output(executeProgram("", BitcodeFile, SharedObject, 0,
+ &ProgramExitedNonzero));
+
+ std::string Error;
+ bool FilesDifferent = false;
+ if (int Diff = DiffFilesWithTolerance(sys::Path(ReferenceOutputFile),
+ sys::Path(Output.toString()),
+ AbsTolerance, RelTolerance, &Error)) {
+ if (Diff == 2) {
+ std::cerr << "While diffing output: " << Error << '\n';
+ exit(1);
+ }
+ FilesDifferent = true;
+ }
+
+ // Remove the generated output.
+ 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/tools/bugpoint/ExtractFunction.cpp b/tools/bugpoint/ExtractFunction.cpp
new file mode 100644
index 0000000..e4affbb
--- /dev/null
+++ b/tools/bugpoint/ExtractFunction.cpp
@@ -0,0 +1,375 @@
+//===- 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/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Pass.h"
+#include "llvm/Analysis/Verifier.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/System/Path.h"
+#include "llvm/System/Signals.h"
+#include <set>
+#include <fstream>
+#include <iostream>
+using namespace llvm;
+
+namespace llvm {
+ bool DisableSimplifyCFG = false;
+} // 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) const {
+ Module *Result = CloneModule(Program);
+
+ const BasicBlock *PBB = I->getParent();
+ const Function *PF = PBB->getParent();
+
+ Module::iterator RFI = Result->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 (isa<StructType>(TheInst->getType()))
+ TheInst->replaceAllUsesWith(UndefValue::get(TheInst->getType()));
+ else if (TheInst->getType() != Type::VoidTy)
+ TheInst->replaceAllUsesWith(Constant::getNullValue(TheInst->getType()));
+
+ // Remove the instruction from the program.
+ TheInst->getParent()->getInstList().erase(TheInst);
+
+
+ //writeProgramToFile("current.bc", Result);
+
+ // Spiff up the output a little bit.
+ PassManager Passes;
+ // Make sure that the appropriate target data is always used...
+ Passes.add(new TargetData(Result));
+
+ /// FIXME: If this used runPasses() like the methods below, we could get rid
+ /// of the -disable-* options!
+ if (Simplification > 1 && !NoDCE)
+ Passes.add(createDeadCodeEliminationPass());
+ if (Simplification && !DisableSimplifyCFG)
+ Passes.add(createCFGSimplificationPass()); // Delete dead control flow
+
+ Passes.add(createVerifierPass());
+ Passes.run(*Result);
+ return Result;
+}
+
+static const PassInfo *getPI(Pass *P) {
+ const PassInfo *PI = P->getPassInfo();
+ delete P;
+ return PI;
+}
+
+/// 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<const PassInfo*> CleanupPasses;
+ CleanupPasses.push_back(getPI(createGlobalDCEPass()));
+ CleanupPasses.push_back(getPI(createDeadTypeEliminationPass()));
+
+ if (MayModifySemantics)
+ CleanupPasses.push_back(getPI(createDeadArgHackingPass()));
+ else
+ CleanupPasses.push_back(getPI(createDeadArgEliminationPass()));
+
+ Module *New = runPassesOn(M, CleanupPasses);
+ if (New == 0) {
+ std::cerr << "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<const PassInfo*> LoopExtractPasses;
+ LoopExtractPasses.push_back(getPI(createSingleLoopExtractorPass()));
+
+ Module *NewM = runPassesOn(M, LoopExtractPasses);
+ if (NewM == 0) {
+ Module *Old = swapProgramIn(M);
+ std::cout << "*** Loop extraction failed: ";
+ EmitProgressBitcode("loopextraction", true);
+ std::cout << "*** Sorry. :( Please report a bug!\n";
+ swapProgramIn(Old);
+ return 0;
+ }
+
+ // Check to see if we created any new functions. If not, no loops were
+ // extracted and we should return null. Limit the number of loops we extract
+ // to avoid taking forever.
+ static unsigned NumExtracted = 32;
+ if (M->size() == NewM->size() || --NumExtracted == 0) {
+ delete NewM;
+ return 0;
+ } else {
+ assert(M->size() < NewM->size() && "Loop extract removed functions?");
+ Module::iterator MI = NewM->begin();
+ for (unsigned i = 0, e = M->size(); i != e; ++i)
+ ++MI;
+ }
+
+ return NewM;
+}
+
+
+// DeleteFunctionBody - "Remove" the function by deleting all of its basic
+// blocks, making it external.
+//
+void llvm::DeleteFunctionBody(Function *F) {
+ // delete the body of the function...
+ F->deleteBody();
+ assert(F->isDeclaration() && "This didn't make the function external!");
+}
+
+/// GetTorInit - Given a list of entries for static ctors/dtors, return them
+/// as a constant array.
+static Constant *GetTorInit(std::vector<std::pair<Function*, int> > &TorList) {
+ assert(!TorList.empty() && "Don't create empty tor list!");
+ std::vector<Constant*> ArrayElts;
+ for (unsigned i = 0, e = TorList.size(); i != e; ++i) {
+ std::vector<Constant*> Elts;
+ Elts.push_back(ConstantInt::get(Type::Int32Ty, TorList[i].second));
+ Elts.push_back(TorList[i].first);
+ ArrayElts.push_back(ConstantStruct::get(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,
+ DenseMap<const Value*, Value*> ValueMap) {
+ 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>(ValueMap[F]);
+ M2Tors.push_back(std::make_pair(F, Priority));
+ }
+ }
+ }
+ }
+
+ GV->eraseFromParent();
+ if (!M1Tors.empty()) {
+ Constant *M1Init = GetTorInit(M1Tors);
+ new GlobalVariable(M1Init->getType(), false, GlobalValue::AppendingLinkage,
+ M1Init, GlobalName, M1);
+ }
+
+ 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(M2Init->getType(), false, GlobalValue::AppendingLinkage,
+ M2Init, GlobalName, M2);
+ }
+}
+
+
+/// 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,
+ DenseMap<const Value*, Value*> &ValueMap) {
+ // 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->getNameStart() == '\01')
+ I->setName(I->getNameStart()+1, I->getNameLen()-1);
+ I->setLinkage(GlobalValue::ExternalLinkage);
+ }
+
+ DenseMap<const Value*, Value*> NewValueMap;
+ Module *New = CloneModule(M, NewValueMap);
+
+ // 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>(ValueMap[F[i]]);
+ DEBUG(std::cerr << "Removing function ");
+ DEBUG(WriteAsOperand(std::cerr, TNOF, false));
+ DEBUG(std::cerr << "\n");
+ TestFunctions.insert(cast<Function>(NewValueMap[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, NewValueMap);
+ SplitStaticCtorDtor("llvm.global_dtors", M, New, NewValueMap);
+
+ 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) {
+ char *ExtraArg = NULL;
+
+ sys::Path uniqueFilename("bugpoint-extractblocks");
+ std::string ErrMsg;
+ if (uniqueFilename.createTemporaryFileOnDisk(true, &ErrMsg)) {
+ std::cout << "*** Basic Block extraction failed!\n";
+ std::cerr << "Error creating temporary file: " << ErrMsg << "\n";
+ M = swapProgramIn(M);
+ EmitProgressBitcode("basicblockextractfail", true);
+ swapProgramIn(M);
+ return 0;
+ }
+ sys::RemoveFileOnSignal(uniqueFilename);
+
+ std::ofstream BlocksToNotExtractFile(uniqueFilename.c_str());
+ if (!BlocksToNotExtractFile) {
+ std::cout << "*** Basic Block extraction failed!\n";
+ std::cerr << "Error writing list of blocks to not extract: " << ErrMsg
+ << "\n";
+ M = swapProgramIn(M);
+ EmitProgressBitcode("basicblockextractfail", true);
+ swapProgramIn(M);
+ 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 << BB->getParent()->getName() << " "
+ << BB->getName() << "\n";
+ }
+ BlocksToNotExtractFile.close();
+
+ const char *uniqueFN = uniqueFilename.c_str();
+ ExtraArg = (char*)malloc(23 + strlen(uniqueFN));
+ strcat(strcpy(ExtraArg, "--extract-blocks-file="), uniqueFN);
+
+ std::vector<const PassInfo*> PI;
+ std::vector<BasicBlock *> EmptyBBs; // This parameter is ignored.
+ PI.push_back(getPI(createBlockExtractorPass(EmptyBBs)));
+ Module *Ret = runPassesOn(M, PI, false, 1, &ExtraArg);
+
+ if (uniqueFilename.exists())
+ uniqueFilename.eraseFromDisk(); // Free disk space
+ free(ExtraArg);
+
+ if (Ret == 0) {
+ std::cout << "*** Basic Block extraction failed, please report a bug!\n";
+ M = swapProgramIn(M);
+ EmitProgressBitcode("basicblockextractfail", true);
+ swapProgramIn(M);
+ }
+ return Ret;
+}
diff --git a/tools/bugpoint/FindBugs.cpp b/tools/bugpoint/FindBugs.cpp
new file mode 100644
index 0000000..e42cce4
--- /dev/null
+++ b/tools/bugpoint/FindBugs.cpp
@@ -0,0 +1,112 @@
+//===-- 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 <algorithm>
+#include <ctime>
+#include <iostream>
+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<const PassInfo*> &AllPasses) {
+ setPassesToRun(AllPasses);
+ std::cout << "Starting bug finding procedure...\n\n";
+
+ // Creating a reference output if necessary
+ if (initializeExecutionEnvironment()) return false;
+
+ std::cout << "\n";
+ if (ReferenceOutputFile.empty()) {
+ std::cout << "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.
+ //
+ std::cout << "Running selected passes on program to test for crash: ";
+ for(int i = 0, e = PassesToRun.size(); i != e; i++) {
+ std::cout << "-" << PassesToRun[i]->getPassArgument( )<< " ";
+ }
+
+ std::string Filename;
+ if(runPasses(PassesToRun, Filename, false)) {
+ std::cout << "\n";
+ std::cout << "Optimizer passes caused failure!\n\n";
+ debugOptimizerCrash();
+ return true;
+ } else {
+ std::cout << "Combination " << num << " optimized successfully!\n";
+ }
+
+ //
+ // Step 3: Compile the optimized code.
+ //
+ std::cout << "Running the code generator to test for a crash: ";
+ try {
+ compileProgram(Program);
+ std::cout << '\n';
+ } catch (ToolExecutionError &TEE) {
+ std::cout << "\n*** compileProgram threw an exception: ";
+ std::cout << TEE.what();
+ return debugCodeGeneratorCrash();
+ }
+
+ //
+ // Step 4: Run the program and compare its output to the reference
+ // output (created above).
+ //
+ std::cout << "*** Checking if passes caused miscompliation:\n";
+ try {
+ if (diffProgram(Filename, "", false)) {
+ std::cout << "\n*** diffProgram returned true!\n";
+ debugMiscompilation();
+ return true;
+ } else {
+ std::cout << "\n*** diff'd output matches!\n";
+ }
+ } catch (ToolExecutionError &TEE) {
+ std::cerr << TEE.what();
+ debugCodeGeneratorCrash();
+ return true;
+ }
+
+ sys::Path(Filename).eraseFromDisk();
+
+ std::cout << "\n\n";
+ num++;
+ } //end while
+
+ // Unreachable.
+}
diff --git a/tools/bugpoint/ListReducer.h b/tools/bugpoint/ListReducer.h
new file mode 100644
index 0000000..de3f389
--- /dev/null
+++ b/tools/bugpoint/ListReducer.h
@@ -0,0 +1,189 @@
+//===- 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 <vector>
+#include <iostream>
+#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
+ };
+
+ 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) = 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::vector<ElTy> empty;
+ std::srand(0x6e5ea738); // Seed the random number generator
+ switch (doTest(TheList, empty)) {
+ 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!
+ std::cerr << "bugpoint ListReducer internal error: selected empty set.\n";
+ abort();
+
+ case NoFailure:
+ return false; // there is no failure with the full set of passes/funcs!
+ }
+
+ // 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) {
+ std::cerr << "\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());
+ std::cerr << "\n\n*** Testing shuffled set...\n\n";
+ // Check that random shuffle doesn't loose the bug
+ if (doTest(ShuffledList, empty) == 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;
+ std::cerr << "\n\n*** Shuffling does not hide the bug...\n\n";
+ } else {
+ ShufflingEnabled = false; // Disable shuffling further on
+ std::cerr << "\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)) {
+ 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;
+ }
+ }
+
+ // 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) {
+ std::cerr << "\n\n*** Reduction Interrupted, cleaning up...\n\n";
+ return true;
+ }
+
+ std::vector<ElTy> TestList(TheList);
+ TestList.erase(TestList.begin()+i);
+
+ if (doTest(EmptyList, TestList) == KeepSuffix) {
+ // We can trim down the list!
+ TheList.swap(TestList);
+ --i; // Don't skip an element of the list
+ Changed = 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/tools/bugpoint/Makefile b/tools/bugpoint/Makefile
new file mode 100644
index 0000000..b821b6c
--- /dev/null
+++ b/tools/bugpoint/Makefile
@@ -0,0 +1,17 @@
+##===- 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
+REQUIRES_EH := 1
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp
new file mode 100644
index 0000000..7e8ff78
--- /dev/null
+++ b/tools/bugpoint/Miscompilation.cpp
@@ -0,0 +1,932 @@
+//===- 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 "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/Support/Mangler.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::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));
+
+ class ReduceMiscompilingPasses : public ListReducer<const PassInfo*> {
+ BugDriver &BD;
+ public:
+ ReduceMiscompilingPasses(BugDriver &bd) : BD(bd) {}
+
+ virtual TestResult doTest(std::vector<const PassInfo*> &Prefix,
+ std::vector<const PassInfo*> &Suffix);
+ };
+}
+
+/// 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<const PassInfo*> &Prefix,
+ std::vector<const PassInfo*> &Suffix) {
+ // First, run the program with just the Suffix passes. If it is still broken
+ // with JUST the kept passes, discard the prefix passes.
+ std::cout << "Checking to see if '" << getPassesString(Suffix)
+ << "' compile correctly: ";
+
+ std::string BitcodeResult;
+ if (BD.runPasses(Suffix, BitcodeResult, false/*delete*/, true/*quiet*/)) {
+ std::cerr << " Error running this sequence of passes"
+ << " on the input program!\n";
+ BD.setPassesToRun(Suffix);
+ BD.EmitProgressBitcode("pass-error", false);
+ exit(BD.debugOptimizerCrash());
+ }
+
+ // Check to see if the finished program matches the reference output...
+ if (BD.diffProgram(BitcodeResult, "", true /*delete bitcode*/)) {
+ std::cout << " nope.\n";
+ if (Suffix.empty()) {
+ std::cerr << BD.getToolName() << ": I'm confused: the test fails when "
+ << "no passes are run, nondeterministic program?\n";
+ exit(1);
+ }
+ return KeepSuffix; // Miscompilation detected!
+ }
+ std::cout << " 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.
+ std::cout << "Checking to see if '" << getPassesString(Prefix)
+ << "' compile 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(Prefix, BitcodeResult, false/*delete*/, true/*quiet*/)) {
+ std::cerr << " Error running this sequence of passes"
+ << " on the input program!\n";
+ BD.setPassesToRun(Prefix);
+ BD.EmitProgressBitcode("pass-error", false);
+ exit(BD.debugOptimizerCrash());
+ }
+
+ // If the prefix maintains the predicate by itself, only keep the prefix!
+ if (BD.diffProgram(BitcodeResult)) {
+ std::cout << " nope.\n";
+ sys::Path(BitcodeResult).eraseFromDisk();
+ return KeepPrefix;
+ }
+ std::cout << " 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.
+ //
+ Module *PrefixOutput = ParseInputFile(BitcodeResult);
+ if (PrefixOutput == 0) {
+ std::cerr << 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;
+
+ std::cout << "Checking to see if '" << getPassesString(Suffix)
+ << "' passes compile correctly after the '"
+ << getPassesString(Prefix) << "' passes: ";
+
+ Module *OriginalInput = BD.swapProgramIn(PrefixOutput);
+ if (BD.runPasses(Suffix, BitcodeResult, false/*delete*/, true/*quiet*/)) {
+ std::cerr << " Error running this sequence of passes"
+ << " on the input program!\n";
+ BD.setPassesToRun(Suffix);
+ BD.EmitProgressBitcode("pass-error", false);
+ exit(BD.debugOptimizerCrash());
+ }
+
+ // Run the result...
+ if (BD.diffProgram(BitcodeResult, "", true/*delete bitcode*/)) {
+ std::cout << " nope.\n";
+ delete OriginalInput; // We pruned down the original input...
+ return KeepSuffix;
+ }
+
+ // Otherwise, we must not be running the bad pass anymore.
+ std::cout << " yup.\n"; // No miscompilation!
+ delete BD.swapProgramIn(OriginalInput); // Restore orig program & free test
+ return NoFailure;
+}
+
+namespace {
+ class ReduceMiscompilingFunctions : public ListReducer<Function*> {
+ BugDriver &BD;
+ bool (*TestFn)(BugDriver &, Module *, Module *);
+ public:
+ ReduceMiscompilingFunctions(BugDriver &bd,
+ bool (*F)(BugDriver &, Module *, Module *))
+ : BD(bd), TestFn(F) {}
+
+ virtual TestResult doTest(std::vector<Function*> &Prefix,
+ std::vector<Function*> &Suffix) {
+ if (!Suffix.empty() && TestFuncs(Suffix))
+ return KeepSuffix;
+ if (!Prefix.empty() && TestFuncs(Prefix))
+ return KeepPrefix;
+ return NoFailure;
+ }
+
+ bool TestFuncs(const std::vector<Function*> &Prefix);
+ };
+}
+
+/// TestMergedProgram - Given two modules, link them together and run the
+/// program, checking to see if the program matches the diff. If the diff
+/// matches, return false, otherwise return true. If the DeleteInputs argument
+/// is set to true then this function deletes both input modules before it
+/// returns.
+///
+static bool TestMergedProgram(BugDriver &BD, Module *M1, Module *M2,
+ bool DeleteInputs) {
+ // Link the two portions of the program back to together.
+ std::string ErrorMsg;
+ if (!DeleteInputs) {
+ M1 = CloneModule(M1);
+ M2 = CloneModule(M2);
+ }
+ if (Linker::LinkModules(M1, M2, &ErrorMsg)) {
+ std::cerr << BD.getToolName() << ": Error linking modules together:"
+ << ErrorMsg << '\n';
+ exit(1);
+ }
+ delete M2; // We are done with this module.
+
+ Module *OldProgram = BD.swapProgramIn(M1);
+
+ // Execute the program. If it does not match the expected output, we must
+ // return true.
+ bool Broken = BD.diffProgram();
+
+ // Delete the linked module & restore the original
+ BD.swapProgramIn(OldProgram);
+ delete M1;
+ return Broken;
+}
+
+/// 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){
+ // Test to see if the function is misoptimized if we ONLY run it on the
+ // functions listed in Funcs.
+ std::cout << "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);
+ std::cout << '\n';
+
+ // Split the module into the two halves of the program we want.
+ DenseMap<const Value*, Value*> ValueMap;
+ Module *ToNotOptimize = CloneModule(BD.getProgram(), ValueMap);
+ Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, Funcs,
+ ValueMap);
+
+ // Run the predicate, note that the predicate will delete both input modules.
+ return TestFn(BD, ToOptimize, ToNotOptimize);
+}
+
+/// DisambiguateGlobalSymbols - Mangle symbols to guarantee uniqueness by
+/// modifying predominantly internal symbols rather than external ones.
+///
+static void DisambiguateGlobalSymbols(Module *M) {
+ // Try not to cause collisions by minimizing chances of renaming an
+ // already-external symbol, so take in external globals and functions as-is.
+ // The code should work correctly without disambiguation (assuming the same
+ // mangler is used by the two code generators), but having symbols with the
+ // same name causes warnings to be emitted by the code generator.
+ Mangler Mang(*M);
+ // Agree with the CBE on symbol naming
+ Mang.markCharUnacceptable('.');
+ Mang.setPreserveAsmNames(true);
+ for (Module::global_iterator I = M->global_begin(), E = M->global_end();
+ I != E; ++I)
+ I->setName(Mang.getValueName(I));
+ for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
+ I->setName(Mang.getValueName(I));
+}
+
+/// 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::vector<Function*> &MiscompiledFunctions) {
+ bool MadeChange = false;
+ while (1) {
+ if (BugpointIsInterrupted) return MadeChange;
+
+ DenseMap<const Value*, Value*> ValueMap;
+ Module *ToNotOptimize = CloneModule(BD.getProgram(), ValueMap);
+ Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize,
+ MiscompiledFunctions,
+ ValueMap);
+ 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;
+ }
+
+ std::cerr << "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();
+ if (TestMergedProgram(BD, ToOptimizeLoopExtracted, ToNotOptimize, false)) {
+ BD.switchToInterpreter(AI);
+
+ // Merged program doesn't work anymore!
+ std::cerr << " *** ERROR: Loop extraction broke the program. :("
+ << " Please report a bug!\n";
+ std::cerr << " Continuing on with un-loop-extracted version.\n";
+
+ BD.writeProgramToFile("bugpoint-loop-extract-fail-tno.bc", ToNotOptimize);
+ BD.writeProgramToFile("bugpoint-loop-extract-fail-to.bc", ToOptimize);
+ BD.writeProgramToFile("bugpoint-loop-extract-fail-to-le.bc",
+ ToOptimizeLoopExtracted);
+
+ std::cerr << "Please submit the bugpoint-loop-extract-fail-*.bc files.\n";
+ delete ToOptimize;
+ delete ToNotOptimize;
+ delete ToOptimizeLoopExtracted;
+ return MadeChange;
+ }
+ delete ToOptimize;
+ BD.switchToInterpreter(AI);
+
+ std::cout << " Testing after loop extraction:\n";
+ // Clone modules, the tester function will free them.
+ Module *TOLEBackup = CloneModule(ToOptimizeLoopExtracted);
+ Module *TNOBackup = CloneModule(ToNotOptimize);
+ if (!TestFn(BD, ToOptimizeLoopExtracted, ToNotOptimize)) {
+ std::cout << "*** 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;
+
+ std::cout << "*** Loop extraction successful!\n";
+
+ std::vector<std::pair<std::string, const FunctionType*> > MisCompFunctions;
+ for (Module::iterator I = ToOptimizeLoopExtracted->begin(),
+ E = ToOptimizeLoopExtracted->end(); I != E; ++I)
+ if (!I->isDeclaration())
+ MisCompFunctions.push_back(std::make_pair(I->getName(),
+ I->getFunctionType()));
+
+ // Okay, great! Now we know that we extracted a loop and that loop
+ // extraction both didn't break the program, and didn't mask the problem.
+ // Replace the current program with the loop extracted version, and try to
+ // extract another loop.
+ std::string ErrorMsg;
+ if (Linker::LinkModules(ToNotOptimize, ToOptimizeLoopExtracted, &ErrorMsg)){
+ std::cerr << BD.getToolName() << ": Error linking modules together:"
+ << ErrorMsg << '\n';
+ exit(1);
+ }
+ delete ToOptimizeLoopExtracted;
+
+ // All of the Function*'s in the MiscompiledFunctions list are in the old
+ // module. Update this list to include all of the functions in the
+ // optimized and loop extracted module.
+ MiscompiledFunctions.clear();
+ for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) {
+ Function *NewF = ToNotOptimize->getFunction(MisCompFunctions[i].first);
+
+ assert(NewF && "Function not found??");
+ assert(NewF->getFunctionType() == MisCompFunctions[i].second &&
+ "found wrong function type?");
+ MiscompiledFunctions.push_back(NewF);
+ }
+
+ BD.setNewProgram(ToNotOptimize);
+ MadeChange = true;
+ }
+}
+
+namespace {
+ class ReduceMiscompiledBlocks : public ListReducer<BasicBlock*> {
+ BugDriver &BD;
+ bool (*TestFn)(BugDriver &, Module *, Module *);
+ std::vector<Function*> FunctionsBeingTested;
+ public:
+ ReduceMiscompiledBlocks(BugDriver &bd,
+ bool (*F)(BugDriver &, Module *, Module *),
+ const std::vector<Function*> &Fns)
+ : BD(bd), TestFn(F), FunctionsBeingTested(Fns) {}
+
+ virtual TestResult doTest(std::vector<BasicBlock*> &Prefix,
+ std::vector<BasicBlock*> &Suffix) {
+ if (!Suffix.empty() && TestFuncs(Suffix))
+ return KeepSuffix;
+ if (TestFuncs(Prefix))
+ return KeepPrefix;
+ return NoFailure;
+ }
+
+ bool TestFuncs(const std::vector<BasicBlock*> &Prefix);
+ };
+}
+
+/// 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) {
+ // Test to see if the function is misoptimized if we ONLY run it on the
+ // functions listed in Funcs.
+ std::cout << "Checking to see if the program is misoptimized when all ";
+ if (!BBs.empty()) {
+ std::cout << "but these " << BBs.size() << " blocks are extracted: ";
+ for (unsigned i = 0, e = BBs.size() < 10 ? BBs.size() : 10; i != e; ++i)
+ std::cout << BBs[i]->getName() << " ";
+ if (BBs.size() > 10) std::cout << "...";
+ } else {
+ std::cout << "blocks are extracted.";
+ }
+ std::cout << '\n';
+
+ // Split the module into the two halves of the program we want.
+ DenseMap<const Value*, Value*> ValueMap;
+ Module *ToNotOptimize = CloneModule(BD.getProgram(), ValueMap);
+ Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize,
+ FunctionsBeingTested,
+ ValueMap);
+
+ // 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(BBs, ToOptimize)) {
+ delete ToOptimize;
+ // Run the predicate, not that the predicate will delete both input modules.
+ return TestFn(BD, New, ToNotOptimize);
+ }
+ 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::vector<Function*> &MiscompiledFunctions) {
+ 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.
+ if (ReduceMiscompiledBlocks(BD, TestFn,
+ MiscompiledFunctions).TestFuncs(std::vector<BasicBlock*>())) {
+ Blocks.clear();
+ } else {
+ ReduceMiscompiledBlocks(BD, TestFn,MiscompiledFunctions).reduceList(Blocks);
+ if (Blocks.size() == OldSize)
+ return false;
+ }
+
+ DenseMap<const Value*, Value*> ValueMap;
+ Module *ProgClone = CloneModule(BD.getProgram(), ValueMap);
+ Module *ToExtract = SplitFunctionsOutOfModule(ProgClone,
+ MiscompiledFunctions,
+ ValueMap);
+ Module *Extracted = BD.ExtractMappedBlocksFromModule(Blocks, ToExtract);
+ if (Extracted == 0) {
+ // Weird, extraction should have worked.
+ std::cerr << "Nondeterministic problem extracting blocks??\n";
+ delete ProgClone;
+ delete ToExtract;
+ return false;
+ }
+
+ // Otherwise, block extraction succeeded. Link the two program fragments back
+ // together.
+ delete ToExtract;
+
+ std::vector<std::pair<std::string, const FunctionType*> > MisCompFunctions;
+ for (Module::iterator I = Extracted->begin(), E = Extracted->end();
+ I != E; ++I)
+ if (!I->isDeclaration())
+ MisCompFunctions.push_back(std::make_pair(I->getName(),
+ I->getFunctionType()));
+
+ std::string ErrorMsg;
+ if (Linker::LinkModules(ProgClone, Extracted, &ErrorMsg)) {
+ std::cerr << BD.getToolName() << ": Error linking modules together:"
+ << ErrorMsg << '\n';
+ exit(1);
+ }
+ delete Extracted;
+
+ // Set the new program and delete the old one.
+ BD.setNewProgram(ProgClone);
+
+ // Update the list of miscompiled functions.
+ MiscompiledFunctions.clear();
+
+ for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) {
+ Function *NewF = ProgClone->getFunction(MisCompFunctions[i].first);
+ assert(NewF && "Function not found??");
+ assert(NewF->getFunctionType() == MisCompFunctions[i].second &&
+ "Function has wrong type??");
+ MiscompiledFunctions.push_back(NewF);
+ }
+
+ return true;
+}
+
+
+/// DebugAMiscompilation - This is a generic driver to narrow down
+/// miscompilations, either in an optimization or a code generator.
+///
+static std::vector<Function*>
+DebugAMiscompilation(BugDriver &BD,
+ bool (*TestFn)(BugDriver &, Module *, Module *)) {
+ // 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);
+
+ std::cout << "\n*** The following function"
+ << (MiscompiledFunctions.size() == 1 ? " is" : "s are")
+ << " being miscompiled: ";
+ PrintFunctionList(MiscompiledFunctions);
+ std::cout << '\n';
+
+ // See if we can rip any loops out of the miscompiled functions and still
+ // trigger the problem.
+
+ if (!BugpointIsInterrupted && !DisableLoopExtraction &&
+ ExtractLoops(BD, TestFn, MiscompiledFunctions)) {
+ // Okay, we extracted some loops and the problem still appears. See if we
+ // can eliminate some of the created functions from being candidates.
+
+ // Loop extraction can introduce functions with the same name (foo_code).
+ // Make sure to disambiguate the symbols so that when the program is split
+ // apart that we can link it back together again.
+ DisambiguateGlobalSymbols(BD.getProgram());
+
+ // Do the reduction...
+ if (!BugpointIsInterrupted)
+ ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions);
+
+ std::cout << "\n*** The following function"
+ << (MiscompiledFunctions.size() == 1 ? " is" : "s are")
+ << " being miscompiled: ";
+ PrintFunctionList(MiscompiledFunctions);
+ std::cout << '\n';
+ }
+
+ if (!BugpointIsInterrupted &&
+ ExtractBlocks(BD, TestFn, MiscompiledFunctions)) {
+ // Okay, we extracted some blocks and the problem still appears. See if we
+ // can eliminate some of the created functions from being candidates.
+
+ // Block extraction can introduce functions with the same name (foo_code).
+ // Make sure to disambiguate the symbols so that when the program is split
+ // apart that we can link it back together again.
+ DisambiguateGlobalSymbols(BD.getProgram());
+
+ // Do the reduction...
+ ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions);
+
+ std::cout << "\n*** The following function"
+ << (MiscompiledFunctions.size() == 1 ? " is" : "s are")
+ << " being miscompiled: ";
+ PrintFunctionList(MiscompiledFunctions);
+ std::cout << '\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) {
+ // Run the optimization passes on ToOptimize, producing a transformed version
+ // of the functions being tested.
+ std::cout << " Optimizing functions being tested: ";
+ Module *Optimized = BD.runPassesOn(Test, BD.getPassesToRun(),
+ /*AutoDebugCrashes*/true);
+ std::cout << "done.\n";
+ delete Test;
+
+ std::cout << " Checking to see if the merged program executes correctly: ";
+ bool Broken = TestMergedProgram(BD, Optimized, Safe, true);
+ std::cout << (Broken ? " nope.\n" : " yup.\n");
+ return Broken;
+}
+
+
+/// debugMiscompilation - This method is used when the passes selected are not
+/// crashing, but the generated output is semantically different from the
+/// input.
+///
+bool BugDriver::debugMiscompilation() {
+ // Make sure something was miscompiled...
+ if (!BugpointIsInterrupted)
+ if (!ReduceMiscompilingPasses(*this).reduceList(PassesToRun)) {
+ std::cerr << "*** Optimized program matches reference output! No problem"
+ << " detected...\nbugpoint can't help you with your problem!\n";
+ return false;
+ }
+
+ std::cout << "\n*** Found miscompiling pass"
+ << (getPassesToRun().size() == 1 ? "" : "es") << ": "
+ << getPassesString(getPassesToRun()) << '\n';
+ EmitProgressBitcode("passinput");
+
+ std::vector<Function*> MiscompiledFunctions =
+ DebugAMiscompilation(*this, TestOptimizer);
+
+ // Output a bunch of bitcode files for the user...
+ std::cout << "Outputting reduced bitcode files which expose the problem:\n";
+ DenseMap<const Value*, Value*> ValueMap;
+ Module *ToNotOptimize = CloneModule(getProgram(), ValueMap);
+ Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize,
+ MiscompiledFunctions,
+ ValueMap);
+
+ std::cout << " Non-optimized portion: ";
+ ToNotOptimize = swapProgramIn(ToNotOptimize);
+ EmitProgressBitcode("tonotoptimize", true);
+ setNewProgram(ToNotOptimize); // Delete hacked module.
+
+ std::cout << " Portion that is input to optimizer: ";
+ ToOptimize = swapProgramIn(ToOptimize);
+ EmitProgressBitcode("tooptimize");
+ setNewProgram(ToOptimize); // Delete hacked module.
+
+ return false;
+}
+
+/// 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("entry", newMain);
+ CallInst *call = CallInst::Create(oldMainProto, args.begin(), args.end(),
+ "", BB);
+
+ // If the type of old function wasn't void, return value of call
+ ReturnInst::Create(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",
+ PointerType::getUnqual(Type::Int8Ty),
+ PointerType::getUnqual(Type::Int8Ty), (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->getName());
+ GlobalVariable *funcName =
+ new GlobalVariable(InitArray->getType(), true /*isConstant*/,
+ GlobalValue::InternalLinkage, InitArray,
+ F->getName() + "_name", Safe);
+
+ // 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::Int32Ty));
+ Value *GEP = ConstantExpr::getGetElementPtr(funcName, &GEPargs[0], 2);
+ std::vector<Value*> ResolverArgs;
+ ResolverArgs.push_back(GEP);
+
+ // Rewrite uses of F in global initializers, etc. to uses of a wrapper
+ // function that dynamically resolves the calls to F via our JIT API
+ if (!F->use_empty()) {
+ // Create a new global to hold the cached function pointer.
+ Constant *NullPtr = ConstantPointerNull::get(F->getType());
+ GlobalVariable *Cache =
+ new GlobalVariable(F->getType(), false,GlobalValue::InternalLinkage,
+ NullPtr,F->getName()+".fpcache", F->getParent());
+
+ // Construct a new stub function that will re-route calls to F
+ const FunctionType *FuncTy = F->getFunctionType();
+ Function *FuncWrapper = Function::Create(FuncTy,
+ GlobalValue::InternalLinkage,
+ F->getName() + "_wrapper",
+ F->getParent());
+ BasicBlock *EntryBB = BasicBlock::Create("entry", FuncWrapper);
+ BasicBlock *DoCallBB = BasicBlock::Create("usecache", FuncWrapper);
+ BasicBlock *LookupBB = BasicBlock::Create("lookupfp", FuncWrapper);
+
+ // Check to see if we already looked up the value.
+ Value *CachedVal = new LoadInst(Cache, "fpcache", EntryBB);
+ Value *IsNull = new ICmpInst(ICmpInst::ICMP_EQ, CachedVal,
+ NullPtr, "isNull", EntryBB);
+ BranchInst::Create(LookupBB, DoCallBB, IsNull, EntryBB);
+
+ // Resolve the call to function F via the JIT API:
+ //
+ // call resolver(GetElementPtr...)
+ CallInst *Resolver =
+ CallInst::Create(resolverFunc, ResolverArgs.begin(),
+ ResolverArgs.end(), "resolver", LookupBB);
+
+ // Cast the result from the resolver to correctly-typed function.
+ CastInst *CastedResolver =
+ new BitCastInst(Resolver,
+ PointerType::getUnqual(F->getFunctionType()),
+ "resolverCast", LookupBB);
+
+ // Save the value in our cache.
+ new StoreInst(CastedResolver, Cache, LookupBB);
+ BranchInst::Create(DoCallBB, LookupBB);
+
+ PHINode *FuncPtr = PHINode::Create(NullPtr->getType(),
+ "fp", DoCallBB);
+ FuncPtr->addIncoming(CastedResolver, LookupBB);
+ FuncPtr->addIncoming(CachedVal, EntryBB);
+
+ // Save the argument list.
+ std::vector<Value*> Args;
+ for (Function::arg_iterator i = FuncWrapper->arg_begin(),
+ e = FuncWrapper->arg_end(); i != e; ++i)
+ Args.push_back(i);
+
+ // Pass on the arguments to the real function, return its result
+ if (F->getReturnType() == Type::VoidTy) {
+ CallInst::Create(FuncPtr, Args.begin(), Args.end(), "", DoCallBB);
+ ReturnInst::Create(DoCallBB);
+ } else {
+ CallInst *Call = CallInst::Create(FuncPtr, Args.begin(), Args.end(),
+ "retval", DoCallBB);
+ ReturnInst::Create(Call, DoCallBB);
+ }
+
+ // Use the wrapper function instead of the old function
+ F->replaceAllUsesWith(FuncWrapper);
+ }
+ }
+ }
+ }
+
+ if (verifyModule(*Test) || verifyModule(*Safe)) {
+ std::cerr << "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) {
+ CleanupAndPrepareModules(BD, Test, Safe);
+
+ sys::Path TestModuleBC("bugpoint.test.bc");
+ std::string ErrMsg;
+ if (TestModuleBC.makeUnique(true, &ErrMsg)) {
+ std::cerr << BD.getToolName() << "Error making unique filename: "
+ << ErrMsg << "\n";
+ exit(1);
+ }
+ if (BD.writeProgramToFile(TestModuleBC.toString(), Test)) {
+ std::cerr << "Error writing bitcode to `" << TestModuleBC << "'\nExiting.";
+ exit(1);
+ }
+ delete Test;
+
+ // Make the shared library
+ sys::Path SafeModuleBC("bugpoint.safe.bc");
+ if (SafeModuleBC.makeUnique(true, &ErrMsg)) {
+ std::cerr << BD.getToolName() << "Error making unique filename: "
+ << ErrMsg << "\n";
+ exit(1);
+ }
+
+ if (BD.writeProgramToFile(SafeModuleBC.toString(), Safe)) {
+ std::cerr << "Error writing bitcode to `" << SafeModuleBC << "'\nExiting.";
+ exit(1);
+ }
+ std::string SharedObject = BD.compileSharedObject(SafeModuleBC.toString());
+ delete Safe;
+
+ // Run the code generator on the `Test' code, loading the shared library.
+ // The function returns whether or not the new output differs from reference.
+ int Result = BD.diffProgram(TestModuleBC.toString(), SharedObject, false);
+
+ if (Result)
+ std::cerr << ": still failing!\n";
+ else
+ std::cerr << ": didn't fail.\n";
+ TestModuleBC.eraseFromDisk();
+ SafeModuleBC.eraseFromDisk();
+ sys::Path(SharedObject).eraseFromDisk();
+
+ return Result;
+}
+
+
+/// debugCodeGenerator - debug errors in LLC, LLI, or CBE.
+///
+bool BugDriver::debugCodeGenerator() {
+ if ((void*)SafeInterpreter == (void*)Interpreter) {
+ std::string Result = executeProgramSafely("bugpoint.safe.out");
+ std::cout << "\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);
+
+ // Split the module into the two halves of the program we want.
+ DenseMap<const Value*, Value*> ValueMap;
+ Module *ToNotCodeGen = CloneModule(getProgram(), ValueMap);
+ Module *ToCodeGen = SplitFunctionsOutOfModule(ToNotCodeGen, Funcs, ValueMap);
+
+ // Condition the modules
+ CleanupAndPrepareModules(*this, ToCodeGen, ToNotCodeGen);
+
+ sys::Path TestModuleBC("bugpoint.test.bc");
+ std::string ErrMsg;
+ if (TestModuleBC.makeUnique(true, &ErrMsg)) {
+ std::cerr << getToolName() << "Error making unique filename: "
+ << ErrMsg << "\n";
+ exit(1);
+ }
+
+ if (writeProgramToFile(TestModuleBC.toString(), ToCodeGen)) {
+ std::cerr << "Error writing bitcode to `" << TestModuleBC << "'\nExiting.";
+ exit(1);
+ }
+ delete ToCodeGen;
+
+ // Make the shared library
+ sys::Path SafeModuleBC("bugpoint.safe.bc");
+ if (SafeModuleBC.makeUnique(true, &ErrMsg)) {
+ std::cerr << getToolName() << "Error making unique filename: "
+ << ErrMsg << "\n";
+ exit(1);
+ }
+
+ if (writeProgramToFile(SafeModuleBC.toString(), ToNotCodeGen)) {
+ std::cerr << "Error writing bitcode to `" << SafeModuleBC << "'\nExiting.";
+ exit(1);
+ }
+ std::string SharedObject = compileSharedObject(SafeModuleBC.toString());
+ delete ToNotCodeGen;
+
+ std::cout << "You can reproduce the problem with the command line: \n";
+ if (isExecutingJIT()) {
+ std::cout << " lli -load " << SharedObject << " " << TestModuleBC;
+ } else {
+ std::cout << " llc -f " << TestModuleBC << " -o " << TestModuleBC<< ".s\n";
+ std::cout << " gcc " << SharedObject << " " << TestModuleBC
+ << ".s -o " << TestModuleBC << ".exe";
+#if defined (HAVE_LINK_R)
+ std::cout << " -Wl,-R.";
+#endif
+ std::cout << "\n";
+ std::cout << " " << TestModuleBC << ".exe";
+ }
+ for (unsigned i=0, e = InputArgv.size(); i != e; ++i)
+ std::cout << " " << InputArgv[i];
+ std::cout << '\n';
+ std::cout << "The shared object was created with:\n llc -march=c "
+ << SafeModuleBC << " -o temporary.c\n"
+ << " gcc -xc temporary.c -O2 -o " << SharedObject
+#if defined(sparc) || defined(__sparc__) || defined(__sparcv9)
+ << " -G" // Compile a shared library, `-G' for Sparc
+#else
+ << " -fPIC -shared" // `-shared' for Linux/X86, maybe others
+#endif
+ << " -fno-strict-aliasing\n";
+
+ return false;
+}
diff --git a/tools/bugpoint/OptimizerDriver.cpp b/tools/bugpoint/OptimizerDriver.cpp
new file mode 100644
index 0000000..3ded5e8
--- /dev/null
+++ b/tools/bugpoint/OptimizerDriver.cpp
@@ -0,0 +1,266 @@
+//===- OptimizerDriver.cpp - Allow BugPoint to run passes safely ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines an interface that allows bugpoint to run various passes
+// without the threat of a buggy pass corrupting bugpoint (of course, bugpoint
+// may have its own bugs, but that's another story...). It achieves this by
+// forking a copy of itself and having the child process do the optimizations.
+// If this client dies, we can always fork a new one. :)
+//
+//===----------------------------------------------------------------------===//
+
+// Note: as a short term hack, the old Unix-specific code and platform-
+// independent code co-exist via conditional compilation until it is verified
+// that the new code works correctly on Unix.
+
+#include "BugDriver.h"
+#include "llvm/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Streams.h"
+#include "llvm/System/Path.h"
+#include "llvm/System/Program.h"
+#include "llvm/Config/alloca.h"
+
+#define DONT_GET_PLUGIN_LOADER_OPTION
+#include "llvm/Support/PluginLoader.h"
+
+#include <fstream>
+using namespace llvm;
+
+
+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);
+ cl::opt<bool> UseValgrind("enable-valgrind",
+ cl::desc("Run optimizations through valgrind"));
+}
+
+/// 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,
+ Module *M) const {
+ std::ios::openmode io_mode = std::ios::out | std::ios::trunc |
+ std::ios::binary;
+ std::ofstream Out(Filename.c_str(), io_mode);
+ if (!Out.good()) return true;
+
+ WriteBitcodeToFile(M ? M : Program, Out);
+ return false;
+}
+
+
+/// EmitProgressBitcode - This function is used to output the current Program
+/// to a file named "bugpoint-ID.bc".
+///
+void BugDriver::EmitProgressBitcode(const std::string &ID, bool NoFlyer) {
+ // 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 = "bugpoint-" + ID + ".bc";
+ if (writeProgramToFile(Filename)) {
+ cerr << "Error opening file '" << Filename << "' for writing!\n";
+ return;
+ }
+
+ cout << "Emitted bitcode to '" << Filename << "'\n";
+ if (NoFlyer || PassesToRun.empty()) return;
+ cout << "\n*** You can reproduce the problem with: ";
+ cout << "opt " << Filename << " ";
+ cout << getPassesString(PassesToRun) << "\n";
+}
+
+int BugDriver::runPassesAsChild(const std::vector<const PassInfo*> &Passes) {
+
+ std::ios::openmode io_mode = std::ios::out | std::ios::trunc |
+ std::ios::binary;
+ std::ofstream OutFile(ChildOutput.c_str(), io_mode);
+ if (!OutFile.good()) {
+ cerr << "Error opening bitcode file: " << ChildOutput << "\n";
+ return 1;
+ }
+
+ PassManager PM;
+ // Make sure that the appropriate target data is always used...
+ PM.add(new TargetData(Program));
+
+ for (unsigned i = 0, e = Passes.size(); i != e; ++i) {
+ if (Passes[i]->getNormalCtor())
+ PM.add(Passes[i]->getNormalCtor()());
+ else
+ cerr << "Cannot create pass yet: " << Passes[i]->getPassName() << "\n";
+ }
+ // Check that the module is well formed on completion of optimization
+ PM.add(createVerifierPass());
+
+ // Write bitcode out to disk as the last step...
+ PM.add(CreateBitcodeWriterPass(OutFile));
+
+ // Run all queued passes.
+ PM.run(*Program);
+
+ return 0;
+}
+
+cl::opt<bool> SilencePasses("silence-passes", cl::desc("Suppress output of running passes (both stdout and stderr)"));
+
+/// 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
+/// cout a single line message indicating whether compilation was successful or
+/// failed.
+///
+bool BugDriver::runPasses(const std::vector<const PassInfo*> &Passes,
+ std::string &OutputFilename, bool DeleteOutput,
+ bool Quiet, unsigned NumExtraArgs,
+ const char * const *ExtraArgs) const {
+ // setup the output file name
+ cout << std::flush;
+ sys::Path uniqueFilename("bugpoint-output.bc");
+ std::string ErrMsg;
+ if (uniqueFilename.makeUnique(true, &ErrMsg)) {
+ cerr << getToolName() << ": Error making unique filename: "
+ << ErrMsg << "\n";
+ return(1);
+ }
+ OutputFilename = uniqueFilename.toString();
+
+ // set up the input file name
+ sys::Path inputFilename("bugpoint-input.bc");
+ if (inputFilename.makeUnique(true, &ErrMsg)) {
+ cerr << getToolName() << ": Error making unique filename: "
+ << ErrMsg << "\n";
+ return(1);
+ }
+ std::ios::openmode io_mode = std::ios::out | std::ios::trunc |
+ std::ios::binary;
+ std::ofstream InFile(inputFilename.c_str(), io_mode);
+ if (!InFile.good()) {
+ cerr << "Error opening bitcode file: " << inputFilename << "\n";
+ return(1);
+ }
+ WriteBitcodeToFile(Program, InFile);
+ InFile.close();
+
+ // setup the child process' arguments
+ const char** args = (const char**)
+ alloca(sizeof(const char*) *
+ (Passes.size()+13+2*PluginLoader::getNumPlugins()+NumExtraArgs));
+ int n = 0;
+ sys::Path tool = sys::Program::FindProgramByName(ToolName);
+ if (UseValgrind) {
+ args[n++] = "valgrind";
+ args[n++] = "--error-exitcode=1";
+ args[n++] = "-q";
+ args[n++] = tool.c_str();
+ } else
+ args[n++] = ToolName.c_str();
+
+ args[n++] = "-as-child";
+ args[n++] = "-child-output";
+ args[n++] = OutputFilename.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<const PassInfo*>::const_iterator I = Passes.begin(),
+ E = Passes.end(); I != E; ++I )
+ pass_args.push_back( std::string("-") + (*I)->getPassArgument() );
+ for (std::vector<std::string>::const_iterator I = pass_args.begin(),
+ E = pass_args.end(); I != E; ++I )
+ args[n++] = I->c_str();
+ args[n++] = inputFilename.c_str();
+ for (unsigned i = 0; i < NumExtraArgs; ++i)
+ args[n++] = *ExtraArgs;
+ args[n++] = 0;
+
+ 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, 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)
+ cout << "Success!\n";
+ else if (result > 0)
+ cout << "Exited with error code '" << result << "'\n";
+ else if (result < 0) {
+ if (result == -1)
+ cout << "Execute failed: " << ErrMsg << "\n";
+ else
+ cout << "Crashed with signal #" << abs(result) << "\n";
+ }
+ if (result & 0x01000000)
+ cout << "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<const PassInfo*> &Passes,
+ bool AutoDebugCrashes, unsigned NumExtraArgs,
+ const char * const *ExtraArgs) {
+ Module *OldProgram = swapProgramIn(M);
+ std::string BitcodeResult;
+ if (runPasses(Passes, BitcodeResult, false/*delete*/, true/*quiet*/,
+ NumExtraArgs, ExtraArgs)) {
+ if (AutoDebugCrashes) {
+ cerr << " Error running this sequence of passes"
+ << " on the input program!\n";
+ delete OldProgram;
+ EmitProgressBitcode("pass-error", false);
+ exit(debugOptimizerCrash());
+ }
+ swapProgramIn(OldProgram);
+ return 0;
+ }
+
+ // Restore the current program.
+ swapProgramIn(OldProgram);
+
+ Module *Ret = ParseInputFile(BitcodeResult);
+ if (Ret == 0) {
+ cerr << 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/tools/bugpoint/TestPasses.cpp b/tools/bugpoint/TestPasses.cpp
new file mode 100644
index 0000000..900bf63
--- /dev/null
+++ b/tools/bugpoint/TestPasses.cpp
@@ -0,0 +1,75 @@
+//===- TestPasses.cpp - "buggy" passes used to test bugpoint --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains "buggy" passes that are used to test bugpoint, to check
+// that it is narrowing down testcases correctly.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/BasicBlock.h"
+#include "llvm/Constant.h"
+#include "llvm/Instructions.h"
+#include "llvm/Pass.h"
+#include "llvm/Type.h"
+#include "llvm/Support/InstVisitor.h"
+
+using namespace llvm;
+
+namespace {
+ /// CrashOnCalls - This pass is used to test bugpoint. It intentionally
+ /// crashes on any call instructions.
+ class CrashOnCalls : public BasicBlockPass {
+ public:
+ static char ID; // Pass ID, replacement for typeid
+ CrashOnCalls() : BasicBlockPass(&ID) {}
+ private:
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ }
+
+ bool runOnBasicBlock(BasicBlock &BB) {
+ for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I)
+ if (isa<CallInst>(*I))
+ abort();
+
+ return false;
+ }
+ };
+
+ char CrashOnCalls::ID = 0;
+ RegisterPass<CrashOnCalls>
+ X("bugpoint-crashcalls",
+ "BugPoint Test Pass - Intentionally crash on CallInsts");
+}
+
+namespace {
+ /// DeleteCalls - This pass is used to test bugpoint. It intentionally
+ /// deletes some call instructions, "misoptimizing" the program.
+ class DeleteCalls : public BasicBlockPass {
+ public:
+ static char ID; // Pass ID, replacement for typeid
+ DeleteCalls() : BasicBlockPass(&ID) {}
+ private:
+ bool runOnBasicBlock(BasicBlock &BB) {
+ for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I)
+ if (CallInst *CI = dyn_cast<CallInst>(I)) {
+ if (!CI->use_empty())
+ CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
+ CI->getParent()->getInstList().erase(CI);
+ break;
+ }
+ return false;
+ }
+ };
+
+ char DeleteCalls::ID = 0;
+ RegisterPass<DeleteCalls>
+ Y("bugpoint-deletecalls",
+ "BugPoint Test Pass - Intentionally 'misoptimize' CallInsts");
+}
diff --git a/tools/bugpoint/ToolRunner.cpp b/tools/bugpoint/ToolRunner.cpp
new file mode 100644
index 0000000..978e60b
--- /dev/null
+++ b/tools/bugpoint/ToolRunner.cpp
@@ -0,0 +1,748 @@
+//===-- 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/Config/config.h" // for HAVE_LINK_R
+#include "llvm/System/Program.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/FileUtilities.h"
+#include <fstream>
+#include <sstream>
+#include <iostream>
+using namespace llvm;
+
+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>
+ 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"));
+}
+
+ToolExecutionError::~ToolExecutionError() throw() { }
+
+/// RunProgramWithTimeout - This function provides an alternate interface to the
+/// sys::Program::ExecuteAndWait interface.
+/// @see sys:Program::ExecuteAndWait
+static int RunProgramWithTimeout(const sys::Path &ProgramPath,
+ const char **Args,
+ const sys::Path &StdInFile,
+ const sys::Path &StdOutFile,
+ const sys::Path &StdErrFile,
+ unsigned NumSeconds = 0,
+ unsigned MemoryLimit = 0) {
+ const sys::Path* redirects[3];
+ redirects[0] = &StdInFile;
+ redirects[1] = &StdOutFile;
+ redirects[2] = &StdErrFile;
+
+ if (0) {
+ std::cerr << "RUN:";
+ for (unsigned i = 0; Args[i]; ++i)
+ std::cerr << " " << Args[i];
+ std::cerr << "\n";
+ }
+
+ return
+ sys::Program::ExecuteAndWait(ProgramPath, Args, 0, redirects,
+ NumSeconds, MemoryLimit);
+}
+
+
+
+static void ProcessFailure(sys::Path ProgPath, const char** Args) {
+ 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)) {
+ std::cerr << "Error making unique filename: " << ErrMsg << "\n";
+ exit(1);
+ }
+ RunProgramWithTimeout(ProgPath, Args, sys::Path(""), ErrorFilename,
+ ErrorFilename); // 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();
+ throw ToolExecutionError(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,
+ 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,
+ const std::vector<std::string> &GCCArgs,
+ const std::vector<std::string> &SharedLibs,
+ unsigned Timeout,
+ unsigned MemoryLimit) {
+ if (!SharedLibs.empty())
+ throw ToolExecutionError("LLI currently does not support "
+ "loading shared libraries.");
+
+ std::vector<const char*> LLIArgs;
+ LLIArgs.push_back(LLIPath.c_str());
+ LLIArgs.push_back("-force-interpreter=true");
+
+ // 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);
+
+ std::cout << "<lli>" << std::flush;
+ DEBUG(std::cerr << "\nAbout to run:\t";
+ for (unsigned i=0, e = LLIArgs.size()-1; i != e; ++i)
+ std::cerr << " " << LLIArgs[i];
+ std::cerr << "\n";
+ );
+ return RunProgramWithTimeout(sys::Path(LLIPath), &LLIArgs[0],
+ sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
+ Timeout, MemoryLimit);
+}
+
+// LLI create method - Try to find the LLI executable
+AbstractInterpreter *AbstractInterpreter::createLLI(const std::string &ProgPath,
+ std::string &Message,
+ const std::vector<std::string> *ToolArgs) {
+ std::string LLIPath = FindExecutable("lli", ProgPath).toString();
+ if (!LLIPath.empty()) {
+ Message = "Found lli: " + LLIPath + "\n";
+ return new LLI(LLIPath, ToolArgs);
+ }
+
+ Message = "Cannot find `lli' in executable directory or PATH!\n";
+ return 0;
+}
+
+//===---------------------------------------------------------------------===//
+// Custom execution command implementation of AbstractIntepreter interface
+//
+// Allows using a custom command for executing the bitcode, thus allows,
+// for example, to invoke a cross compiler for code generation followed by
+// a simulator that executes the generated binary.
+namespace {
+ class CustomExecutor : public AbstractInterpreter {
+ std::string ExecutionCommand;
+ std::vector<std::string> ExecutorArgs;
+ public:
+ CustomExecutor(
+ const std::string &ExecutionCmd, std::vector<std::string> ExecArgs) :
+ ExecutionCommand(ExecutionCmd), ExecutorArgs(ExecArgs) {}
+
+ virtual int ExecuteProgram(const std::string &Bitcode,
+ const std::vector<std::string> &Args,
+ const std::string &InputFile,
+ const std::string &OutputFile,
+ 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,
+ const std::vector<std::string> &GCCArgs,
+ const std::vector<std::string> &SharedLibs,
+ unsigned Timeout,
+ unsigned MemoryLimit) {
+
+ std::vector<const char*> ProgramArgs;
+ ProgramArgs.push_back(ExecutionCommand.c_str());
+
+ for (std::size_t i = 0; i < ExecutorArgs.size(); ++i)
+ ProgramArgs.push_back(ExecutorArgs.at(i).c_str());
+ ProgramArgs.push_back(Bitcode.c_str());
+ ProgramArgs.push_back(0);
+
+ // Add optional parameters to the running program from Argv
+ for (unsigned i=0, e = Args.size(); i != e; ++i)
+ ProgramArgs.push_back(Args[i].c_str());
+
+ return RunProgramWithTimeout(
+ sys::Path(ExecutionCommand),
+ &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile),
+ sys::Path(OutputFile), Timeout, MemoryLimit);
+}
+
+// Custom execution environment create method, takes the execution command
+// as arguments
+AbstractInterpreter *AbstractInterpreter::createCustom(
+ const std::string &ProgramPath,
+ std::string &Message,
+ const std::string &ExecCommandLine) {
+
+ std::string Command = "";
+ std::vector<std::string> Args;
+ std::string delimiters = " ";
+
+ // Tokenize the ExecCommandLine to the command and the args to allow
+ // defining a full command line as the command instead of just the
+ // executed program. We cannot just pass the whole string after the command
+ // as a single argument because then program sees only a single
+ // command line argument (with spaces in it: "foo bar" instead
+ // of "foo" and "bar").
+
+ // code borrowed from:
+ // http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html
+ std::string::size_type lastPos =
+ ExecCommandLine.find_first_not_of(delimiters, 0);
+ std::string::size_type pos =
+ ExecCommandLine.find_first_of(delimiters, lastPos);
+
+ while (std::string::npos != pos || std::string::npos != lastPos) {
+ std::string token = ExecCommandLine.substr(lastPos, pos - lastPos);
+ if (Command == "")
+ Command = token;
+ else
+ Args.push_back(token);
+ // Skip delimiters. Note the "not_of"
+ lastPos = ExecCommandLine.find_first_not_of(delimiters, pos);
+ // Find next "non-delimiter"
+ pos = ExecCommandLine.find_first_of(delimiters, lastPos);
+ }
+
+ std::string CmdPath = FindExecutable(Command, ProgramPath).toString();
+ if (CmdPath.empty()) {
+ Message =
+ std::string("Cannot find '") + Command +
+ "' in executable directory or PATH!\n";
+ return 0;
+ }
+
+ Message = "Found command in: " + CmdPath + "\n";
+
+ return new CustomExecutor(CmdPath, Args);
+}
+
+//===----------------------------------------------------------------------===//
+// LLC Implementation of AbstractIntepreter interface
+//
+GCC::FileType LLC::OutputCode(const std::string &Bitcode,
+ sys::Path &OutputAsmFile) {
+ sys::Path uniqueFile(Bitcode+".llc.s");
+ std::string ErrMsg;
+ if (uniqueFile.makeUnique(true, &ErrMsg)) {
+ std::cerr << "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 ("-f"); // Overwrite as necessary...
+ LLCArgs.push_back (Bitcode.c_str()); // This is the input bitcode
+ LLCArgs.push_back (0);
+
+ std::cout << "<llc>" << std::flush;
+ DEBUG(std::cerr << "\nAbout to run:\t";
+ for (unsigned i=0, e = LLCArgs.size()-1; i != e; ++i)
+ std::cerr << " " << LLCArgs[i];
+ std::cerr << "\n";
+ );
+ if (RunProgramWithTimeout(sys::Path(LLCPath), &LLCArgs[0],
+ sys::Path(), sys::Path(), sys::Path()))
+ ProcessFailure(sys::Path(LLCPath), &LLCArgs[0]);
+
+ return GCC::AsmFile;
+}
+
+void LLC::compileProgram(const std::string &Bitcode) {
+ sys::Path OutputAsmFile;
+ OutputCode(Bitcode, OutputAsmFile);
+ OutputAsmFile.eraseFromDisk();
+}
+
+int LLC::ExecuteProgram(const std::string &Bitcode,
+ const std::vector<std::string> &Args,
+ const std::string &InputFile,
+ const std::string &OutputFile,
+ const std::vector<std::string> &ArgsForGCC,
+ const std::vector<std::string> &SharedLibs,
+ unsigned Timeout,
+ unsigned MemoryLimit) {
+
+ sys::Path OutputAsmFile;
+ OutputCode(Bitcode, OutputAsmFile);
+ FileRemover OutFileRemover(OutputAsmFile);
+
+ std::vector<std::string> GCCArgs(ArgsForGCC);
+ GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end());
+ GCCArgs.insert(GCCArgs.end(), gccArgs.begin(), gccArgs.end());
+
+ // Assuming LLC worked, compile the result with GCC and run it.
+ return gcc->ExecuteProgram(OutputAsmFile.toString(), Args, GCC::AsmFile,
+ InputFile, OutputFile, GCCArgs,
+ Timeout, MemoryLimit);
+}
+
+/// createLLC - Try to find the LLC executable
+///
+LLC *AbstractInterpreter::createLLC(const std::string &ProgramPath,
+ std::string &Message,
+ const std::vector<std::string> *Args,
+ const std::vector<std::string> *GCCArgs) {
+ std::string LLCPath = FindExecutable("llc", ProgramPath).toString();
+ if (LLCPath.empty()) {
+ Message = "Cannot find `llc' in executable directory or PATH!\n";
+ return 0;
+ }
+
+ Message = "Found llc: " + LLCPath + "\n";
+ GCC *gcc = GCC::create(ProgramPath, Message, GCCArgs);
+ if (!gcc) {
+ std::cerr << Message << "\n";
+ exit(1);
+ }
+ return new LLC(LLCPath, gcc, Args, GCCArgs);
+}
+
+//===---------------------------------------------------------------------===//
+// 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,
+ 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,
+ 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);
+
+ std::cout << "<jit>" << std::flush;
+ DEBUG(std::cerr << "\nAbout to run:\t";
+ for (unsigned i=0, e = JITArgs.size()-1; i != e; ++i)
+ std::cerr << " " << JITArgs[i];
+ std::cerr << "\n";
+ );
+ DEBUG(std::cerr << "\nSending output to " << OutputFile << "\n");
+ return RunProgramWithTimeout(sys::Path(LLIPath), &JITArgs[0],
+ sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
+ Timeout, MemoryLimit);
+}
+
+/// createJIT - Try to find the LLI executable
+///
+AbstractInterpreter *AbstractInterpreter::createJIT(const std::string &ProgPath,
+ std::string &Message, const std::vector<std::string> *Args) {
+ std::string LLIPath = FindExecutable("lli", ProgPath).toString();
+ if (!LLIPath.empty()) {
+ Message = "Found lli: " + LLIPath + "\n";
+ return new JIT(LLIPath, Args);
+ }
+
+ Message = "Cannot find `lli' in executable directory or PATH!\n";
+ return 0;
+}
+
+GCC::FileType CBE::OutputCode(const std::string &Bitcode,
+ sys::Path &OutputCFile) {
+ sys::Path uniqueFile(Bitcode+".cbe.c");
+ std::string ErrMsg;
+ if (uniqueFile.makeUnique(true, &ErrMsg)) {
+ std::cerr << "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 ("-f"); // Overwrite as necessary...
+ LLCArgs.push_back (Bitcode.c_str()); // This is the input bitcode
+ LLCArgs.push_back (0);
+
+ std::cout << "<cbe>" << std::flush;
+ DEBUG(std::cerr << "\nAbout to run:\t";
+ for (unsigned i=0, e = LLCArgs.size()-1; i != e; ++i)
+ std::cerr << " " << LLCArgs[i];
+ std::cerr << "\n";
+ );
+ if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], sys::Path(), sys::Path(),
+ sys::Path()))
+ ProcessFailure(LLCPath, &LLCArgs[0]);
+ return GCC::CFile;
+}
+
+void CBE::compileProgram(const std::string &Bitcode) {
+ sys::Path OutputCFile;
+ OutputCode(Bitcode, OutputCFile);
+ OutputCFile.eraseFromDisk();
+}
+
+int CBE::ExecuteProgram(const std::string &Bitcode,
+ const std::vector<std::string> &Args,
+ const std::string &InputFile,
+ const std::string &OutputFile,
+ const std::vector<std::string> &ArgsForGCC,
+ const std::vector<std::string> &SharedLibs,
+ unsigned Timeout,
+ unsigned MemoryLimit) {
+ sys::Path OutputCFile;
+ OutputCode(Bitcode, OutputCFile);
+
+ FileRemover CFileRemove(OutputCFile);
+
+ std::vector<std::string> GCCArgs(ArgsForGCC);
+ GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end());
+
+ return gcc->ExecuteProgram(OutputCFile.toString(), Args, GCC::CFile,
+ InputFile, OutputFile, GCCArgs,
+ Timeout, MemoryLimit);
+}
+
+/// createCBE - Try to find the 'llc' executable
+///
+CBE *AbstractInterpreter::createCBE(const std::string &ProgramPath,
+ std::string &Message,
+ const std::vector<std::string> *Args,
+ const std::vector<std::string> *GCCArgs) {
+ sys::Path LLCPath = FindExecutable("llc", ProgramPath);
+ if (LLCPath.isEmpty()) {
+ Message =
+ "Cannot find `llc' in executable directory or PATH!\n";
+ return 0;
+ }
+
+ Message = "Found llc: " + LLCPath.toString() + "\n";
+ GCC *gcc = GCC::create(ProgramPath, Message, GCCArgs);
+ if (!gcc) {
+ std::cerr << Message << "\n";
+ exit(1);
+ }
+ return new CBE(LLCPath, gcc, Args);
+}
+
+//===---------------------------------------------------------------------===//
+// GCC abstraction
+//
+int GCC::ExecuteProgram(const std::string &ProgramFile,
+ const std::vector<std::string> &Args,
+ FileType fileType,
+ const std::string &InputFile,
+ const std::string &OutputFile,
+ const std::vector<std::string> &ArgsForGCC,
+ unsigned Timeout,
+ unsigned MemoryLimit) {
+ std::vector<const char*> GCCArgs;
+
+ GCCArgs.push_back(GCCPath.c_str());
+
+ 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
+ GCCArgs.push_back("-x");
+ if (fileType == CFile) {
+ GCCArgs.push_back("c");
+ GCCArgs.push_back("-fno-strict-aliasing");
+ } else {
+ GCCArgs.push_back("assembler");
+#ifdef __APPLE__
+ GCCArgs.push_back("-force_cpusubtype_ALL");
+#endif
+ }
+ 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)) {
+ std::cerr << "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
+#ifdef __sparc__
+ GCCArgs.push_back("-mcpu=v9");
+#endif
+ GCCArgs.push_back(0); // NULL terminator
+
+ std::cout << "<gcc>" << std::flush;
+ DEBUG(std::cerr << "\nAbout to run:\t";
+ for (unsigned i=0, e = GCCArgs.size()-1; i != e; ++i)
+ std::cerr << " " << GCCArgs[i];
+ std::cerr << "\n";
+ );
+ if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(),
+ sys::Path())) {
+ ProcessFailure(GCCPath, &GCCArgs[0]);
+ exit(1);
+ }
+
+ std::vector<const char*> ProgramArgs;
+
+ if (RemoteClientPath.isEmpty())
+ ProgramArgs.push_back(OutputBinary.c_str());
+ else {
+ ProgramArgs.push_back(RemoteClientPath.c_str());
+ ProgramArgs.push_back(RemoteHost.c_str());
+ ProgramArgs.push_back("-l");
+ ProgramArgs.push_back(RemoteUser.c_str());
+ if (!RemoteExtra.empty()) {
+ ProgramArgs.push_back(RemoteExtra.c_str());
+ }
+
+ char* env_pwd = getenv("PWD");
+ std::string 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!
+ std::cout << "<program>" << std::flush;
+ DEBUG(std::cerr << "\nAbout to run:\t";
+ for (unsigned i=0, e = ProgramArgs.size()-1; i != e; ++i)
+ std::cerr << " " << ProgramArgs[i];
+ std::cerr << "\n";
+ );
+
+ FileRemover OutputBinaryRemover(OutputBinary);
+
+ if (RemoteClientPath.isEmpty())
+ return RunProgramWithTimeout(OutputBinary, &ProgramArgs[0],
+ sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
+ Timeout, MemoryLimit);
+ else
+ return RunProgramWithTimeout(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) {
+ sys::Path uniqueFilename(InputFile+LTDL_SHLIB_EXT);
+ std::string ErrMsg;
+ if (uniqueFilename.makeUnique(true, &ErrMsg)) {
+ std::cerr << "Error making unique filename: " << ErrMsg << "\n";
+ exit(1);
+ }
+ OutputFile = uniqueFilename.toString();
+
+ std::vector<const char*> GCCArgs;
+
+ GCCArgs.push_back(GCCPath.c_str());
+
+ 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
+ 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 defined(sparc) || defined(__sparc__) || defined(__sparcv9)
+ GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc
+#elif defined(__APPLE__)
+ // 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
+#endif
+
+#if defined(__ia64__) || defined(__alpha__) || defined(__amd64__)
+ GCCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC
+#endif
+#ifdef __sparc__
+ GCCArgs.push_back("-mcpu=v9");
+#endif
+ 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
+
+
+
+ std::cout << "<gcc>" << std::flush;
+ DEBUG(std::cerr << "\nAbout to run:\t";
+ for (unsigned i=0, e = GCCArgs.size()-1; i != e; ++i)
+ std::cerr << " " << GCCArgs[i];
+ std::cerr << "\n";
+ );
+ if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(),
+ sys::Path())) {
+ ProcessFailure(GCCPath, &GCCArgs[0]);
+ return 1;
+ }
+ return 0;
+}
+
+/// create - Try to find the `gcc' executable
+///
+GCC *GCC::create(const std::string &ProgramPath, std::string &Message,
+ const std::vector<std::string> *Args) {
+ sys::Path GCCPath = FindExecutable("gcc", ProgramPath);
+ if (GCCPath.isEmpty()) {
+ Message = "Cannot find `gcc' in executable directory or PATH!\n";
+ return 0;
+ }
+
+ sys::Path RemoteClientPath;
+ if (!RemoteClient.empty())
+ RemoteClientPath = FindExecutable(RemoteClient.c_str(), ProgramPath);
+
+ Message = "Found gcc: " + GCCPath.toString() + "\n";
+ return new GCC(GCCPath, RemoteClientPath, Args);
+}
diff --git a/tools/bugpoint/ToolRunner.h b/tools/bugpoint/ToolRunner.h
new file mode 100644
index 0000000..721f66c
--- /dev/null
+++ b/tools/bugpoint/ToolRunner.h
@@ -0,0 +1,230 @@
+//===-- 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/Support/SystemUtils.h"
+#include <exception>
+#include <vector>
+
+namespace llvm {
+
+class CBE;
+class LLC;
+
+/// ToolExecutionError - An instance of this class is thrown by the
+/// AbstractInterpreter instances if there is an error running a tool (e.g., LLC
+/// crashes) which prevents execution of the program.
+///
+class ToolExecutionError : std::exception {
+ std::string Message;
+public:
+ explicit ToolExecutionError(const std::string &M) : Message(M) {}
+ virtual ~ToolExecutionError() throw();
+ virtual const char* what() const throw() { return Message.c_str(); }
+};
+
+
+//===---------------------------------------------------------------------===//
+// 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, CFile };
+
+ static GCC *create(const std::string &ProgramPath, std::string &Message,
+ 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,
+ 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);
+};
+
+
+//===---------------------------------------------------------------------===//
+/// 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 std::string &ProgramPath, std::string &Message,
+ const std::vector<std::string> *Args = 0,
+ const std::vector<std::string> *GCCArgs = 0);
+ static LLC *createLLC(const std::string &ProgramPath, std::string &Message,
+ const std::vector<std::string> *Args = 0,
+ const std::vector<std::string> *GCCArgs = 0);
+
+ static AbstractInterpreter* createLLI(const std::string &ProgramPath,
+ std::string &Message,
+ const std::vector<std::string> *Args=0);
+
+ static AbstractInterpreter* createJIT(const std::string &ProgramPath,
+ std::string &Message,
+ const std::vector<std::string> *Args=0);
+
+ static AbstractInterpreter* createCustom(const std::string &ProgramPath,
+ 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. If the code generator fails, an exception should be
+ /// thrown, otherwise, this function will just return.
+ virtual void compileProgram(const std::string &Bitcode) {}
+
+ /// OutputCode - Compile the specified program from bitcode to code
+ /// understood by the GCC driver (either C or asm). If the code generator
+ /// fails, an exception should be thrown, otherwise, this function returns the
+ /// type of code emitted.
+ virtual GCC::FileType OutputCode(const std::string &Bitcode,
+ sys::Path &OutFile) {
+ throw std::string("OutputCode not supported by this AbstractInterpreter!");
+ }
+
+ /// ExecuteProgram - Run the specified bitcode file, emitting output to the
+ /// specified filename. This returns the exit code of the program.
+ ///
+ virtual int ExecuteProgram(const std::string &Bitcode,
+ const std::vector<std::string> &Args,
+ const std::string &InputFile,
+ const std::string &OutputFile,
+ 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. If the code generator fails, an exception should be
+ /// thrown, otherwise, this function will just return.
+ virtual void compileProgram(const std::string &Bitcode);
+
+ virtual int ExecuteProgram(const std::string &Bitcode,
+ const std::vector<std::string> &Args,
+ const std::string &InputFile,
+ const std::string &OutputFile,
+ 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, an exception should be thrown, otherwise, this function returns the
+ /// type of code emitted.
+ virtual GCC::FileType OutputCode(const std::string &Bitcode,
+ sys::Path &OutFile);
+};
+
+
+//===---------------------------------------------------------------------===//
+// 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.
+ std::vector<std::string> gccArgs; // Extra args to pass to GCC.
+ GCC *gcc;
+public:
+ LLC(const std::string &llcPath, GCC *Gcc,
+ const std::vector<std::string> *Args,
+ const std::vector<std::string> *GCCArgs)
+ : LLCPath(llcPath), gcc(Gcc) {
+ ToolArgs.clear();
+ if (Args) ToolArgs = *Args;
+ if (GCCArgs) gccArgs = *GCCArgs;
+ }
+ ~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. If the code generator fails, an exception should be
+ /// thrown, otherwise, this function will just return.
+ virtual void compileProgram(const std::string &Bitcode);
+
+ virtual int ExecuteProgram(const std::string &Bitcode,
+ const std::vector<std::string> &Args,
+ const std::string &InputFile,
+ const std::string &OutputFile,
+ 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);
+
+ virtual GCC::FileType OutputCode(const std::string &Bitcode,
+ sys::Path &OutFile);
+
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/tools/bugpoint/bugpoint.cpp b/tools/bugpoint/bugpoint.cpp
new file mode 100644
index 0000000..20f0e99
--- /dev/null
+++ b/tools/bugpoint/bugpoint.cpp
@@ -0,0 +1,104 @@
+//===- 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/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/System/Process.h"
+#include "llvm/System/Signals.h"
+#include "llvm/LinkAllVMCore.h"
+#include <iostream>
+using namespace llvm;
+
+// AsChild - Specifies that this invocation of bugpoint is being generated
+// from a parent process. It is not intended to be used by users so the
+// option is hidden.
+static cl::opt<bool>
+AsChild("as-child", cl::desc("Run bugpoint as child process"),
+ cl::ReallyHidden);
+
+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<unsigned>
+MemoryLimit("mlimit", cl::init(100), cl::value_desc("MBytes"),
+ cl::desc("Maximum amount of memory to use. 0 disables check."));
+
+// 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);
+
+/// BugpointIsInterrupted - Set to true when the user presses ctrl-c.
+bool llvm::BugpointIsInterrupted = false;
+
+static void BugpointInterruptFunction() {
+ BugpointIsInterrupted = true;
+}
+
+int main(int argc, char **argv) {
+ llvm::sys::PrintStackTraceOnErrorSignal();
+ llvm::PrettyStackTraceProgram X(argc, argv);
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ cl::ParseCommandLineOptions(argc, argv,
+ "LLVM automatic testcase reducer. See\nhttp://"
+ "llvm.org/cmds/bugpoint.html"
+ " for more information.\n");
+ sys::SetInterruptFunction(BugpointInterruptFunction);
+
+ BugDriver D(argv[0], AsChild, FindBugs, TimeoutValue, MemoryLimit);
+ if (D.addSources(InputFilenames)) return 1;
+ D.addPasses(PassList.begin(), PassList.end());
+
+ // Bugpoint has the ability of generating a plethora of core files, so to
+ // avoid filling up the disk, we prevent it
+ sys::Process::PreventCoreFiles();
+
+ try {
+ return D.run();
+ } catch (ToolExecutionError &TEE) {
+ std::cerr << "Tool execution error: " << TEE.what() << '\n';
+ } catch (const std::string& msg) {
+ std::cerr << argv[0] << ": " << msg << "\n";
+ } catch (const std::bad_alloc &e) {
+ std::cerr << "Oh no, a bugpoint process ran out of memory!\n"
+ "To increase the allocation limits for bugpoint child\n"
+ "processes, use the -mlimit option.\n";
+ } catch (const std::exception &e) {
+ std::cerr << "Whoops, a std::exception leaked out of bugpoint: "
+ << e.what() << "\n"
+ << "This is a bug in bugpoint!\n";
+ } catch (...) {
+ std::cerr << "Whoops, an exception leaked out of bugpoint. "
+ << "This is a bug in bugpoint!\n";
+ }
+ return 1;
+}
diff --git a/tools/gccas/Makefile b/tools/gccas/Makefile
new file mode 100644
index 0000000..ff84d96
--- /dev/null
+++ b/tools/gccas/Makefile
@@ -0,0 +1,28 @@
+##===- tools/gccas/Makefile --------------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+LEVEL = ../..
+
+include $(LEVEL)/Makefile.common
+
+install-local:: $(PROJ_bindir)/gccas
+
+$(PROJ_bindir)/gccas : gccas.sh Makefile
+ $(Echo) Installing gccas shell script.
+ $(Verb) sed "s#@TOOLDIR@#$(PROJ_bindir)#" $< > $@
+ $(Verb) chmod 0755 $@
+
+all-local:: $(ToolDir)/gccas
+
+$(ToolDir)/gccas : gccas.sh Makefile
+ $(Echo) Making $(ToolDir)/gccas shell script.
+ $(Verb) sed "s#@TOOLDIR@#$(ToolDir)#" $< > $@
+ $(Verb) chmod 0755 $@
+
+clean-local::
+ $(Verb)$(RM) -f $(ToolDir)/gccas
diff --git a/tools/gccas/gccas.sh b/tools/gccas/gccas.sh
new file mode 100644
index 0000000..9cacad4
--- /dev/null
+++ b/tools/gccas/gccas.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+##===- tools/gccas.sh ------------------------------------------*- bash -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+#
+# Synopsis: This shell script is a replacement for the old "gccas" tool that
+# existed in LLVM versions before 2.0. The functionality of gccas has
+# now been moved to opt and llvm-as. This shell script provides
+# backwards compatibility so build environments invoking gccas can
+# still get the net effect of llvm-as/opt by running gccas.
+#
+# Syntax: gccas OPTIONS... [asm file]
+#
+##===----------------------------------------------------------------------===##
+#
+echo "gccas: This tool is deprecated, please use opt" 1>&2
+TOOLDIR=@TOOLDIR@
+OPTOPTS="-std-compile-opts -f"
+ASOPTS=""
+lastwasdasho=0
+for option in "$@" ; do
+ option=`echo "$option" | sed 's/^--/-/'`
+ case "$option" in
+ -disable-opt)
+ OPTOPTS="$OPTOPTS $option"
+ ;;
+ -disable-inlining)
+ OPTOPTS="$OPTOPTS $option"
+ ;;
+ -verify)
+ OPTOPTS="$OPTOPTS -verify-each"
+ ;;
+ -strip-debug)
+ OPTOPTS="$OPTOPTS $option"
+ ;;
+ -o)
+ OPTOPTS="$OPTOPTS -o"
+ lastwasdasho=1
+ ;;
+ -disable-compression)
+ # ignore
+ ;;
+ -traditional-format)
+ # ignore
+ ;;
+ -*)
+ OPTOPTS="$OPTOPTS $option"
+ ;;
+ *)
+ if test $lastwasdasho -eq 1 ; then
+ OPTOPTS="$OPTOPTS $option"
+ lastwasdasho=0
+ else
+ ASOPTS="$ASOPTS $option"
+ fi
+ ;;
+ esac
+done
+${TOOLDIR}/llvm-as $ASOPTS -o - | ${TOOLDIR}/opt $OPTOPTS
diff --git a/tools/gccld/Makefile b/tools/gccld/Makefile
new file mode 100644
index 0000000..b2d3f73
--- /dev/null
+++ b/tools/gccld/Makefile
@@ -0,0 +1,29 @@
+##===- tools/gccld/Makefile --------------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+
+include $(LEVEL)/Makefile.common
+
+install-local:: $(PROJ_bindir)/gccld
+
+$(PROJ_bindir)/gccld : gccld.sh Makefile
+ $(Echo) Installing gccld shell script.
+ $(Verb) sed "s#@TOOLDIR@#$(PROJ_bindir)#" $< > $@
+ $(Verb) chmod 0755 $@
+
+all-local:: $(ToolDir)/gccld
+
+$(ToolDir)/gccld : gccld.sh Makefile
+ $(Echo) Making $(ToolDir)/gccld shell script.
+ $(Verb) sed "s#@TOOLDIR@#$(ToolDir)#" $< > $@
+ $(Verb) chmod 0755 $@
+
+clean-local::
+ $(Verb)$(RM) -f $(ToolDir)/gccld
diff --git a/tools/gccld/gccld.sh b/tools/gccld/gccld.sh
new file mode 100644
index 0000000..b092607
--- /dev/null
+++ b/tools/gccld/gccld.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+##===- tools/gccld/gccld.sh ------------------------------------*- bash -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+#
+# Synopsis: This shell script is a replacement for the old "gccld" tool that
+# existed in LLVM versions before 2.0. The functionality of gccld has
+# now been moved to llvm-ld. This shell script provides backwards
+# compatibility so build environments invoking gccld can still get
+# link (under the covers) with llvm-ld.
+#
+# Syntax: gccld OPTIONS... (see llvm-ld for details)
+#
+##===----------------------------------------------------------------------===##
+#
+echo "gccld: This tool is deprecated, please use llvm-ld" 1>&2
+TOOLDIR=@TOOLDIR@
+$TOOLDIR/llvm-ld "$@"
diff --git a/tools/gold/Makefile b/tools/gold/Makefile
new file mode 100644
index 0000000..f282a35
--- /dev/null
+++ b/tools/gold/Makefile
@@ -0,0 +1,30 @@
+#===- tools/gold/Makefile ----------------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+LIBRARYNAME = LLVMgold
+
+# Include this here so we can get the configuration of the targets
+# that have been configured for construction. We have to do this
+# early so we can set up LINK_COMPONENTS before including Makefile.rules
+include $(LEVEL)/Makefile.config
+
+LINK_LIBS_IN_SHARED=1
+SHARED_LIBRARY = 1
+BUILD_ARCHIVE = 0
+DONT_BUILD_RELINKED = 1
+
+LINK_COMPONENTS :=
+LIBS += -llto
+
+# Because off_t is used in the public API, the largefile parts are required for
+# ABI compatibility.
+CXXFLAGS+=-I$(BINUTILS_INCDIR) -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -lLTO
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/gold/README.txt b/tools/gold/README.txt
new file mode 100644
index 0000000..92ee3d1
--- /dev/null
+++ b/tools/gold/README.txt
@@ -0,0 +1,21 @@
+This directory contains a plugin that is designed to work with binutils
+gold linker. At present time, this is not the default linker in
+binutils, and the default build of gold does not support plugins.
+
+Obtaining binutils:
+
+ cvs -z 9 -d :pserver:anoncvs@sourceware.org:/cvs/src login
+ {enter "anoncvs" as the password}
+ cvs -z 9 -d :pserver:anoncvs@sourceware.org:/cvs/src co binutils
+
+This will create a src/ directory. Make a build/ directory and from
+there configure binutils with "../src/configure --enable-gold --enable-plugins".
+Then build binutils with "make all-gold".
+
+To build the LLVMgold plugin, configure LLVM with the option
+--with-binutils-include=/path/to/binutils/src/include/ --enable-pic. To use the
+plugin, run "ld-new --plugin /path/to/libLLVMgold.so".
+Without PIC libLTO and libLLVMgold are not being built (because they would fail
+link on x86-64 with a relocation error: PIC and non-PIC can't be combined).
+As an alternative to passing --enable-pic, you can use 'make ENABLE_PIC=1' in
+your entire LLVM build.
diff --git a/tools/gold/gold-plugin.cpp b/tools/gold/gold-plugin.cpp
new file mode 100644
index 0000000..86d3fd3
--- /dev/null
+++ b/tools/gold/gold-plugin.cpp
@@ -0,0 +1,394 @@
+//===-- gold-plugin.cpp - Plugin to gold for Link Time Optimization ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a gold plugin for LLVM. It provides an LLVM implementation of the
+// interface described in http://gcc.gnu.org/wiki/whopr/driver .
+//
+//===----------------------------------------------------------------------===//
+
+#include "plugin-api.h"
+
+#include "llvm-c/lto.h"
+
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Path.h"
+
+#include <cerrno>
+#include <cstdlib>
+#include <cstring>
+#include <fstream>
+#include <list>
+#include <vector>
+
+using namespace llvm;
+
+namespace {
+ ld_plugin_status discard_message(int level, const char *format, ...) {
+ // Die loudly. Recent versions of Gold pass ld_plugin_message as the first
+ // callback in the transfer vector. This should never be called.
+ abort();
+ }
+
+ ld_plugin_add_symbols add_symbols = NULL;
+ ld_plugin_get_symbols get_symbols = NULL;
+ ld_plugin_add_input_file add_input_file = NULL;
+ ld_plugin_message message = discard_message;
+
+ int api_version = 0;
+ int gold_version = 0;
+
+ bool generate_api_file = false;
+ const char *gcc_path = NULL;
+
+ struct claimed_file {
+ lto_module_t M;
+ void *handle;
+ std::vector<ld_plugin_symbol> syms;
+ };
+
+ lto_codegen_model output_type = LTO_CODEGEN_PIC_MODEL_STATIC;
+ std::list<claimed_file> Modules;
+ std::vector<sys::Path> Cleanup;
+}
+
+ld_plugin_status claim_file_hook(const ld_plugin_input_file *file,
+ int *claimed);
+ld_plugin_status all_symbols_read_hook(void);
+ld_plugin_status cleanup_hook(void);
+
+extern "C" ld_plugin_status onload(ld_plugin_tv *tv);
+ld_plugin_status onload(ld_plugin_tv *tv) {
+ // We're given a pointer to the first transfer vector. We read through them
+ // until we find one where tv_tag == LDPT_NULL. The REGISTER_* tagged values
+ // contain pointers to functions that we need to call to register our own
+ // hooks. The others are addresses of functions we can use to call into gold
+ // for services.
+
+ bool registeredClaimFile = false;
+ bool registeredAllSymbolsRead = false;
+ bool registeredCleanup = false;
+
+ for (; tv->tv_tag != LDPT_NULL; ++tv) {
+ switch (tv->tv_tag) {
+ case LDPT_API_VERSION:
+ api_version = tv->tv_u.tv_val;
+ break;
+ case LDPT_GOLD_VERSION: // major * 100 + minor
+ gold_version = tv->tv_u.tv_val;
+ break;
+ case LDPT_LINKER_OUTPUT:
+ switch (tv->tv_u.tv_val) {
+ case LDPO_REL: // .o
+ case LDPO_DYN: // .so
+ output_type = LTO_CODEGEN_PIC_MODEL_DYNAMIC;
+ break;
+ case LDPO_EXEC: // .exe
+ output_type = LTO_CODEGEN_PIC_MODEL_STATIC;
+ break;
+ default:
+ (*message)(LDPL_ERROR, "Unknown output file type %d",
+ tv->tv_u.tv_val);
+ return LDPS_ERR;
+ }
+ // TODO: add an option to disable PIC.
+ //output_type = LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC;
+ break;
+ case LDPT_OPTION:
+ if (strcmp("generate-api-file", tv->tv_u.tv_string) == 0) {
+ generate_api_file = true;
+ } else if (strncmp("gcc=", tv->tv_u.tv_string, 4) == 0) {
+ if (gcc_path) {
+ (*message)(LDPL_WARNING, "Path to gcc specified twice. "
+ "Discarding %s", tv->tv_u.tv_string);
+ } else {
+ gcc_path = strdup(tv->tv_u.tv_string + 4);
+ }
+ } else {
+ (*message)(LDPL_WARNING, "Ignoring flag %s", tv->tv_u.tv_string);
+ }
+ break;
+ case LDPT_REGISTER_CLAIM_FILE_HOOK: {
+ ld_plugin_register_claim_file callback;
+ callback = tv->tv_u.tv_register_claim_file;
+
+ if ((*callback)(claim_file_hook) != LDPS_OK)
+ return LDPS_ERR;
+
+ registeredClaimFile = true;
+ } break;
+ case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK: {
+ ld_plugin_register_all_symbols_read callback;
+ callback = tv->tv_u.tv_register_all_symbols_read;
+
+ if ((*callback)(all_symbols_read_hook) != LDPS_OK)
+ return LDPS_ERR;
+
+ registeredAllSymbolsRead = true;
+ } break;
+ case LDPT_REGISTER_CLEANUP_HOOK: {
+ ld_plugin_register_cleanup callback;
+ callback = tv->tv_u.tv_register_cleanup;
+
+ if ((*callback)(cleanup_hook) != LDPS_OK)
+ return LDPS_ERR;
+
+ registeredCleanup = true;
+ } break;
+ case LDPT_ADD_SYMBOLS:
+ add_symbols = tv->tv_u.tv_add_symbols;
+ break;
+ case LDPT_GET_SYMBOLS:
+ get_symbols = tv->tv_u.tv_get_symbols;
+ break;
+ case LDPT_ADD_INPUT_FILE:
+ add_input_file = tv->tv_u.tv_add_input_file;
+ break;
+ case LDPT_MESSAGE:
+ message = tv->tv_u.tv_message;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!registeredClaimFile) {
+ (*message)(LDPL_ERROR, "register_claim_file not passed to LLVMgold.");
+ return LDPS_ERR;
+ }
+ if (!add_symbols) {
+ (*message)(LDPL_ERROR, "add_symbols not passed to LLVMgold.");
+ return LDPS_ERR;
+ }
+
+ return LDPS_OK;
+}
+
+/// claim_file_hook - called by gold to see whether this file is one that
+/// our plugin can handle. We'll try to open it and register all the symbols
+/// with add_symbol if possible.
+ld_plugin_status claim_file_hook(const ld_plugin_input_file *file,
+ int *claimed) {
+ void *buf = NULL;
+ if (file->offset) {
+ // Gold has found what might be IR part-way inside of a file, such as
+ // an .a archive.
+ if (lseek(file->fd, file->offset, SEEK_SET) == -1) {
+ (*message)(LDPL_ERROR,
+ "Failed to seek to archive member of %s at offset %d: %s\n",
+ file->name,
+ file->offset, strerror(errno));
+ return LDPS_ERR;
+ }
+ buf = malloc(file->filesize);
+ if (!buf) {
+ (*message)(LDPL_ERROR,
+ "Failed to allocate buffer for archive member of size: %d\n",
+ file->filesize);
+ return LDPS_ERR;
+ }
+ if (read(file->fd, buf, file->filesize) != file->filesize) {
+ (*message)(LDPL_ERROR,
+ "Failed to read archive member of %s at offset %d: %s\n",
+ file->name,
+ file->offset,
+ strerror(errno));
+ free(buf);
+ return LDPS_ERR;
+ }
+ if (!lto_module_is_object_file_in_memory(buf, file->filesize)) {
+ free(buf);
+ return LDPS_OK;
+ }
+ } else if (!lto_module_is_object_file(file->name))
+ return LDPS_OK;
+
+ *claimed = 1;
+ Modules.resize(Modules.size() + 1);
+ claimed_file &cf = Modules.back();
+
+ cf.M = buf ? lto_module_create_from_memory(buf, file->filesize) :
+ lto_module_create(file->name);
+ free(buf);
+ if (!cf.M) {
+ (*message)(LDPL_ERROR, "Failed to create LLVM module: %s",
+ lto_get_error_message());
+ return LDPS_ERR;
+ }
+ cf.handle = file->handle;
+ unsigned sym_count = lto_module_get_num_symbols(cf.M);
+ cf.syms.reserve(sym_count);
+
+ for (unsigned i = 0; i != sym_count; ++i) {
+ lto_symbol_attributes attrs = lto_module_get_symbol_attribute(cf.M, i);
+ if ((attrs & LTO_SYMBOL_SCOPE_MASK) == LTO_SYMBOL_SCOPE_INTERNAL)
+ continue;
+
+ cf.syms.push_back(ld_plugin_symbol());
+ ld_plugin_symbol &sym = cf.syms.back();
+ sym.name = const_cast<char *>(lto_module_get_symbol_name(cf.M, i));
+ sym.version = NULL;
+
+ int scope = attrs & LTO_SYMBOL_SCOPE_MASK;
+ switch (scope) {
+ case LTO_SYMBOL_SCOPE_HIDDEN:
+ sym.visibility = LDPV_HIDDEN;
+ break;
+ case LTO_SYMBOL_SCOPE_PROTECTED:
+ sym.visibility = LDPV_PROTECTED;
+ break;
+ case 0: // extern
+ case LTO_SYMBOL_SCOPE_DEFAULT:
+ sym.visibility = LDPV_DEFAULT;
+ break;
+ default:
+ (*message)(LDPL_ERROR, "Unknown scope attribute: %d", scope);
+ return LDPS_ERR;
+ }
+
+ int definition = attrs & LTO_SYMBOL_DEFINITION_MASK;
+ switch (definition) {
+ case LTO_SYMBOL_DEFINITION_REGULAR:
+ sym.def = LDPK_DEF;
+ break;
+ case LTO_SYMBOL_DEFINITION_UNDEFINED:
+ sym.def = LDPK_UNDEF;
+ break;
+ case LTO_SYMBOL_DEFINITION_TENTATIVE:
+ sym.def = LDPK_COMMON;
+ break;
+ case LTO_SYMBOL_DEFINITION_WEAK:
+ sym.def = LDPK_WEAKDEF;
+ break;
+ case LTO_SYMBOL_DEFINITION_WEAKUNDEF:
+ sym.def = LDPK_WEAKUNDEF;
+ break;
+ default:
+ (*message)(LDPL_ERROR, "Unknown definition attribute: %d", definition);
+ return LDPS_ERR;
+ }
+
+ // LLVM never emits COMDAT.
+ sym.size = 0;
+ sym.comdat_key = NULL;
+
+ sym.resolution = LDPR_UNKNOWN;
+ }
+
+ cf.syms.reserve(cf.syms.size());
+
+ if (!cf.syms.empty()) {
+ if ((*add_symbols)(cf.handle, cf.syms.size(), &cf.syms[0]) != LDPS_OK) {
+ (*message)(LDPL_ERROR, "Unable to add symbols!");
+ return LDPS_ERR;
+ }
+ }
+
+ return LDPS_OK;
+}
+
+/// all_symbols_read_hook - gold informs us that all symbols have been read.
+/// At this point, we use get_symbols to see if any of our definitions have
+/// been overridden by a native object file. Then, perform optimization and
+/// codegen.
+ld_plugin_status all_symbols_read_hook(void) {
+ lto_code_gen_t cg = lto_codegen_create();
+
+ for (std::list<claimed_file>::iterator I = Modules.begin(),
+ E = Modules.end(); I != E; ++I)
+ lto_codegen_add_module(cg, I->M);
+
+ std::ofstream api_file;
+ if (generate_api_file) {
+ api_file.open("apifile.txt", std::ofstream::out | std::ofstream::trunc);
+ if (!api_file.is_open()) {
+ (*message)(LDPL_FATAL, "Unable to open apifile.txt for writing.");
+ abort();
+ }
+ }
+
+ // If we don't preserve any symbols, libLTO will assume that all symbols are
+ // needed. Keep all symbols unless we're producing a final executable.
+ if (output_type == LTO_CODEGEN_PIC_MODEL_STATIC) {
+ bool anySymbolsPreserved = false;
+ for (std::list<claimed_file>::iterator I = Modules.begin(),
+ E = Modules.end(); I != E; ++I) {
+ (*get_symbols)(I->handle, I->syms.size(), &I->syms[0]);
+ for (unsigned i = 0, e = I->syms.size(); i != e; i++) {
+ if (I->syms[i].resolution == LDPR_PREVAILING_DEF ||
+ (I->syms[i].def == LDPK_COMMON &&
+ I->syms[i].resolution == LDPR_RESOLVED_IR)) {
+ lto_codegen_add_must_preserve_symbol(cg, I->syms[i].name);
+ anySymbolsPreserved = true;
+
+ if (generate_api_file)
+ api_file << I->syms[i].name << "\n";
+ }
+ }
+ }
+
+ if (generate_api_file)
+ api_file.close();
+
+ if (!anySymbolsPreserved) {
+ // This entire file is unnecessary!
+ lto_codegen_dispose(cg);
+ return LDPS_OK;
+ }
+ }
+
+ lto_codegen_set_pic_model(cg, output_type);
+ lto_codegen_set_debug_model(cg, LTO_DEBUG_MODEL_DWARF);
+ if (gcc_path)
+ lto_codegen_set_gcc_path(cg, gcc_path);
+
+ size_t bufsize = 0;
+ const char *buffer = static_cast<const char *>(lto_codegen_compile(cg,
+ &bufsize));
+
+ std::string ErrMsg;
+
+ sys::Path uniqueObjPath("/tmp/llvmgold.o");
+ if (uniqueObjPath.createTemporaryFileOnDisk(true, &ErrMsg)) {
+ (*message)(LDPL_ERROR, "%s", ErrMsg.c_str());
+ return LDPS_ERR;
+ }
+ raw_fd_ostream *objFile = new raw_fd_ostream(uniqueObjPath.c_str(), true,
+ ErrMsg);
+ if (!ErrMsg.empty()) {
+ delete objFile;
+ (*message)(LDPL_ERROR, "%s", ErrMsg.c_str());
+ return LDPS_ERR;
+ }
+
+ objFile->write(buffer, bufsize);
+ objFile->close();
+
+ lto_codegen_dispose(cg);
+
+ if ((*add_input_file)(const_cast<char*>(uniqueObjPath.c_str())) != LDPS_OK) {
+ (*message)(LDPL_ERROR, "Unable to add .o file to the link.");
+ (*message)(LDPL_ERROR, "File left behind in: %s", uniqueObjPath.c_str());
+ return LDPS_ERR;
+ }
+
+ Cleanup.push_back(uniqueObjPath);
+
+ return LDPS_OK;
+}
+
+ld_plugin_status cleanup_hook(void) {
+ std::string ErrMsg;
+
+ for (int i = 0, e = Cleanup.size(); i != e; ++i)
+ if (Cleanup[i].eraseFromDisk(false, &ErrMsg))
+ (*message)(LDPL_ERROR, "Failed to delete '%s': %s", Cleanup[i].c_str(),
+ ErrMsg.c_str());
+
+ return LDPS_OK;
+}
diff --git a/tools/llc/CMakeLists.txt b/tools/llc/CMakeLists.txt
new file mode 100644
index 0000000..e98b5a2
--- /dev/null
+++ b/tools/llc/CMakeLists.txt
@@ -0,0 +1,5 @@
+set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} bitreader)
+
+add_llvm_tool(llc
+ llc.cpp
+ )
diff --git a/tools/llc/Makefile b/tools/llc/Makefile
new file mode 100644
index 0000000..8514040
--- /dev/null
+++ b/tools/llc/Makefile
@@ -0,0 +1,21 @@
+#===- tools/llc/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 = llc
+
+# Include this here so we can get the configuration of the targets
+# that have been configured for construction. We have to do this
+# early so we can set up LINK_COMPONENTS before including Makefile.rules
+include $(LEVEL)/Makefile.config
+
+LINK_COMPONENTS := $(TARGETS_TO_BUILD) bitreader
+
+include $(LLVM_SRC_ROOT)/Makefile.rules
+
diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp
new file mode 100644
index 0000000..4808f0e
--- /dev/null
+++ b/tools/llc/llc.cpp
@@ -0,0 +1,349 @@
+//===-- llc.cpp - Implement the LLVM Native Code Generator ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the llc code generator driver. It provides a convenient
+// command-line interface for generating native assembly-language code
+// or C code, given LLVM bitcode.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/CodeGen/FileWriters.h"
+#include "llvm/CodeGen/LinkAllCodegenComponents.h"
+#include "llvm/CodeGen/LinkAllAsmWriterComponents.h"
+#include "llvm/Target/SubtargetFeature.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetMachineRegistry.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Module.h"
+#include "llvm/ModuleProvider.h"
+#include "llvm/PassManager.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PluginLoader.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/RegistryParser.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/System/Signals.h"
+#include "llvm/Config/config.h"
+#include "llvm/LinkAllVMCore.h"
+#include <fstream>
+#include <iostream>
+#include <memory>
+using namespace llvm;
+
+// General options for llc. Other pass-specific options are specified
+// within the corresponding llc passes, and target-specific options
+// and back-end code generation options are specified with the target machine.
+//
+static cl::opt<std::string>
+InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-"));
+
+static cl::opt<std::string>
+OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"));
+
+static cl::opt<bool> Force("f", cl::desc("Overwrite output files"));
+
+// Determine optimization level.
+static cl::opt<char>
+OptLevel("O",
+ cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
+ "(default = '-O2')"),
+ cl::Prefix,
+ cl::ZeroOrMore,
+ cl::init(' '));
+
+static cl::opt<std::string>
+TargetTriple("mtriple", cl::desc("Override target triple for module"));
+
+static cl::opt<const TargetMachineRegistry::entry*, false,
+ RegistryParser<TargetMachine> >
+MArch("march", cl::desc("Architecture to generate code for:"));
+
+static cl::opt<std::string>
+MCPU("mcpu",
+ cl::desc("Target a specific cpu type (-mcpu=help for details)"),
+ cl::value_desc("cpu-name"),
+ cl::init(""));
+
+static cl::list<std::string>
+MAttrs("mattr",
+ cl::CommaSeparated,
+ cl::desc("Target specific attributes (-mattr=help for details)"),
+ cl::value_desc("a1,+a2,-a3,..."));
+
+cl::opt<TargetMachine::CodeGenFileType>
+FileType("filetype", cl::init(TargetMachine::AssemblyFile),
+ cl::desc("Choose a file type (not all types are supported by all targets):"),
+ cl::values(
+ clEnumValN(TargetMachine::AssemblyFile, "asm",
+ "Emit an assembly ('.s') file"),
+ clEnumValN(TargetMachine::ObjectFile, "obj",
+ "Emit a native object ('.o') file [experimental]"),
+ clEnumValN(TargetMachine::DynamicLibrary, "dynlib",
+ "Emit a native dynamic library ('.so') file"
+ " [experimental]"),
+ clEnumValEnd));
+
+cl::opt<bool> NoVerify("disable-verify", cl::Hidden,
+ cl::desc("Do not verify input module"));
+
+
+// GetFileNameRoot - Helper function to get the basename of a filename.
+static inline std::string
+GetFileNameRoot(const std::string &InputFilename) {
+ std::string IFN = InputFilename;
+ std::string outputFilename;
+ int Len = IFN.length();
+ if ((Len > 2) &&
+ IFN[Len-3] == '.' && IFN[Len-2] == 'b' && IFN[Len-1] == 'c') {
+ outputFilename = std::string(IFN.begin(), IFN.end()-3); // s/.bc/.s/
+ } else {
+ outputFilename = IFN;
+ }
+ return outputFilename;
+}
+
+static raw_ostream *GetOutputStream(const char *ProgName) {
+ if (OutputFilename != "") {
+ if (OutputFilename == "-")
+ return &outs();
+
+ // Specified an output filename?
+ if (!Force && std::ifstream(OutputFilename.c_str())) {
+ // If force is not specified, make sure not to overwrite a file!
+ std::cerr << ProgName << ": error opening '" << OutputFilename
+ << "': file exists!\n"
+ << "Use -f command line argument to force output\n";
+ return 0;
+ }
+ // Make sure that the Out file gets unlinked from the disk if we get a
+ // SIGINT
+ sys::RemoveFileOnSignal(sys::Path(OutputFilename));
+
+ std::string error;
+ raw_ostream *Out = new raw_fd_ostream(OutputFilename.c_str(), true, error);
+ if (!error.empty()) {
+ std::cerr << error << '\n';
+ delete Out;
+ return 0;
+ }
+
+ return Out;
+ }
+
+ if (InputFilename == "-") {
+ OutputFilename = "-";
+ return &outs();
+ }
+
+ OutputFilename = GetFileNameRoot(InputFilename);
+
+ bool Binary = false;
+ switch (FileType) {
+ case TargetMachine::AssemblyFile:
+ if (MArch->Name[0] == 'c') {
+ if (MArch->Name[1] == 0)
+ OutputFilename += ".cbe.c";
+ else if (MArch->Name[1] == 'p' && MArch->Name[2] == 'p')
+ OutputFilename += ".cpp";
+ else
+ OutputFilename += ".s";
+ } else
+ OutputFilename += ".s";
+ break;
+ case TargetMachine::ObjectFile:
+ OutputFilename += ".o";
+ Binary = true;
+ break;
+ case TargetMachine::DynamicLibrary:
+ OutputFilename += LTDL_SHLIB_EXT;
+ Binary = true;
+ break;
+ }
+
+ if (!Force && std::ifstream(OutputFilename.c_str())) {
+ // If force is not specified, make sure not to overwrite a file!
+ std::cerr << ProgName << ": error opening '" << OutputFilename
+ << "': file exists!\n"
+ << "Use -f command line argument to force output\n";
+ return 0;
+ }
+
+ // Make sure that the Out file gets unlinked from the disk if we get a
+ // SIGINT
+ sys::RemoveFileOnSignal(sys::Path(OutputFilename));
+
+ std::string error;
+ raw_ostream *Out = new raw_fd_ostream(OutputFilename.c_str(), Binary, error);
+ if (!error.empty()) {
+ std::cerr << error << '\n';
+ delete Out;
+ return 0;
+ }
+
+ return Out;
+}
+
+// main - Entry point for the llc compiler.
+//
+int main(int argc, char **argv) {
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n");
+
+ // Load the module to be compiled...
+ std::string ErrorMessage;
+ std::auto_ptr<Module> M;
+
+ std::auto_ptr<MemoryBuffer> Buffer(
+ MemoryBuffer::getFileOrSTDIN(InputFilename, &ErrorMessage));
+ if (Buffer.get())
+ M.reset(ParseBitcodeFile(Buffer.get(), &ErrorMessage));
+ if (M.get() == 0) {
+ std::cerr << argv[0] << ": bitcode didn't read correctly.\n";
+ std::cerr << "Reason: " << ErrorMessage << "\n";
+ return 1;
+ }
+ Module &mod = *M.get();
+
+ // If we are supposed to override the target triple, do so now.
+ if (!TargetTriple.empty())
+ mod.setTargetTriple(TargetTriple);
+
+ // Allocate target machine. First, check whether the user has
+ // explicitly specified an architecture to compile for.
+ if (MArch == 0) {
+ std::string Err;
+ MArch = TargetMachineRegistry::getClosestStaticTargetForModule(mod, Err);
+ if (MArch == 0) {
+ std::cerr << argv[0] << ": error auto-selecting target for module '"
+ << Err << "'. Please use the -march option to explicitly "
+ << "pick a target.\n";
+ return 1;
+ }
+ }
+
+ // Package up features to be passed to target/subtarget
+ std::string FeaturesStr;
+ if (MCPU.size() || MAttrs.size()) {
+ SubtargetFeatures Features;
+ Features.setCPU(MCPU);
+ for (unsigned i = 0; i != MAttrs.size(); ++i)
+ Features.AddFeature(MAttrs[i]);
+ FeaturesStr = Features.getString();
+ }
+
+ std::auto_ptr<TargetMachine> target(MArch->CtorFn(mod, FeaturesStr));
+ assert(target.get() && "Could not allocate target machine!");
+ TargetMachine &Target = *target.get();
+
+ // Figure out where we are going to send the output...
+ raw_ostream *Out = GetOutputStream(argv[0]);
+ if (Out == 0) return 1;
+
+ CodeGenOpt::Level OLvl = CodeGenOpt::Default;
+ switch (OptLevel) {
+ default:
+ std::cerr << argv[0] << ": invalid optimization level.\n";
+ return 1;
+ case ' ': break;
+ case '0': OLvl = CodeGenOpt::None; break;
+ case '1':
+ case '2': OLvl = CodeGenOpt::Default; break;
+ case '3': OLvl = CodeGenOpt::Aggressive; break;
+ }
+
+ // If this target requires addPassesToEmitWholeFile, do it now. This is
+ // used by strange things like the C backend.
+ if (Target.WantsWholeFile()) {
+ PassManager PM;
+ PM.add(new TargetData(*Target.getTargetData()));
+ if (!NoVerify)
+ PM.add(createVerifierPass());
+
+ // Ask the target to add backend passes as necessary.
+ if (Target.addPassesToEmitWholeFile(PM, *Out, FileType, OLvl)) {
+ std::cerr << argv[0] << ": target does not support generation of this"
+ << " file type!\n";
+ if (Out != &outs()) delete Out;
+ // And the Out file is empty and useless, so remove it now.
+ sys::Path(OutputFilename).eraseFromDisk();
+ return 1;
+ }
+ PM.run(mod);
+ } else {
+ // Build up all of the passes that we want to do to the module.
+ ExistingModuleProvider Provider(M.release());
+ FunctionPassManager Passes(&Provider);
+ Passes.add(new TargetData(*Target.getTargetData()));
+
+#ifndef NDEBUG
+ if (!NoVerify)
+ Passes.add(createVerifierPass());
+#endif
+
+ // Ask the target to add backend passes as necessary.
+ MachineCodeEmitter *MCE = 0;
+
+ // Override default to generate verbose assembly.
+ Target.setAsmVerbosityDefault(true);
+
+ switch (Target.addPassesToEmitFile(Passes, *Out, FileType, OLvl)) {
+ default:
+ assert(0 && "Invalid file model!");
+ return 1;
+ case FileModel::Error:
+ std::cerr << argv[0] << ": target does not support generation of this"
+ << " file type!\n";
+ if (Out != &outs()) delete Out;
+ // And the Out file is empty and useless, so remove it now.
+ sys::Path(OutputFilename).eraseFromDisk();
+ return 1;
+ case FileModel::AsmFile:
+ break;
+ case FileModel::MachOFile:
+ MCE = AddMachOWriter(Passes, *Out, Target);
+ break;
+ case FileModel::ElfFile:
+ MCE = AddELFWriter(Passes, *Out, Target);
+ break;
+ }
+
+ if (Target.addPassesToEmitFileFinish(Passes, MCE, OLvl)) {
+ std::cerr << argv[0] << ": target does not support generation of this"
+ << " file type!\n";
+ if (Out != &outs()) delete Out;
+ // And the Out file is empty and useless, so remove it now.
+ sys::Path(OutputFilename).eraseFromDisk();
+ return 1;
+ }
+
+ Passes.doInitialization();
+
+ // Run our queue of passes all at once now, efficiently.
+ // TODO: this could lazily stream functions out of the module.
+ for (Module::iterator I = mod.begin(), E = mod.end(); I != E; ++I)
+ if (!I->isDeclaration())
+ Passes.run(*I);
+
+ Passes.doFinalization();
+ }
+
+ // Delete the ostream if it's not a stdout stream
+ if (Out != &outs()) delete Out;
+
+ return 0;
+}
diff --git a/tools/lli/CMakeLists.txt b/tools/lli/CMakeLists.txt
new file mode 100644
index 0000000..ce70d46e
--- /dev/null
+++ b/tools/lli/CMakeLists.txt
@@ -0,0 +1,5 @@
+set(LLVM_LINK_COMPONENTS jit interpreter nativecodegen bitreader selectiondag)
+
+add_llvm_tool(lli
+ lli.cpp
+ )
diff --git a/tools/lli/Makefile b/tools/lli/Makefile
new file mode 100644
index 0000000..8f6eeed
--- /dev/null
+++ b/tools/lli/Makefile
@@ -0,0 +1,15 @@
+##===- tools/lli/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 := lli
+LINK_COMPONENTS := jit interpreter nativecodegen bitreader selectiondag
+
+# Enable JIT support
+include $(LEVEL)/Makefile.common
diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp
new file mode 100644
index 0000000..6d3cbbc
--- /dev/null
+++ b/tools/lli/lli.cpp
@@ -0,0 +1,214 @@
+//===- lli.cpp - LLVM Interpreter / Dynamic compiler ----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This utility provides a simple wrapper around the LLVM Execution Engines,
+// which allow the direct execution of LLVM programs through a Just-In-Time
+// compiler, or through an intepreter if no JIT is available for this platform.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Module.h"
+#include "llvm/ModuleProvider.h"
+#include "llvm/Type.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/CodeGen/LinkAllCodegenComponents.h"
+#include "llvm/ExecutionEngine/JIT.h"
+#include "llvm/ExecutionEngine/Interpreter.h"
+#include "llvm/ExecutionEngine/GenericValue.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PluginLoader.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/System/Process.h"
+#include "llvm/System/Signals.h"
+#include <iostream>
+#include <cerrno>
+using namespace llvm;
+
+namespace {
+ cl::opt<std::string>
+ InputFile(cl::desc("<input bitcode>"), cl::Positional, cl::init("-"));
+
+ cl::list<std::string>
+ InputArgv(cl::ConsumeAfter, cl::desc("<program arguments>..."));
+
+ cl::opt<bool> ForceInterpreter("force-interpreter",
+ cl::desc("Force interpretation: disable JIT"),
+ cl::init(false));
+
+ // Determine optimization level.
+ cl::opt<char>
+ OptLevel("O",
+ cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
+ "(default = '-O2')"),
+ cl::Prefix,
+ cl::ZeroOrMore,
+ cl::init(' '));
+
+ cl::opt<std::string>
+ TargetTriple("mtriple", cl::desc("Override target triple for module"));
+
+ cl::opt<std::string>
+ EntryFunc("entry-function",
+ cl::desc("Specify the entry function (default = 'main') "
+ "of the executable"),
+ cl::value_desc("function"),
+ cl::init("main"));
+
+ cl::opt<std::string>
+ FakeArgv0("fake-argv0",
+ cl::desc("Override the 'argv[0]' value passed into the executing"
+ " program"), cl::value_desc("executable"));
+
+ cl::opt<bool>
+ DisableCoreFiles("disable-core-files", cl::Hidden,
+ cl::desc("Disable emission of core files if possible"));
+
+ cl::opt<bool>
+ NoLazyCompilation("disable-lazy-compilation",
+ cl::desc("Disable JIT lazy compilation"),
+ cl::init(false));
+}
+
+static ExecutionEngine *EE = 0;
+
+static void do_shutdown() {
+ delete EE;
+ llvm_shutdown();
+}
+
+//===----------------------------------------------------------------------===//
+// main Driver function
+//
+int main(int argc, char **argv, char * const *envp) {
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+
+ atexit(do_shutdown); // Call llvm_shutdown() on exit.
+ cl::ParseCommandLineOptions(argc, argv,
+ "llvm interpreter & dynamic compiler\n");
+
+ // If the user doesn't want core files, disable them.
+ if (DisableCoreFiles)
+ sys::Process::PreventCoreFiles();
+
+ // Load the bitcode...
+ std::string ErrorMsg;
+ ModuleProvider *MP = NULL;
+ if (MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFile,&ErrorMsg)) {
+ MP = getBitcodeModuleProvider(Buffer, &ErrorMsg);
+ if (!MP) delete Buffer;
+ }
+
+ if (!MP) {
+ std::cerr << argv[0] << ": error loading program '" << InputFile << "': "
+ << ErrorMsg << "\n";
+ exit(1);
+ }
+
+ // Get the module as the MP could go away once EE takes over.
+ Module *Mod = NoLazyCompilation
+ ? MP->materializeModule(&ErrorMsg) : MP->getModule();
+ if (!Mod) {
+ std::cerr << argv[0] << ": bitcode didn't read correctly.\n";
+ std::cerr << "Reason: " << ErrorMsg << "\n";
+ exit(1);
+ }
+
+ // If we are supposed to override the target triple, do so now.
+ if (!TargetTriple.empty())
+ Mod->setTargetTriple(TargetTriple);
+
+ CodeGenOpt::Level OLvl = CodeGenOpt::Default;
+ switch (OptLevel) {
+ default:
+ std::cerr << argv[0] << ": invalid optimization level.\n";
+ return 1;
+ case ' ': break;
+ case '0': OLvl = CodeGenOpt::None; break;
+ case '1':
+ case '2': OLvl = CodeGenOpt::Default; break;
+ case '3': OLvl = CodeGenOpt::Aggressive; break;
+ }
+
+ EE = ExecutionEngine::create(MP, ForceInterpreter, &ErrorMsg, OLvl);
+ if (!EE && !ErrorMsg.empty()) {
+ std::cerr << argv[0] << ":error creating EE: " << ErrorMsg << "\n";
+ exit(1);
+ }
+
+ if (NoLazyCompilation)
+ EE->DisableLazyCompilation();
+
+ // If the user specifically requested an argv[0] to pass into the program,
+ // do it now.
+ if (!FakeArgv0.empty()) {
+ InputFile = FakeArgv0;
+ } else {
+ // Otherwise, if there is a .bc suffix on the executable strip it off, it
+ // might confuse the program.
+ if (InputFile.rfind(".bc") == InputFile.length() - 3)
+ InputFile.erase(InputFile.length() - 3);
+ }
+
+ // Add the module's name to the start of the vector of arguments to main().
+ InputArgv.insert(InputArgv.begin(), InputFile);
+
+ // Call the main function from M as if its signature were:
+ // int main (int argc, char **argv, const char **envp)
+ // using the contents of Args to determine argc & argv, and the contents of
+ // EnvVars to determine envp.
+ //
+ Function *EntryFn = Mod->getFunction(EntryFunc);
+ if (!EntryFn) {
+ std::cerr << '\'' << EntryFunc << "\' function not found in module.\n";
+ return -1;
+ }
+
+ // If the program doesn't explicitly call exit, we will need the Exit
+ // function later on to make an explicit call, so get the function now.
+ Constant *Exit = Mod->getOrInsertFunction("exit", Type::VoidTy,
+ Type::Int32Ty, NULL);
+
+ // Reset errno to zero on entry to main.
+ errno = 0;
+
+ // Run static constructors.
+ EE->runStaticConstructorsDestructors(false);
+
+ if (NoLazyCompilation) {
+ for (Module::iterator I = Mod->begin(), E = Mod->end(); I != E; ++I) {
+ Function *Fn = &*I;
+ if (Fn != EntryFn && !Fn->isDeclaration())
+ EE->getPointerToFunction(Fn);
+ }
+ }
+
+ // Run main.
+ int Result = EE->runFunctionAsMain(EntryFn, InputArgv, envp);
+
+ // Run static destructors.
+ EE->runStaticConstructorsDestructors(true);
+
+ // If the program didn't call exit explicitly, we should call it now.
+ // This ensures that any atexit handlers get called correctly.
+ if (Function *ExitF = dyn_cast<Function>(Exit)) {
+ std::vector<GenericValue> Args;
+ GenericValue ResultGV;
+ ResultGV.IntVal = APInt(32, Result);
+ Args.push_back(ResultGV);
+ EE->runFunction(ExitF, Args);
+ std::cerr << "ERROR: exit(" << Result << ") returned!\n";
+ abort();
+ } else {
+ std::cerr << "ERROR: exit defined with wrong prototype!\n";
+ abort();
+ }
+}
diff --git a/tools/llvm-ar/CMakeLists.txt b/tools/llvm-ar/CMakeLists.txt
new file mode 100644
index 0000000..c8b0b72
--- /dev/null
+++ b/tools/llvm-ar/CMakeLists.txt
@@ -0,0 +1,8 @@
+set(LLVM_LINK_COMPONENTS archive)
+set(LLVM_REQUIRES_EH 1)
+
+add_llvm_tool(llvm-ar
+ llvm-ar.cpp
+ )
+
+# TODO: Support check-local.
diff --git a/tools/llvm-ar/Makefile b/tools/llvm-ar/Makefile
new file mode 100644
index 0000000..e4fe4e8
--- /dev/null
+++ b/tools/llvm-ar/Makefile
@@ -0,0 +1,25 @@
+##===- tools/llvm-ar/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 = llvm-ar
+LINK_COMPONENTS = archive
+REQUIRES_EH := 1
+
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS = 1
+
+include $(LEVEL)/Makefile.common
+
+check-local::
+ $(Echo) Checking llvm-ar
+ $(Verb) $(ToolDir)/llvm-ar zRrS nada.a .
+ $(Verb) $(ToolDir)/llvm-ar tv nada.a | \
+ grep Debug/llvm-ar.d >/dev/null 2>&1
+ $(Verb) $(RM) -f nada.a
diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp
new file mode 100644
index 0000000..5d81fc7
--- /dev/null
+++ b/tools/llvm-ar/llvm-ar.cpp
@@ -0,0 +1,776 @@
+//===-- llvm-ar.cpp - LLVM archive librarian utility ----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Builds up (relatively) standard unix archive files (.a) containing LLVM
+// bitcode or other files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Module.h"
+#include "llvm/Bitcode/Archive.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/System/Signals.h"
+#include <iostream>
+#include <algorithm>
+#include <iomanip>
+#include <memory>
+using namespace llvm;
+
+// Option for compatibility with AIX, not used but must allow it to be present.
+static cl::opt<bool>
+X32Option ("X32_64", cl::Hidden,
+ cl::desc("Ignored option for compatibility with AIX"));
+
+// llvm-ar operation code and modifier flags. This must come first.
+static cl::opt<std::string>
+Options(cl::Positional, cl::Required, cl::desc("{operation}[modifiers]..."));
+
+// llvm-ar remaining positional arguments.
+static cl::list<std::string>
+RestOfArgs(cl::Positional, cl::OneOrMore,
+ cl::desc("[relpos] [count] <archive-file> [members]..."));
+
+// MoreHelp - Provide additional help output explaining the operations and
+// modifiers of llvm-ar. This object instructs the CommandLine library
+// to print the text of the constructor when the --help option is given.
+static cl::extrahelp MoreHelp(
+ "\nOPERATIONS:\n"
+ " d[NsS] - delete file(s) from the archive\n"
+ " m[abiSs] - move file(s) in the archive\n"
+ " p[kN] - print file(s) found in the archive\n"
+ " q[ufsS] - quick append file(s) to the archive\n"
+ " r[abfiuzRsS] - replace or insert file(s) into the archive\n"
+ " t - display contents of archive\n"
+ " x[No] - extract file(s) from the archive\n"
+ "\nMODIFIERS (operation specific):\n"
+ " [a] - put file(s) after [relpos]\n"
+ " [b] - put file(s) before [relpos] (same as [i])\n"
+ " [f] - truncate inserted file names\n"
+ " [i] - put file(s) before [relpos] (same as [b])\n"
+ " [k] - always print bitcode files (default is to skip them)\n"
+ " [N] - use instance [count] of name\n"
+ " [o] - preserve original dates\n"
+ " [P] - use full path names when matching\n"
+ " [R] - recurse through directories when inserting\n"
+ " [s] - create an archive index (cf. ranlib)\n"
+ " [S] - do not build a symbol table\n"
+ " [u] - update only files newer than archive contents\n"
+ " [z] - compress files before inserting/extracting\n"
+ "\nMODIFIERS (generic):\n"
+ " [c] - do not warn if the library had to be created\n"
+ " [v] - be verbose about actions taken\n"
+ " [V] - be *really* verbose about actions taken\n"
+);
+
+// This enumeration delineates the kinds of operations on an archive
+// that are permitted.
+enum ArchiveOperation {
+ NoOperation, ///< An operation hasn't been specified
+ Print, ///< Print the contents of the archive
+ Delete, ///< Delete the specified members
+ Move, ///< Move members to end or as given by {a,b,i} modifiers
+ QuickAppend, ///< Quickly append to end of archive
+ ReplaceOrInsert, ///< Replace or Insert members
+ DisplayTable, ///< Display the table of contents
+ Extract ///< Extract files back to file system
+};
+
+// Modifiers to follow operation to vary behavior
+bool AddAfter = false; ///< 'a' modifier
+bool AddBefore = false; ///< 'b' modifier
+bool Create = false; ///< 'c' modifier
+bool TruncateNames = false; ///< 'f' modifier
+bool InsertBefore = false; ///< 'i' modifier
+bool DontSkipBitcode = false; ///< 'k' modifier
+bool UseCount = false; ///< 'N' modifier
+bool OriginalDates = false; ///< 'o' modifier
+bool FullPath = false; ///< 'P' modifier
+bool RecurseDirectories = false; ///< 'R' modifier
+bool SymTable = true; ///< 's' & 'S' modifiers
+bool OnlyUpdate = false; ///< 'u' modifier
+bool Verbose = false; ///< 'v' modifier
+bool ReallyVerbose = false; ///< 'V' modifier
+bool Compression = false; ///< 'z' modifier
+
+// Relative Positional Argument (for insert/move). This variable holds
+// the name of the archive member to which the 'a', 'b' or 'i' modifier
+// refers. Only one of 'a', 'b' or 'i' can be specified so we only need
+// one variable.
+std::string RelPos;
+
+// Select which of multiple entries in the archive with the same name should be
+// used (specified with -N) for the delete and extract operations.
+int Count = 1;
+
+// This variable holds the name of the archive file as given on the
+// command line.
+std::string ArchiveName;
+
+// This variable holds the list of member files to proecess, as given
+// on the command line.
+std::vector<std::string> Members;
+
+// This variable holds the (possibly expanded) list of path objects that
+// correspond to files we will
+std::set<sys::Path> Paths;
+
+// The Archive object to which all the editing operations will be sent.
+Archive* TheArchive = 0;
+
+// getRelPos - Extract the member filename from the command line for
+// the [relpos] argument associated with a, b, and i modifiers
+void getRelPos() {
+ if(RestOfArgs.size() > 0) {
+ RelPos = RestOfArgs[0];
+ RestOfArgs.erase(RestOfArgs.begin());
+ }
+ else
+ throw "Expected [relpos] for a, b, or i modifier";
+}
+
+// getCount - Extract the [count] argument associated with the N modifier
+// from the command line and check its value.
+void getCount() {
+ if(RestOfArgs.size() > 0) {
+ Count = atoi(RestOfArgs[0].c_str());
+ RestOfArgs.erase(RestOfArgs.begin());
+ }
+ else
+ throw "Expected [count] value with N modifier";
+
+ // Non-positive counts are not allowed
+ if (Count < 1)
+ throw "Invalid [count] value (not a positive integer)";
+}
+
+// getArchive - Get the archive file name from the command line
+void getArchive() {
+ if(RestOfArgs.size() > 0) {
+ ArchiveName = RestOfArgs[0];
+ RestOfArgs.erase(RestOfArgs.begin());
+ }
+ else
+ throw "An archive name must be specified.";
+}
+
+// getMembers - Copy over remaining items in RestOfArgs to our Members vector
+// This is just for clarity.
+void getMembers() {
+ if(RestOfArgs.size() > 0)
+ Members = std::vector<std::string>(RestOfArgs);
+}
+
+// parseCommandLine - Parse the command line options as presented and return the
+// operation specified. Process all modifiers and check to make sure that
+// constraints on modifier/operation pairs have not been violated.
+ArchiveOperation parseCommandLine() {
+
+ // Keep track of number of operations. We can only specify one
+ // per execution.
+ unsigned NumOperations = 0;
+
+ // Keep track of the number of positional modifiers (a,b,i). Only
+ // one can be specified.
+ unsigned NumPositional = 0;
+
+ // Keep track of which operation was requested
+ ArchiveOperation Operation = NoOperation;
+
+ for(unsigned i=0; i<Options.size(); ++i) {
+ switch(Options[i]) {
+ case 'd': ++NumOperations; Operation = Delete; break;
+ case 'm': ++NumOperations; Operation = Move ; break;
+ case 'p': ++NumOperations; Operation = Print; break;
+ case 'q': ++NumOperations; Operation = QuickAppend; break;
+ case 'r': ++NumOperations; Operation = ReplaceOrInsert; break;
+ case 't': ++NumOperations; Operation = DisplayTable; break;
+ case 'x': ++NumOperations; Operation = Extract; break;
+ case 'c': Create = true; break;
+ case 'f': TruncateNames = true; break;
+ case 'k': DontSkipBitcode = true; break;
+ case 'l': /* accepted but unused */ break;
+ case 'o': OriginalDates = true; break;
+ case 'P': FullPath = true; break;
+ case 'R': RecurseDirectories = true; break;
+ case 's': SymTable = true; break;
+ case 'S': SymTable = false; break;
+ case 'u': OnlyUpdate = true; break;
+ case 'v': Verbose = true; break;
+ case 'V': Verbose = ReallyVerbose = true; break;
+ case 'z': Compression = true; break;
+ case 'a':
+ getRelPos();
+ AddAfter = true;
+ NumPositional++;
+ break;
+ case 'b':
+ getRelPos();
+ AddBefore = true;
+ NumPositional++;
+ break;
+ case 'i':
+ getRelPos();
+ InsertBefore = true;
+ NumPositional++;
+ break;
+ case 'N':
+ getCount();
+ UseCount = true;
+ break;
+ default:
+ cl::PrintHelpMessage();
+ }
+ }
+
+ // At this point, the next thing on the command line must be
+ // the archive name.
+ getArchive();
+
+ // Everything on the command line at this point is a member.
+ getMembers();
+
+ // Perform various checks on the operation/modifier specification
+ // to make sure we are dealing with a legal request.
+ if (NumOperations == 0)
+ throw "You must specify at least one of the operations";
+ if (NumOperations > 1)
+ throw "Only one operation may be specified";
+ if (NumPositional > 1)
+ throw "You may only specify one of a, b, and i modifiers";
+ if (AddAfter || AddBefore || InsertBefore)
+ if (Operation != Move && Operation != ReplaceOrInsert)
+ throw "The 'a', 'b' and 'i' modifiers can only be specified with "
+ "the 'm' or 'r' operations";
+ if (RecurseDirectories && Operation != ReplaceOrInsert)
+ throw "The 'R' modifiers is only applicabe to the 'r' operation";
+ if (OriginalDates && Operation != Extract)
+ throw "The 'o' modifier is only applicable to the 'x' operation";
+ if (TruncateNames && Operation!=QuickAppend && Operation!=ReplaceOrInsert)
+ throw "The 'f' modifier is only applicable to the 'q' and 'r' operations";
+ if (OnlyUpdate && Operation != ReplaceOrInsert)
+ throw "The 'u' modifier is only applicable to the 'r' operation";
+ if (Compression && Operation!=ReplaceOrInsert && Operation!=Extract)
+ throw "The 'z' modifier is only applicable to the 'r' and 'x' operations";
+ if (Count > 1 && Members.size() > 1)
+ throw "Only one member name may be specified with the 'N' modifier";
+
+ // Return the parsed operation to the caller
+ return Operation;
+}
+
+// recurseDirectories - Implements the "R" modifier. This function scans through
+// the Paths vector (built by buildPaths, below) and replaces any directories it
+// finds with all the files in that directory (recursively). It uses the
+// sys::Path::getDirectoryContent method to perform the actual directory scans.
+bool
+recurseDirectories(const sys::Path& path,
+ std::set<sys::Path>& result, std::string* ErrMsg) {
+ result.clear();
+ if (RecurseDirectories) {
+ std::set<sys::Path> content;
+ if (path.getDirectoryContents(content, ErrMsg))
+ return true;
+
+ for (std::set<sys::Path>::iterator I = content.begin(), E = content.end();
+ I != E; ++I) {
+ // Make sure it exists and is a directory
+ sys::PathWithStatus PwS(*I);
+ const sys::FileStatus *Status = PwS.getFileStatus(false, ErrMsg);
+ if (!Status)
+ return true;
+ if (Status->isDir) {
+ std::set<sys::Path> moreResults;
+ if (recurseDirectories(*I, moreResults, ErrMsg))
+ return true;
+ result.insert(moreResults.begin(), moreResults.end());
+ } else {
+ result.insert(*I);
+ }
+ }
+ }
+ return false;
+}
+
+// buildPaths - Convert the strings in the Members vector to sys::Path objects
+// and make sure they are valid and exist exist. This check is only needed for
+// the operations that add/replace files to the archive ('q' and 'r')
+bool buildPaths(bool checkExistence, std::string* ErrMsg) {
+ for (unsigned i = 0; i < Members.size(); i++) {
+ sys::Path aPath;
+ if (!aPath.set(Members[i]))
+ throw std::string("File member name invalid: ") + Members[i];
+ if (checkExistence) {
+ if (!aPath.exists())
+ throw std::string("File does not exist: ") + Members[i];
+ std::string Err;
+ sys::PathWithStatus PwS(aPath);
+ const sys::FileStatus *si = PwS.getFileStatus(false, &Err);
+ if (!si)
+ throw Err;
+ if (si->isDir) {
+ std::set<sys::Path> dirpaths;
+ if (recurseDirectories(aPath, dirpaths, ErrMsg))
+ return true;
+ Paths.insert(dirpaths.begin(),dirpaths.end());
+ } else {
+ Paths.insert(aPath);
+ }
+ } else {
+ Paths.insert(aPath);
+ }
+ }
+ return false;
+}
+
+// printSymbolTable - print out the archive's symbol table.
+void printSymbolTable() {
+ std::cout << "\nArchive Symbol Table:\n";
+ const Archive::SymTabType& symtab = TheArchive->getSymbolTable();
+ for (Archive::SymTabType::const_iterator I=symtab.begin(), E=symtab.end();
+ I != E; ++I ) {
+ unsigned offset = TheArchive->getFirstFileOffset() + I->second;
+ std::cout << " " << std::setw(9) << offset << "\t" << I->first <<"\n";
+ }
+}
+
+// doPrint - Implements the 'p' operation. This function traverses the archive
+// looking for members that match the path list. It is careful to uncompress
+// things that should be and to skip bitcode files unless the 'k' modifier was
+// given.
+bool doPrint(std::string* ErrMsg) {
+ if (buildPaths(false, ErrMsg))
+ return true;
+ unsigned countDown = Count;
+ for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end();
+ I != E; ++I ) {
+ if (Paths.empty() ||
+ (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) {
+ if (countDown == 1) {
+ const char* data = reinterpret_cast<const char*>(I->getData());
+
+ // Skip things that don't make sense to print
+ if (I->isLLVMSymbolTable() || I->isSVR4SymbolTable() ||
+ I->isBSD4SymbolTable() || (!DontSkipBitcode && I->isBitcode()))
+ continue;
+
+ if (Verbose)
+ std::cout << "Printing " << I->getPath().toString() << "\n";
+
+ unsigned len = I->getSize();
+ std::cout.write(data, len);
+ } else {
+ countDown--;
+ }
+ }
+ }
+ return false;
+}
+
+// putMode - utility function for printing out the file mode when the 't'
+// operation is in verbose mode.
+void
+printMode(unsigned mode) {
+ if (mode & 004)
+ std::cout << "r";
+ else
+ std::cout << "-";
+ if (mode & 002)
+ std::cout << "w";
+ else
+ std::cout << "-";
+ if (mode & 001)
+ std::cout << "x";
+ else
+ std::cout << "-";
+}
+
+// doDisplayTable - Implement the 't' operation. This function prints out just
+// the file names of each of the members. However, if verbose mode is requested
+// ('v' modifier) then the file type, permission mode, user, group, size, and
+// modification time are also printed.
+bool
+doDisplayTable(std::string* ErrMsg) {
+ if (buildPaths(false, ErrMsg))
+ return true;
+ for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end();
+ I != E; ++I ) {
+ if (Paths.empty() ||
+ (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) {
+ if (Verbose) {
+ // FIXME: Output should be this format:
+ // Zrw-r--r-- 500/ 500 525 Nov 8 17:42 2004 Makefile
+ if (I->isBitcode())
+ std::cout << "b";
+ else if (I->isCompressed())
+ std::cout << "Z";
+ else
+ std::cout << " ";
+ unsigned mode = I->getMode();
+ printMode((mode >> 6) & 007);
+ printMode((mode >> 3) & 007);
+ printMode(mode & 007);
+ std::cout << " " << std::setw(4) << I->getUser();
+ std::cout << "/" << std::setw(4) << I->getGroup();
+ std::cout << " " << std::setw(8) << I->getSize();
+ std::cout << " " << std::setw(20) <<
+ I->getModTime().toString().substr(4);
+ std::cout << " " << I->getPath().toString() << "\n";
+ } else {
+ std::cout << I->getPath().toString() << "\n";
+ }
+ }
+ }
+ if (ReallyVerbose)
+ printSymbolTable();
+ return false;
+}
+
+// doExtract - Implement the 'x' operation. This function extracts files back to
+// the file system, making sure to uncompress any that were compressed
+bool
+doExtract(std::string* ErrMsg) {
+ if (buildPaths(false, ErrMsg))
+ return true;
+ for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end();
+ I != E; ++I ) {
+ if (Paths.empty() ||
+ (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) {
+
+ // Make sure the intervening directories are created
+ if (I->hasPath()) {
+ sys::Path dirs(I->getPath());
+ dirs.eraseComponent();
+ if (dirs.createDirectoryOnDisk(/*create_parents=*/true, ErrMsg))
+ return true;
+ }
+
+ // Open up a file stream for writing
+ std::ios::openmode io_mode = std::ios::out | std::ios::trunc |
+ std::ios::binary;
+ std::ofstream file(I->getPath().c_str(), io_mode);
+
+ // Get the data and its length
+ const char* data = reinterpret_cast<const char*>(I->getData());
+ unsigned len = I->getSize();
+
+ // Write the data.
+ file.write(data,len);
+ file.close();
+
+ // If we're supposed to retain the original modification times, etc. do so
+ // now.
+ if (OriginalDates)
+ I->getPath().setStatusInfoOnDisk(I->getFileStatus());
+ }
+ }
+ return false;
+}
+
+// doDelete - Implement the delete operation. This function deletes zero or more
+// members from the archive. Note that if the count is specified, there should
+// be no more than one path in the Paths list or else this algorithm breaks.
+// That check is enforced in parseCommandLine (above).
+bool
+doDelete(std::string* ErrMsg) {
+ if (buildPaths(false, ErrMsg))
+ return true;
+ if (Paths.empty())
+ return false;
+ unsigned countDown = Count;
+ for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end();
+ I != E; ) {
+ if (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end()) {
+ if (countDown == 1) {
+ Archive::iterator J = I;
+ ++I;
+ TheArchive->erase(J);
+ } else
+ countDown--;
+ } else {
+ ++I;
+ }
+ }
+
+ // We're done editting, reconstruct the archive.
+ if (TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg))
+ return true;
+ if (ReallyVerbose)
+ printSymbolTable();
+ return false;
+}
+
+// doMore - Implement the move operation. This function re-arranges just the
+// order of the archive members so that when the archive is written the move
+// of the members is accomplished. Note the use of the RelPos variable to
+// determine where the items should be moved to.
+bool
+doMove(std::string* ErrMsg) {
+ if (buildPaths(false, ErrMsg))
+ return true;
+
+ // By default and convention the place to move members to is the end of the
+ // archive.
+ Archive::iterator moveto_spot = TheArchive->end();
+
+ // However, if the relative positioning modifiers were used, we need to scan
+ // the archive to find the member in question. If we don't find it, its no
+ // crime, we just move to the end.
+ if (AddBefore || InsertBefore || AddAfter) {
+ for (Archive::iterator I = TheArchive->begin(), E= TheArchive->end();
+ I != E; ++I ) {
+ if (RelPos == I->getPath().toString()) {
+ if (AddAfter) {
+ moveto_spot = I;
+ moveto_spot++;
+ } else {
+ moveto_spot = I;
+ }
+ break;
+ }
+ }
+ }
+
+ // Keep a list of the paths remaining to be moved
+ std::set<sys::Path> remaining(Paths);
+
+ // Scan the archive again, this time looking for the members to move to the
+ // moveto_spot.
+ for (Archive::iterator I = TheArchive->begin(), E= TheArchive->end();
+ I != E && !remaining.empty(); ++I ) {
+ std::set<sys::Path>::iterator found =
+ std::find(remaining.begin(),remaining.end(),I->getPath());
+ if (found != remaining.end()) {
+ if (I != moveto_spot)
+ TheArchive->splice(moveto_spot,*TheArchive,I);
+ remaining.erase(found);
+ }
+ }
+
+ // We're done editting, reconstruct the archive.
+ if (TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg))
+ return true;
+ if (ReallyVerbose)
+ printSymbolTable();
+ return false;
+}
+
+// doQuickAppend - Implements the 'q' operation. This function just
+// indiscriminantly adds the members to the archive and rebuilds it.
+bool
+doQuickAppend(std::string* ErrMsg) {
+ // Get the list of paths to append.
+ if (buildPaths(true, ErrMsg))
+ return true;
+ if (Paths.empty())
+ return false;
+
+ // Append them quickly.
+ for (std::set<sys::Path>::iterator PI = Paths.begin(), PE = Paths.end();
+ PI != PE; ++PI) {
+ if (TheArchive->addFileBefore(*PI,TheArchive->end(),ErrMsg))
+ return true;
+ }
+
+ // We're done editting, reconstruct the archive.
+ if (TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg))
+ return true;
+ if (ReallyVerbose)
+ printSymbolTable();
+ return false;
+}
+
+// doReplaceOrInsert - Implements the 'r' operation. This function will replace
+// any existing files or insert new ones into the archive.
+bool
+doReplaceOrInsert(std::string* ErrMsg) {
+
+ // Build the list of files to be added/replaced.
+ if (buildPaths(true, ErrMsg))
+ return true;
+ if (Paths.empty())
+ return false;
+
+ // Keep track of the paths that remain to be inserted.
+ std::set<sys::Path> remaining(Paths);
+
+ // Default the insertion spot to the end of the archive
+ Archive::iterator insert_spot = TheArchive->end();
+
+ // Iterate over the archive contents
+ for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end();
+ I != E && !remaining.empty(); ++I ) {
+
+ // Determine if this archive member matches one of the paths we're trying
+ // to replace.
+
+ std::set<sys::Path>::iterator found = remaining.end();
+ for (std::set<sys::Path>::iterator RI = remaining.begin(),
+ RE = remaining.end(); RI != RE; ++RI ) {
+ std::string compare(RI->toString());
+ if (TruncateNames && compare.length() > 15) {
+ const char* nm = compare.c_str();
+ unsigned len = compare.length();
+ size_t slashpos = compare.rfind('/');
+ if (slashpos != std::string::npos) {
+ nm += slashpos + 1;
+ len -= slashpos +1;
+ }
+ if (len > 15)
+ len = 15;
+ compare.assign(nm,len);
+ }
+ if (compare == I->getPath().toString()) {
+ found = RI;
+ break;
+ }
+ }
+
+ if (found != remaining.end()) {
+ std::string Err;
+ sys::PathWithStatus PwS(*found);
+ const sys::FileStatus *si = PwS.getFileStatus(false, &Err);
+ if (!si)
+ return true;
+ if (!si->isDir) {
+ if (OnlyUpdate) {
+ // Replace the item only if it is newer.
+ if (si->modTime > I->getModTime())
+ if (I->replaceWith(*found, ErrMsg))
+ return true;
+ } else {
+ // Replace the item regardless of time stamp
+ if (I->replaceWith(*found, ErrMsg))
+ return true;
+ }
+ } else {
+ // We purposefully ignore directories.
+ }
+
+ // Remove it from our "to do" list
+ remaining.erase(found);
+ }
+
+ // Determine if this is the place where we should insert
+ if ((AddBefore || InsertBefore) && (RelPos == I->getPath().toString()))
+ insert_spot = I;
+ else if (AddAfter && (RelPos == I->getPath().toString())) {
+ insert_spot = I;
+ insert_spot++;
+ }
+ }
+
+ // If we didn't replace all the members, some will remain and need to be
+ // inserted at the previously computed insert-spot.
+ if (!remaining.empty()) {
+ for (std::set<sys::Path>::iterator PI = remaining.begin(),
+ PE = remaining.end(); PI != PE; ++PI) {
+ if (TheArchive->addFileBefore(*PI,insert_spot, ErrMsg))
+ return true;
+ }
+ }
+
+ // We're done editting, reconstruct the archive.
+ if (TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg))
+ return true;
+ if (ReallyVerbose)
+ printSymbolTable();
+ return false;
+}
+
+// main - main program for llvm-ar .. see comments in the code
+int main(int argc, char **argv) {
+ // Print a stack trace if we signal out.
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+
+ // Have the command line options parsed and handle things
+ // like --help and --version.
+ cl::ParseCommandLineOptions(argc, argv,
+ "LLVM Archiver (llvm-ar)\n\n"
+ " This program archives bitcode files into single libraries\n"
+ );
+
+ int exitCode = 0;
+
+ // Make sure we don't exit with "unhandled exception".
+ try {
+ // Do our own parsing of the command line because the CommandLine utility
+ // can't handle the grouped positional parameters without a dash.
+ ArchiveOperation Operation = parseCommandLine();
+
+ // Check the path name of the archive
+ sys::Path ArchivePath;
+ if (!ArchivePath.set(ArchiveName))
+ throw std::string("Archive name invalid: ") + ArchiveName;
+
+ // Create or open the archive object.
+ if (!ArchivePath.exists()) {
+ // Produce a warning if we should and we're creating the archive
+ if (!Create)
+ std::cerr << argv[0] << ": creating " << ArchivePath.toString() << "\n";
+ TheArchive = Archive::CreateEmpty(ArchivePath);
+ TheArchive->writeToDisk();
+ } else {
+ std::string Error;
+ TheArchive = Archive::OpenAndLoad(ArchivePath, &Error);
+ if (TheArchive == 0) {
+ std::cerr << argv[0] << ": error loading '" << ArchivePath << "': "
+ << Error << "!\n";
+ return 1;
+ }
+ }
+
+ // Make sure we're not fooling ourselves.
+ assert(TheArchive && "Unable to instantiate the archive");
+
+ // Make sure we clean up the archive even on failure.
+ std::auto_ptr<Archive> AutoArchive(TheArchive);
+
+ // Perform the operation
+ std::string ErrMsg;
+ bool haveError = false;
+ switch (Operation) {
+ case Print: haveError = doPrint(&ErrMsg); break;
+ case Delete: haveError = doDelete(&ErrMsg); break;
+ case Move: haveError = doMove(&ErrMsg); break;
+ case QuickAppend: haveError = doQuickAppend(&ErrMsg); break;
+ case ReplaceOrInsert: haveError = doReplaceOrInsert(&ErrMsg); break;
+ case DisplayTable: haveError = doDisplayTable(&ErrMsg); break;
+ case Extract: haveError = doExtract(&ErrMsg); break;
+ case NoOperation:
+ std::cerr << argv[0] << ": No operation was selected.\n";
+ break;
+ }
+ if (haveError) {
+ std::cerr << argv[0] << ": " << ErrMsg << "\n";
+ return 1;
+ }
+ } catch (const char*msg) {
+ // These errors are usage errors, thrown only by the various checks in the
+ // code above.
+ std::cerr << argv[0] << ": " << msg << "\n\n";
+ cl::PrintHelpMessage();
+ exitCode = 1;
+ } catch (const std::string& msg) {
+ // These errors are thrown by LLVM libraries (e.g. lib System) and represent
+ // a more serious error so we bump the exitCode and don't print the usage.
+ std::cerr << argv[0] << ": " << msg << "\n";
+ exitCode = 2;
+ } catch (...) {
+ // This really shouldn't happen, but just in case ....
+ std::cerr << argv[0] << ": An unexpected unknown exception occurred.\n";
+ exitCode = 3;
+ }
+
+ // Return result code back to operating system.
+ return exitCode;
+}
diff --git a/tools/llvm-as/CMakeLists.txt b/tools/llvm-as/CMakeLists.txt
new file mode 100644
index 0000000..eef4a13
--- /dev/null
+++ b/tools/llvm-as/CMakeLists.txt
@@ -0,0 +1,6 @@
+set(LLVM_LINK_COMPONENTS asmparser bitwriter)
+set(LLVM_REQUIRES_EH 1)
+
+add_llvm_tool(llvm-as
+ llvm-as.cpp
+ )
diff --git a/tools/llvm-as/Makefile b/tools/llvm-as/Makefile
new file mode 100644
index 0000000..ae449c4
--- /dev/null
+++ b/tools/llvm-as/Makefile
@@ -0,0 +1,18 @@
+##===- tools/llvm-as/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 = llvm-as
+LINK_COMPONENTS := asmparser bitwriter
+REQUIRES_EH := 1
+
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS = 1
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/llvm-as/llvm-as.cpp b/tools/llvm-as/llvm-as.cpp
new file mode 100644
index 0000000..79ece8f
--- /dev/null
+++ b/tools/llvm-as/llvm-as.cpp
@@ -0,0 +1,149 @@
+//===--- llvm-as.cpp - The low-level LLVM assembler -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This utility may be invoked in the following manner:
+// llvm-as --help - Output information about command line switches
+// llvm-as [options] - Read LLVM asm from stdin, write bitcode to stdout
+// llvm-as [options] x.ll - Read LLVM asm from the x.ll file, write bitcode
+// to the x.bc file.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Module.h"
+#include "llvm/Assembly/Parser.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Streams.h"
+#include "llvm/Support/SystemUtils.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Signals.h"
+#include <fstream>
+#include <iostream>
+#include <memory>
+using namespace llvm;
+
+static cl::opt<std::string>
+InputFilename(cl::Positional, cl::desc("<input .llvm file>"), cl::init("-"));
+
+static cl::opt<std::string>
+OutputFilename("o", cl::desc("Override output filename"),
+ cl::value_desc("filename"));
+
+static cl::opt<bool>
+Force("f", cl::desc("Overwrite output files"));
+
+static cl::opt<bool>
+DisableOutput("disable-output", cl::desc("Disable output"), cl::init(false));
+
+static cl::opt<bool>
+DumpAsm("d", cl::desc("Print assembly as parsed"), cl::Hidden);
+
+static cl::opt<bool>
+DisableVerify("disable-verify", cl::Hidden,
+ cl::desc("Do not run verifier on input LLVM (dangerous!)"));
+
+int main(int argc, char **argv) {
+ // Print a stack trace if we signal out.
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ cl::ParseCommandLineOptions(argc, argv, "llvm .ll -> .bc assembler\n");
+
+ int exitCode = 0;
+ std::ostream *Out = 0;
+ try {
+ // Parse the file now...
+ ParseError Err;
+ std::auto_ptr<Module> M(ParseAssemblyFile(InputFilename, Err));
+ if (M.get() == 0) {
+ Err.PrintError(argv[0], errs());
+ return 1;
+ }
+
+ if (!DisableVerify) {
+ std::string Err;
+ if (verifyModule(*M.get(), ReturnStatusAction, &Err)) {
+ cerr << argv[0]
+ << ": assembly parsed, but does not verify as correct!\n";
+ cerr << Err;
+ return 1;
+ }
+ }
+
+ if (DumpAsm) cerr << "Here's the assembly:\n" << *M.get();
+
+ if (OutputFilename != "") { // Specified an output filename?
+ if (OutputFilename != "-") { // Not stdout?
+ if (!Force && std::ifstream(OutputFilename.c_str())) {
+ // If force is not specified, make sure not to overwrite a file!
+ cerr << argv[0] << ": error opening '" << OutputFilename
+ << "': file exists!\n"
+ << "Use -f command line argument to force output\n";
+ return 1;
+ }
+ Out = new std::ofstream(OutputFilename.c_str(), std::ios::out |
+ std::ios::trunc | std::ios::binary);
+ } else { // Specified stdout
+ // FIXME: cout is not binary!
+ Out = &std::cout;
+ }
+ } else {
+ if (InputFilename == "-") {
+ OutputFilename = "-";
+ Out = &std::cout;
+ } else {
+ std::string IFN = InputFilename;
+ int Len = IFN.length();
+ if (IFN[Len-3] == '.' && IFN[Len-2] == 'l' && IFN[Len-1] == 'l') {
+ // Source ends in .ll
+ OutputFilename = std::string(IFN.begin(), IFN.end()-3);
+ } else {
+ OutputFilename = IFN; // Append a .bc to it
+ }
+ OutputFilename += ".bc";
+
+ if (!Force && std::ifstream(OutputFilename.c_str())) {
+ // If force is not specified, make sure not to overwrite a file!
+ cerr << argv[0] << ": error opening '" << OutputFilename
+ << "': file exists!\n"
+ << "Use -f command line argument to force output\n";
+ return 1;
+ }
+
+ Out = new std::ofstream(OutputFilename.c_str(), std::ios::out |
+ std::ios::trunc | std::ios::binary);
+ // Make sure that the Out file gets unlinked from the disk if we get a
+ // SIGINT
+ sys::RemoveFileOnSignal(sys::Path(OutputFilename));
+ }
+ }
+
+ if (!Out->good()) {
+ cerr << argv[0] << ": error opening " << OutputFilename << "!\n";
+ return 1;
+ }
+
+ if (!DisableOutput)
+ if (Force || !CheckBitcodeOutputToConsole(Out,true))
+ WriteBitcodeToFile(M.get(), *Out);
+ } catch (const std::string& msg) {
+ cerr << argv[0] << ": " << msg << "\n";
+ exitCode = 1;
+ } catch (...) {
+ cerr << argv[0] << ": Unexpected unknown exception occurred.\n";
+ exitCode = 1;
+ }
+
+ if (Out != &std::cout) delete Out;
+ return exitCode;
+}
+
diff --git a/tools/llvm-bcanalyzer/CMakeLists.txt b/tools/llvm-bcanalyzer/CMakeLists.txt
new file mode 100644
index 0000000..732bc32
--- /dev/null
+++ b/tools/llvm-bcanalyzer/CMakeLists.txt
@@ -0,0 +1,6 @@
+set(LLVM_LINK_COMPONENTS bitreader)
+set(LLVM_REQUIRES_EH 1)
+
+add_llvm_tool(llvm-bcanalyzer
+ llvm-bcanalyzer.cpp
+ )
diff --git a/tools/llvm-bcanalyzer/Makefile b/tools/llvm-bcanalyzer/Makefile
new file mode 100644
index 0000000..251f758
--- /dev/null
+++ b/tools/llvm-bcanalyzer/Makefile
@@ -0,0 +1,18 @@
+##===- tools/llvm-bcanalyzer/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 = llvm-bcanalyzer
+LINK_COMPONENTS := bitreader
+REQUIRES_EH := 1
+
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS = 1
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
new file mode 100644
index 0000000..b401a21
--- /dev/null
+++ b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
@@ -0,0 +1,600 @@
+//===-- llvm-bcanalyzer.cpp - Bitcode Analyzer --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tool may be invoked in the following manner:
+// llvm-bcanalyzer [options] - Read LLVM bitcode from stdin
+// llvm-bcanalyzer [options] x.bc - Read LLVM bitcode from the x.bc file
+//
+// Options:
+// --help - Output information about command line switches
+// --dump - Dump low-level bitcode structure in readable format
+//
+// This tool provides analytical information about a bitcode file. It is
+// intended as an aid to developers of bitcode reading and writing software. It
+// produces on std::out a summary of the bitcode file that shows various
+// statistics about the contents of the file. By default this information is
+// detailed and contains information about individual bitcode blocks and the
+// functions in the module.
+// The tool is also able to print a bitcode file in a straight forward text
+// format that shows the containment and relationships of the information in
+// the bitcode file (-dump option).
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Bitcode/LLVMBitCodes.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/System/Signals.h"
+#include <map>
+#include <fstream>
+#include <iostream>
+#include <algorithm>
+using namespace llvm;
+
+static cl::opt<std::string>
+ InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-"));
+
+static cl::opt<std::string>
+ OutputFilename("-o", cl::init("-"), cl::desc("<output file>"));
+
+static cl::opt<bool> Dump("dump", cl::desc("Dump low level bitcode trace"));
+
+//===----------------------------------------------------------------------===//
+// Bitcode specific analysis.
+//===----------------------------------------------------------------------===//
+
+static cl::opt<bool> NoHistogram("disable-histogram",
+ cl::desc("Do not print per-code histogram"));
+
+static cl::opt<bool>
+NonSymbolic("non-symbolic",
+ cl::desc("Emit numberic info in dump even if"
+ " symbolic info is available"));
+
+/// CurStreamType - If we can sniff the flavor of this stream, we can produce
+/// better dump info.
+static enum {
+ UnknownBitstream,
+ LLVMIRBitstream
+} CurStreamType;
+
+
+/// GetBlockName - Return a symbolic block name if known, otherwise return
+/// null.
+static const char *GetBlockName(unsigned BlockID,
+ const BitstreamReader &StreamFile) {
+ // Standard blocks for all bitcode files.
+ if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) {
+ if (BlockID == bitc::BLOCKINFO_BLOCK_ID)
+ return "BLOCKINFO_BLOCK";
+ return 0;
+ }
+
+ // Check to see if we have a blockinfo record for this block, with a name.
+ if (const BitstreamReader::BlockInfo *Info =
+ StreamFile.getBlockInfo(BlockID)) {
+ if (!Info->Name.empty())
+ return Info->Name.c_str();
+ }
+
+
+ if (CurStreamType != LLVMIRBitstream) return 0;
+
+ switch (BlockID) {
+ default: return 0;
+ case bitc::MODULE_BLOCK_ID: return "MODULE_BLOCK";
+ case bitc::PARAMATTR_BLOCK_ID: return "PARAMATTR_BLOCK";
+ case bitc::TYPE_BLOCK_ID: return "TYPE_BLOCK";
+ case bitc::CONSTANTS_BLOCK_ID: return "CONSTANTS_BLOCK";
+ case bitc::FUNCTION_BLOCK_ID: return "FUNCTION_BLOCK";
+ case bitc::TYPE_SYMTAB_BLOCK_ID: return "TYPE_SYMTAB";
+ case bitc::VALUE_SYMTAB_BLOCK_ID: return "VALUE_SYMTAB";
+ }
+}
+
+/// GetCodeName - Return a symbolic code name if known, otherwise return
+/// null.
+static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
+ const BitstreamReader &StreamFile) {
+ // Standard blocks for all bitcode files.
+ if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) {
+ if (BlockID == bitc::BLOCKINFO_BLOCK_ID) {
+ switch (CodeID) {
+ default: return 0;
+ case bitc::BLOCKINFO_CODE_SETBID: return "SETBID";
+ case bitc::BLOCKINFO_CODE_BLOCKNAME: return "BLOCKNAME";
+ case bitc::BLOCKINFO_CODE_SETRECORDNAME: return "SETRECORDNAME";
+ }
+ }
+ return 0;
+ }
+
+ // Check to see if we have a blockinfo record for this record, with a name.
+ if (const BitstreamReader::BlockInfo *Info =
+ StreamFile.getBlockInfo(BlockID)) {
+ for (unsigned i = 0, e = Info->RecordNames.size(); i != e; ++i)
+ if (Info->RecordNames[i].first == CodeID)
+ return Info->RecordNames[i].second.c_str();
+ }
+
+
+ if (CurStreamType != LLVMIRBitstream) return 0;
+
+ switch (BlockID) {
+ default: return 0;
+ case bitc::MODULE_BLOCK_ID:
+ switch (CodeID) {
+ default: return 0;
+ case bitc::MODULE_CODE_VERSION: return "VERSION";
+ case bitc::MODULE_CODE_TRIPLE: return "TRIPLE";
+ case bitc::MODULE_CODE_DATALAYOUT: return "DATALAYOUT";
+ case bitc::MODULE_CODE_ASM: return "ASM";
+ case bitc::MODULE_CODE_SECTIONNAME: return "SECTIONNAME";
+ case bitc::MODULE_CODE_DEPLIB: return "DEPLIB";
+ case bitc::MODULE_CODE_GLOBALVAR: return "GLOBALVAR";
+ case bitc::MODULE_CODE_FUNCTION: return "FUNCTION";
+ case bitc::MODULE_CODE_ALIAS: return "ALIAS";
+ case bitc::MODULE_CODE_PURGEVALS: return "PURGEVALS";
+ case bitc::MODULE_CODE_GCNAME: return "GCNAME";
+ }
+ case bitc::PARAMATTR_BLOCK_ID:
+ switch (CodeID) {
+ default: return 0;
+ case bitc::PARAMATTR_CODE_ENTRY: return "ENTRY";
+ }
+ case bitc::TYPE_BLOCK_ID:
+ switch (CodeID) {
+ default: return 0;
+ case bitc::TYPE_CODE_NUMENTRY: return "NUMENTRY";
+ case bitc::TYPE_CODE_VOID: return "VOID";
+ case bitc::TYPE_CODE_FLOAT: return "FLOAT";
+ case bitc::TYPE_CODE_DOUBLE: return "DOUBLE";
+ case bitc::TYPE_CODE_LABEL: return "LABEL";
+ case bitc::TYPE_CODE_OPAQUE: return "OPAQUE";
+ case bitc::TYPE_CODE_INTEGER: return "INTEGER";
+ case bitc::TYPE_CODE_POINTER: return "POINTER";
+ case bitc::TYPE_CODE_FUNCTION: return "FUNCTION";
+ case bitc::TYPE_CODE_STRUCT: return "STRUCT";
+ case bitc::TYPE_CODE_ARRAY: return "ARRAY";
+ case bitc::TYPE_CODE_VECTOR: return "VECTOR";
+ case bitc::TYPE_CODE_X86_FP80: return "X86_FP80";
+ case bitc::TYPE_CODE_FP128: return "FP128";
+ case bitc::TYPE_CODE_PPC_FP128: return "PPC_FP128";
+ case bitc::TYPE_CODE_METADATA: return "METADATA";
+ }
+
+ case bitc::CONSTANTS_BLOCK_ID:
+ switch (CodeID) {
+ default: return 0;
+ case bitc::CST_CODE_SETTYPE: return "SETTYPE";
+ case bitc::CST_CODE_NULL: return "NULL";
+ case bitc::CST_CODE_UNDEF: return "UNDEF";
+ case bitc::CST_CODE_INTEGER: return "INTEGER";
+ case bitc::CST_CODE_WIDE_INTEGER: return "WIDE_INTEGER";
+ case bitc::CST_CODE_FLOAT: return "FLOAT";
+ case bitc::CST_CODE_AGGREGATE: return "AGGREGATE";
+ case bitc::CST_CODE_STRING: return "STRING";
+ case bitc::CST_CODE_CSTRING: return "CSTRING";
+ case bitc::CST_CODE_CE_BINOP: return "CE_BINOP";
+ case bitc::CST_CODE_CE_CAST: return "CE_CAST";
+ case bitc::CST_CODE_CE_GEP: return "CE_GEP";
+ case bitc::CST_CODE_CE_SELECT: return "CE_SELECT";
+ case bitc::CST_CODE_CE_EXTRACTELT: return "CE_EXTRACTELT";
+ case bitc::CST_CODE_CE_INSERTELT: return "CE_INSERTELT";
+ case bitc::CST_CODE_CE_SHUFFLEVEC: return "CE_SHUFFLEVEC";
+ case bitc::CST_CODE_CE_CMP: return "CE_CMP";
+ case bitc::CST_CODE_INLINEASM: return "INLINEASM";
+ case bitc::CST_CODE_CE_SHUFVEC_EX: return "CE_SHUFVEC_EX";
+ case bitc::CST_CODE_MDSTRING: return "MDSTRING";
+ case bitc::CST_CODE_MDNODE: return "MDNODE";
+ }
+ case bitc::FUNCTION_BLOCK_ID:
+ switch (CodeID) {
+ default: return 0;
+ case bitc::FUNC_CODE_DECLAREBLOCKS: return "DECLAREBLOCKS";
+
+ case bitc::FUNC_CODE_INST_BINOP: return "INST_BINOP";
+ case bitc::FUNC_CODE_INST_CAST: return "INST_CAST";
+ case bitc::FUNC_CODE_INST_GEP: return "INST_GEP";
+ case bitc::FUNC_CODE_INST_SELECT: return "INST_SELECT";
+ case bitc::FUNC_CODE_INST_EXTRACTELT: return "INST_EXTRACTELT";
+ case bitc::FUNC_CODE_INST_INSERTELT: return "INST_INSERTELT";
+ case bitc::FUNC_CODE_INST_SHUFFLEVEC: return "INST_SHUFFLEVEC";
+ case bitc::FUNC_CODE_INST_CMP: return "INST_CMP";
+
+ case bitc::FUNC_CODE_INST_RET: return "INST_RET";
+ case bitc::FUNC_CODE_INST_BR: return "INST_BR";
+ case bitc::FUNC_CODE_INST_SWITCH: return "INST_SWITCH";
+ case bitc::FUNC_CODE_INST_INVOKE: return "INST_INVOKE";
+ case bitc::FUNC_CODE_INST_UNWIND: return "INST_UNWIND";
+ case bitc::FUNC_CODE_INST_UNREACHABLE: return "INST_UNREACHABLE";
+
+ case bitc::FUNC_CODE_INST_PHI: return "INST_PHI";
+ case bitc::FUNC_CODE_INST_MALLOC: return "INST_MALLOC";
+ case bitc::FUNC_CODE_INST_FREE: return "INST_FREE";
+ case bitc::FUNC_CODE_INST_ALLOCA: return "INST_ALLOCA";
+ case bitc::FUNC_CODE_INST_LOAD: return "INST_LOAD";
+ case bitc::FUNC_CODE_INST_STORE: return "INST_STORE";
+ case bitc::FUNC_CODE_INST_CALL: return "INST_CALL";
+ case bitc::FUNC_CODE_INST_VAARG: return "INST_VAARG";
+ case bitc::FUNC_CODE_INST_STORE2: return "INST_STORE2";
+ case bitc::FUNC_CODE_INST_GETRESULT: return "INST_GETRESULT";
+ case bitc::FUNC_CODE_INST_EXTRACTVAL: return "INST_EXTRACTVAL";
+ case bitc::FUNC_CODE_INST_INSERTVAL: return "INST_INSERTVAL";
+ case bitc::FUNC_CODE_INST_CMP2: return "INST_CMP2";
+ case bitc::FUNC_CODE_INST_VSELECT: return "INST_VSELECT";
+ }
+ case bitc::TYPE_SYMTAB_BLOCK_ID:
+ switch (CodeID) {
+ default: return 0;
+ case bitc::TST_CODE_ENTRY: return "ENTRY";
+ }
+ case bitc::VALUE_SYMTAB_BLOCK_ID:
+ switch (CodeID) {
+ default: return 0;
+ case bitc::VST_CODE_ENTRY: return "ENTRY";
+ case bitc::VST_CODE_BBENTRY: return "BBENTRY";
+ }
+ }
+}
+
+struct PerRecordStats {
+ unsigned NumInstances;
+ unsigned NumAbbrev;
+ uint64_t TotalBits;
+
+ PerRecordStats() : NumInstances(0), NumAbbrev(0), TotalBits(0) {}
+};
+
+struct PerBlockIDStats {
+ /// NumInstances - This the number of times this block ID has been seen.
+ unsigned NumInstances;
+
+ /// NumBits - The total size in bits of all of these blocks.
+ uint64_t NumBits;
+
+ /// NumSubBlocks - The total number of blocks these blocks contain.
+ unsigned NumSubBlocks;
+
+ /// NumAbbrevs - The total number of abbreviations.
+ unsigned NumAbbrevs;
+
+ /// NumRecords - The total number of records these blocks contain, and the
+ /// number that are abbreviated.
+ unsigned NumRecords, NumAbbreviatedRecords;
+
+ /// CodeFreq - Keep track of the number of times we see each code.
+ std::vector<PerRecordStats> CodeFreq;
+
+ PerBlockIDStats()
+ : NumInstances(0), NumBits(0),
+ NumSubBlocks(0), NumAbbrevs(0), NumRecords(0), NumAbbreviatedRecords(0) {}
+};
+
+static std::map<unsigned, PerBlockIDStats> BlockIDStats;
+
+
+
+/// Error - All bitcode analysis errors go through this function, making this a
+/// good place to breakpoint if debugging.
+static bool Error(const std::string &Err) {
+ std::cerr << Err << "\n";
+ return true;
+}
+
+/// ParseBlock - Read a block, updating statistics, etc.
+static bool ParseBlock(BitstreamCursor &Stream, unsigned IndentLevel) {
+ std::string Indent(IndentLevel*2, ' ');
+ uint64_t BlockBitStart = Stream.GetCurrentBitNo();
+ unsigned BlockID = Stream.ReadSubBlockID();
+
+ // Get the statistics for this BlockID.
+ PerBlockIDStats &BlockStats = BlockIDStats[BlockID];
+
+ BlockStats.NumInstances++;
+
+ // BLOCKINFO is a special part of the stream.
+ if (BlockID == bitc::BLOCKINFO_BLOCK_ID) {
+ if (Dump) std::cerr << Indent << "<BLOCKINFO_BLOCK/>\n";
+ if (Stream.ReadBlockInfoBlock())
+ return Error("Malformed BlockInfoBlock");
+ uint64_t BlockBitEnd = Stream.GetCurrentBitNo();
+ BlockStats.NumBits += BlockBitEnd-BlockBitStart;
+ return false;
+ }
+
+ unsigned NumWords = 0;
+ if (Stream.EnterSubBlock(BlockID, &NumWords))
+ return Error("Malformed block record");
+
+ const char *BlockName = 0;
+ if (Dump) {
+ std::cerr << Indent << "<";
+ if ((BlockName = GetBlockName(BlockID, *Stream.getBitStreamReader())))
+ std::cerr << BlockName;
+ else
+ std::cerr << "UnknownBlock" << BlockID;
+
+ if (NonSymbolic && BlockName)
+ std::cerr << " BlockID=" << BlockID;
+
+ std::cerr << " NumWords=" << NumWords
+ << " BlockCodeSize=" << Stream.GetAbbrevIDWidth() << ">\n";
+ }
+
+ SmallVector<uint64_t, 64> Record;
+
+ // Read all the records for this block.
+ while (1) {
+ if (Stream.AtEndOfStream())
+ return Error("Premature end of bitstream");
+
+ uint64_t RecordStartBit = Stream.GetCurrentBitNo();
+
+ // Read the code for this record.
+ unsigned AbbrevID = Stream.ReadCode();
+ switch (AbbrevID) {
+ case bitc::END_BLOCK: {
+ if (Stream.ReadBlockEnd())
+ return Error("Error at end of block");
+ uint64_t BlockBitEnd = Stream.GetCurrentBitNo();
+ BlockStats.NumBits += BlockBitEnd-BlockBitStart;
+ if (Dump) {
+ std::cerr << Indent << "</";
+ if (BlockName)
+ std::cerr << BlockName << ">\n";
+ else
+ std::cerr << "UnknownBlock" << BlockID << ">\n";
+ }
+ return false;
+ }
+ case bitc::ENTER_SUBBLOCK: {
+ uint64_t SubBlockBitStart = Stream.GetCurrentBitNo();
+ if (ParseBlock(Stream, IndentLevel+1))
+ return true;
+ ++BlockStats.NumSubBlocks;
+ uint64_t SubBlockBitEnd = Stream.GetCurrentBitNo();
+
+ // Don't include subblock sizes in the size of this block.
+ BlockBitStart += SubBlockBitEnd-SubBlockBitStart;
+ break;
+ }
+ case bitc::DEFINE_ABBREV:
+ Stream.ReadAbbrevRecord();
+ ++BlockStats.NumAbbrevs;
+ break;
+ default:
+ Record.clear();
+
+ ++BlockStats.NumRecords;
+ if (AbbrevID != bitc::UNABBREV_RECORD)
+ ++BlockStats.NumAbbreviatedRecords;
+
+ const char *BlobStart = 0;
+ unsigned BlobLen = 0;
+ unsigned Code = Stream.ReadRecord(AbbrevID, Record, BlobStart, BlobLen);
+
+
+
+ // Increment the # occurrences of this code.
+ if (BlockStats.CodeFreq.size() <= Code)
+ BlockStats.CodeFreq.resize(Code+1);
+ BlockStats.CodeFreq[Code].NumInstances++;
+ BlockStats.CodeFreq[Code].TotalBits +=
+ Stream.GetCurrentBitNo()-RecordStartBit;
+ if (AbbrevID != bitc::UNABBREV_RECORD)
+ BlockStats.CodeFreq[Code].NumAbbrev++;
+
+ if (Dump) {
+ std::cerr << Indent << " <";
+ if (const char *CodeName =
+ GetCodeName(Code, BlockID, *Stream.getBitStreamReader()))
+ std::cerr << CodeName;
+ else
+ std::cerr << "UnknownCode" << Code;
+ if (NonSymbolic &&
+ GetCodeName(Code, BlockID, *Stream.getBitStreamReader()))
+ std::cerr << " codeid=" << Code;
+ if (AbbrevID != bitc::UNABBREV_RECORD)
+ std::cerr << " abbrevid=" << AbbrevID;
+
+ for (unsigned i = 0, e = Record.size(); i != e; ++i)
+ std::cerr << " op" << i << "=" << (int64_t)Record[i];
+
+ std::cerr << "/>";
+
+ if (BlobStart) {
+ std::cerr << " blob data = ";
+ bool BlobIsPrintable = true;
+ for (unsigned i = 0; i != BlobLen; ++i)
+ if (!isprint(BlobStart[i])) {
+ BlobIsPrintable = false;
+ break;
+ }
+
+ if (BlobIsPrintable)
+ std::cerr << "'" << std::string(BlobStart, BlobStart+BlobLen) <<"'";
+ else
+ std::cerr << "unprintable, " << BlobLen << " bytes.";
+ }
+
+ std::cerr << "\n";
+ }
+
+ break;
+ }
+ }
+}
+
+static void PrintSize(double Bits) {
+ fprintf(stderr, "%.2f/%.2fB/%lluW", Bits, Bits/8,(unsigned long long)Bits/32);
+}
+static void PrintSize(uint64_t Bits) {
+ fprintf(stderr, "%llub/%.2fB/%lluW", (unsigned long long)Bits,
+ (double)Bits/8, (unsigned long long)Bits/32);
+}
+
+
+/// AnalyzeBitcode - Analyze the bitcode file specified by InputFilename.
+static int AnalyzeBitcode() {
+ // Read the input file.
+ MemoryBuffer *MemBuf = MemoryBuffer::getFileOrSTDIN(InputFilename.c_str());
+
+ if (MemBuf == 0)
+ return Error("Error reading '" + InputFilename + "'.");
+
+ if (MemBuf->getBufferSize() & 3)
+ return Error("Bitcode stream should be a multiple of 4 bytes in length");
+
+ unsigned char *BufPtr = (unsigned char *)MemBuf->getBufferStart();
+ unsigned char *EndBufPtr = BufPtr+MemBuf->getBufferSize();
+
+ // If we have a wrapper header, parse it and ignore the non-bc file contents.
+ // The magic number is 0x0B17C0DE stored in little endian.
+ if (isBitcodeWrapper(BufPtr, EndBufPtr))
+ if (SkipBitcodeWrapperHeader(BufPtr, EndBufPtr))
+ return Error("Invalid bitcode wrapper header");
+
+ BitstreamReader StreamFile(BufPtr, EndBufPtr);
+ BitstreamCursor Stream(StreamFile);
+ StreamFile.CollectBlockInfoNames();
+
+ // Read the stream signature.
+ char Signature[6];
+ Signature[0] = Stream.Read(8);
+ Signature[1] = Stream.Read(8);
+ Signature[2] = Stream.Read(4);
+ Signature[3] = Stream.Read(4);
+ Signature[4] = Stream.Read(4);
+ Signature[5] = Stream.Read(4);
+
+ // Autodetect the file contents, if it is one we know.
+ CurStreamType = UnknownBitstream;
+ if (Signature[0] == 'B' && Signature[1] == 'C' &&
+ Signature[2] == 0x0 && Signature[3] == 0xC &&
+ Signature[4] == 0xE && Signature[5] == 0xD)
+ CurStreamType = LLVMIRBitstream;
+
+ unsigned NumTopBlocks = 0;
+
+ // Parse the top-level structure. We only allow blocks at the top-level.
+ while (!Stream.AtEndOfStream()) {
+ unsigned Code = Stream.ReadCode();
+ if (Code != bitc::ENTER_SUBBLOCK)
+ return Error("Invalid record at top-level");
+
+ if (ParseBlock(Stream, 0))
+ return true;
+ ++NumTopBlocks;
+ }
+
+ if (Dump) std::cerr << "\n\n";
+
+ uint64_t BufferSizeBits = (EndBufPtr-BufPtr)*CHAR_BIT;
+ // Print a summary of the read file.
+ std::cerr << "Summary of " << InputFilename << ":\n";
+ std::cerr << " Total size: ";
+ PrintSize(BufferSizeBits);
+ std::cerr << "\n";
+ std::cerr << " Stream type: ";
+ switch (CurStreamType) {
+ default: assert(0 && "Unknown bitstream type");
+ case UnknownBitstream: std::cerr << "unknown\n"; break;
+ case LLVMIRBitstream: std::cerr << "LLVM IR\n"; break;
+ }
+ std::cerr << " # Toplevel Blocks: " << NumTopBlocks << "\n";
+ std::cerr << "\n";
+
+ // Emit per-block stats.
+ std::cerr << "Per-block Summary:\n";
+ for (std::map<unsigned, PerBlockIDStats>::iterator I = BlockIDStats.begin(),
+ E = BlockIDStats.end(); I != E; ++I) {
+ std::cerr << " Block ID #" << I->first;
+ if (const char *BlockName = GetBlockName(I->first, StreamFile))
+ std::cerr << " (" << BlockName << ")";
+ std::cerr << ":\n";
+
+ const PerBlockIDStats &Stats = I->second;
+ std::cerr << " Num Instances: " << Stats.NumInstances << "\n";
+ std::cerr << " Total Size: ";
+ PrintSize(Stats.NumBits);
+ std::cerr << "\n";
+ std::cerr << " % of file: "
+ << Stats.NumBits/(double)BufferSizeBits*100 << "\n";
+ if (Stats.NumInstances > 1) {
+ std::cerr << " Average Size: ";
+ PrintSize(Stats.NumBits/(double)Stats.NumInstances);
+ std::cerr << "\n";
+ std::cerr << " Tot/Avg SubBlocks: " << Stats.NumSubBlocks << "/"
+ << Stats.NumSubBlocks/(double)Stats.NumInstances << "\n";
+ std::cerr << " Tot/Avg Abbrevs: " << Stats.NumAbbrevs << "/"
+ << Stats.NumAbbrevs/(double)Stats.NumInstances << "\n";
+ std::cerr << " Tot/Avg Records: " << Stats.NumRecords << "/"
+ << Stats.NumRecords/(double)Stats.NumInstances << "\n";
+ } else {
+ std::cerr << " Num SubBlocks: " << Stats.NumSubBlocks << "\n";
+ std::cerr << " Num Abbrevs: " << Stats.NumAbbrevs << "\n";
+ std::cerr << " Num Records: " << Stats.NumRecords << "\n";
+ }
+ if (Stats.NumRecords)
+ std::cerr << " % Abbrev Recs: " << (Stats.NumAbbreviatedRecords/
+ (double)Stats.NumRecords)*100 << "\n";
+ std::cerr << "\n";
+
+ // Print a histogram of the codes we see.
+ if (!NoHistogram && !Stats.CodeFreq.empty()) {
+ std::vector<std::pair<unsigned, unsigned> > FreqPairs; // <freq,code>
+ for (unsigned i = 0, e = Stats.CodeFreq.size(); i != e; ++i)
+ if (unsigned Freq = Stats.CodeFreq[i].NumInstances)
+ FreqPairs.push_back(std::make_pair(Freq, i));
+ std::stable_sort(FreqPairs.begin(), FreqPairs.end());
+ std::reverse(FreqPairs.begin(), FreqPairs.end());
+
+ std::cerr << "\tRecord Histogram:\n";
+ fprintf(stderr, "\t\t Count # Bits %% Abv Record Kind\n");
+ for (unsigned i = 0, e = FreqPairs.size(); i != e; ++i) {
+ const PerRecordStats &RecStats = Stats.CodeFreq[FreqPairs[i].second];
+
+ fprintf(stderr, "\t\t%7d %9llu ", RecStats.NumInstances,
+ (unsigned long long)RecStats.TotalBits);
+
+ if (RecStats.NumAbbrev)
+ fprintf(stderr, "%7.2f ",
+ (double)RecStats.NumAbbrev/RecStats.NumInstances*100);
+ else
+ fprintf(stderr, " ");
+
+ if (const char *CodeName =
+ GetCodeName(FreqPairs[i].second, I->first, StreamFile))
+ fprintf(stderr, "%s\n", CodeName);
+ else
+ fprintf(stderr, "UnknownCode%d\n", FreqPairs[i].second);
+ }
+ std::cerr << "\n";
+
+ }
+ }
+ return 0;
+}
+
+
+int main(int argc, char **argv) {
+ // Print a stack trace if we signal out.
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ cl::ParseCommandLineOptions(argc, argv, "llvm-bcanalyzer file analyzer\n");
+
+ return AnalyzeBitcode();
+}
diff --git a/tools/llvm-config/CMakeLists.txt b/tools/llvm-config/CMakeLists.txt
new file mode 100644
index 0000000..29287ab
--- /dev/null
+++ b/tools/llvm-config/CMakeLists.txt
@@ -0,0 +1,120 @@
+include(TestBigEndian)
+
+if( NOT PERL_FOUND )
+ message(FATAL_ERROR "Perl required but not found!")
+endif( NOT PERL_FOUND )
+
+set(PERL ${PERL_EXECUTABLE})
+set(VERSION PACKAGE_VERSION)
+set(PREFIX ${LLVM_BINARY_DIR}) # TODO: Root for `make install'.
+execute_process(COMMAND date
+ OUTPUT_VARIABLE LLVM_CONFIGTIME
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+# LLVM_ON_UNIX and LLVM_ON_WIN32 already set.
+# those are set to blank by `autoconf' on MinGW, so it seems they are not required:
+#set(LLVMGCCDIR "")
+#set(LLVMGCC "")
+#set(LLVMGXX "")
+#set(LLVMGCC_VERSION "")
+#set(LLVMGCC_MAJVERS "")
+test_big_endian(IS_BIG_ENDIAN)
+if( IS_BIG_ENDIAN )
+ set(ENDIAN "big")
+else( IS_BIG_ENDIAN )
+ set(ENDIAN "little")
+endif( IS_BIG_ENDIAN )
+set(SHLIBEXT ${LTDL_SHLIB_EXT})
+#EXEEXT already set.
+set(OS "${CMAKE_SYSTEM}")
+set(ARCH "X86") # TODO: This gives "i686" in Linux: "${CMAKE_SYSTEM_PROCESSOR}")
+
+get_system_libs(LLVM_SYSTEM_LIBS_LIST)
+foreach(l ${LLVM_SYSTEM_LIBS_LIST})
+ set(LLVM_SYSTEM_LIBS ${LLVM_SYSTEM_LIBS} "-l${l}")
+endforeach()
+
+include(GetTargetTriple)
+get_target_triple(target)
+
+foreach(c ${LLVM_TARGETS_TO_BUILD})
+ set(TARGETS_BUILT "${TARGETS_BUILT} ${c}")
+endforeach(c)
+set(TARGETS_TO_BUILD ${TARGETS_BUILT})
+set(TARGET_HAS_JIT "1") # TODO
+
+# Avoids replacement at config-time:
+set(LLVM_CPPFLAGS "@LLVM_CPPFLAGS@")
+set(LLVM_CFLAGS "@LLVM_CFLAGS@")
+set(LLVM_CXXFLAGS "@LLVM_CXXFLAGS@")
+set(LLVM_LDFLAGS "@LLVM_LDFLAGS@")
+set(LIBS "@LIBS@")
+set(LLVM_BUILDMODE "@LLVM_BUILDMODE@")
+
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/llvm-config.in.in
+ ${CMAKE_CURRENT_BINARY_DIR}/llvm-config.in
+ @ONLY
+)
+
+set(LIBDEPS ${CMAKE_CURRENT_BINARY_DIR}/LibDeps.txt)
+set(LIBDEPS_TMP ${CMAKE_CURRENT_BINARY_DIR}/LibDeps.txt.tmp)
+set(FINAL_LIBDEPS ${CMAKE_CURRENT_BINARY_DIR}/FinalLibDeps.txt)
+set(LLVM_CONFIG ${LLVM_TOOLS_BINARY_DIR}/llvm-config)
+set(LLVM_CONFIG_IN ${CMAKE_CURRENT_BINARY_DIR}/llvm-config.in)
+
+if( CMAKE_CROSSCOMPILING )
+ set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
+endif()
+
+find_program(NM_PATH nm PATH_SUFFIXES /bin)
+
+if( NOT NM_PATH )
+ message(FATAL_ERROR "`nm' not found")
+endif()
+
+add_custom_command(OUTPUT ${LIBDEPS_TMP}
+ COMMAND ${PERL_EXECUTABLE} ${LLVM_MAIN_SRC_DIR}/utils/GenLibDeps.pl -flat ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR} ${NM_PATH} > ${LIBDEPS_TMP}
+ DEPENDS ${llvm_libs}
+ COMMENT "Regenerating ${LIBDEPS_TMP}")
+
+add_custom_command(OUTPUT ${LIBDEPS}
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${LIBDEPS_TMP} ${LIBDEPS}
+ DEPENDS ${LIBDEPS_TMP}
+ COMMENT "Updated ${LIBDEPS} because dependencies changed")
+
+add_custom_command(OUTPUT ${FINAL_LIBDEPS}
+ COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/find-cycles.pl < ${LIBDEPS} > ${FINAL_LIBDEPS} || ${CMAKE_COMMAND} -E remove -f ${FINAL_LIBDEPS}
+ DEPENDS ${LIBDEPS}
+ COMMENT "Checking for cyclic dependencies between LLVM libraries.")
+
+string(TOUPPER "${CMAKE_BUILD_TYPE}" uppercase_CMAKE_BUILD_TYPE)
+set(C_FLGS "${CMAKE_C_FLAGS_${uppercase_CMAKE_BUILD_TYPE}} ${LLVM_DEFINITIONS}")
+set(CXX_FLGS "${CMAKE_CXX_FLAGS_${uppercase_CMAKE_BUILD_TYPE}} ${LLVM_DEFINITIONS}")
+set(CPP_FLGS "${CMAKE_CPP_FLAGS_${uppercase_CMAKE_BUILD_TYPE}} ${LLVM_DEFINITIONS}")
+
+add_custom_command(OUTPUT ${LLVM_CONFIG}
+ COMMAND echo 's!@LLVM_CPPFLAGS@!${CPP_FLGS}!' > temp.sed
+ COMMAND echo 's!@LLVM_CFLAGS@!${C_FLGS}!' >> temp.sed
+ COMMAND echo 's!@LLVM_CXXFLAGS@!${CXX_FLGS}!' >> temp.sed
+ # TODO: Use general flags for linking! not just for shared libs:
+ COMMAND echo 's!@LLVM_LDFLAGS@!${CMAKE_SHARED_LINKER_FLAGS}!' >> temp.sed
+ COMMAND echo 's!@LIBS@!${LLVM_SYSTEM_LIBS}!' >> temp.sed
+ COMMAND echo 's!@LLVM_BUILDMODE@!${CMAKE_BUILD_TYPE}!' >> temp.sed
+ COMMAND sed -f temp.sed < ${LLVM_CONFIG_IN} > ${LLVM_CONFIG}
+ COMMAND ${CMAKE_COMMAND} -E remove -f temp.sed
+ COMMAND cat ${FINAL_LIBDEPS} >> ${LLVM_CONFIG}
+ COMMAND chmod +x ${LLVM_CONFIG}
+ COMMAND cd ${CMAKE_BINARY_DIR} && ${CMAKE_COMMAND} -U HAVE_LLVM_CONFIG -D LLVM_BINARY_DIR="${LLVM_BINARY_DIR}" ${CMAKE_SOURCE_DIR}
+ DEPENDS ${FINAL_LIBDEPS} ${LLVM_CONFIG_IN}
+ COMMENT "Building llvm-config script."
+ )
+
+add_custom_target(llvm-config.target ALL
+ DEPENDS ${LLVM_CONFIG})
+
+add_dependencies(llvm-config.target ${llvm_lib_targets})
+
+install(FILES ${LLVM_CONFIG}
+ PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE
+ WORLD_READ WORLD_EXECUTE
+ DESTINATION bin)
diff --git a/tools/llvm-config/Makefile b/tools/llvm-config/Makefile
new file mode 100644
index 0000000..6eedca0
--- /dev/null
+++ b/tools/llvm-config/Makefile
@@ -0,0 +1,92 @@
+##===- tools/llvm-config/Makefile --------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+
+EXTRA_DIST = LibDeps.txt FinalLibDeps.txt llvm-config.in.in find-cycles.pl
+REQUIRES_EH := 1
+
+include $(LEVEL)/Makefile.common
+
+# If we don't have Perl, we can't generate the library dependencies upon which
+# llvm-config depends. Therefore, only if we detect perl will we do anything
+# useful.
+ifeq ($(HAVE_PERL),1)
+
+# Combine preprocessor flags (except for -I) and CXX flags.
+SUB_CPPFLAGS = ${CPP.BaseFlags}
+SUB_CFLAGS = ${CPP.BaseFlags} ${C.Flags}
+SUB_CXXFLAGS = ${CPP.BaseFlags} ${CXX.Flags}
+
+# This is blank for now. We need to be careful about adding stuff here:
+# LDFLAGS tend not to be portable, and we don't currently require the
+# user to use libtool when linking against LLVM.
+SUB_LDFLAGS =
+
+FinalLibDeps = $(PROJ_OBJ_DIR)/FinalLibDeps.txt
+LibDeps = $(PROJ_OBJ_DIR)/LibDeps.txt
+LibDepsTemp = $(PROJ_OBJ_DIR)/LibDeps.txt.tmp
+GenLibDeps = $(PROJ_SRC_ROOT)/utils/GenLibDeps.pl
+
+$(LibDepsTemp): $(GenLibDeps) $(LibDir) $(wildcard $(LibDir)/*.a $(LibDir)/*.o)
+ $(Echo) "Regenerating LibDeps.txt.tmp"
+ $(Verb) $(PERL) $(GenLibDeps) -flat $(LibDir) "$(NM_PATH)" > $(LibDepsTemp)
+
+$(LibDeps): $(LibDepsTemp)
+ $(Verb) $(CMP) -s $@ $< || ( $(CP) $< $@ && \
+ $(EchoCmd) Updated LibDeps.txt because dependencies changed )
+
+# Find all the cyclic dependencies between various LLVM libraries, so we
+# don't have to process them at runtime.
+$(FinalLibDeps): find-cycles.pl $(LibDeps)
+ $(Echo) "Checking for cyclic dependencies between LLVM libraries."
+ $(Verb) $(PERL) $< < $(LibDeps) > $@ || rm -f $@
+
+# Rerun our configure substitutions as needed.
+ConfigInIn = $(PROJ_SRC_DIR)/llvm-config.in.in
+llvm-config.in: $(ConfigInIn) $(ConfigStatusScript)
+ $(Verb) cd $(PROJ_OBJ_ROOT) ; \
+ $(ConfigStatusScript) tools/llvm-config/llvm-config.in
+
+# Build our final script.
+$(ToolDir)/llvm-config: llvm-config.in $(FinalLibDeps)
+ $(Echo) "Building llvm-config script."
+ $(Verb) $(ECHO) 's/@LLVM_CPPFLAGS@/$(subst /,\/,$(SUB_CPPFLAGS))/' \
+ > temp.sed
+ $(Verb) $(ECHO) 's/@LLVM_CFLAGS@/$(subst /,\/,$(SUB_CFLAGS))/' \
+ >> temp.sed
+ $(Verb) $(ECHO) 's/@LLVM_CXXFLAGS@/$(subst /,\/,$(SUB_CXXFLAGS))/' \
+ >> temp.sed
+ $(Verb) $(ECHO) 's/@LLVM_LDFLAGS@/$(subst /,\/,$(SUB_LDFLAGS))/' \
+ >> temp.sed
+ $(Verb) $(ECHO) 's/@LLVM_BUILDMODE@/$(subst /,\/,$(BuildMode))/' \
+ >> temp.sed
+ $(Verb) $(SED) -f temp.sed < $< > $@
+ $(Verb) $(RM) temp.sed
+ $(Verb) cat $(FinalLibDeps) >> $@
+ $(Verb) chmod +x $@
+
+else
+# We don't have perl, just generate a dummy llvm-config
+$(ToolDir)/llvm-config:
+ $(Echo) "Building place holder llvm-config script."
+ $(Verb) $(ECHO) 'echo llvm-config: Perl not found so llvm-config could not be generated' >> $@
+ $(Verb) chmod +x $@
+
+endif
+# Hook into the standard Makefile rules.
+all-local:: $(ToolDir)/llvm-config
+clean-local::
+ $(Verb) $(RM) -f $(ToolDir)/llvm-config llvm-config.in $(FinalLibDeps) \
+ $(LibDeps) GenLibDeps.out
+install-local:: all-local
+ $(Echo) Installing llvm-config
+ $(Verb) $(MKDIR) $(PROJ_bindir)
+ $(Verb) $(ScriptInstall) $(ToolDir)/llvm-config $(PROJ_bindir)
+
diff --git a/tools/llvm-config/find-cycles.pl b/tools/llvm-config/find-cycles.pl
new file mode 100755
index 0000000..8156abd
--- /dev/null
+++ b/tools/llvm-config/find-cycles.pl
@@ -0,0 +1,165 @@
+#!/usr/bin/perl
+#
+# Program: find-cycles.pl
+#
+# Synopsis: Given a list of possibly cyclic dependencies, merge all the
+# cycles. This makes it possible to topologically sort the
+# dependencies between different parts of LLVM.
+#
+# Syntax: find-cycles.pl < LibDeps.txt > FinalLibDeps.txt
+#
+# Input: cycmem1: cycmem2 dep1 dep2
+# cycmem2: cycmem1 dep3 dep4
+# boring: dep4
+#
+# Output: cycmem1 cycmem2: dep1 dep2 dep3 dep4
+# boring: dep4
+#
+# This file was written by Eric Kidd, and is placed into the public domain.
+#
+
+use 5.006;
+use strict;
+use warnings;
+
+my %DEPS;
+my @CYCLES;
+sub find_all_cycles;
+
+# Read our dependency information.
+while (<>) {
+ chomp;
+ my ($module, $dependency_str) = /^\s*([^:]+):\s*(.*)\s*$/;
+ die "Malformed data: $_" unless defined $dependency_str;
+ my @dependencies = split(/ /, $dependency_str);
+ $DEPS{$module} = \@dependencies;
+}
+
+# Partition our raw dependencies into sets of cyclically-connected nodes.
+find_all_cycles();
+
+# Print out the finished cycles, with their dependencies.
+my @output;
+my $cycles_found = 0;
+foreach my $cycle (@CYCLES) {
+ my @modules = sort keys %{$cycle};
+
+ # Merge the dependencies of all modules in this cycle.
+ my %dependencies;
+ foreach my $module (@modules) {
+ @dependencies{@{$DEPS{$module}}} = 1;
+ }
+
+ # Prune the known cyclic dependencies.
+ foreach my $module (@modules) {
+ delete $dependencies{$module};
+ }
+
+ # Warn about possible linker problems.
+ my @archives = grep(/\.a$/, @modules);
+ if (@archives > 1) {
+ $cycles_found = $cycles_found + 1;
+ print STDERR "find-cycles.pl: Circular dependency between *.a files:\n";
+ print STDERR "find-cycles.pl: ", join(' ', @archives), "\n";
+ push @modules, @archives; # WORKAROUND: Duplicate *.a files. Ick.
+ }
+
+ # Add to our output. (@modules is already as sorted as we need it to be.)
+ push @output, (join(' ', @modules) . ': ' .
+ join(' ', sort keys %dependencies) . "\n");
+}
+print sort @output;
+
+exit $cycles_found;
+
+#==========================================================================
+# Depedency Cycle Support
+#==========================================================================
+# For now, we have cycles in our dependency graph. Ideally, each cycle
+# would be collapsed down to a single *.a file, saving us all this work.
+#
+# To understand this code, you'll need a working knowledge of Perl 5,
+# and possibly some quality time with 'man perlref'.
+
+my %SEEN;
+my %CYCLES;
+sub find_cycles ($@);
+sub found_cycles ($@);
+
+sub find_all_cycles {
+ # Find all multi-item cycles.
+ my @modules = sort keys %DEPS;
+ foreach my $module (@modules) { find_cycles($module); }
+
+ # Build fake one-item "cycles" for the remaining modules, so we can
+ # treat them uniformly.
+ foreach my $module (@modules) {
+ unless (defined $CYCLES{$module}) {
+ my %cycle = ($module, 1);
+ $CYCLES{$module} = \%cycle;
+ }
+ }
+
+ # Find all our unique cycles. We have to do this the hard way because
+ # we apparently can't store hash references as hash keys without making
+ # 'strict refs' sad.
+ my %seen;
+ foreach my $cycle (values %CYCLES) {
+ unless ($seen{$cycle}) {
+ $seen{$cycle} = 1;
+ push @CYCLES, $cycle;
+ }
+ }
+}
+
+# Walk through our graph depth-first (keeping a trail in @path), and report
+# any cycles we find.
+sub find_cycles ($@) {
+ my ($module, @path) = @_;
+ if (str_in_list($module, @path)) {
+ found_cycle($module, @path);
+ } else {
+ return if defined $SEEN{$module};
+ $SEEN{$module} = 1;
+ foreach my $dep (@{$DEPS{$module}}) {
+ find_cycles($dep, @path, $module);
+ }
+ }
+}
+
+# Give a cycle, attempt to merge it with pre-existing cycle data.
+sub found_cycle ($@) {
+ my ($module, @path) = @_;
+
+ # Pop any modules which aren't part of our cycle.
+ while ($path[0] ne $module) { shift @path; }
+ #print join("->", @path, $module) . "\n";
+
+ # Collect the modules in our cycle into a hash.
+ my %cycle;
+ foreach my $item (@path) {
+ $cycle{$item} = 1;
+ if (defined $CYCLES{$item}) {
+ # Looks like we intersect with an existing cycle, so merge
+ # all those in, too.
+ foreach my $old_item (keys %{$CYCLES{$item}}) {
+ $cycle{$old_item} = 1;
+ }
+ }
+ }
+
+ # Update our global cycle table.
+ my $cycle_ref = \%cycle;
+ foreach my $item (keys %cycle) {
+ $CYCLES{$item} = $cycle_ref;
+ }
+ #print join(":", sort keys %cycle) . "\n";
+}
+
+sub str_in_list ($@) {
+ my ($str, @list) = @_;
+ foreach my $item (@list) {
+ return 1 if ($item eq $str);
+ }
+ return 0;
+}
diff --git a/tools/llvm-config/llvm-config.in.in b/tools/llvm-config/llvm-config.in.in
new file mode 100644
index 0000000..36b5112
--- /dev/null
+++ b/tools/llvm-config/llvm-config.in.in
@@ -0,0 +1,460 @@
+#!@PERL@
+##===- tools/llvm-config ---------------------------------------*- perl -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+#
+# Synopsis: Prints out compiler options needed to build against an installed
+# copy of LLVM.
+#
+# Syntax: llvm-config OPTIONS... [COMPONENTS...]
+#
+##===----------------------------------------------------------------------===##
+
+use 5.006;
+use strict;
+use warnings;
+
+#---- begin autoconf values ----
+my $PACKAGE_NAME = q{@PACKAGE_NAME@};
+my $VERSION = q{@PACKAGE_VERSION@};
+my $PREFIX = q{@LLVM_PREFIX@};
+my $LLVM_CONFIGTIME = q{@LLVM_CONFIGTIME@};
+my $LLVM_SRC_ROOT = q{@abs_top_srcdir@};
+my $LLVM_OBJ_ROOT = q{@abs_top_builddir@};
+my $LLVM_ON_WIN32 = q{@LLVM_ON_WIN32@};
+my $LLVM_ON_UNIX = q{@LLVM_ON_UNIX@};
+my $LLVMGCCDIR = q{@LLVMGCCDIR@};
+my $LLVMGCC = q{@LLVMGCC@};
+my $LLVMGXX = q{@LLVMGXX@};
+my $LLVMGCC_VERSION = q{@LLVMGCC_VERSION@};
+my $LLVMGCC_MAJVERS = q{@LLVMGCC_MAJVERS@};
+my $ENDIAN = q{@ENDIAN@};
+my $SHLIBEXT = q{@SHLIBEXT@};
+my $EXEEXT = q{@EXEEXT@};
+my $OS = q{@OS@};
+my $ARCH = lc(q{@ARCH@});
+my $TARGET_TRIPLE = q{@target@};
+my $TARGETS_TO_BUILD = q{@TARGETS_TO_BUILD@};
+my $TARGET_HAS_JIT = q{@TARGET_HAS_JIT@};
+my @TARGETS_BUILT = map { lc($_) } qw{@TARGETS_TO_BUILD@};
+#---- end autoconf values ----
+
+# Must pretend x86_64 architecture is really x86, otherwise the native backend
+# won't get linked in.
+$ARCH = "x86" if $ARCH eq "x86_64";
+
+#---- begin Makefile values ----
+my $CPPFLAGS = q{@LLVM_CPPFLAGS@};
+my $CFLAGS = q{@LLVM_CFLAGS@};
+my $CXXFLAGS = q{@LLVM_CXXFLAGS@};
+my $LDFLAGS = q{@LLVM_LDFLAGS@};
+my $SYSTEM_LIBS = q{@LIBS@};
+my $LLVM_BUILDMODE = q{@LLVM_BUILDMODE@};
+#---- end Makefile values ----
+
+# Figure out where llvm-config is being run from. Primarily, we care if it has
+# been installed, or is running from the build directory, which changes the
+# locations of some files.
+
+# Convert the current executable name into its directory (e.g. ".").
+my ($RUN_DIR) = ($0 =~ /^(.*)\/.*$/);
+
+# Find the unix pwd program: we don't want to use the bash builtin, as it does
+# not look through symlinks etc.
+my $PWD = `which pwd`;
+chomp($PWD);
+$PWD = "pwd" if (!-e $PWD);
+
+# Turn the directory into an absolute directory on the file system, also pop up
+# from "bin" into the build or prefix dir.
+my $ABS_RUN_DIR = `cd $RUN_DIR/..; $PWD`;
+chomp($ABS_RUN_DIR);
+
+# Compute the absolute object directory build, e.g. "foo/llvm/Debug".
+my $ABS_OBJ_ROOT = "$LLVM_OBJ_ROOT/$LLVM_BUILDMODE";
+$ABS_OBJ_ROOT = `cd $ABS_OBJ_ROOT; $PWD` if (-d $ABS_OBJ_ROOT);
+chomp($ABS_OBJ_ROOT);
+
+my $INCLUDEDIR = "$ABS_RUN_DIR/include";
+my $LIBDIR = "$ABS_RUN_DIR/lib";
+my $BINDIR = "$ABS_RUN_DIR/bin";
+if ($ABS_RUN_DIR eq $ABS_OBJ_ROOT) {
+ # If we are running out of the build directory, the include dir is in the
+ # srcdir.
+ $INCLUDEDIR = "$LLVM_SRC_ROOT/include";
+} else {
+ # If installed, ignore the prefix the tree was configured with, use the
+ # current prefix.
+ $PREFIX = $ABS_RUN_DIR;
+}
+
+sub usage;
+sub fix_library_names (@);
+sub fix_library_files (@);
+sub expand_dependencies (@);
+sub name_map_entries;
+
+# Parse our command-line arguments.
+usage if @ARGV == 0;
+my @components;
+my $has_opt = 0;
+my $want_libs = 0;
+my $want_libnames = 0;
+my $want_libfiles = 0;
+my $want_components = 0;
+foreach my $arg (@ARGV) {
+ if ($arg =~ /^-/) {
+ if ($arg eq "--version") {
+ $has_opt = 1; print "$VERSION\n";
+ } elsif ($arg eq "--prefix") {
+ $has_opt = 1; print "$PREFIX\n";
+ } elsif ($arg eq "--bindir") {
+ $has_opt = 1; print "$BINDIR\n";
+ } elsif ($arg eq "--includedir") {
+ $has_opt = 1; print "$INCLUDEDIR\n";
+ } elsif ($arg eq "--libdir") {
+ $has_opt = 1; print "$LIBDIR\n";
+ } elsif ($arg eq "--cppflags") {
+ $has_opt = 1; print "-I$INCLUDEDIR $CPPFLAGS\n";
+ } elsif ($arg eq "--cflags") {
+ $has_opt = 1; print "-I$INCLUDEDIR $CFLAGS\n";
+ } elsif ($arg eq "--cxxflags") {
+ $has_opt = 1; print "-I$INCLUDEDIR $CXXFLAGS\n";
+ } elsif ($arg eq "--ldflags") {
+ $has_opt = 1; print "-L$LIBDIR $LDFLAGS $SYSTEM_LIBS\n";
+ } elsif ($arg eq "--libs") {
+ $has_opt = 1; $want_libs = 1;
+ } elsif ($arg eq "--libnames") {
+ $has_opt = 1; $want_libnames = 1;
+ } elsif ($arg eq "--libfiles") {
+ $has_opt = 1; $want_libfiles = 1;
+ } elsif ($arg eq "--components") {
+ $has_opt = 1; print join(' ', name_map_entries), "\n";
+ } elsif ($arg eq "--targets-built") {
+ $has_opt = 1; print join(' ', @TARGETS_BUILT), "\n";
+ } elsif ($arg eq "--host-target") {
+ $has_opt = 1; print "$TARGET_TRIPLE\n";
+ } elsif ($arg eq "--build-mode") {
+ $has_opt = 1; print "$LLVM_BUILDMODE\n";
+ } elsif ($arg eq "--obj-root") {
+ $has_opt = 1; print `cd $LLVM_OBJ_ROOT/; $PWD`;
+ } elsif ($arg eq "--src-root") {
+ $has_opt = 1; print `cd $LLVM_SRC_ROOT/; $PWD`;
+ } else {
+ usage();
+ }
+ } else {
+ push @components, $arg;
+ }
+}
+
+# If no options were specified, fail.
+usage unless $has_opt;
+
+# If no components were specified, default to 'all'.
+if (@components == 0) {
+ push @components, 'all';
+}
+
+# Force component names to lower case.
+@components = map lc, @components;
+
+# Handle any arguments which require building our dependency graph.
+if ($want_libs || $want_libnames || $want_libfiles) {
+ my @libs = expand_dependencies(@components);
+ print join(' ', fix_library_names(@libs)), "\n" if ($want_libs);
+ print join(' ', @libs), "\n" if ($want_libnames);
+ print join(' ', fix_library_files(@libs)), "\n" if ($want_libfiles);
+}
+
+exit 0;
+
+#==========================================================================
+# Support Routines
+#==========================================================================
+
+sub usage {
+ print STDERR <<__EOD__;
+Usage: llvm-config <OPTION>... [<COMPONENT>...]
+
+Get various configuration information needed to compile programs which use
+LLVM. Typically called from 'configure' scripts. Examples:
+ llvm-config --cxxflags
+ llvm-config --ldflags
+ llvm-config --libs engine bcreader scalaropts
+
+Options:
+ --version Print LLVM version.
+ --prefix Print the installation prefix.
+ --src-root Print the source root LLVM was built from.
+ --obj-root Print the object root used to build LLVM.
+ --bindir Directory containing LLVM executables.
+ --includedir Directory containing LLVM headers.
+ --libdir Directory containing LLVM libraries.
+ --cppflags C preprocessor flags for files that include LLVM headers.
+ --cflags C compiler flags for files that include LLVM headers.
+ --cxxflags C++ compiler flags for files that include LLVM headers.
+ --ldflags Print Linker flags.
+ --libs Libraries needed to link against LLVM components.
+ --libnames Bare library names for in-tree builds.
+ --libfiles Fully qualified library filenames for makefile depends.
+ --components List of all possible components.
+ --targets-built List of all targets currently built.
+ --host-target Target triple used to configure LLVM.
+ --build-mode Print build mode of LLVM tree (e.g. Debug or Release).
+Typical components:
+ all All LLVM libraries (default).
+ backend Either a native backend or the C backend.
+ engine Either a native JIT or a bytecode interpreter.
+__EOD__
+ exit(1);
+}
+
+# Use -lfoo instead of libfoo.a whenever possible, and add directories to
+# files which can't be found using -L.
+sub fix_library_names (@) {
+ my @libs = @_;
+ my @result;
+ foreach my $lib (@libs) {
+ # Transform the bare library name appropriately.
+ my ($basename) = ($lib =~ /^lib([^.]*)\.a/);
+ if (defined $basename) {
+ push @result, "-l$basename";
+ } else {
+ push @result, "$LIBDIR/$lib";
+ }
+ }
+ return @result;
+}
+
+# Turn the list of libraries into a list of files.
+sub fix_library_files(@) {
+ my @libs = @_;
+ my @result;
+ foreach my $lib (@libs) {
+ # Transform the bare library name into a filename.
+ push @result, "$LIBDIR/$lib";
+ }
+ return @result;
+}
+
+#==========================================================================
+# Library Dependency Analysis
+#==========================================================================
+# Given a few human-readable library names, find all their dependencies
+# and sort them into an order which the linker will like. If we packed
+# our libraries into fewer archives, we could make the linker do much
+# of this work for us.
+#
+# Libraries have two different types of names in this code: Human-friendly
+# "component" names entered on the command-line, and the raw file names
+# we use internally (and ultimately pass to the linker).
+#
+# To understand this code, you'll need a working knowledge of Perl 5,
+# and possibly some quality time with 'man perlref'.
+
+sub load_dependencies;
+sub build_name_map;
+sub have_native_backend;
+sub find_best_engine;
+sub expand_names (@);
+sub find_all_required_sets (@);
+sub find_all_required_sets_helper ($$@);
+
+# Each "set" contains one or more libraries which must be included as a
+# group (due to cyclic dependencies). Sets are represented as a Perl array
+# reference pointing to a list of internal library names.
+my @SETS;
+
+# Various mapping tables.
+my %LIB_TO_SET_MAP; # Maps internal library names to their sets.
+my %SET_DEPS; # Maps sets to a list of libraries they depend on.
+my %NAME_MAP; # Maps human-entered names to internal names.
+
+# Have our dependencies been loaded yet?
+my $DEPENDENCIES_LOADED = 0;
+
+# Given a list of human-friendly component names, translate them into a
+# complete set of linker arguments.
+sub expand_dependencies (@) {
+ my @libs = @_;
+ load_dependencies;
+ my @required_sets = find_all_required_sets(expand_names(@libs));
+ my @sorted_sets = topologically_sort_sets(@required_sets);
+
+ # Expand the library sets into libraries.
+ my @result;
+ foreach my $set (@sorted_sets) { push @result, @{$set}; }
+ return @result;
+}
+
+# Load in the raw dependency data stored at the end of this file.
+sub load_dependencies {
+ return if $DEPENDENCIES_LOADED;
+ $DEPENDENCIES_LOADED = 1;
+ while (<DATA>) {
+ # Parse our line.
+ my ($libs, $deps) = /^\s*([^:]+):\s*(.*)\s*$/;
+ die "Malformed dependency data" unless defined $deps;
+ my @libs = split(' ', $libs);
+ my @deps = split(' ', $deps);
+
+ # Record our dependency data.
+ my $set = \@libs;
+ push @SETS, $set;
+ foreach my $lib (@libs) { $LIB_TO_SET_MAP{$lib} = $set; }
+ $SET_DEPS{$set} = \@deps;
+ }
+ build_name_map;
+}
+
+# Build a map converting human-friendly component names into internal
+# library names.
+sub build_name_map {
+ # Add entries for all the actual libraries.
+ foreach my $set (@SETS) {
+ foreach my $lib (sort @$set) {
+ my $short_name = $lib;
+ $short_name =~ s/^(lib)?LLVM([^.]*)\..*$/$2/;
+ $short_name =~ tr/A-Z/a-z/;
+ $NAME_MAP{$short_name} = [$lib];
+ }
+ }
+
+ # Add target-specific entries
+ foreach my $target (@TARGETS_BUILT) {
+ # FIXME: Temporary, until we don't switch all targets
+ if (defined $NAME_MAP{$target.'asmprinter'}) {
+ $NAME_MAP{$target} = [$target.'asmprinter', $target.'codegen']
+ }
+ }
+
+ # Add virtual entries.
+ $NAME_MAP{'native'} = have_native_backend() ? [$ARCH] : [];
+ $NAME_MAP{'nativecodegen'} = have_native_backend() ? [$ARCH.'codegen'] : [];
+ $NAME_MAP{'backend'} = have_native_backend() ? ['native'] : ['cbackend'];
+ $NAME_MAP{'engine'} = find_best_engine;
+ $NAME_MAP{'all'} = [name_map_entries]; # Must be last.
+}
+
+# Return true if we have a native backend to use.
+sub have_native_backend {
+ my %BUILT;
+ foreach my $target (@TARGETS_BUILT) { $BUILT{$target} = 1; }
+ return defined $NAME_MAP{$ARCH} && defined $BUILT{$ARCH};
+}
+
+# Find a working subclass of ExecutionEngine for this platform.
+sub find_best_engine {
+ if (have_native_backend && $TARGET_HAS_JIT) {
+ return ['jit', 'native'];
+ } else {
+ return ['interpreter'];
+ }
+}
+
+# Get all the human-friendly component names.
+sub name_map_entries {
+ load_dependencies;
+ return sort keys %NAME_MAP;
+}
+
+# Map human-readable names to internal library names.
+sub expand_names (@) {
+ my @names = @_;
+ my @result;
+ foreach my $name (@names) {
+ if (defined $LIB_TO_SET_MAP{$name}) {
+ # We've hit bottom: An actual library name.
+ push @result, $name;
+ } elsif (defined $NAME_MAP{$name}) {
+ # We've found a short name to expand.
+ push @result, expand_names(@{$NAME_MAP{$name}});
+ } else {
+ print STDERR "llvm-config: unknown component name: $name\n";
+ exit(1);
+ }
+ }
+ return @result;
+}
+
+# Given a list of internal library names, return all sets of libraries which
+# will need to be included by the linker (in no particular order).
+sub find_all_required_sets (@) {
+ my @libs = @_;
+ my %sets_added;
+ my @result;
+ find_all_required_sets_helper(\%sets_added, \@result, @libs);
+ return @result;
+}
+
+# Recursive closures are pretty broken in Perl, so we're going to separate
+# this function from find_all_required_sets and pass in the state we need
+# manually, as references. Yes, this is fairly unpleasant.
+sub find_all_required_sets_helper ($$@) {
+ my ($sets_added, $result, @libs) = @_;
+ foreach my $lib (@libs) {
+ my $set = $LIB_TO_SET_MAP{$lib};
+ next if defined $$sets_added{$set};
+ $$sets_added{$set} = 1;
+ push @$result, $set;
+ find_all_required_sets_helper($sets_added, $result, @{$SET_DEPS{$set}});
+ }
+}
+
+# Print a list of sets, with a label. Used for debugging.
+sub print_sets ($@) {
+ my ($label, @sets) = @_;
+ my @output;
+ foreach my $set (@sets) { push @output, join(',', @$set); }
+ print "$label: ", join(';', @output), "\n";
+}
+
+# Returns true if $lib is a key in $added.
+sub has_lib_been_added ($$) {
+ my ($added, $lib) = @_;
+ return defined $$added{$LIB_TO_SET_MAP{$lib}};
+}
+
+# Returns true if all the dependencies of $set appear in $added.
+sub have_all_deps_been_added ($$) {
+ my ($added, $set) = @_;
+ #print_sets(" Checking", $set);
+ #print_sets(" Wants", $SET_DEPS{$set});
+ foreach my $lib (@{$SET_DEPS{$set}}) {
+ return 0 unless has_lib_been_added($added, $lib);
+ }
+ return 1;
+}
+
+# Given a list of sets, topologically sort them using dependencies.
+sub topologically_sort_sets (@) {
+ my @sets = @_;
+ my %added;
+ my @result;
+ SCAN: while (@sets) { # We'll delete items from @sets as we go.
+ #print_sets("So far", reverse(@result));
+ #print_sets("Remaining", @sets);
+ for (my $i = 0; $i < @sets; ++$i) {
+ my $set = $sets[$i];
+ if (have_all_deps_been_added(\%added, $set)) {
+ push @result, $set;
+ $added{$set} = 1;
+ #print "Removing $i.\n";
+ splice(@sets, $i, 1);
+ next SCAN; # Restart our scan.
+ }
+ }
+ die "Can't find a library with no dependencies";
+ }
+ return reverse(@result);
+}
+
+# Our library dependency data will be added after the '__END__' token, and will
+# be read through the magic <DATA> filehandle.
+__END__
diff --git a/tools/llvm-db/CLICommand.h b/tools/llvm-db/CLICommand.h
new file mode 100644
index 0000000..0beec91
--- /dev/null
+++ b/tools/llvm-db/CLICommand.h
@@ -0,0 +1,111 @@
+//===- CLICommand.h - Classes used to represent commands --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a small class hierarchy used to represent the various types
+// of commands in the CLI debugger front-end.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLICOMMAND_H
+#define CLICOMMAND_H
+
+#include <string>
+#include <vector>
+#include <cassert>
+
+namespace llvm {
+ class CLIDebugger;
+
+ /// CLICommand - Base class of the hierarchy, used to provide the abstract
+ /// interface common to all commands.
+ ///
+ class CLICommand {
+ /// ShortHelp, LongHelp - The short and long helps strings printed for the
+ /// command. The ShortHelp string should be a single line of text without a
+ /// newline. The LongHelp string should be a full description with
+ /// terminating newline.
+ std::string ShortHelp, LongHelp;
+
+ /// RefCount - This contains the number of entries in the CLIDebugger
+ /// CommandTable that points to this command.
+ unsigned RefCount;
+
+ /// OptionNames - This contains a list of names for the option. Keeping
+ /// track of this is done just to make the help output more helpful.
+ ///
+ std::vector<std::string> OptionNames;
+ public:
+ CLICommand(const std::string &SH, const std::string &LH)
+ : ShortHelp(SH), LongHelp(LH), RefCount(0) {}
+
+ virtual ~CLICommand() {}
+
+ /// addRef/dropRef - Implement a simple reference counting scheme to make
+ /// sure we delete commands that are no longer used.
+ void addRef() { ++RefCount; }
+ void dropRef() {
+ if (--RefCount == 0) delete this;
+ }
+
+ /// getPrimaryOptionName - Return the first name the option was added under.
+ /// This is the name we report for the option in the help output.
+ std::string getPrimaryOptionName() const {
+ return OptionNames.empty() ? "" : OptionNames[0];
+ }
+
+ /// getOptionName - Return all of the names the option is registered as.
+ ///
+ const std::vector<std::string> &getOptionNames() const {
+ return OptionNames;
+ }
+
+ /// addOptionName - Add a name that this option is known as.
+ ///
+ void addOptionName(const std::string &Name) {
+ OptionNames.push_back(Name);
+ }
+
+ /// removeOptionName - Eliminate one of the names for this option.
+ ///
+ void removeOptionName(const std::string &Name) {
+ unsigned i = 0;
+ for (; OptionNames[i] != Name; ++i)
+ assert(i+1 < OptionNames.size() && "Didn't find option name!");
+ OptionNames.erase(OptionNames.begin()+i);
+ }
+
+
+ /// getShortHelp - Return the short help string for this command.
+ ///
+ const std::string &getShortHelp() { return ShortHelp; }
+
+ /// getLongHelp - Return the long help string for this command, if it
+ /// exists.
+ const std::string &getLongHelp() { return LongHelp; }
+
+ virtual void runCommand(CLIDebugger &D, std::string &Arguments) = 0;
+ };
+
+ /// BuiltinCLICommand - This class represents commands that are built directly
+ /// into the debugger.
+ class BuiltinCLICommand : public CLICommand {
+ // Impl - Pointer to the method that implements the command
+ void (CLIDebugger::*Impl)(std::string&);
+ public:
+ BuiltinCLICommand(const std::string &ShortHelp, const std::string &LongHelp,
+ void (CLIDebugger::*impl)(std::string&))
+ : CLICommand(ShortHelp, LongHelp), Impl(impl) {}
+
+ void runCommand(CLIDebugger &D, std::string &Arguments) {
+ (D.*Impl)(Arguments);
+ }
+ };
+}
+
+#endif
diff --git a/tools/llvm-db/CLIDebugger.cpp b/tools/llvm-db/CLIDebugger.cpp
new file mode 100644
index 0000000..1d2a838
--- /dev/null
+++ b/tools/llvm-db/CLIDebugger.cpp
@@ -0,0 +1,308 @@
+//===-- CLIDebugger.cpp - Command Line Interface to the Debugger ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the main implementation of the Command Line Interface to
+// the debugger.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CLIDebugger.h"
+#include "CLICommand.h"
+#include "llvm/Debugger/SourceFile.h"
+#include "llvm/ADT/StringExtras.h"
+#include <iostream>
+using namespace llvm;
+
+/// CLIDebugger constructor - This initializes the debugger to its default
+/// state, and initializes the command table.
+///
+CLIDebugger::CLIDebugger()
+ : TheProgramInfo(0), TheRuntimeInfo(0), Prompt("(llvm-db) "), ListSize(10) {
+ // Initialize instance variables
+ CurrentFile = 0;
+ LineListedStart = 1;
+ LineListedEnd = 1;
+ LastCurrentFrame = 0;
+ CurrentLanguage = 0;
+
+ CLICommand *C;
+ //===--------------------------------------------------------------------===//
+ // Program startup and shutdown options
+ //
+ addCommand("file", new BuiltinCLICommand(
+ "Use specified file as the program to be debugged",
+ "The debugger looks in the current directory and the program $PATH for the"
+ " specified LLVM program. It then unloads the currently loaded program and"
+ " loads the specified program.\n",
+ &CLIDebugger::fileCommand));
+
+ addCommand("create", new BuiltinCLICommand(
+ "Start the program, halting its execution in main",
+ "This command creates an instance of the current program, but stops"
+ "\nexecution immediately.\n",
+ &CLIDebugger::createCommand));
+
+ addCommand("kill", new BuiltinCLICommand(
+ "Kills the execution of the current program being debugged", "",
+ &CLIDebugger::killCommand));
+
+ addCommand("quit", new BuiltinCLICommand(
+ "Exit the debugger", "",
+ &CLIDebugger::quitCommand));
+
+ //===--------------------------------------------------------------------===//
+ // Program execution commands
+ //
+ addCommand("run", C = new BuiltinCLICommand(
+ "Start the program running from the beginning", "",
+ &CLIDebugger::runCommand));
+ addCommand("r", C);
+
+ addCommand("cont", C = new BuiltinCLICommand(
+ "Continue program being debugged until the next stop point", "",
+ &CLIDebugger::contCommand));
+ addCommand("c", C); addCommand("fg", C);
+
+ addCommand("step", C = new BuiltinCLICommand(
+ "Step program until it reaches a new source line", "",
+ &CLIDebugger::stepCommand));
+ addCommand("s", C);
+
+ addCommand("next", C = new BuiltinCLICommand(
+ "Step program until it reaches a new source line, stepping over calls", "",
+ &CLIDebugger::nextCommand));
+ addCommand("n", C);
+
+ addCommand("finish", new BuiltinCLICommand(
+ "Execute until the selected stack frame returns",
+ "Upon return, the value returned is printed and put in the value history.\n",
+ &CLIDebugger::finishCommand));
+
+ //===--------------------------------------------------------------------===//
+ // Stack frame commands
+ //
+ addCommand("backtrace", C = new BuiltinCLICommand(
+ "Print backtrace of all stack frames, or innermost COUNT frames",
+ "FIXME: describe. Takes 'n', '-n' or 'full'\n",
+ &CLIDebugger::backtraceCommand));
+ addCommand("bt", C);
+
+ addCommand("up", new BuiltinCLICommand(
+ "Select and print stack frame that called this one",
+ "An argument says how many frames up to go.\n",
+ &CLIDebugger::upCommand));
+
+ addCommand("down", new BuiltinCLICommand(
+ "Select and print stack frame called by this one",
+ "An argument says how many frames down go.\n",
+ &CLIDebugger::downCommand));
+
+ addCommand("frame", C = new BuiltinCLICommand(
+ "Select and print a stack frame",
+ "With no argument, print the selected stack frame. (See also 'info frame').\n"
+ "An argument specifies the frame to select.\n",
+ &CLIDebugger::frameCommand));
+ addCommand("f", C);
+
+ //===--------------------------------------------------------------------===//
+ // Breakpoint related commands
+ //
+ addCommand("break", C = new BuiltinCLICommand(
+ "Set breakpoint at specified line or function",
+ "FIXME: describe.\n",
+ &CLIDebugger::breakCommand));
+ addCommand("b", C);
+
+
+ //===--------------------------------------------------------------------===//
+ // Miscellaneous commands
+ //
+ addCommand("info", new BuiltinCLICommand(
+ "Generic command for showing things about the program being debugged",
+ "info functions: display information about functions in the program.\ninfo"
+ " source : display information about the current source file.\ninfo source"
+ "s : Display source file names for the program\ninfo target : print status"
+ " of inferior process\n",
+ &CLIDebugger::infoCommand));
+
+ addCommand("list", C = new BuiltinCLICommand(
+ "List specified function or line",
+ "FIXME: document\n",
+ &CLIDebugger::listCommand));
+ addCommand("l", C);
+
+ addCommand("set", new BuiltinCLICommand(
+ "Change program or debugger variable",
+ "FIXME: document\n",
+ &CLIDebugger::setCommand));
+
+ addCommand("show", new BuiltinCLICommand(
+ "Generic command for showing things about the debugger",
+ "FIXME: document\n",
+ &CLIDebugger::showCommand));
+
+ addCommand("help", C = new BuiltinCLICommand(
+ "Prints information about available commands", "",
+ &CLIDebugger::helpCommand));
+ addCommand("h", C);
+}
+
+
+/// addCommand - Add a command to the CommandTable, potentially displacing a
+/// preexisting command.
+void CLIDebugger::addCommand(const std::string &Option, CLICommand *Cmd) {
+ assert(Cmd && "Cannot set a null command!");
+ CLICommand *&CS = CommandTable[Option];
+ if (CS == Cmd) return; // noop
+
+ // If we already have a command, decrement the command's reference count.
+ if (CS) {
+ CS->removeOptionName(Option);
+ CS->dropRef();
+ }
+ CS = Cmd;
+
+ // Remember that we are using this command.
+ Cmd->addRef();
+ Cmd->addOptionName(Option);
+}
+
+static bool isValidPrefix(const std::string &Prefix, const std::string &Option){
+ return Prefix.size() <= Option.size() &&
+ Prefix == std::string(Option.begin(), Option.begin()+Prefix.size());
+}
+
+/// getCommand - This looks up the specified command using a fuzzy match.
+/// If the string exactly matches a command or is an unambiguous prefix of a
+/// command, it returns the command. Otherwise it throws an exception
+/// indicating the possible ambiguous choices.
+CLICommand *CLIDebugger::getCommand(const std::string &Command) {
+
+ // Look up the command in the table.
+ std::map<std::string, CLICommand*>::iterator CI =
+ CommandTable.lower_bound(Command);
+
+ if (Command == "") {
+ throw "Null command should not get here!";
+ } else if (CI == CommandTable.end() ||
+ !isValidPrefix(Command, CI->first)) {
+ // If this command has no relation to anything in the command table,
+ // print the error message.
+ throw "Unknown command: '" + Command +
+ "'. Use 'help' for list of commands.";
+ } else if (CI->first == Command) {
+ // We have an exact match on the command
+ return CI->second;
+ } else {
+ // Otherwise, we have a prefix match. Check to see if this is
+ // unambiguous, and if so, run it.
+ std::map<std::string, CLICommand*>::iterator CI2 = CI;
+
+ // If the next command is a valid completion of this one, we are
+ // ambiguous.
+ if (++CI2 != CommandTable.end() && isValidPrefix(Command, CI2->first)) {
+ std::string ErrorMsg =
+ "Ambiguous command '" + Command + "'. Options: " + CI->first;
+ for (++CI; CI != CommandTable.end() &&
+ isValidPrefix(Command, CI->first); ++CI)
+ ErrorMsg += ", " + CI->first;
+ throw ErrorMsg;
+ } else {
+ // It's an unambiguous prefix of a command, use it.
+ return CI->second;
+ }
+ }
+}
+
+
+/// run - Start the debugger, returning when the user exits the debugger. This
+/// starts the main event loop of the CLI debugger.
+///
+int CLIDebugger::run() {
+ std::string Command;
+ std::cout << Prompt;
+
+ // Keep track of the last command issued, so that we can reissue it if the
+ // user hits enter as the command.
+ CLICommand *LastCommand = 0;
+ std::string LastArgs;
+
+ // Continue reading commands until the end of file.
+ while (getline(std::cin, Command)) {
+ std::string Arguments = Command;
+
+ // Split off the command from the arguments to the command.
+ Command = getToken(Arguments, " \t\n\v\f\r\\/;.*&");
+
+ try {
+ CLICommand *CurCommand;
+
+ if (Command == "") {
+ CurCommand = LastCommand;
+ Arguments = LastArgs;
+ } else {
+ CurCommand = getCommand(Command);
+ }
+
+ // Save the command we are running in case the user wants us to repeat it
+ // next time.
+ LastCommand = CurCommand;
+ LastArgs = Arguments;
+
+ // Finally, execute the command.
+ if (CurCommand)
+ CurCommand->runCommand(*this, Arguments);
+
+ } catch (int RetVal) {
+ // The quit command exits the command loop by throwing an integer return
+ // code.
+ return RetVal;
+ } catch (const std::string &Error) {
+ std::cout << "Error: " << Error << "\n";
+ } catch (const char *Error) {
+ std::cout << "Error: " << Error << "\n";
+ } catch (const NonErrorException &E) {
+ std::cout << E.getMessage() << "\n";
+ } catch (...) {
+ std::cout << "ERROR: Debugger caught unexpected exception!\n";
+ // Attempt to continue.
+ }
+
+ // Write the prompt to get the next bit of user input
+ std::cout << Prompt;
+ }
+
+ return 0;
+}
+
+
+/// askYesNo - Ask the user a question, and demand a yes/no response. If
+/// the user says yes, return true.
+///
+bool CLIDebugger::askYesNo(const std::string &Message) const {
+ std::string Answer;
+ std::cout << Message << " (y or n) " << std::flush;
+ while (getline(std::cin, Answer)) {
+ std::string Val = getToken(Answer);
+ if (getToken(Answer).empty()) {
+ if (Val == "yes" || Val == "y" || Val == "YES" || Val == "Y" ||
+ Val == "Yes")
+ return true;
+ if (Val == "no" || Val == "n" || Val == "NO" || Val == "N" ||
+ Val == "No")
+ return false;
+ }
+
+ std::cout << "Please answer y or n.\n" << Message << " (y or n) "
+ << std::flush;
+ }
+
+ // Ran out of input?
+ return false;
+}
diff --git a/tools/llvm-db/CLIDebugger.h b/tools/llvm-db/CLIDebugger.h
new file mode 100644
index 0000000..56ea14d
--- /dev/null
+++ b/tools/llvm-db/CLIDebugger.h
@@ -0,0 +1,205 @@
+//===- CLIDebugger.h - LLVM Command Line Interface Debugger -----*- C++ -*-===//
+//
+// 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 CLIDebugger class, which implements a command line
+// interface to the LLVM Debugger library.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLIDEBUGGER_H
+#define CLIDEBUGGER_H
+
+#include "llvm/Debugger/Debugger.h"
+#include <map>
+
+namespace llvm {
+ class CLICommand;
+ class SourceFile;
+ class SourceLanguage;
+ class ProgramInfo;
+ class RuntimeInfo;
+
+ /// CLIDebugger - This class implements the command line interface for the
+ /// LLVM debugger.
+ class CLIDebugger {
+ /// Dbg - The low-level LLVM debugger object that we use to do our dirty
+ /// work.
+ Debugger Dbg;
+
+ /// CommandTable - This table contains a mapping from command names to the
+ /// CLICommand object that implements the command.
+ std::map<std::string, CLICommand*> CommandTable;
+
+ //===------------------------------------------------------------------===//
+ // Data related to the program that is currently loaded. Note that the Dbg
+ // variable also captures some information about the loaded program. This
+ // pointer is non-null iff Dbg.isProgramLoaded() is true.
+ //
+ ProgramInfo *TheProgramInfo;
+
+ //===------------------------------------------------------------------===//
+ // Data related to the program that is currently executing, but has stopped.
+ // Note that the Dbg variable also captures some information about the
+ // loaded program. This pointer is non-null iff Dbg.isProgramRunning() is
+ // true.
+ //
+ RuntimeInfo *TheRuntimeInfo;
+
+ /// LastCurrentFrame - This variable holds the Frame ID of the top-level
+ /// stack frame from the last time that the program was executed. We keep
+ /// this because we only want to print the source location when the current
+ /// function changes.
+ void *LastCurrentFrame;
+
+ //===------------------------------------------------------------------===//
+ // Data directly exposed through the debugger prompt
+ //
+ std::string Prompt; // set prompt, show prompt
+ unsigned ListSize; // set listsize, show listsize
+
+ //===------------------------------------------------------------------===//
+ // Data to support user interaction
+ //
+
+ /// CurrentFile - The current source file we are inspecting, or null if
+ /// none.
+ const SourceFile *CurrentFile;
+ unsigned LineListedStart, LineListedEnd;
+
+ /// CurrentLanguage - This contains the source language in use, if one is
+ /// explicitly set by the user. If this is null (the default), the language
+ /// is automatically determined from the current stack frame.
+ ///
+ const SourceLanguage *CurrentLanguage;
+
+ public:
+ CLIDebugger();
+
+ /// getDebugger - Return the current LLVM debugger implementation being
+ /// used.
+ Debugger &getDebugger() { return Dbg; }
+
+ /// run - Start the debugger, returning when the user exits the debugger.
+ /// This starts the main event loop of the CLI debugger.
+ ///
+ int run();
+
+ /// addCommand - Add a command to the CommandTable, potentially displacing a
+ /// preexisting command.
+ void addCommand(const std::string &Option, CLICommand *Cmd);
+
+ /// addSourceDirectory - Add a directory to search when looking for the
+ /// source code of the program.
+ void addSourceDirectory(const std::string &Dir) {
+ // FIXME: implement
+ }
+
+ /// getCurrentLanguage - Return the current source language that the user is
+ /// playing around with. This is aquired from the current stack frame of a
+ /// running program if one exists, but this value can be explicitly set by
+ /// the user as well.
+ const SourceLanguage &getCurrentLanguage() const;
+
+ /// getProgramInfo - Return a reference to the ProgramInfo object for the
+ /// currently loaded program. If there is no program loaded, throw an
+ /// exception.
+ ProgramInfo &getProgramInfo() const {
+ if (TheProgramInfo == 0)
+ throw "No program is loaded.";
+ return *TheProgramInfo;
+ }
+
+ /// getRuntimeInfo - Return a reference to the current RuntimeInfo object.
+ /// If there is no program running, throw an exception.
+ RuntimeInfo &getRuntimeInfo() const {
+ if (TheRuntimeInfo == 0)
+ throw "No program is running.";
+ return *TheRuntimeInfo;
+ }
+
+ private: // Internal implementation methods
+
+ /// getCommand - This looks up the specified command using a fuzzy match.
+ /// If the string exactly matches a command or is an unambiguous prefix of a
+ /// command, it returns the command. Otherwise it throws an exception
+ /// indicating the possible ambiguous choices.
+ CLICommand *getCommand(const std::string &Command);
+
+ /// askYesNo - Ask the user a question, and demand a yes/no response. If
+ /// the user says yes, return true.
+ bool askYesNo(const std::string &Message) const;
+
+ /// printProgramLocation - Given a loaded and created child process that has
+ /// stopped, print its current source location.
+ void printProgramLocation(bool PrintLocation = true);
+
+ /// eliminateRunInfo - We are about to run the program. Forget any state
+ /// about how the program used to be stopped.
+ void eliminateRunInfo();
+
+ /// programStoppedSuccessfully - This method updates internal data
+ /// structures to reflect the fact that the program just executed a while,
+ /// and has successfully stopped.
+ void programStoppedSuccessfully();
+
+ public: /// Builtin debugger commands, invokable by the user
+ // Program startup and shutdown options
+ void fileCommand(std::string &Options); // file
+ void createCommand(std::string &Options); // create
+ void killCommand(std::string &Options); // kill
+ void quitCommand(std::string &Options); // quit
+
+ // Program execution commands
+ void runCommand(std::string &Options); // run|r
+ void contCommand(std::string &Options); // cont|c|fg
+ void stepCommand(std::string &Options); // step|s [count]
+ void nextCommand(std::string &Options); // next|n [count]
+ void finishCommand(std::string &Options); // finish
+
+ // Stack frame commands
+ void backtraceCommand(std::string &Options); // backtrace|bt [count]
+ void upCommand(std::string &Options); // up
+ void downCommand(std::string &Options); // down
+ void frameCommand(std::string &Options); // frame
+
+
+ // Breakpoint related commands
+ void breakCommand(std::string &Options); // break|b <id>
+
+ // Miscellaneous commands
+ void infoCommand(std::string &Options); // info
+ void listCommand(std::string &Options); // list
+ void setCommand(std::string &Options); // set
+ void showCommand(std::string &Options); // show
+ void helpCommand(std::string &Options); // help
+
+ private:
+ /// startProgramRunning - If the program has been updated, reload it, then
+ /// start executing the program.
+ void startProgramRunning();
+
+ /// printSourceLine - Print the specified line of the current source file.
+ /// If the specified line is invalid (the source file could not be loaded or
+ /// the line number is out of range), don't print anything, but return true.
+ bool printSourceLine(unsigned LineNo);
+
+ /// parseLineSpec - Parses a line specifier, for use by the 'list' command.
+ /// If SourceFile is returned as a void pointer, then it was not specified.
+ /// If the line specifier is invalid, an exception is thrown.
+ void parseLineSpec(std::string &LineSpec, const SourceFile *&SourceFile,
+ unsigned &LineNo);
+
+ /// parseProgramOptions - This method parses the Options string and loads it
+ /// as options to be passed to the program. This is used by the run command
+ /// and by 'set args'.
+ void parseProgramOptions(std::string &Options);
+ };
+}
+
+#endif
diff --git a/tools/llvm-db/CMakeLists.txt b/tools/llvm-db/CMakeLists.txt
new file mode 100644
index 0000000..af64908
--- /dev/null
+++ b/tools/llvm-db/CMakeLists.txt
@@ -0,0 +1,8 @@
+set(LLVM_LINK_COMPONENTS debugger)
+set(LLVM_REQUIRES_EH 1)
+
+add_llvm_tool(llvm-db
+ CLIDebugger.cpp
+ Commands.cpp
+ llvm-db.cpp
+ )
diff --git a/tools/llvm-db/Commands.cpp b/tools/llvm-db/Commands.cpp
new file mode 100644
index 0000000..ffebdd5
--- /dev/null
+++ b/tools/llvm-db/Commands.cpp
@@ -0,0 +1,865 @@
+//===-- Commands.cpp - Implement various commands for the CLI -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements many builtin user commands.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CLIDebugger.h"
+#include "CLICommand.h"
+#include "llvm/Debugger/ProgramInfo.h"
+#include "llvm/Debugger/RuntimeInfo.h"
+#include "llvm/Debugger/SourceLanguage.h"
+#include "llvm/Debugger/SourceFile.h"
+#include "llvm/Debugger/InferiorProcess.h"
+#include "llvm/Support/FileUtilities.h"
+#include "llvm/ADT/StringExtras.h"
+#include <iostream>
+#include <cstdlib>
+using namespace llvm;
+
+/// getCurrentLanguage - Return the current source language that the user is
+/// playing around with. This is aquired from the current stack frame of a
+/// running program if one exists, but this value can be explicitly set by the
+/// user as well.
+const SourceLanguage &CLIDebugger::getCurrentLanguage() const {
+ // If the user explicitly switched languages with 'set language', use what
+ // they asked for.
+ if (CurrentLanguage) {
+ return *CurrentLanguage;
+ } else if (Dbg.isProgramRunning()) {
+ // Otherwise, if the program is running, infer the current language from it.
+ const GlobalVariable *FuncDesc =
+ getRuntimeInfo().getCurrentFrame().getFunctionDesc();
+ return getProgramInfo().getFunction(FuncDesc).getSourceFile().getLanguage();
+ } else {
+ // Otherwise, default to C like GDB apparently does.
+ return SourceLanguage::getCFamilyInstance();
+ }
+}
+
+/// startProgramRunning - If the program has been updated, reload it, then
+/// start executing the program.
+void CLIDebugger::startProgramRunning() {
+ eliminateRunInfo();
+
+ // If the program has been modified, reload it!
+ sys::PathWithStatus Program(Dbg.getProgramPath());
+ std::string Err;
+ const sys::FileStatus *Status = Program.getFileStatus(false, &Err);
+ if (!Status)
+ throw Err;
+ if (TheProgramInfo->getProgramTimeStamp() != Status->getTimestamp()) {
+ std::cout << "'" << Program << "' has changed; re-reading program.\n";
+
+ // Unload an existing program. This kills the program if necessary.
+ Dbg.unloadProgram();
+ delete TheProgramInfo;
+ TheProgramInfo = 0;
+ CurrentFile = 0;
+
+ Dbg.loadProgram(Program.toString());
+ TheProgramInfo = new ProgramInfo(Dbg.getProgram());
+ }
+
+ std::cout << "Starting program: " << Dbg.getProgramPath() << "\n";
+ Dbg.createProgram();
+
+ // There was no current frame.
+ LastCurrentFrame = 0;
+}
+
+/// printSourceLine - Print the specified line of the current source file.
+/// If the specified line is invalid (the source file could not be loaded or
+/// the line number is out of range), don't print anything, but return true.
+bool CLIDebugger::printSourceLine(unsigned LineNo) {
+ assert(CurrentFile && "There is no current source file to print!");
+ const char *LineStart, *LineEnd;
+ CurrentFile->getSourceLine(LineNo-1, LineStart, LineEnd);
+ if (LineStart == 0) return true;
+ std::cout << LineNo;
+
+ // If this is the line the program is currently stopped at, print a marker.
+ if (Dbg.isProgramRunning()) {
+ unsigned CurLineNo, CurColNo;
+ const SourceFileInfo *CurSFI;
+ getRuntimeInfo().getCurrentFrame().getSourceLocation(CurLineNo, CurColNo,
+ CurSFI);
+
+ if (CurLineNo == LineNo && CurrentFile == &CurSFI->getSourceText())
+ std::cout << " ->";
+ }
+
+ std::cout << "\t" << std::string(LineStart, LineEnd) << "\n";
+ return false;
+}
+
+/// printProgramLocation - Print a line of the place where the current stack
+/// frame has stopped and the source line it is on.
+///
+void CLIDebugger::printProgramLocation(bool PrintLocation) {
+ assert(Dbg.isProgramLoaded() && Dbg.isProgramRunning() &&
+ "Error program is not loaded and running!");
+
+ // Figure out where the program stopped...
+ StackFrame &SF = getRuntimeInfo().getCurrentFrame();
+ unsigned LineNo, ColNo;
+ const SourceFileInfo *FileDesc;
+ SF.getSourceLocation(LineNo, ColNo, FileDesc);
+
+ // If requested, print out some program information about WHERE we are.
+ if (PrintLocation) {
+ // FIXME: print the current function arguments
+ if (const GlobalVariable *FuncDesc = SF.getFunctionDesc())
+ std::cout << getProgramInfo().getFunction(FuncDesc).getSymbolicName();
+ else
+ std::cout << "<unknown function>";
+
+ CurrentFile = &FileDesc->getSourceText();
+
+ std::cout << " at " << CurrentFile->getFilename() << ":" << LineNo;
+ if (ColNo) std::cout << ":" << ColNo;
+ std::cout << "\n";
+ }
+
+ if (printSourceLine(LineNo))
+ std::cout << "<could not load source file>\n";
+ else {
+ LineListedStart = LineNo-ListSize/2+1;
+ if ((int)LineListedStart < 1) LineListedStart = 1;
+ LineListedEnd = LineListedStart+1;
+ }
+}
+
+/// eliminateRunInfo - We are about to run the program. Forget any state
+/// about how the program used to be stopped.
+void CLIDebugger::eliminateRunInfo() {
+ delete TheRuntimeInfo;
+ TheRuntimeInfo = 0;
+}
+
+/// programStoppedSuccessfully - This method updates internal data
+/// structures to reflect the fact that the program just executed a while,
+/// and has successfully stopped.
+void CLIDebugger::programStoppedSuccessfully() {
+ assert(TheRuntimeInfo==0 && "Someone forgot to release the old RuntimeInfo!");
+
+ TheRuntimeInfo = new RuntimeInfo(TheProgramInfo, Dbg.getRunningProcess());
+
+ // FIXME: if there are any breakpoints at the current location, print them as
+ // well.
+
+ // Since the program as successfully stopped, print its location.
+ void *CurrentFrame = getRuntimeInfo().getCurrentFrame().getFrameID();
+ printProgramLocation(CurrentFrame != LastCurrentFrame);
+ LastCurrentFrame = CurrentFrame;
+}
+
+
+
+/// getUnsignedIntegerOption - Get an unsigned integer number from the Val
+/// string. Check to make sure that the string contains an unsigned integer
+/// token, and if not, throw an exception. If isOnlyOption is set, also throw
+/// an exception if there is extra junk at the end of the string.
+static unsigned getUnsignedIntegerOption(const char *Msg, std::string &Val,
+ bool isOnlyOption = true) {
+ std::string Tok = getToken(Val);
+ if (Tok.empty() || (isOnlyOption && !getToken(Val).empty()))
+ throw std::string(Msg) + " expects an unsigned integer argument.";
+
+ char *EndPtr;
+ unsigned Result = strtoul(Tok.c_str(), &EndPtr, 0);
+ if (EndPtr != Tok.c_str()+Tok.size())
+ throw std::string(Msg) + " expects an unsigned integer argument.";
+
+ return Result;
+}
+
+/// getOptionalUnsignedIntegerOption - This method is just like
+/// getUnsignedIntegerOption, but if the argument value is not specified, a
+/// default is returned instead of causing an error.
+static unsigned
+getOptionalUnsignedIntegerOption(const char *Msg, unsigned Default,
+ std::string &Val, bool isOnlyOption = true) {
+ // Check to see if the value was specified...
+ std::string TokVal = getToken(Val);
+ if (TokVal.empty()) return Default;
+
+ // If it was specified, add it back to the value we are parsing...
+ Val = TokVal+Val;
+
+ // And parse normally.
+ return getUnsignedIntegerOption(Msg, Val, isOnlyOption);
+}
+
+
+/// parseProgramOptions - This method parses the Options string and loads it
+/// as options to be passed to the program. This is used by the run command
+/// and by 'set args'.
+void CLIDebugger::parseProgramOptions(std::string &Options) {
+ // FIXME: tokenizing by whitespace is clearly incorrect. Instead we should
+ // honor quotes and other things that a shell would. Also in the future we
+ // should support redirection of standard IO.
+
+ std::vector<std::string> Arguments;
+ for (std::string A = getToken(Options); !A.empty(); A = getToken(Options))
+ Arguments.push_back(A);
+ Dbg.setProgramArguments(Arguments.begin(), Arguments.end());
+}
+
+
+//===----------------------------------------------------------------------===//
+// Program startup and shutdown options
+//===----------------------------------------------------------------------===//
+
+
+/// file command - If the user specifies an option, search the PATH for the
+/// specified program/bitcode file and load it. If the user does not specify
+/// an option, unload the current program.
+void CLIDebugger::fileCommand(std::string &Options) {
+ std::string Prog = getToken(Options);
+ if (!getToken(Options).empty())
+ throw "file command takes at most one argument.";
+
+ // Check to make sure the user knows what they are doing
+ if (Dbg.isProgramRunning() &&
+ !askYesNo("A program is already loaded. Kill it?"))
+ return;
+
+ // Unload an existing program. This kills the program if necessary.
+ eliminateRunInfo();
+ delete TheProgramInfo;
+ TheProgramInfo = 0;
+ Dbg.unloadProgram();
+ CurrentFile = 0;
+
+ // If requested, start the new program.
+ if (Prog.empty()) {
+ std::cout << "Unloaded program.\n";
+ } else {
+ std::cout << "Loading program... " << std::flush;
+ Dbg.loadProgram(Prog);
+ assert(Dbg.isProgramLoaded() &&
+ "loadProgram succeeded, but not program loaded!");
+ TheProgramInfo = new ProgramInfo(Dbg.getProgram());
+ std::cout << "successfully loaded '" << Dbg.getProgramPath() << "'!\n";
+ }
+}
+
+
+void CLIDebugger::createCommand(std::string &Options) {
+ if (!getToken(Options).empty())
+ throw "create command does not take any arguments.";
+ if (!Dbg.isProgramLoaded()) throw "No program loaded.";
+ if (Dbg.isProgramRunning() &&
+ !askYesNo("The program is already running. Restart from the beginning?"))
+ return;
+
+ // Start the program running.
+ startProgramRunning();
+
+ // The program stopped!
+ programStoppedSuccessfully();
+}
+
+void CLIDebugger::killCommand(std::string &Options) {
+ if (!getToken(Options).empty())
+ throw "kill command does not take any arguments.";
+ if (!Dbg.isProgramRunning())
+ throw "No program is currently being run.";
+
+ if (askYesNo("Kill the program being debugged?"))
+ Dbg.killProgram();
+ eliminateRunInfo();
+}
+
+void CLIDebugger::quitCommand(std::string &Options) {
+ if (!getToken(Options).empty())
+ throw "quit command does not take any arguments.";
+
+ if (Dbg.isProgramRunning() &&
+ !askYesNo("The program is running. Exit anyway?"))
+ return;
+
+ // Throw exception to get out of the user-input loop.
+ throw 0;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Program execution commands
+//===----------------------------------------------------------------------===//
+
+void CLIDebugger::runCommand(std::string &Options) {
+ if (!Dbg.isProgramLoaded()) throw "No program loaded.";
+ if (Dbg.isProgramRunning() &&
+ !askYesNo("The program is already running. Restart from the beginning?"))
+ return;
+
+ // Parse all of the options to the run command, which specify program
+ // arguments to run with.
+ parseProgramOptions(Options);
+
+ eliminateRunInfo();
+
+ // Start the program running.
+ startProgramRunning();
+
+ // Start the program running...
+ Options = "";
+ contCommand(Options);
+}
+
+void CLIDebugger::contCommand(std::string &Options) {
+ if (!getToken(Options).empty()) throw "cont argument not supported yet.";
+ if (!Dbg.isProgramRunning()) throw "Program is not running.";
+
+ eliminateRunInfo();
+
+ Dbg.contProgram();
+
+ // The program stopped!
+ programStoppedSuccessfully();
+}
+
+void CLIDebugger::stepCommand(std::string &Options) {
+ if (!Dbg.isProgramRunning()) throw "Program is not running.";
+
+ // Figure out how many times to step.
+ unsigned Amount =
+ getOptionalUnsignedIntegerOption("'step' command", 1, Options);
+
+ eliminateRunInfo();
+
+ // Step the specified number of times.
+ for (; Amount; --Amount)
+ Dbg.stepProgram();
+
+ // The program stopped!
+ programStoppedSuccessfully();
+}
+
+void CLIDebugger::nextCommand(std::string &Options) {
+ if (!Dbg.isProgramRunning()) throw "Program is not running.";
+ unsigned Amount =
+ getOptionalUnsignedIntegerOption("'next' command", 1, Options);
+
+ eliminateRunInfo();
+
+ for (; Amount; --Amount)
+ Dbg.nextProgram();
+
+ // The program stopped!
+ programStoppedSuccessfully();
+}
+
+void CLIDebugger::finishCommand(std::string &Options) {
+ if (!getToken(Options).empty())
+ throw "finish command does not take any arguments.";
+ if (!Dbg.isProgramRunning()) throw "Program is not running.";
+
+ // Figure out where we are exactly. If the user requests that we return from
+ // a frame that is not the top frame, make sure we get it.
+ void *CurrentFrame = getRuntimeInfo().getCurrentFrame().getFrameID();
+
+ eliminateRunInfo();
+
+ Dbg.finishProgram(CurrentFrame);
+
+ // The program stopped!
+ programStoppedSuccessfully();
+}
+
+//===----------------------------------------------------------------------===//
+// Stack frame commands
+//===----------------------------------------------------------------------===//
+
+void CLIDebugger::backtraceCommand(std::string &Options) {
+ // Accepts "full", n, -n
+ if (!getToken(Options).empty())
+ throw "FIXME: bt command argument not implemented yet!";
+
+ RuntimeInfo &RI = getRuntimeInfo();
+ ProgramInfo &PI = getProgramInfo();
+
+ try {
+ for (unsigned i = 0; ; ++i) {
+ StackFrame &SF = RI.getStackFrame(i);
+ std::cout << "#" << i;
+ if (i == RI.getCurrentFrameIdx())
+ std::cout << " ->";
+ std::cout << "\t" << SF.getFrameID() << " in ";
+ if (const GlobalVariable *G = SF.getFunctionDesc())
+ std::cout << PI.getFunction(G).getSymbolicName();
+
+ unsigned LineNo, ColNo;
+ const SourceFileInfo *SFI;
+ SF.getSourceLocation(LineNo, ColNo, SFI);
+ if (!SFI->getBaseName().empty()) {
+ std::cout << " at " << SFI->getBaseName();
+ if (LineNo) {
+ std::cout << ":" << LineNo;
+ if (ColNo)
+ std::cout << ":" << ColNo;
+ }
+ }
+
+ // FIXME: when we support shared libraries, we should print ' from foo.so'
+ // if the stack frame is from a different object than the current one.
+
+ std::cout << "\n";
+ }
+ } catch (...) {
+ // Stop automatically when we run off the bottom of the stack.
+ }
+}
+
+void CLIDebugger::upCommand(std::string &Options) {
+ unsigned Num =
+ getOptionalUnsignedIntegerOption("'up' command", 1, Options);
+
+ RuntimeInfo &RI = getRuntimeInfo();
+ unsigned CurFrame = RI.getCurrentFrameIdx();
+
+ // Check to see if we go can up the specified number of frames.
+ try {
+ RI.getStackFrame(CurFrame+Num);
+ } catch (...) {
+ if (Num == 1)
+ throw "Initial frame selected; you cannot go up.";
+ else
+ throw "Cannot go up " + utostr(Num) + " frames!";
+ }
+
+ RI.setCurrentFrameIdx(CurFrame+Num);
+ printProgramLocation();
+}
+
+void CLIDebugger::downCommand(std::string &Options) {
+ unsigned Num =
+ getOptionalUnsignedIntegerOption("'down' command", 1, Options);
+
+ RuntimeInfo &RI = getRuntimeInfo();
+ unsigned CurFrame = RI.getCurrentFrameIdx();
+
+ // Check to see if we can go up the specified number of frames.
+ if (CurFrame < Num) {
+ if (Num == 1)
+ throw "Bottom (i.e., innermost) frame selected; you cannot go down.";
+ else
+ throw "Cannot go down " + utostr(Num) + " frames!";
+ }
+
+ RI.setCurrentFrameIdx(CurFrame-Num);
+ printProgramLocation();
+}
+
+void CLIDebugger::frameCommand(std::string &Options) {
+ RuntimeInfo &RI = getRuntimeInfo();
+ unsigned CurFrame = RI.getCurrentFrameIdx();
+
+ unsigned Num =
+ getOptionalUnsignedIntegerOption("'frame' command", CurFrame, Options);
+
+ // Check to see if we go to the specified frame.
+ RI.getStackFrame(Num);
+
+ RI.setCurrentFrameIdx(Num);
+ printProgramLocation();
+}
+
+
+//===----------------------------------------------------------------------===//
+// Breakpoint related commands
+//===----------------------------------------------------------------------===//
+
+void CLIDebugger::breakCommand(std::string &Options) {
+ // Figure out where the user wants a breakpoint.
+ const SourceFile *File;
+ unsigned LineNo;
+
+ // Check to see if the user specified a line specifier.
+ std::string Option = getToken(Options); // strip whitespace
+ if (!Option.empty()) {
+ Options = Option + Options; // reconstruct string
+
+ // Parse the line specifier.
+ parseLineSpec(Options, File, LineNo);
+ } else {
+ // Build a line specifier for the current stack frame.
+ throw "FIXME: breaking at the current location is not implemented yet!";
+ }
+
+ if (!File) File = CurrentFile;
+ if (File == 0)
+ throw "Unknown file to place breakpoint!";
+
+ std::cerr << "Break: " << File->getFilename() << ":" << LineNo << "\n";
+
+ throw "breakpoints not implemented yet!";
+}
+
+//===----------------------------------------------------------------------===//
+// Miscellaneous commands
+//===----------------------------------------------------------------------===//
+
+void CLIDebugger::infoCommand(std::string &Options) {
+ std::string What = getToken(Options);
+
+ if (What.empty() || !getToken(Options).empty()){
+ std::string infoStr("info");
+ helpCommand(infoStr);
+ return;
+ }
+
+ if (What == "frame") {
+ } else if (What == "functions") {
+ const std::map<const GlobalVariable*, SourceFunctionInfo*> &Functions
+ = getProgramInfo().getSourceFunctions();
+ std::cout << "All defined functions:\n";
+ // FIXME: GDB groups these by source file. We could do that I guess.
+ for (std::map<const GlobalVariable*, SourceFunctionInfo*>::const_iterator
+ I = Functions.begin(), E = Functions.end(); I != E; ++I) {
+ std::cout << I->second->getSymbolicName() << "\n";
+ }
+
+ } else if (What == "source") {
+ if (CurrentFile == 0)
+ throw "No current source file.";
+
+ // Get the SourceFile information for the current file.
+ const SourceFileInfo &SF =
+ getProgramInfo().getSourceFile(CurrentFile->getDescriptor());
+
+ std::cout << "Current source file is: " << SF.getBaseName() << "\n"
+ << "Compilation directory is: " << SF.getDirectory() << "\n";
+ if (unsigned NL = CurrentFile->getNumLines())
+ std::cout << "Located in: " << CurrentFile->getFilename() << "\n"
+ << "Contains " << NL << " lines\n";
+ else
+ std::cout << "Could not find source file.\n";
+ std::cout << "Source language is "
+ << SF.getLanguage().getSourceLanguageName() << "\n";
+
+ } else if (What == "sources") {
+ const std::map<const GlobalVariable*, SourceFileInfo*> &SourceFiles =
+ getProgramInfo().getSourceFiles();
+ std::cout << "Source files for the program:\n";
+ for (std::map<const GlobalVariable*, SourceFileInfo*>::const_iterator I =
+ SourceFiles.begin(), E = SourceFiles.end(); I != E;) {
+ std::cout << I->second->getDirectory() << "/"
+ << I->second->getBaseName();
+ ++I;
+ if (I != E) std::cout << ", ";
+ }
+ std::cout << "\n";
+ } else if (What == "target") {
+ std::cout << Dbg.getRunningProcess().getStatus();
+ } else {
+ // See if this is something handled by the current language.
+ if (getCurrentLanguage().printInfo(What))
+ return;
+
+ throw "Unknown info command '" + What + "'. Try 'help info'.";
+ }
+}
+
+/// parseLineSpec - Parses a line specifier, for use by the 'list' command.
+/// If SourceFile is returned as a void pointer, then it was not specified.
+/// If the line specifier is invalid, an exception is thrown.
+void CLIDebugger::parseLineSpec(std::string &LineSpec,
+ const SourceFile *&SourceFile,
+ unsigned &LineNo) {
+ SourceFile = 0;
+ LineNo = 0;
+
+ // First, check to see if we have a : separator.
+ std::string FirstPart = getToken(LineSpec, ":");
+ std::string SecondPart = getToken(LineSpec, ":");
+ if (!getToken(LineSpec).empty()) throw "Malformed line specification!";
+
+ // If there is no second part, we must have either "function", "number",
+ // "+offset", or "-offset".
+ if (SecondPart.empty()) {
+ if (FirstPart.empty()) throw "Malformed line specification!";
+ if (FirstPart[0] == '+') {
+ FirstPart.erase(FirstPart.begin(), FirstPart.begin()+1);
+ // For +n, return LineListedEnd+n
+ LineNo = LineListedEnd +
+ getUnsignedIntegerOption("Line specifier '+'", FirstPart);
+
+ } else if (FirstPart[0] == '-') {
+ FirstPart.erase(FirstPart.begin(), FirstPart.begin()+1);
+ // For -n, return LineListedEnd-n
+ LineNo = LineListedEnd -
+ getUnsignedIntegerOption("Line specifier '-'", FirstPart);
+ if ((int)LineNo < 1) LineNo = 1;
+ } else if (FirstPart[0] == '*') {
+ throw "Address expressions not supported as source locations!";
+ } else {
+ // Ok, check to see if this is just a line number.
+ std::string Saved = FirstPart;
+ try {
+ LineNo = getUnsignedIntegerOption("", Saved);
+ } catch (...) {
+ // Ok, it's not a valid line number. It must be a source-language
+ // entity name.
+ std::string Name = getToken(FirstPart);
+ if (!getToken(FirstPart).empty())
+ throw "Extra junk in line specifier after '" + Name + "'.";
+ SourceFunctionInfo *SFI =
+ getCurrentLanguage().lookupFunction(Name, getProgramInfo(),
+ TheRuntimeInfo);
+ if (SFI == 0)
+ throw "Unknown identifier '" + Name + "'.";
+
+ unsigned L, C;
+ SFI->getSourceLocation(L, C);
+ if (L == 0) throw "Could not locate '" + Name + "'!";
+ LineNo = L;
+ SourceFile = &SFI->getSourceFile().getSourceText();
+ return;
+ }
+ }
+
+ } else {
+ // Ok, this must be a filename qualified line number or function name.
+ // First, figure out the source filename.
+ std::string SourceFilename = getToken(FirstPart);
+ if (!getToken(FirstPart).empty())
+ throw "Invalid filename qualified source location!";
+
+ // Next, check to see if this is just a line number.
+ std::string Saved = SecondPart;
+ try {
+ LineNo = getUnsignedIntegerOption("", Saved);
+ } catch (...) {
+ // Ok, it's not a valid line number. It must be a function name.
+ throw "FIXME: Filename qualified function names are not support "
+ "as line specifiers yet!";
+ }
+
+ // Ok, we got the line number. Now check out the source file name to make
+ // sure it's all good. If it is, return it. If not, throw exception.
+ SourceFile =&getProgramInfo().getSourceFile(SourceFilename).getSourceText();
+ }
+}
+
+void CLIDebugger::listCommand(std::string &Options) {
+ if (!Dbg.isProgramLoaded())
+ throw "No program is loaded. Use the 'file' command.";
+
+ // Handle "list foo," correctly, by returning " " as the second token
+ Options += " ";
+
+ std::string FirstLineSpec = getToken(Options, ",");
+ std::string SecondLineSpec = getToken(Options, ",");
+ if (!getToken(Options, ",").empty())
+ throw "list command only expects two source location specifiers!";
+
+ // StartLine, EndLine - The starting and ending line numbers to print.
+ unsigned StartLine = 0, EndLine = 0;
+
+ if (SecondLineSpec.empty()) { // No second line specifier provided?
+ // Handle special forms like "", "+", "-", etc.
+ std::string TmpSpec = FirstLineSpec;
+ std::string Tok = getToken(TmpSpec);
+ if (getToken(TmpSpec).empty() && (Tok == "" || Tok == "+" || Tok == "-")) {
+ if (Tok == "+" || Tok == "") {
+ StartLine = LineListedEnd;
+ EndLine = StartLine + ListSize;
+ } else {
+ assert(Tok == "-");
+ StartLine = LineListedStart-ListSize;
+ EndLine = LineListedStart;
+ if ((int)StartLine <= 0) StartLine = 1;
+ }
+ } else {
+ // Must be a normal line specifier.
+ const SourceFile *File;
+ unsigned LineNo;
+ parseLineSpec(FirstLineSpec, File, LineNo);
+
+ // If the user only specified one file specifier, we should display
+ // ListSize lines centered at the specified line.
+ if (File != 0) CurrentFile = File;
+ StartLine = LineNo - (ListSize+1)/2;
+ if ((int)StartLine <= 0) StartLine = 1;
+ EndLine = StartLine + ListSize;
+ }
+
+ } else {
+ // Parse two line specifiers...
+ const SourceFile *StartFile, *EndFile;
+ unsigned StartLineNo, EndLineNo;
+ parseLineSpec(FirstLineSpec, StartFile, StartLineNo);
+ unsigned SavedLLE = LineListedEnd;
+ LineListedEnd = StartLineNo;
+ try {
+ parseLineSpec(SecondLineSpec, EndFile, EndLineNo);
+ } catch (...) {
+ LineListedEnd = SavedLLE;
+ throw;
+ }
+
+ // Inherit file specified by the first line spec if there was one.
+ if (EndFile == 0) EndFile = StartFile;
+
+ if (StartFile != EndFile)
+ throw "Start and end line specifiers are in different files!";
+ CurrentFile = StartFile;
+ StartLine = StartLineNo;
+ EndLine = EndLineNo+1;
+ }
+
+ assert((int)StartLine > 0 && (int)EndLine > 0 && StartLine <= EndLine &&
+ "Error reading line specifiers!");
+
+ // If there was no current file, and the user didn't specify one to list, we
+ // have an error.
+ if (CurrentFile == 0)
+ throw "There is no current file to list.";
+
+ // Remember for next time.
+ LineListedStart = StartLine;
+ LineListedEnd = StartLine;
+
+ for (unsigned LineNo = StartLine; LineNo != EndLine; ++LineNo) {
+ // Print the source line, unless it is invalid.
+ if (printSourceLine(LineNo))
+ break;
+ LineListedEnd = LineNo+1;
+ }
+
+ // If we didn't print any lines, find out why.
+ if (LineListedEnd == StartLine) {
+ // See if we can read line #0 from the file, if not, we couldn't load the
+ // file.
+ const char *LineStart, *LineEnd;
+ CurrentFile->getSourceLine(0, LineStart, LineEnd);
+ if (LineStart == 0)
+ throw "Could not load source file '" + CurrentFile->getFilename() + "'!";
+ else
+ std::cout << "<end of file>\n";
+ }
+}
+
+void CLIDebugger::setCommand(std::string &Options) {
+ std::string What = getToken(Options);
+
+ if (What.empty())
+ throw "set command expects at least two arguments.";
+ if (What == "args") {
+ parseProgramOptions(Options);
+ } else if (What == "language") {
+ std::string Lang = getToken(Options);
+ if (!getToken(Options).empty())
+ throw "set language expects one argument at most.";
+ if (Lang == "") {
+ std::cout << "The currently understood settings are:\n\n"
+ << "local or auto Automatic setting based on source file\n"
+ << "c Use the C language\n"
+ << "c++ Use the C++ language\n"
+ << "unknown Use when source language is not supported\n";
+ } else if (Lang == "local" || Lang == "auto") {
+ CurrentLanguage = 0;
+ } else if (Lang == "c") {
+ CurrentLanguage = &SourceLanguage::getCFamilyInstance();
+ } else if (Lang == "c++") {
+ CurrentLanguage = &SourceLanguage::getCPlusPlusInstance();
+ } else if (Lang == "unknown") {
+ CurrentLanguage = &SourceLanguage::getUnknownLanguageInstance();
+ } else {
+ throw "Unknown language '" + Lang + "'.";
+ }
+
+ } else if (What == "listsize") {
+ ListSize = getUnsignedIntegerOption("'set prompt' command", Options);
+ } else if (What == "prompt") {
+ // Include any trailing whitespace or other tokens, but not leading
+ // whitespace.
+ Prompt = getToken(Options); // Strip leading whitespace
+ Prompt += Options; // Keep trailing whitespace or other stuff
+ } else {
+ // FIXME: Try to parse this as a source-language program expression.
+ throw "Don't know how to set '" + What + "'!";
+ }
+}
+
+void CLIDebugger::showCommand(std::string &Options) {
+ std::string What = getToken(Options);
+
+ if (What.empty() || !getToken(Options).empty())
+ throw "show command expects one argument.";
+
+ if (What == "args") {
+ std::cout << "Argument list to give program when started is \"";
+ // FIXME: This doesn't print stuff correctly if the arguments have spaces in
+ // them, but currently the only way to get that is to use the --args command
+ // line argument. This should really handle escaping all hard characters as
+ // needed.
+ for (unsigned i = 0, e = Dbg.getNumProgramArguments(); i != e; ++i)
+ std::cout << (i ? " " : "") << Dbg.getProgramArgument(i);
+ std::cout << "\"\n";
+
+ } else if (What == "language") {
+ std::cout << "The current source language is '";
+ if (CurrentLanguage)
+ std::cout << CurrentLanguage->getSourceLanguageName();
+ else
+ std::cout << "auto; currently "
+ << getCurrentLanguage().getSourceLanguageName();
+ std::cout << "'.\n";
+ } else if (What == "listsize") {
+ std::cout << "Number of source lines llvm-db will list by default is "
+ << ListSize << ".\n";
+ } else if (What == "prompt") {
+ std::cout << "llvm-db's prompt is \"" << Prompt << "\".\n";
+ } else {
+ throw "Unknown show command '" + What + "'. Try 'help show'.";
+ }
+}
+
+void CLIDebugger::helpCommand(std::string &Options) {
+ // Print out all of the commands in the CommandTable
+ std::string Command = getToken(Options);
+ if (!getToken(Options).empty())
+ throw "help command takes at most one argument.";
+
+ // Getting detailed help on a particular command?
+ if (!Command.empty()) {
+ CLICommand *C = getCommand(Command);
+ std::cout << C->getShortHelp() << ".\n" << C->getLongHelp();
+
+ // If there are aliases for this option, print them out.
+ const std::vector<std::string> &Names = C->getOptionNames();
+ if (Names.size() > 1) {
+ std::cout << "The '" << Command << "' command is known as: '"
+ << Names[0] << "'";
+ for (unsigned i = 1, e = Names.size(); i != e; ++i)
+ std::cout << ", '" << Names[i] << "'";
+ std::cout << "\n";
+ }
+
+ } else {
+ unsigned MaxSize = 0;
+ for (std::map<std::string, CLICommand*>::iterator I = CommandTable.begin(),
+ E = CommandTable.end(); I != E; ++I)
+ if (I->first.size() > MaxSize &&
+ I->first == I->second->getPrimaryOptionName())
+ MaxSize = I->first.size();
+
+ // Loop over all of the commands, printing the short help version
+ for (std::map<std::string, CLICommand*>::iterator I = CommandTable.begin(),
+ E = CommandTable.end(); I != E; ++I)
+ if (I->first == I->second->getPrimaryOptionName())
+ std::cout << I->first << std::string(MaxSize - I->first.size(), ' ')
+ << " - " << I->second->getShortHelp() << "\n";
+ }
+}
diff --git a/tools/llvm-db/Makefile b/tools/llvm-db/Makefile
new file mode 100644
index 0000000..df81649
--- /dev/null
+++ b/tools/llvm-db/Makefile
@@ -0,0 +1,15 @@
+##===- tools/llvm-db/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 = llvm-db
+LINK_COMPONENTS := debugger
+REQUIRES_EH := 1
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/llvm-db/llvm-db.cpp b/tools/llvm-db/llvm-db.cpp
new file mode 100644
index 0000000..04e6162
--- /dev/null
+++ b/tools/llvm-db/llvm-db.cpp
@@ -0,0 +1,100 @@
+//===- llvm-db.cpp - LLVM Debugger ----------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This utility implements a simple text-mode front-end to the LLVM debugger
+// library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CLIDebugger.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/System/Signals.h"
+#include <iostream>
+using namespace llvm;
+
+namespace {
+ // Command line options for specifying the program to debug and options to use
+ cl::opt<std::string>
+ InputFile(cl::desc("<program>"), cl::Positional, cl::init(""));
+
+ cl::list<std::string>
+ InputArgs("args", cl::Positional, cl::desc("<program and arguments>"),
+ cl::ZeroOrMore);
+
+ // Command line options to control various directory related stuff
+ cl::list<std::string>
+ SourceDirectories("directory", cl::value_desc("directory"),
+ cl::desc("Add directory to the search for source files"));
+ cl::alias SDA("d", cl::desc("Alias for --directory"),
+ cl::aliasopt(SourceDirectories));
+
+ cl::opt<std::string>
+ WorkingDirectory("cd", cl::desc("Use directory as current working directory"),
+ cl::value_desc("directory"));
+
+ // Command line options specific to the llvm-db debugger driver
+ cl::opt<bool> Quiet("quiet", cl::desc("Do not print introductory messages"));
+ cl::alias QA1("silent", cl::desc("Alias for -quiet"), cl::aliasopt(Quiet));
+ cl::alias QA2("q", cl::desc("Alias for -quiet"), cl::aliasopt(Quiet));
+}
+
+//===----------------------------------------------------------------------===//
+// main Driver function
+//
+int main(int argc, char **argv, char * const *envp) {
+ // Print a stack trace if we signal out.
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ std::cout << "NOTE: llvm-db is known useless right now.\n";
+ try {
+ cl::ParseCommandLineOptions(argc, argv,
+ "llvm source-level debugger\n");
+
+ if (!Quiet)
+ std::cout << "llvm-db: The LLVM source-level debugger\n";
+
+ // Merge Inputfile and InputArgs into the InputArgs list...
+ if (!InputFile.empty() && InputArgs.empty())
+ InputArgs.push_back(InputFile);
+
+ // Create the CLI debugger...
+ CLIDebugger D;
+
+ // Initialize the debugger with the command line options we read...
+ Debugger &Dbg = D.getDebugger();
+
+ // Initialize the debugger environment.
+ Dbg.initializeEnvironment(envp);
+ Dbg.setWorkingDirectory(WorkingDirectory);
+ for (unsigned i = 0, e = SourceDirectories.size(); i != e; ++i)
+ D.addSourceDirectory(SourceDirectories[i]);
+
+ if (!InputArgs.empty()) {
+ try {
+ D.fileCommand(InputArgs[0]);
+ } catch (const std::string &Error) {
+ std::cout << "Error: " << Error << "\n";
+ }
+
+ Dbg.setProgramArguments(InputArgs.begin()+1, InputArgs.end());
+ }
+
+ // Now that we have initialized the debugger, run it.
+ return D.run();
+ } catch (const std::string& msg) {
+ std::cerr << argv[0] << ": " << msg << "\n";
+ } catch (...) {
+ std::cerr << argv[0] << ": Unexpected unknown exception occurred.\n";
+ }
+ return 1;
+}
diff --git a/tools/llvm-dis/CMakeLists.txt b/tools/llvm-dis/CMakeLists.txt
new file mode 100644
index 0000000..d62a6b5
--- /dev/null
+++ b/tools/llvm-dis/CMakeLists.txt
@@ -0,0 +1,6 @@
+set(LLVM_LINK_COMPONENTS bitreader)
+set(LLVM_REQUIRES_EH 1)
+
+add_llvm_tool(llvm-dis
+ llvm-dis.cpp
+ )
diff --git a/tools/llvm-dis/Makefile b/tools/llvm-dis/Makefile
new file mode 100644
index 0000000..dfd5e34
--- /dev/null
+++ b/tools/llvm-dis/Makefile
@@ -0,0 +1,18 @@
+##===- tools/llvm-dis/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 = llvm-dis
+LINK_COMPONENTS := bitreader
+REQUIRES_EH := 1
+
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS = 1
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/llvm-dis/llvm-dis.cpp b/tools/llvm-dis/llvm-dis.cpp
new file mode 100644
index 0000000..471e5e2
--- /dev/null
+++ b/tools/llvm-dis/llvm-dis.cpp
@@ -0,0 +1,143 @@
+//===-- llvm-dis.cpp - The low-level LLVM disassembler --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This utility may be invoked in the following manner:
+// llvm-dis [options] - Read LLVM bitcode from stdin, write asm to stdout
+// llvm-dis [options] x.bc - Read LLVM bitcode from the x.bc file, write asm
+// to the x.ll file.
+// Options:
+// --help - Output information about command line switches
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Assembly/PrintModulePass.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Streams.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Signals.h"
+#include <iostream>
+#include <fstream>
+#include <memory>
+using namespace llvm;
+
+static cl::opt<std::string>
+InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-"));
+
+static cl::opt<std::string>
+OutputFilename("o", cl::desc("Override output filename"),
+ cl::value_desc("filename"));
+
+static cl::opt<bool>
+Force("f", cl::desc("Overwrite output files"));
+
+static cl::opt<bool>
+DontPrint("disable-output", cl::desc("Don't output the .ll file"), cl::Hidden);
+
+int main(int argc, char **argv) {
+ // Print a stack trace if we signal out.
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ try {
+ cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n");
+
+ std::ostream *Out = &std::cout; // Default to printing to stdout.
+ std::string ErrorMessage;
+
+ std::auto_ptr<Module> M;
+
+ if (MemoryBuffer *Buffer
+ = MemoryBuffer::getFileOrSTDIN(InputFilename, &ErrorMessage)) {
+ M.reset(ParseBitcodeFile(Buffer, &ErrorMessage));
+ delete Buffer;
+ }
+
+ if (M.get() == 0) {
+ cerr << argv[0] << ": ";
+ if (ErrorMessage.size())
+ cerr << ErrorMessage << "\n";
+ else
+ cerr << "bitcode didn't read correctly.\n";
+ return 1;
+ }
+
+ if (DontPrint) {
+ // Just use stdout. We won't actually print anything on it.
+ } else if (OutputFilename != "") { // Specified an output filename?
+ if (OutputFilename != "-") { // Not stdout?
+ if (!Force && std::ifstream(OutputFilename.c_str())) {
+ // If force is not specified, make sure not to overwrite a file!
+ cerr << argv[0] << ": error opening '" << OutputFilename
+ << "': file exists! Sending to standard output.\n";
+ } else {
+ Out = new std::ofstream(OutputFilename.c_str());
+ }
+ }
+ } else {
+ if (InputFilename == "-") {
+ OutputFilename = "-";
+ } else {
+ std::string IFN = InputFilename;
+ int Len = IFN.length();
+ if (IFN[Len-3] == '.' && IFN[Len-2] == 'b' && IFN[Len-1] == 'c') {
+ // Source ends in .bc
+ OutputFilename = std::string(IFN.begin(), IFN.end()-3)+".ll";
+ } else {
+ OutputFilename = IFN+".ll";
+ }
+
+ if (!Force && std::ifstream(OutputFilename.c_str())) {
+ // If force is not specified, make sure not to overwrite a file!
+ cerr << argv[0] << ": error opening '" << OutputFilename
+ << "': file exists! Sending to standard output.\n";
+ } else {
+ Out = new std::ofstream(OutputFilename.c_str());
+
+ // Make sure that the Out file gets unlinked from the disk if we get a
+ // SIGINT
+ sys::RemoveFileOnSignal(sys::Path(OutputFilename));
+ }
+ }
+ }
+
+ if (!Out->good()) {
+ cerr << argv[0] << ": error opening " << OutputFilename
+ << ": sending to stdout instead!\n";
+ Out = &std::cout;
+ }
+
+ // All that llvm-dis does is write the assembly to a file.
+ if (!DontPrint) {
+ PassManager Passes;
+ raw_os_ostream L(*Out);
+ Passes.add(createPrintModulePass(&L));
+ Passes.run(*M.get());
+ }
+
+ if (Out != &std::cout) {
+ ((std::ofstream*)Out)->close();
+ delete Out;
+ }
+ return 0;
+ } catch (const std::string& msg) {
+ cerr << argv[0] << ": " << msg << "\n";
+ } catch (...) {
+ cerr << argv[0] << ": Unexpected unknown exception occurred.\n";
+ }
+
+ return 1;
+}
+
diff --git a/tools/llvm-extract/CMakeLists.txt b/tools/llvm-extract/CMakeLists.txt
new file mode 100644
index 0000000..88e9343
--- /dev/null
+++ b/tools/llvm-extract/CMakeLists.txt
@@ -0,0 +1,5 @@
+set(LLVM_LINK_COMPONENTS ipo bitreader bitwriter)
+
+add_llvm_tool(llvm-extract
+ llvm-extract.cpp
+ )
diff --git a/tools/llvm-extract/Makefile b/tools/llvm-extract/Makefile
new file mode 100644
index 0000000..2ef8841
--- /dev/null
+++ b/tools/llvm-extract/Makefile
@@ -0,0 +1,18 @@
+##===- tools/llvm-extract/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 = llvm-extract
+LINK_COMPONENTS := ipo bitreader bitwriter
+
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS = 1
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/llvm-extract/llvm-extract.cpp b/tools/llvm-extract/llvm-extract.cpp
new file mode 100644
index 0000000..46840f2
--- /dev/null
+++ b/tools/llvm-extract/llvm-extract.cpp
@@ -0,0 +1,136 @@
+//===- llvm-extract.cpp - LLVM function extraction utility ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This utility changes the input module to only contain a single function,
+// which is primarily used for debugging transformations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/System/Signals.h"
+#include <iostream>
+#include <memory>
+#include <fstream>
+using namespace llvm;
+
+// InputFilename - The filename to read from.
+static cl::opt<std::string>
+InputFilename(cl::Positional, cl::desc("<input bitcode file>"),
+ cl::init("-"), cl::value_desc("filename"));
+
+static cl::opt<std::string>
+OutputFilename("o", cl::desc("Specify output filename"),
+ cl::value_desc("filename"), cl::init("-"));
+
+static cl::opt<bool>
+Force("f", cl::desc("Overwrite output files"));
+
+static cl::opt<bool>
+DeleteFn("delete", cl::desc("Delete specified Globals from Module"));
+
+static cl::opt<bool>
+Relink("relink",
+ cl::desc("Turn external linkage for callees of function to delete"));
+
+// ExtractFunc - The function to extract from the module...
+static cl::opt<std::string>
+ExtractFunc("func", cl::desc("Specify function to extract"), cl::init(""),
+ cl::value_desc("function"));
+
+// ExtractGlobal - The global to extract from the module...
+static cl::opt<std::string>
+ExtractGlobal("glob", cl::desc("Specify global to extract"), cl::init(""),
+ cl::value_desc("global"));
+
+int main(int argc, char **argv) {
+ // Print a stack trace if we signal out.
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ cl::ParseCommandLineOptions(argc, argv, "llvm extractor\n");
+
+ std::auto_ptr<Module> M;
+
+ MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFilename);
+ if (Buffer == 0) {
+ cerr << argv[0] << ": Error reading file '" + InputFilename + "'\n";
+ return 1;
+ } else {
+ M.reset(ParseBitcodeFile(Buffer));
+ }
+ delete Buffer;
+
+ if (M.get() == 0) {
+ cerr << argv[0] << ": bitcode didn't read correctly.\n";
+ return 1;
+ }
+
+ // Figure out which function we should extract
+ GlobalVariable *G = !ExtractGlobal.empty() ?
+ M.get()->getNamedGlobal(ExtractGlobal) : 0;
+
+ // Figure out which function we should extract
+ if (ExtractFunc.empty() && ExtractGlobal.empty()) ExtractFunc = "main";
+ Function *F = M.get()->getFunction(ExtractFunc);
+
+ if (F == 0 && G == 0) {
+ cerr << argv[0] << ": program doesn't contain function named '"
+ << ExtractFunc << "' or a global named '" << ExtractGlobal << "'!\n";
+ return 1;
+ }
+
+ // In addition to deleting all other functions, we also want to spiff it
+ // up a little bit. Do this now.
+ PassManager Passes;
+ Passes.add(new TargetData(M.get())); // Use correct TargetData
+ // Either isolate the function or delete it from the Module
+ std::vector<GlobalValue*> GVs;
+ if (F) GVs.push_back(F);
+ if (G) GVs.push_back(G);
+
+ Passes.add(createGVExtractionPass(GVs, DeleteFn, Relink));
+ if (!DeleteFn)
+ Passes.add(createGlobalDCEPass()); // Delete unreachable globals
+ Passes.add(createDeadTypeEliminationPass()); // Remove dead types...
+ Passes.add(createStripDeadPrototypesPass()); // Remove dead func decls
+
+ std::ostream *Out = 0;
+
+ if (OutputFilename != "-") { // Not stdout?
+ if (!Force && std::ifstream(OutputFilename.c_str())) {
+ // If force is not specified, make sure not to overwrite a file!
+ cerr << argv[0] << ": error opening '" << OutputFilename
+ << "': file exists!\n"
+ << "Use -f command line argument to force output\n";
+ return 1;
+ }
+ std::ios::openmode io_mode = std::ios::out | std::ios::trunc |
+ std::ios::binary;
+ Out = new std::ofstream(OutputFilename.c_str(), io_mode);
+ } else { // Specified stdout
+ // FIXME: cout is not binary!
+ Out = &std::cout;
+ }
+
+ Passes.add(CreateBitcodeWriterPass(*Out));
+ Passes.run(*M.get());
+
+ if (Out != &std::cout)
+ delete Out;
+ return 0;
+}
diff --git a/tools/llvm-ld/CMakeLists.txt b/tools/llvm-ld/CMakeLists.txt
new file mode 100644
index 0000000..51f0dc1
--- /dev/null
+++ b/tools/llvm-ld/CMakeLists.txt
@@ -0,0 +1,7 @@
+set(LLVM_LINK_COMPONENTS ipo scalaropts linker archive bitwriter)
+set(LLVM_REQUIRES_EH 1)
+
+add_llvm_tool(llvm-ld
+ Optimize.cpp
+ llvm-ld.cpp
+ )
diff --git a/tools/llvm-ld/Makefile b/tools/llvm-ld/Makefile
new file mode 100644
index 0000000..92cac2a
--- /dev/null
+++ b/tools/llvm-ld/Makefile
@@ -0,0 +1,16 @@
+##===- tools/llvm-ld/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 = llvm-ld
+LINK_COMPONENTS = ipo scalaropts linker archive bitwriter
+REQUIRES_EH := 1
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/llvm-ld/Optimize.cpp b/tools/llvm-ld/Optimize.cpp
new file mode 100644
index 0000000..f788f06
--- /dev/null
+++ b/tools/llvm-ld/Optimize.cpp
@@ -0,0 +1,194 @@
+//===- Optimize.cpp - Optimize a complete 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 all optimization of the linked module for llvm-ld.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Analysis/Passes.h"
+#include "llvm/Analysis/LoopPass.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/System/DynamicLibrary.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Support/PassNameParser.h"
+#include "llvm/Support/PluginLoader.h"
+#include <iostream>
+using namespace llvm;
+
+// Pass Name Options as generated by the PassNameParser
+static cl::list<const PassInfo*, bool, PassNameParser>
+ OptimizationList(cl::desc("Optimizations available:"));
+
+//Don't verify at the end
+static cl::opt<bool> DontVerify("disable-verify", cl::ReallyHidden);
+
+static cl::opt<bool> DisableInline("disable-inlining",
+ cl::desc("Do not run the inliner pass"));
+
+static cl::opt<bool>
+DisableOptimizations("disable-opt",
+ cl::desc("Do not run any optimization passes"));
+
+static cl::opt<bool> DisableInternalize("disable-internalize",
+ cl::desc("Do not mark all symbols as internal"));
+
+static cl::opt<bool> VerifyEach("verify-each",
+ cl::desc("Verify intermediate results of all passes"));
+
+static cl::alias ExportDynamic("export-dynamic",
+ cl::aliasopt(DisableInternalize),
+ cl::desc("Alias for -disable-internalize"));
+
+static cl::opt<bool> Strip("strip-all",
+ cl::desc("Strip all symbol info from executable"));
+
+static cl::alias A0("s", cl::desc("Alias for --strip-all"),
+ cl::aliasopt(Strip));
+
+static cl::opt<bool> StripDebug("strip-debug",
+ cl::desc("Strip debugger symbol info from executable"));
+
+static cl::alias A1("S", cl::desc("Alias for --strip-debug"),
+ cl::aliasopt(StripDebug));
+
+// A utility function that adds a pass to the pass manager but will also add
+// a verifier pass after if we're supposed to verify.
+static inline void addPass(PassManager &PM, Pass *P) {
+ // Add the pass to the pass manager...
+ PM.add(P);
+
+ // If we are verifying all of the intermediate steps, add the verifier...
+ if (VerifyEach)
+ PM.add(createVerifierPass());
+}
+
+namespace llvm {
+
+/// Optimize - Perform link time optimizations. This will run the scalar
+/// optimizations, any loaded plugin-optimization modules, and then the
+/// inter-procedural optimizations if applicable.
+void Optimize(Module* M) {
+
+ // Instantiate the pass manager to organize the passes.
+ PassManager Passes;
+
+ // If we're verifying, start off with a verification pass.
+ if (VerifyEach)
+ Passes.add(createVerifierPass());
+
+ // Add an appropriate TargetData instance for this module...
+ addPass(Passes, new TargetData(M));
+
+ if (!DisableOptimizations) {
+ // Now that composite has been compiled, scan through the module, looking
+ // for a main function. If main is defined, mark all other functions
+ // internal.
+ if (!DisableInternalize)
+ addPass(Passes, createInternalizePass(true));
+
+ // Propagate constants at call sites into the functions they call. This
+ // opens opportunities for globalopt (and inlining) by substituting function
+ // pointers passed as arguments to direct uses of functions.
+ addPass(Passes, createIPSCCPPass());
+
+ // Now that we internalized some globals, see if we can hack on them!
+ addPass(Passes, createGlobalOptimizerPass());
+
+ // Linking modules together can lead to duplicated global constants, only
+ // keep one copy of each constant...
+ addPass(Passes, createConstantMergePass());
+
+ // Remove unused arguments from functions...
+ addPass(Passes, createDeadArgEliminationPass());
+
+ // Reduce the code after globalopt and ipsccp. Both can open up significant
+ // simplification opportunities, and both can propagate functions through
+ // function pointers. When this happens, we often have to resolve varargs
+ // calls, etc, so let instcombine do this.
+ addPass(Passes, createInstructionCombiningPass());
+
+ if (!DisableInline)
+ addPass(Passes, createFunctionInliningPass()); // Inline small functions
+
+ addPass(Passes, createPruneEHPass()); // Remove dead EH info
+ addPass(Passes, createGlobalOptimizerPass()); // Optimize globals again.
+ addPass(Passes, createGlobalDCEPass()); // Remove dead functions
+
+ // If we didn't decide to inline a function, check to see if we can
+ // transform it to pass arguments by value instead of by reference.
+ addPass(Passes, createArgumentPromotionPass());
+
+ // The IPO passes may leave cruft around. Clean up after them.
+ addPass(Passes, createInstructionCombiningPass());
+ addPass(Passes, createJumpThreadingPass()); // Thread jumps.
+ addPass(Passes, createScalarReplAggregatesPass()); // Break up allocas
+
+ // Run a few AA driven optimizations here and now, to cleanup the code.
+ addPass(Passes, createFunctionAttrsPass()); // Add nocapture
+ addPass(Passes, createGlobalsModRefPass()); // IP alias analysis
+
+ addPass(Passes, createLICMPass()); // Hoist loop invariants
+ addPass(Passes, createGVNPass()); // Remove redundancies
+ addPass(Passes, createMemCpyOptPass()); // Remove dead memcpy's
+ addPass(Passes, createDeadStoreEliminationPass()); // Nuke dead stores
+
+ // Cleanup and simplify the code after the scalar optimizations.
+ addPass(Passes, createInstructionCombiningPass());
+
+ addPass(Passes, createJumpThreadingPass()); // Thread jumps.
+ addPass(Passes, createPromoteMemoryToRegisterPass()); // Cleanup jumpthread.
+
+ // Delete basic blocks, which optimization passes may have killed...
+ addPass(Passes, createCFGSimplificationPass());
+
+ // Now that we have optimized the program, discard unreachable functions...
+ addPass(Passes, createGlobalDCEPass());
+ }
+
+ // If the -s or -S command line options were specified, strip the symbols out
+ // of the resulting program to make it smaller. -s and -S are GNU ld options
+ // that we are supporting; they alias -strip-all and -strip-debug.
+ if (Strip || StripDebug)
+ addPass(Passes, createStripSymbolsPass(StripDebug && !Strip));
+
+ // Create a new optimization pass for each one specified on the command line
+ std::auto_ptr<TargetMachine> target;
+ for (unsigned i = 0; i < OptimizationList.size(); ++i) {
+ const PassInfo *Opt = OptimizationList[i];
+ if (Opt->getNormalCtor())
+ addPass(Passes, Opt->getNormalCtor()());
+ else
+ std::cerr << "llvm-ld: cannot create pass: " << Opt->getPassName()
+ << "\n";
+ }
+
+ // The user's passes may leave cruft around. Clean up after them them but
+ // only if we haven't got DisableOptimizations set
+ if (!DisableOptimizations) {
+ addPass(Passes, createInstructionCombiningPass());
+ addPass(Passes, createCFGSimplificationPass());
+ addPass(Passes, createAggressiveDCEPass());
+ addPass(Passes, createGlobalDCEPass());
+ }
+
+ // Make sure everything is still good.
+ if (!DontVerify)
+ Passes.add(createVerifierPass());
+
+ // Run our queue of passes all at once now, efficiently.
+ Passes.run(*M);
+}
+
+}
diff --git a/tools/llvm-ld/llvm-ld.cpp b/tools/llvm-ld/llvm-ld.cpp
new file mode 100644
index 0000000..fd2e0f7
--- /dev/null
+++ b/tools/llvm-ld/llvm-ld.cpp
@@ -0,0 +1,708 @@
+//===- llvm-ld.cpp - LLVM 'ld' compatible linker --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This utility is intended to be compatible with GCC, and follows standard
+// system 'ld' conventions. As such, the default output file is ./a.out.
+// Additionally, this program outputs a shell script that is used to invoke LLI
+// to execute the program. In this manner, the generated executable (a.out for
+// example), is directly executable, whereas the bitcode file actually lives in
+// the a.out.bc file generated by this program. Also, Force is on by default.
+//
+// Note that if someone (or a script) deletes the executable program generated,
+// the .bc file will be left around. Considering that this is a temporary hack,
+// I'm not too worried about this.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/LinkAllVMCore.h"
+#include "llvm/Linker.h"
+#include "llvm/System/Program.h"
+#include "llvm/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetMachineRegistry.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Streams.h"
+#include "llvm/Support/SystemUtils.h"
+#include "llvm/System/Signals.h"
+#include "llvm/Config/config.h"
+#include <fstream>
+#include <memory>
+#include <cstring>
+using namespace llvm;
+
+// Input/Output Options
+static cl::list<std::string> InputFilenames(cl::Positional, cl::OneOrMore,
+ cl::desc("<input bitcode files>"));
+
+static cl::opt<std::string> OutputFilename("o", cl::init("a.out"),
+ cl::desc("Override output filename"),
+ cl::value_desc("filename"));
+
+static cl::opt<bool> Verbose("v",
+ cl::desc("Print information about actions taken"));
+
+static cl::list<std::string> LibPaths("L", cl::Prefix,
+ cl::desc("Specify a library search path"),
+ cl::value_desc("directory"));
+
+static cl::list<std::string> FrameworkPaths("F", cl::Prefix,
+ cl::desc("Specify a framework search path"),
+ cl::value_desc("directory"));
+
+static cl::list<std::string> Libraries("l", cl::Prefix,
+ cl::desc("Specify libraries to link to"),
+ cl::value_desc("library prefix"));
+
+static cl::list<std::string> Frameworks("framework",
+ cl::desc("Specify frameworks to link to"),
+ cl::value_desc("framework"));
+
+// Options to control the linking, optimization, and code gen processes
+static cl::opt<bool> LinkAsLibrary("link-as-library",
+ cl::desc("Link the .bc files together as a library, not an executable"));
+
+static cl::alias Relink("r", cl::aliasopt(LinkAsLibrary),
+ cl::desc("Alias for -link-as-library"));
+
+static cl::opt<bool> Native("native",
+ cl::desc("Generate a native binary instead of a shell script"));
+
+static cl::opt<bool>NativeCBE("native-cbe",
+ cl::desc("Generate a native binary with the C backend and GCC"));
+
+static cl::list<std::string> PostLinkOpts("post-link-opts",
+ cl::value_desc("path"),
+ cl::desc("Run one or more optimization programs after linking"));
+
+static cl::list<std::string> XLinker("Xlinker", cl::value_desc("option"),
+ cl::desc("Pass options to the system linker"));
+
+// Compatibility options that llvm-ld ignores but are supported for
+// compatibility with LD
+static cl::opt<std::string> CO3("soname", cl::Hidden,
+ cl::desc("Compatibility option: ignored"));
+
+static cl::opt<std::string> CO4("version-script", cl::Hidden,
+ cl::desc("Compatibility option: ignored"));
+
+static cl::opt<bool> CO5("eh-frame-hdr", cl::Hidden,
+ cl::desc("Compatibility option: ignored"));
+
+static cl::opt<std::string> CO6("h", cl::Hidden,
+ cl::desc("Compatibility option: ignored"));
+
+static cl::opt<bool> CO7("start-group", cl::Hidden,
+ cl::desc("Compatibility option: ignored"));
+
+static cl::opt<bool> CO8("end-group", cl::Hidden,
+ cl::desc("Compatibility option: ignored"));
+
+static cl::opt<std::string> CO9("m", cl::Hidden,
+ cl::desc("Compatibility option: ignored"));
+
+/// This is just for convenience so it doesn't have to be passed around
+/// everywhere.
+static std::string progname;
+
+/// PrintAndExit - Prints a message to standard error and exits with error code
+///
+/// Inputs:
+/// Message - The message to print to standard error.
+///
+static void PrintAndExit(const std::string &Message, int errcode = 1) {
+ cerr << progname << ": " << Message << "\n";
+ llvm_shutdown();
+ exit(errcode);
+}
+
+static void PrintCommand(const std::vector<const char*> &args) {
+ std::vector<const char*>::const_iterator I = args.begin(), E = args.end();
+ for (; I != E; ++I)
+ if (*I)
+ cout << "'" << *I << "'" << " ";
+ cout << "\n" << std::flush;
+}
+
+/// CopyEnv - This function takes an array of environment variables and makes a
+/// copy of it. This copy can then be manipulated any way the caller likes
+/// without affecting the process's real environment.
+///
+/// Inputs:
+/// envp - An array of C strings containing an environment.
+///
+/// Return value:
+/// NULL - An error occurred.
+///
+/// Otherwise, a pointer to a new array of C strings is returned. Every string
+/// in the array is a duplicate of the one in the original array (i.e. we do
+/// not copy the char *'s from one array to another).
+///
+static char ** CopyEnv(char ** const envp) {
+ // Count the number of entries in the old list;
+ unsigned entries; // The number of entries in the old environment list
+ for (entries = 0; envp[entries] != NULL; entries++)
+ /*empty*/;
+
+ // Add one more entry for the NULL pointer that ends the list.
+ ++entries;
+
+ // If there are no entries at all, just return NULL.
+ if (entries == 0)
+ return NULL;
+
+ // Allocate a new environment list.
+ char **newenv = new char* [entries];
+ if ((newenv = new char* [entries]) == NULL)
+ return NULL;
+
+ // Make a copy of the list. Don't forget the NULL that ends the list.
+ entries = 0;
+ while (envp[entries] != NULL) {
+ newenv[entries] = new char[strlen (envp[entries]) + 1];
+ strcpy (newenv[entries], envp[entries]);
+ ++entries;
+ }
+ newenv[entries] = NULL;
+
+ return newenv;
+}
+
+
+/// RemoveEnv - Remove the specified environment variable from the environment
+/// array.
+///
+/// Inputs:
+/// name - The name of the variable to remove. It cannot be NULL.
+/// envp - The array of environment variables. It cannot be NULL.
+///
+/// Notes:
+/// This is mainly done because functions to remove items from the environment
+/// are not available across all platforms. In particular, Solaris does not
+/// seem to have an unsetenv() function or a setenv() function (or they are
+/// undocumented if they do exist).
+///
+static void RemoveEnv(const char * name, char ** const envp) {
+ for (unsigned index=0; envp[index] != NULL; index++) {
+ // Find the first equals sign in the array and make it an EOS character.
+ char *p = strchr (envp[index], '=');
+ if (p == NULL)
+ continue;
+ else
+ *p = '\0';
+
+ // Compare the two strings. If they are equal, zap this string.
+ // Otherwise, restore it.
+ if (!strcmp(name, envp[index]))
+ *envp[index] = '\0';
+ else
+ *p = '=';
+ }
+
+ return;
+}
+
+/// GenerateBitcode - generates a bitcode file from the module provided
+void GenerateBitcode(Module* M, const std::string& FileName) {
+
+ if (Verbose)
+ cout << "Generating Bitcode To " << FileName << '\n';
+
+ // Create the output file.
+ std::ios::openmode io_mode = std::ios::out | std::ios::trunc |
+ std::ios::binary;
+ std::ofstream Out(FileName.c_str(), io_mode);
+ if (!Out.good())
+ PrintAndExit("error opening '" + FileName + "' for writing!");
+
+ // Ensure that the bitcode file gets removed from the disk if we get a
+ // terminating signal.
+ sys::RemoveFileOnSignal(sys::Path(FileName));
+
+ // Write it out
+ WriteBitcodeToFile(M, Out);
+
+ // Close the bitcode file.
+ Out.close();
+}
+
+/// GenerateAssembly - generates a native assembly language source file from the
+/// specified bitcode file.
+///
+/// Inputs:
+/// InputFilename - The name of the input bitcode file.
+/// OutputFilename - The name of the file to generate.
+/// llc - The pathname to use for LLC.
+/// envp - The environment to use when running LLC.
+///
+/// Return non-zero value on error.
+///
+static int GenerateAssembly(const std::string &OutputFilename,
+ const std::string &InputFilename,
+ const sys::Path &llc,
+ std::string &ErrMsg ) {
+ // Run LLC to convert the bitcode file into assembly code.
+ std::vector<const char*> args;
+ args.push_back(llc.c_str());
+ // We will use GCC to assemble the program so set the assembly syntax to AT&T,
+ // regardless of what the target in the bitcode file is.
+ args.push_back("-x86-asm-syntax=att");
+ args.push_back("-f");
+ args.push_back("-o");
+ args.push_back(OutputFilename.c_str());
+ args.push_back(InputFilename.c_str());
+ args.push_back(0);
+
+ if (Verbose) {
+ cout << "Generating Assembly With: \n";
+ PrintCommand(args);
+ }
+
+ return sys::Program::ExecuteAndWait(llc, &args[0], 0, 0, 0, 0, &ErrMsg);
+}
+
+/// GenerateCFile - generates a C source file from the specified bitcode file.
+static int GenerateCFile(const std::string &OutputFile,
+ const std::string &InputFile,
+ const sys::Path &llc,
+ std::string& ErrMsg) {
+ // Run LLC to convert the bitcode file into C.
+ std::vector<const char*> args;
+ args.push_back(llc.c_str());
+ args.push_back("-march=c");
+ args.push_back("-f");
+ args.push_back("-o");
+ args.push_back(OutputFile.c_str());
+ args.push_back(InputFile.c_str());
+ args.push_back(0);
+
+ if (Verbose) {
+ cout << "Generating C Source With: \n";
+ PrintCommand(args);
+ }
+
+ return sys::Program::ExecuteAndWait(llc, &args[0], 0, 0, 0, 0, &ErrMsg);
+}
+
+/// GenerateNative - generates a native object file from the
+/// specified bitcode file.
+///
+/// Inputs:
+/// InputFilename - The name of the input bitcode file.
+/// OutputFilename - The name of the file to generate.
+/// NativeLinkItems - The native libraries, files, code with which to link
+/// LibPaths - The list of directories in which to find libraries.
+/// FrameworksPaths - The list of directories in which to find frameworks.
+/// Frameworks - The list of frameworks (dynamic libraries)
+/// gcc - The pathname to use for GGC.
+/// envp - A copy of the process's current environment.
+///
+/// Outputs:
+/// None.
+///
+/// Returns non-zero value on error.
+///
+static int GenerateNative(const std::string &OutputFilename,
+ const std::string &InputFilename,
+ const Linker::ItemList &LinkItems,
+ const sys::Path &gcc, char ** const envp,
+ std::string& ErrMsg) {
+ // Remove these environment variables from the environment of the
+ // programs that we will execute. It appears that GCC sets these
+ // environment variables so that the programs it uses can configure
+ // themselves identically.
+ //
+ // However, when we invoke GCC below, we want it to use its normal
+ // configuration. Hence, we must sanitize its environment.
+ char ** clean_env = CopyEnv(envp);
+ if (clean_env == NULL)
+ return 1;
+ RemoveEnv("LIBRARY_PATH", clean_env);
+ RemoveEnv("COLLECT_GCC_OPTIONS", clean_env);
+ RemoveEnv("GCC_EXEC_PREFIX", clean_env);
+ RemoveEnv("COMPILER_PATH", clean_env);
+ RemoveEnv("COLLECT_GCC", clean_env);
+
+
+ // Run GCC to assemble and link the program into native code.
+ //
+ // Note:
+ // We can't just assemble and link the file with the system assembler
+ // and linker because we don't know where to put the _start symbol.
+ // GCC mysteriously knows how to do it.
+ std::vector<std::string> args;
+ args.push_back(gcc.c_str());
+ args.push_back("-fno-strict-aliasing");
+ args.push_back("-O3");
+ args.push_back("-o");
+ args.push_back(OutputFilename);
+ args.push_back(InputFilename);
+
+ // Add in the library and framework paths
+ for (unsigned index = 0; index < LibPaths.size(); index++) {
+ args.push_back("-L" + LibPaths[index]);
+ }
+ for (unsigned index = 0; index < FrameworkPaths.size(); index++) {
+ args.push_back("-F" + FrameworkPaths[index]);
+ }
+
+ // Add the requested options
+ for (unsigned index = 0; index < XLinker.size(); index++)
+ args.push_back(XLinker[index]);
+
+ // Add in the libraries to link.
+ for (unsigned index = 0; index < LinkItems.size(); index++)
+ if (LinkItems[index].first != "crtend") {
+ if (LinkItems[index].second)
+ args.push_back("-l" + LinkItems[index].first);
+ else
+ args.push_back(LinkItems[index].first);
+ }
+
+ // Add in frameworks to link.
+ for (unsigned index = 0; index < Frameworks.size(); index++) {
+ args.push_back("-framework");
+ args.push_back(Frameworks[index]);
+ }
+
+ // Now that "args" owns all the std::strings for the arguments, call the c_str
+ // method to get the underlying string array. We do this game so that the
+ // std::string array is guaranteed to outlive the const char* array.
+ std::vector<const char *> Args;
+ for (unsigned i = 0, e = args.size(); i != e; ++i)
+ Args.push_back(args[i].c_str());
+ Args.push_back(0);
+
+ if (Verbose) {
+ cout << "Generating Native Executable With:\n";
+ PrintCommand(Args);
+ }
+
+ // Run the compiler to assembly and link together the program.
+ int R = sys::Program::ExecuteAndWait(
+ gcc, &Args[0], (const char**)clean_env, 0, 0, 0, &ErrMsg);
+ delete [] clean_env;
+ return R;
+}
+
+/// EmitShellScript - Output the wrapper file that invokes the JIT on the LLVM
+/// bitcode file for the program.
+static void EmitShellScript(char **argv) {
+ if (Verbose)
+ cout << "Emitting Shell Script\n";
+#if defined(_WIN32) || defined(__CYGWIN__)
+ // Windows doesn't support #!/bin/sh style shell scripts in .exe files. To
+ // support windows systems, we copy the llvm-stub.exe executable from the
+ // build tree to the destination file.
+ std::string ErrMsg;
+ sys::Path llvmstub = FindExecutable("llvm-stub.exe", argv[0]);
+ if (llvmstub.isEmpty())
+ PrintAndExit("Could not find llvm-stub.exe executable!");
+
+ if (0 != sys::CopyFile(sys::Path(OutputFilename), llvmstub, &ErrMsg))
+ PrintAndExit(ErrMsg);
+
+ return;
+#endif
+
+ // Output the script to start the program...
+ std::ofstream Out2(OutputFilename.c_str());
+ if (!Out2.good())
+ PrintAndExit("error opening '" + OutputFilename + "' for writing!");
+
+ Out2 << "#!/bin/sh\n";
+ // Allow user to setenv LLVMINTERP if lli is not in their PATH.
+ Out2 << "lli=${LLVMINTERP-lli}\n";
+ Out2 << "exec $lli \\\n";
+ // gcc accepts -l<lib> and implicitly searches /lib and /usr/lib.
+ LibPaths.push_back("/lib");
+ LibPaths.push_back("/usr/lib");
+ LibPaths.push_back("/usr/X11R6/lib");
+ // We don't need to link in libc! In fact, /usr/lib/libc.so may not be a
+ // shared object at all! See RH 8: plain text.
+ std::vector<std::string>::iterator libc =
+ std::find(Libraries.begin(), Libraries.end(), "c");
+ if (libc != Libraries.end()) Libraries.erase(libc);
+ // List all the shared object (native) libraries this executable will need
+ // on the command line, so that we don't have to do this manually!
+ for (std::vector<std::string>::iterator i = Libraries.begin(),
+ e = Libraries.end(); i != e; ++i) {
+ // try explicit -L arguments first:
+ sys::Path FullLibraryPath;
+ for (cl::list<std::string>::const_iterator P = LibPaths.begin(),
+ E = LibPaths.end(); P != E; ++P) {
+ FullLibraryPath = *P;
+ FullLibraryPath.appendComponent("lib" + *i);
+ FullLibraryPath.appendSuffix(&(LTDL_SHLIB_EXT[1]));
+ if (!FullLibraryPath.isEmpty()) {
+ if (!FullLibraryPath.isDynamicLibrary()) {
+ // Not a native shared library; mark as invalid
+ FullLibraryPath = sys::Path();
+ } else break;
+ }
+ }
+ if (FullLibraryPath.isEmpty())
+ FullLibraryPath = sys::Path::FindLibrary(*i);
+ if (!FullLibraryPath.isEmpty())
+ Out2 << " -load=" << FullLibraryPath.toString() << " \\\n";
+ }
+ Out2 << " $0.bc ${1+\"$@\"}\n";
+ Out2.close();
+}
+
+// BuildLinkItems -- This function generates a LinkItemList for the LinkItems
+// linker function by combining the Files and Libraries in the order they were
+// declared on the command line.
+static void BuildLinkItems(
+ Linker::ItemList& Items,
+ const cl::list<std::string>& Files,
+ const cl::list<std::string>& Libraries) {
+
+ // Build the list of linkage items for LinkItems.
+
+ cl::list<std::string>::const_iterator fileIt = Files.begin();
+ cl::list<std::string>::const_iterator libIt = Libraries.begin();
+
+ int libPos = -1, filePos = -1;
+ while ( libIt != Libraries.end() || fileIt != Files.end() ) {
+ if (libIt != Libraries.end())
+ libPos = Libraries.getPosition(libIt - Libraries.begin());
+ else
+ libPos = -1;
+ if (fileIt != Files.end())
+ filePos = Files.getPosition(fileIt - Files.begin());
+ else
+ filePos = -1;
+
+ if (filePos != -1 && (libPos == -1 || filePos < libPos)) {
+ // Add a source file
+ Items.push_back(std::make_pair(*fileIt++, false));
+ } else if (libPos != -1 && (filePos == -1 || libPos < filePos)) {
+ // Add a library
+ Items.push_back(std::make_pair(*libIt++, true));
+ }
+ }
+}
+
+// Rightly this should go in a header file but it just seems such a waste.
+namespace llvm {
+extern void Optimize(Module*);
+}
+
+int main(int argc, char **argv, char **envp) {
+ // Print a stack trace if we signal out.
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ try {
+ // Initial global variable above for convenience printing of program name.
+ progname = sys::Path(argv[0]).getBasename();
+
+ // Parse the command line options
+ cl::ParseCommandLineOptions(argc, argv, "llvm linker\n");
+
+ // Construct a Linker (now that Verbose is set)
+ Linker TheLinker(progname, OutputFilename, Verbose);
+
+ // Keep track of the native link items (versus the bitcode items)
+ Linker::ItemList NativeLinkItems;
+
+ // Add library paths to the linker
+ TheLinker.addPaths(LibPaths);
+ TheLinker.addSystemPaths();
+
+ // Remove any consecutive duplicates of the same library...
+ Libraries.erase(std::unique(Libraries.begin(), Libraries.end()),
+ Libraries.end());
+
+ if (LinkAsLibrary) {
+ std::vector<sys::Path> Files;
+ for (unsigned i = 0; i < InputFilenames.size(); ++i )
+ Files.push_back(sys::Path(InputFilenames[i]));
+ if (TheLinker.LinkInFiles(Files))
+ return 1; // Error already printed
+
+ // The libraries aren't linked in but are noted as "dependent" in the
+ // module.
+ for (cl::list<std::string>::const_iterator I = Libraries.begin(),
+ E = Libraries.end(); I != E ; ++I) {
+ TheLinker.getModule()->addLibrary(*I);
+ }
+ } else {
+ // Build a list of the items from our command line
+ Linker::ItemList Items;
+ BuildLinkItems(Items, InputFilenames, Libraries);
+
+ // Link all the items together
+ if (TheLinker.LinkInItems(Items, NativeLinkItems) )
+ return 1; // Error already printed
+ }
+
+ std::auto_ptr<Module> Composite(TheLinker.releaseModule());
+
+ // Optimize the module
+ Optimize(Composite.get());
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+ if (!LinkAsLibrary) {
+ // Default to "a.exe" instead of "a.out".
+ if (OutputFilename.getNumOccurrences() == 0)
+ OutputFilename = "a.exe";
+
+ // If there is no suffix add an "exe" one.
+ sys::Path ExeFile( OutputFilename );
+ if (ExeFile.getSuffix() == "") {
+ ExeFile.appendSuffix("exe");
+ OutputFilename = ExeFile.toString();
+ }
+ }
+#endif
+
+ // Generate the bitcode for the optimized module.
+ std::string RealBitcodeOutput = OutputFilename;
+
+ if (!LinkAsLibrary) RealBitcodeOutput += ".bc";
+ GenerateBitcode(Composite.get(), RealBitcodeOutput);
+
+ // If we are not linking a library, generate either a native executable
+ // or a JIT shell script, depending upon what the user wants.
+ if (!LinkAsLibrary) {
+ // If the user wants to run a post-link optimization, run it now.
+ if (!PostLinkOpts.empty()) {
+ std::vector<std::string> opts = PostLinkOpts;
+ for (std::vector<std::string>::iterator I = opts.begin(),
+ E = opts.end(); I != E; ++I) {
+ sys::Path prog(*I);
+ if (!prog.canExecute()) {
+ prog = sys::Program::FindProgramByName(*I);
+ if (prog.isEmpty())
+ PrintAndExit(std::string("Optimization program '") + *I +
+ "' is not found or not executable.");
+ }
+ // Get the program arguments
+ sys::Path tmp_output("opt_result");
+ std::string ErrMsg;
+ if (tmp_output.createTemporaryFileOnDisk(true, &ErrMsg))
+ PrintAndExit(ErrMsg);
+
+ const char* args[4];
+ args[0] = I->c_str();
+ args[1] = RealBitcodeOutput.c_str();
+ args[2] = tmp_output.c_str();
+ args[3] = 0;
+ if (0 == sys::Program::ExecuteAndWait(prog, args, 0,0,0,0, &ErrMsg)) {
+ if (tmp_output.isBitcodeFile() || tmp_output.isBitcodeFile()) {
+ sys::Path target(RealBitcodeOutput);
+ target.eraseFromDisk();
+ if (tmp_output.renamePathOnDisk(target, &ErrMsg))
+ PrintAndExit(ErrMsg, 2);
+ } else
+ PrintAndExit("Post-link optimization output is not bitcode");
+ } else {
+ PrintAndExit(ErrMsg);
+ }
+ }
+ }
+
+ // If the user wants to generate a native executable, compile it from the
+ // bitcode file.
+ //
+ // Otherwise, create a script that will run the bitcode through the JIT.
+ if (Native) {
+ // Name of the Assembly Language output file
+ sys::Path AssemblyFile ( OutputFilename);
+ AssemblyFile.appendSuffix("s");
+
+ // Mark the output files for removal if we get an interrupt.
+ sys::RemoveFileOnSignal(AssemblyFile);
+ sys::RemoveFileOnSignal(sys::Path(OutputFilename));
+
+ // Determine the locations of the llc and gcc programs.
+ sys::Path llc = FindExecutable("llc", argv[0]);
+ if (llc.isEmpty())
+ PrintAndExit("Failed to find llc");
+
+ sys::Path gcc = FindExecutable("gcc", argv[0]);
+ if (gcc.isEmpty())
+ PrintAndExit("Failed to find gcc");
+
+ // Generate an assembly language file for the bitcode.
+ std::string ErrMsg;
+ if (0 != GenerateAssembly(AssemblyFile.toString(), RealBitcodeOutput,
+ llc, ErrMsg))
+ PrintAndExit(ErrMsg);
+
+ if (0 != GenerateNative(OutputFilename, AssemblyFile.toString(),
+ NativeLinkItems, gcc, envp, ErrMsg))
+ PrintAndExit(ErrMsg);
+
+ // Remove the assembly language file.
+ AssemblyFile.eraseFromDisk();
+ } else if (NativeCBE) {
+ sys::Path CFile (OutputFilename);
+ CFile.appendSuffix("cbe.c");
+
+ // Mark the output files for removal if we get an interrupt.
+ sys::RemoveFileOnSignal(CFile);
+ sys::RemoveFileOnSignal(sys::Path(OutputFilename));
+
+ // Determine the locations of the llc and gcc programs.
+ sys::Path llc = FindExecutable("llc", argv[0]);
+ if (llc.isEmpty())
+ PrintAndExit("Failed to find llc");
+
+ sys::Path gcc = FindExecutable("gcc", argv[0]);
+ if (gcc.isEmpty())
+ PrintAndExit("Failed to find gcc");
+
+ // Generate an assembly language file for the bitcode.
+ std::string ErrMsg;
+ if (0 != GenerateCFile(
+ CFile.toString(), RealBitcodeOutput, llc, ErrMsg))
+ PrintAndExit(ErrMsg);
+
+ if (0 != GenerateNative(OutputFilename, CFile.toString(),
+ NativeLinkItems, gcc, envp, ErrMsg))
+ PrintAndExit(ErrMsg);
+
+ // Remove the assembly language file.
+ CFile.eraseFromDisk();
+
+ } else {
+ EmitShellScript(argv);
+ }
+
+ // Make the script executable...
+ std::string ErrMsg;
+ if (sys::Path(OutputFilename).makeExecutableOnDisk(&ErrMsg))
+ PrintAndExit(ErrMsg);
+
+ // Make the bitcode file readable and directly executable in LLEE as well
+ if (sys::Path(RealBitcodeOutput).makeExecutableOnDisk(&ErrMsg))
+ PrintAndExit(ErrMsg);
+
+ if (sys::Path(RealBitcodeOutput).makeReadableOnDisk(&ErrMsg))
+ PrintAndExit(ErrMsg);
+ }
+ } catch (const std::string& msg) {
+ PrintAndExit(msg,2);
+ } catch (...) {
+ PrintAndExit("Unexpected unknown exception occurred.", 2);
+ }
+
+ // Graceful exit
+ return 0;
+}
diff --git a/tools/llvm-link/CMakeLists.txt b/tools/llvm-link/CMakeLists.txt
new file mode 100644
index 0000000..69a435e
--- /dev/null
+++ b/tools/llvm-link/CMakeLists.txt
@@ -0,0 +1,5 @@
+set(LLVM_LINK_COMPONENTS linker bitreader bitwriter)
+
+add_llvm_tool(llvm-link
+ llvm-link.cpp
+ )
diff --git a/tools/llvm-link/Makefile b/tools/llvm-link/Makefile
new file mode 100644
index 0000000..ddc7a59
--- /dev/null
+++ b/tools/llvm-link/Makefile
@@ -0,0 +1,17 @@
+##===- tools/llvm-link/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 = llvm-link
+LINK_COMPONENTS = linker bitreader bitwriter
+
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS = 1
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/llvm-link/llvm-link.cpp b/tools/llvm-link/llvm-link.cpp
new file mode 100644
index 0000000..15850f4
--- /dev/null
+++ b/tools/llvm-link/llvm-link.cpp
@@ -0,0 +1,154 @@
+//===- llvm-link.cpp - Low-level LLVM linker ------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This utility may be invoked in the following manner:
+// llvm-link a.bc b.bc c.bc -o x.bc
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Linker.h"
+#include "llvm/Module.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Streams.h"
+#include "llvm/System/Signals.h"
+#include "llvm/System/Path.h"
+#include <fstream>
+#include <iostream>
+#include <memory>
+using namespace llvm;
+
+static cl::list<std::string>
+InputFilenames(cl::Positional, cl::OneOrMore,
+ cl::desc("<input bitcode files>"));
+
+static cl::opt<std::string>
+OutputFilename("o", cl::desc("Override output filename"), cl::init("-"),
+ cl::value_desc("filename"));
+
+static cl::opt<bool> Force("f", cl::desc("Overwrite output files"));
+
+static cl::opt<bool>
+Verbose("v", cl::desc("Print information about actions taken"));
+
+static cl::opt<bool>
+DumpAsm("d", cl::desc("Print assembly as linked"), cl::Hidden);
+
+// LoadFile - Read the specified bitcode file in and return it. This routine
+// searches the link path for the specified file to try to find it...
+//
+static inline std::auto_ptr<Module> LoadFile(const std::string &FN) {
+ sys::Path Filename;
+ if (!Filename.set(FN)) {
+ cerr << "Invalid file name: '" << FN << "'\n";
+ return std::auto_ptr<Module>();
+ }
+
+ std::string ErrorMessage;
+ if (Filename.exists()) {
+ if (Verbose) cerr << "Loading '" << Filename.c_str() << "'\n";
+ Module* Result = 0;
+
+ const std::string &FNStr = Filename.toString();
+ if (MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(FNStr,
+ &ErrorMessage)) {
+ Result = ParseBitcodeFile(Buffer, &ErrorMessage);
+ delete Buffer;
+ }
+ if (Result) return std::auto_ptr<Module>(Result); // Load successful!
+
+ if (Verbose) {
+ cerr << "Error opening bitcode file: '" << Filename.c_str() << "'";
+ if (ErrorMessage.size()) cerr << ": " << ErrorMessage;
+ cerr << "\n";
+ }
+ } else {
+ cerr << "Bitcode file: '" << Filename.c_str() << "' does not exist.\n";
+ }
+
+ return std::auto_ptr<Module>();
+}
+
+int main(int argc, char **argv) {
+ // Print a stack trace if we signal out.
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ cl::ParseCommandLineOptions(argc, argv, "llvm linker\n");
+
+ unsigned BaseArg = 0;
+ std::string ErrorMessage;
+
+ std::auto_ptr<Module> Composite(LoadFile(InputFilenames[BaseArg]));
+ if (Composite.get() == 0) {
+ cerr << argv[0] << ": error loading file '"
+ << InputFilenames[BaseArg] << "'\n";
+ return 1;
+ }
+
+ for (unsigned i = BaseArg+1; i < InputFilenames.size(); ++i) {
+ std::auto_ptr<Module> M(LoadFile(InputFilenames[i]));
+ if (M.get() == 0) {
+ cerr << argv[0] << ": error loading file '" <<InputFilenames[i]<< "'\n";
+ return 1;
+ }
+
+ if (Verbose) cerr << "Linking in '" << InputFilenames[i] << "'\n";
+
+ if (Linker::LinkModules(Composite.get(), M.get(), &ErrorMessage)) {
+ cerr << argv[0] << ": link error in '" << InputFilenames[i]
+ << "': " << ErrorMessage << "\n";
+ return 1;
+ }
+ }
+
+ // TODO: Iterate over the -l list and link in any modules containing
+ // global symbols that have not been resolved so far.
+
+ if (DumpAsm) cerr << "Here's the assembly:\n" << *Composite.get();
+
+ // FIXME: cout is not binary!
+ std::ostream *Out = &std::cout; // Default to printing to stdout...
+ if (OutputFilename != "-") {
+ if (!Force && std::ifstream(OutputFilename.c_str())) {
+ // If force is not specified, make sure not to overwrite a file!
+ cerr << argv[0] << ": error opening '" << OutputFilename
+ << "': file exists!\n"
+ << "Use -f command line argument to force output\n";
+ return 1;
+ }
+ std::ios::openmode io_mode = std::ios::out | std::ios::trunc |
+ std::ios::binary;
+ Out = new std::ofstream(OutputFilename.c_str(), io_mode);
+ if (!Out->good()) {
+ cerr << argv[0] << ": error opening '" << OutputFilename << "'!\n";
+ return 1;
+ }
+
+ // Make sure that the Out file gets unlinked from the disk if we get a
+ // SIGINT
+ sys::RemoveFileOnSignal(sys::Path(OutputFilename));
+ }
+
+ if (verifyModule(*Composite.get())) {
+ cerr << argv[0] << ": linked module is broken!\n";
+ return 1;
+ }
+
+ if (Verbose) cerr << "Writing bitcode...\n";
+ WriteBitcodeToFile(Composite.get(), *Out);
+
+ if (Out != &std::cout) delete Out;
+ return 0;
+}
diff --git a/tools/llvm-nm/CMakeLists.txt b/tools/llvm-nm/CMakeLists.txt
new file mode 100644
index 0000000..45cf1b6
--- /dev/null
+++ b/tools/llvm-nm/CMakeLists.txt
@@ -0,0 +1,5 @@
+set(LLVM_LINK_COMPONENTS archive bitreader)
+
+add_llvm_tool(llvm-nm
+ llvm-nm.cpp
+ )
diff --git a/tools/llvm-nm/Makefile b/tools/llvm-nm/Makefile
new file mode 100644
index 0000000..ecf5f8c
--- /dev/null
+++ b/tools/llvm-nm/Makefile
@@ -0,0 +1,17 @@
+##===- tools/llvm-nm/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 = llvm-nm
+LINK_COMPONENTS = archive bitreader
+
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS = 1
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp
new file mode 100644
index 0000000..324e0f6
--- /dev/null
+++ b/tools/llvm-nm/llvm-nm.cpp
@@ -0,0 +1,192 @@
+//===-- llvm-nm.cpp - Symbol table dumping utility for llvm ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This program is a utility that works like traditional Unix "nm",
+// that is, it prints out the names of symbols in a bitcode file,
+// along with some information about each symbol.
+//
+// This "nm" does not print symbols' addresses. It supports many of
+// the features of GNU "nm", including its different output formats.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Module.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Bitcode/Archive.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/System/Signals.h"
+#include <algorithm>
+#include <cctype>
+#include <cerrno>
+#include <cstring>
+#include <iostream>
+using namespace llvm;
+
+namespace {
+ enum OutputFormatTy { bsd, sysv, posix };
+ cl::opt<OutputFormatTy>
+ OutputFormat("format",
+ cl::desc("Specify output format"),
+ cl::values(clEnumVal(bsd, "BSD format"),
+ clEnumVal(sysv, "System V format"),
+ clEnumVal(posix, "POSIX.2 format"),
+ clEnumValEnd), cl::init(bsd));
+ cl::alias OutputFormat2("f", cl::desc("Alias for --format"),
+ cl::aliasopt(OutputFormat));
+
+ cl::list<std::string>
+ InputFilenames(cl::Positional, cl::desc("<input bitcode files>"),
+ cl::ZeroOrMore);
+
+ cl::opt<bool> UndefinedOnly("undefined-only",
+ cl::desc("Show only undefined symbols"));
+ cl::alias UndefinedOnly2("u", cl::desc("Alias for --undefined-only"),
+ cl::aliasopt(UndefinedOnly));
+
+ cl::opt<bool> DefinedOnly("defined-only",
+ cl::desc("Show only defined symbols"));
+
+ cl::opt<bool> ExternalOnly("extern-only",
+ cl::desc("Show only external symbols"));
+ cl::alias ExternalOnly2("g", cl::desc("Alias for --extern-only"),
+ cl::aliasopt(ExternalOnly));
+
+ cl::opt<bool> BSDFormat("B", cl::desc("Alias for --format=bsd"));
+ cl::opt<bool> POSIXFormat("P", cl::desc("Alias for --format=posix"));
+
+ bool MultipleFiles = false;
+
+ std::string ToolName;
+}
+
+static char TypeCharForSymbol(GlobalValue &GV) {
+ if (GV.isDeclaration()) return 'U';
+ if (GV.hasLinkOnceLinkage()) return 'C';
+ if (GV.hasCommonLinkage()) return 'C';
+ if (GV.hasWeakLinkage()) return 'W';
+ if (isa<Function>(GV) && GV.hasInternalLinkage()) return 't';
+ if (isa<Function>(GV)) return 'T';
+ if (isa<GlobalVariable>(GV) && GV.hasInternalLinkage()) return 'd';
+ if (isa<GlobalVariable>(GV)) return 'D';
+ if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(&GV)) {
+ const GlobalValue *AliasedGV = GA->getAliasedGlobal();
+ if (isa<Function>(AliasedGV)) return 'T';
+ if (isa<GlobalVariable>(AliasedGV)) return 'D';
+ }
+ return '?';
+}
+
+static void DumpSymbolNameForGlobalValue(GlobalValue &GV) {
+ // Private linkage and available_externally linkage don't exist in symtab.
+ if (GV.hasPrivateLinkage() || GV.hasAvailableExternallyLinkage()) return;
+
+ const std::string SymbolAddrStr = " "; // Not used yet...
+ char TypeChar = TypeCharForSymbol(GV);
+ if ((TypeChar != 'U') && UndefinedOnly)
+ return;
+ if ((TypeChar == 'U') && DefinedOnly)
+ return;
+ if (GV.hasLocalLinkage () && ExternalOnly)
+ return;
+ if (OutputFormat == posix) {
+ std::cout << GV.getName () << " " << TypeCharForSymbol(GV) << " "
+ << SymbolAddrStr << "\n";
+ } else if (OutputFormat == bsd) {
+ std::cout << SymbolAddrStr << " " << TypeCharForSymbol(GV) << " "
+ << GV.getName () << "\n";
+ } else if (OutputFormat == sysv) {
+ std::string PaddedName (GV.getName ());
+ while (PaddedName.length () < 20)
+ PaddedName += " ";
+ std::cout << PaddedName << "|" << SymbolAddrStr << "| "
+ << TypeCharForSymbol(GV)
+ << " | | | |\n";
+ }
+}
+
+static void DumpSymbolNamesFromModule(Module *M) {
+ const std::string &Filename = M->getModuleIdentifier ();
+ if (OutputFormat == posix && MultipleFiles) {
+ std::cout << Filename << ":\n";
+ } else if (OutputFormat == bsd && MultipleFiles) {
+ std::cout << "\n" << Filename << ":\n";
+ } else if (OutputFormat == sysv) {
+ std::cout << "\n\nSymbols from " << Filename << ":\n\n"
+ << "Name Value Class Type"
+ << " Size Line Section\n";
+ }
+ std::for_each (M->begin(), M->end(), DumpSymbolNameForGlobalValue);
+ std::for_each (M->global_begin(), M->global_end(),
+ DumpSymbolNameForGlobalValue);
+ std::for_each (M->alias_begin(), M->alias_end(),
+ DumpSymbolNameForGlobalValue);
+}
+
+static void DumpSymbolNamesFromFile(std::string &Filename) {
+ std::string ErrorMessage;
+ sys::Path aPath(Filename);
+ // Note: Currently we do not support reading an archive from stdin.
+ if (Filename == "-" || aPath.isBitcodeFile()) {
+ std::auto_ptr<MemoryBuffer> Buffer(
+ MemoryBuffer::getFileOrSTDIN(Filename, &ErrorMessage));
+ Module *Result = 0;
+ if (Buffer.get())
+ Result = ParseBitcodeFile(Buffer.get(), &ErrorMessage);
+
+ if (Result)
+ DumpSymbolNamesFromModule(Result);
+ else {
+ std::cerr << ToolName << ": " << Filename << ": " << ErrorMessage << "\n";
+ return;
+ }
+
+ } else if (aPath.isArchive()) {
+ std::string ErrMsg;
+ Archive* archive = Archive::OpenAndLoad(sys::Path(Filename), &ErrorMessage);
+ if (!archive)
+ std::cerr << ToolName << ": " << Filename << ": " << ErrorMessage << "\n";
+ std::vector<Module *> Modules;
+ if (archive->getAllModules(Modules, &ErrorMessage)) {
+ std::cerr << ToolName << ": " << Filename << ": " << ErrorMessage << "\n";
+ return;
+ }
+ MultipleFiles = true;
+ std::for_each (Modules.begin(), Modules.end(), DumpSymbolNamesFromModule);
+ } else {
+ std::cerr << ToolName << ": " << Filename << ": "
+ << "unrecognizable file type\n";
+ return;
+ }
+}
+
+int main(int argc, char **argv) {
+ // Print a stack trace if we signal out.
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ cl::ParseCommandLineOptions(argc, argv, "llvm symbol table dumper\n");
+
+ ToolName = argv[0];
+ if (BSDFormat) OutputFormat = bsd;
+ if (POSIXFormat) OutputFormat = posix;
+
+ switch (InputFilenames.size()) {
+ case 0: InputFilenames.push_back("-");
+ case 1: break;
+ default: MultipleFiles = true;
+ }
+
+ std::for_each(InputFilenames.begin(), InputFilenames.end(),
+ DumpSymbolNamesFromFile);
+ return 0;
+}
diff --git a/tools/llvm-prof/CMakeLists.txt b/tools/llvm-prof/CMakeLists.txt
new file mode 100644
index 0000000..9a51150
--- /dev/null
+++ b/tools/llvm-prof/CMakeLists.txt
@@ -0,0 +1,6 @@
+set(LLVM_LINK_COMPONENTS bitreader analysis)
+set(LLVM_REQUIRES_EH 1)
+
+add_llvm_tool(llvm-prof
+ llvm-prof.cpp
+ )
diff --git a/tools/llvm-prof/Makefile b/tools/llvm-prof/Makefile
new file mode 100644
index 0000000..3c4948e
--- /dev/null
+++ b/tools/llvm-prof/Makefile
@@ -0,0 +1,18 @@
+##===- tools/llvm-prof/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 = llvm-prof
+LINK_COMPONENTS = bitreader analysis
+REQUIRES_EH := 1
+
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS = 1
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/llvm-prof/llvm-prof.cpp b/tools/llvm-prof/llvm-prof.cpp
new file mode 100644
index 0000000..119dc1a
--- /dev/null
+++ b/tools/llvm-prof/llvm-prof.cpp
@@ -0,0 +1,256 @@
+//===- llvm-prof.cpp - Read in and process llvmprof.out data files --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tools is meant for use with the various LLVM profiling instrumentation
+// passes. It reads in the data file produced by executing an instrumented
+// program, and outputs a nice report.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/InstrTypes.h"
+#include "llvm/Module.h"
+#include "llvm/Assembly/AsmAnnotationWriter.h"
+#include "llvm/Analysis/ProfileInfoLoader.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Signals.h"
+#include <algorithm>
+#include <iostream>
+#include <iomanip>
+#include <map>
+#include <set>
+
+using namespace llvm;
+
+namespace {
+ cl::opt<std::string>
+ BitcodeFile(cl::Positional, cl::desc("<program bitcode file>"),
+ cl::Required);
+
+ cl::opt<std::string>
+ ProfileDataFile(cl::Positional, cl::desc("<llvmprof.out file>"),
+ cl::Optional, cl::init("llvmprof.out"));
+
+ cl::opt<bool>
+ PrintAnnotatedLLVM("annotated-llvm",
+ cl::desc("Print LLVM code with frequency annotations"));
+ cl::alias PrintAnnotated2("A", cl::desc("Alias for --annotated-llvm"),
+ cl::aliasopt(PrintAnnotatedLLVM));
+ cl::opt<bool>
+ PrintAllCode("print-all-code",
+ cl::desc("Print annotated code for the entire program"));
+}
+
+// PairSecondSort - A sorting predicate to sort by the second element of a pair.
+template<class T>
+struct PairSecondSortReverse
+ : public std::binary_function<std::pair<T, unsigned>,
+ std::pair<T, unsigned>, bool> {
+ bool operator()(const std::pair<T, unsigned> &LHS,
+ const std::pair<T, unsigned> &RHS) const {
+ return LHS.second > RHS.second;
+ }
+};
+
+namespace {
+ class ProfileAnnotator : public AssemblyAnnotationWriter {
+ std::map<const Function *, unsigned> &FuncFreqs;
+ std::map<const BasicBlock*, unsigned> &BlockFreqs;
+ std::map<ProfileInfoLoader::Edge, unsigned> &EdgeFreqs;
+ public:
+ ProfileAnnotator(std::map<const Function *, unsigned> &FF,
+ std::map<const BasicBlock*, unsigned> &BF,
+ std::map<ProfileInfoLoader::Edge, unsigned> &EF)
+ : FuncFreqs(FF), BlockFreqs(BF), EdgeFreqs(EF) {}
+
+ virtual void emitFunctionAnnot(const Function *F, raw_ostream &OS) {
+ OS << ";;; %" << F->getName() << " called " << FuncFreqs[F]
+ << " times.\n;;;\n";
+ }
+ virtual void emitBasicBlockStartAnnot(const BasicBlock *BB,
+ raw_ostream &OS) {
+ if (BlockFreqs.empty()) return;
+ if (unsigned Count = BlockFreqs[BB])
+ OS << "\t;;; Basic block executed " << Count << " times.\n";
+ else
+ OS << "\t;;; Never executed!\n";
+ }
+
+ virtual void emitBasicBlockEndAnnot(const BasicBlock *BB, raw_ostream &OS) {
+ if (EdgeFreqs.empty()) return;
+
+ // Figure out how many times each successor executed.
+ std::vector<std::pair<const BasicBlock*, unsigned> > SuccCounts;
+ const TerminatorInst *TI = BB->getTerminator();
+
+ std::map<ProfileInfoLoader::Edge, unsigned>::iterator I =
+ EdgeFreqs.lower_bound(std::make_pair(const_cast<BasicBlock*>(BB), 0U));
+ for (; I != EdgeFreqs.end() && I->first.first == BB; ++I)
+ if (I->second)
+ SuccCounts.push_back(std::make_pair(TI->getSuccessor(I->first.second),
+ I->second));
+ if (!SuccCounts.empty()) {
+ OS << "\t;;; Out-edge counts:";
+ for (unsigned i = 0, e = SuccCounts.size(); i != e; ++i)
+ OS << " [" << SuccCounts[i].second << " -> "
+ << SuccCounts[i].first->getName() << "]";
+ OS << "\n";
+ }
+ }
+ };
+}
+
+
+int main(int argc, char **argv) {
+ // Print a stack trace if we signal out.
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ try {
+ cl::ParseCommandLineOptions(argc, argv, "llvm profile dump decoder\n");
+
+ // Read in the bitcode file...
+ std::string ErrorMessage;
+ Module *M = 0;
+ if (MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(BitcodeFile,
+ &ErrorMessage)) {
+ M = ParseBitcodeFile(Buffer, &ErrorMessage);
+ delete Buffer;
+ }
+ if (M == 0) {
+ std::cerr << argv[0] << ": " << BitcodeFile << ": "
+ << ErrorMessage << "\n";
+ return 1;
+ }
+
+ // Read the profiling information
+ ProfileInfoLoader PI(argv[0], ProfileDataFile, *M);
+
+ std::map<const Function *, unsigned> FuncFreqs;
+ std::map<const BasicBlock*, unsigned> BlockFreqs;
+ std::map<ProfileInfoLoader::Edge, unsigned> EdgeFreqs;
+
+ // Output a report. Eventually, there will be multiple reports selectable on
+ // the command line, for now, just keep things simple.
+
+ // Emit the most frequent function table...
+ std::vector<std::pair<Function*, unsigned> > FunctionCounts;
+ PI.getFunctionCounts(FunctionCounts);
+ FuncFreqs.insert(FunctionCounts.begin(), FunctionCounts.end());
+
+ // Sort by the frequency, backwards.
+ sort(FunctionCounts.begin(), FunctionCounts.end(),
+ PairSecondSortReverse<Function*>());
+
+ uint64_t TotalExecutions = 0;
+ for (unsigned i = 0, e = FunctionCounts.size(); i != e; ++i)
+ TotalExecutions += FunctionCounts[i].second;
+
+ std::cout << "===" << std::string(73, '-') << "===\n"
+ << "LLVM profiling output for execution";
+ if (PI.getNumExecutions() != 1) std::cout << "s";
+ std::cout << ":\n";
+
+ for (unsigned i = 0, e = PI.getNumExecutions(); i != e; ++i) {
+ std::cout << " ";
+ if (e != 1) std::cout << i+1 << ". ";
+ std::cout << PI.getExecution(i) << "\n";
+ }
+
+ std::cout << "\n===" << std::string(73, '-') << "===\n";
+ std::cout << "Function execution frequencies:\n\n";
+
+ // Print out the function frequencies...
+ std::cout << " ## Frequency\n";
+ for (unsigned i = 0, e = FunctionCounts.size(); i != e; ++i) {
+ if (FunctionCounts[i].second == 0) {
+ std::cout << "\n NOTE: " << e-i << " function" <<
+ (e-i-1 ? "s were" : " was") << " never executed!\n";
+ break;
+ }
+
+ std::cout << std::setw(3) << i+1 << ". "
+ << std::setw(5) << FunctionCounts[i].second << "/"
+ << TotalExecutions << " "
+ << FunctionCounts[i].first->getName().c_str() << "\n";
+ }
+
+ std::set<Function*> FunctionsToPrint;
+
+ // If we have block count information, print out the LLVM module with
+ // frequency annotations.
+ if (PI.hasAccurateBlockCounts()) {
+ std::vector<std::pair<BasicBlock*, unsigned> > Counts;
+ PI.getBlockCounts(Counts);
+
+ TotalExecutions = 0;
+ for (unsigned i = 0, e = Counts.size(); i != e; ++i)
+ TotalExecutions += Counts[i].second;
+
+ // Sort by the frequency, backwards.
+ sort(Counts.begin(), Counts.end(),
+ PairSecondSortReverse<BasicBlock*>());
+
+ std::cout << "\n===" << std::string(73, '-') << "===\n";
+ std::cout << "Top 20 most frequently executed basic blocks:\n\n";
+
+ // Print out the function frequencies...
+ std::cout <<" ## %% \tFrequency\n";
+ unsigned BlocksToPrint = Counts.size();
+ if (BlocksToPrint > 20) BlocksToPrint = 20;
+ for (unsigned i = 0; i != BlocksToPrint; ++i) {
+ if (Counts[i].second == 0) break;
+ Function *F = Counts[i].first->getParent();
+ std::cout << std::setw(3) << i+1 << ". "
+ << std::setw(5) << std::setprecision(2)
+ << Counts[i].second/(double)TotalExecutions*100 << "% "
+ << std::setw(5) << Counts[i].second << "/"
+ << TotalExecutions << "\t"
+ << F->getName().c_str() << "() - "
+ << Counts[i].first->getName().c_str() << "\n";
+ FunctionsToPrint.insert(F);
+ }
+
+ BlockFreqs.insert(Counts.begin(), Counts.end());
+ }
+
+ if (PI.hasAccurateEdgeCounts()) {
+ std::vector<std::pair<ProfileInfoLoader::Edge, unsigned> > Counts;
+ PI.getEdgeCounts(Counts);
+ EdgeFreqs.insert(Counts.begin(), Counts.end());
+ }
+
+ if (PrintAnnotatedLLVM || PrintAllCode) {
+ std::cout << "\n===" << std::string(73, '-') << "===\n";
+ std::cout << "Annotated LLVM code for the module:\n\n";
+
+ ProfileAnnotator PA(FuncFreqs, BlockFreqs, EdgeFreqs);
+
+ if (FunctionsToPrint.empty() || PrintAllCode)
+ M->print(std::cout, &PA);
+ else
+ // Print just a subset of the functions.
+ for (std::set<Function*>::iterator I = FunctionsToPrint.begin(),
+ E = FunctionsToPrint.end(); I != E; ++I)
+ (*I)->print(std::cout, &PA);
+ }
+
+ return 0;
+ } catch (const std::string& msg) {
+ std::cerr << argv[0] << ": " << msg << "\n";
+ } catch (...) {
+ std::cerr << argv[0] << ": Unexpected unknown exception occurred.\n";
+ }
+ return 1;
+}
diff --git a/tools/llvm-ranlib/CMakeLists.txt b/tools/llvm-ranlib/CMakeLists.txt
new file mode 100644
index 0000000..3116d2e
--- /dev/null
+++ b/tools/llvm-ranlib/CMakeLists.txt
@@ -0,0 +1,6 @@
+set(LLVM_LINK_COMPONENTS archive)
+set(LLVM_REQUIRES_EH 1)
+
+add_llvm_tool(llvm-ranlib
+ llvm-ranlib.cpp
+ )
diff --git a/tools/llvm-ranlib/Makefile b/tools/llvm-ranlib/Makefile
new file mode 100644
index 0000000..46a10e6
--- /dev/null
+++ b/tools/llvm-ranlib/Makefile
@@ -0,0 +1,18 @@
+##===- tools/llvm-ranlib/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 = llvm-ranlib
+LINK_COMPONENTS = archive
+REQUIRES_EH := 1
+
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS = 1
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/llvm-ranlib/llvm-ranlib.cpp b/tools/llvm-ranlib/llvm-ranlib.cpp
new file mode 100644
index 0000000..7210610
--- /dev/null
+++ b/tools/llvm-ranlib/llvm-ranlib.cpp
@@ -0,0 +1,98 @@
+//===-- llvm-ranlib.cpp - LLVM archive index generator --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Adds or updates an index (symbol table) for an LLVM archive file.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Module.h"
+#include "llvm/Bitcode/Archive.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/System/Signals.h"
+#include <iostream>
+#include <iomanip>
+#include <memory>
+
+using namespace llvm;
+
+// llvm-ar operation code and modifier flags
+static cl::opt<std::string>
+ArchiveName(cl::Positional, cl::Optional, cl::desc("<archive-file>"));
+
+static cl::opt<bool>
+Verbose("verbose",cl::Optional,cl::init(false),
+ cl::desc("Print the symbol table"));
+
+// printSymbolTable - print out the archive's symbol table.
+void printSymbolTable(Archive* TheArchive) {
+ std::cout << "\nArchive Symbol Table:\n";
+ const Archive::SymTabType& symtab = TheArchive->getSymbolTable();
+ for (Archive::SymTabType::const_iterator I=symtab.begin(), E=symtab.end();
+ I != E; ++I ) {
+ unsigned offset = TheArchive->getFirstFileOffset() + I->second;
+ std::cout << " " << std::setw(9) << offset << "\t" << I->first <<"\n";
+ }
+}
+
+int main(int argc, char **argv) {
+ // Print a stack trace if we signal out.
+ llvm::sys::PrintStackTraceOnErrorSignal();
+ llvm::PrettyStackTraceProgram X(argc, argv);
+
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+
+ // Have the command line options parsed and handle things
+ // like --help and --version.
+ cl::ParseCommandLineOptions(argc, argv,
+ "LLVM Archive Index Generator (llvm-ranlib)\n\n"
+ " This program adds or updates an index of bitcode symbols\n"
+ " to an LLVM archive file."
+ );
+
+ int exitCode = 0;
+
+ // Make sure we don't exit with "unhandled exception".
+ try {
+
+ // Check the path name of the archive
+ sys::Path ArchivePath;
+ if (!ArchivePath.set(ArchiveName))
+ throw std::string("Archive name invalid: ") + ArchiveName;
+
+ // Make sure it exists, we don't create empty archives
+ if (!ArchivePath.exists())
+ throw std::string("Archive file does not exist");
+
+ std::string err_msg;
+ std::auto_ptr<Archive>
+ AutoArchive(Archive::OpenAndLoad(ArchivePath,&err_msg));
+ Archive* TheArchive = AutoArchive.get();
+ if (!TheArchive)
+ throw err_msg;
+
+ if (TheArchive->writeToDisk(true, false, false, &err_msg ))
+ throw err_msg;
+
+ if (Verbose)
+ printSymbolTable(TheArchive);
+
+ } catch (const char* msg) {
+ std::cerr << argv[0] << ": " << msg << "\n\n";
+ exitCode = 1;
+ } catch (const std::string& msg) {
+ std::cerr << argv[0] << ": " << msg << "\n";
+ exitCode = 2;
+ } catch (...) {
+ std::cerr << argv[0] << ": An unexpected unknown exception occurred.\n";
+ exitCode = 3;
+ }
+ return exitCode;
+}
diff --git a/tools/llvm-stub/CMakeLists.txt b/tools/llvm-stub/CMakeLists.txt
new file mode 100644
index 0000000..a98dc9e
--- /dev/null
+++ b/tools/llvm-stub/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_llvm_tool(llvm-stub
+ llvm-stub.c
+ )
diff --git a/tools/llvm-stub/Makefile b/tools/llvm-stub/Makefile
new file mode 100644
index 0000000..7ffe149
--- /dev/null
+++ b/tools/llvm-stub/Makefile
@@ -0,0 +1,13 @@
+##===- tools/llvm-stub/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 = llvm-stub
+include $(LEVEL)/Makefile.common
+
diff --git a/tools/llvm-stub/llvm-stub.c b/tools/llvm-stub/llvm-stub.c
new file mode 100644
index 0000000..e5624a9
--- /dev/null
+++ b/tools/llvm-stub/llvm-stub.c
@@ -0,0 +1,74 @@
+/*===- llvm-stub.c - Stub executable to run llvm bitcode files ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tool is used by the gccld program to enable transparent execution of
+// bitcode files by the user. Specifically, gccld outputs two files when asked
+// to compile a <program> file:
+// 1. It outputs the LLVM bitcode file to <program>.bc
+// 2. It outputs a stub executable that runs lli on <program>.bc
+//
+// This allows the end user to just say ./<program> and have the JIT executed
+// automatically. On unix, the stub executable emitted is actually a bourne
+// shell script that does the forwarding. Windows does not like #!/bin/sh
+// programs in .exe files, so we make it an actual program, defined here.
+//
+//===----------------------------------------------------------------------===*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "llvm/Config/config.h"
+
+#if defined(HAVE_UNISTD_H) && !defined(_MSC_VER)
+#include <unistd.h>
+#endif
+
+#ifdef _WIN32
+#include <process.h>
+#include <io.h>
+#endif
+
+int main(int argc, char** argv) {
+ const char *Interp = getenv("LLVMINTERP");
+ const char **Args;
+ if (Interp == 0) Interp = "lli";
+
+ /* Set up the command line options to pass to the JIT. */
+ Args = (const char**)malloc(sizeof(char*) * (argc+2));
+ /* argv[0] is the JIT */
+ Args[0] = Interp;
+
+#ifdef LLVM_ON_WIN32
+ {
+ int len = strlen(argv[0]);
+ if (len < 4 || strcmp(argv[0] + len - 4, ".exe") != 0) {
+ /* .exe suffix is stripped off of argv[0] if the executable was run on the
+ * command line without one. Put it back on.
+ */
+ argv[0] = strcat(strcpy((char*)malloc(len + 5), argv[0]), ".exe");
+ }
+ }
+#endif
+
+ /* argv[1] is argv[0] + ".bc". */
+ Args[1] = strcat(strcpy((char*)malloc(strlen(argv[0])+4), argv[0]), ".bc");
+
+ /* The rest of the args are as before. */
+ memcpy(Args+2, argv+1, sizeof(char*)*argc);
+
+ /* Run the JIT. */
+ execvp(Interp, (char *const*)Args);
+
+ /* if _execv returns, the JIT could not be started. */
+ fprintf(stderr, "Could not execute the LLVM JIT. Either add 'lli' to your"
+ " path, or set the\ninterpreter you want to use in the LLVMINTERP "
+ "environment variable.\n");
+ return 1;
+}
diff --git a/tools/llvmc/CMakeLists.txt b/tools/llvmc/CMakeLists.txt
new file mode 100644
index 0000000..bebaaeb
--- /dev/null
+++ b/tools/llvmc/CMakeLists.txt
@@ -0,0 +1,4 @@
+# add_subdirectory(driver)
+
+# TODO: support plugins and user-configured builds.
+# See ./doc/LLVMC-Reference.rst "Customizing LLVMC: the compilation graph"
diff --git a/tools/llvmc/Makefile b/tools/llvmc/Makefile
new file mode 100644
index 0000000..df91728
--- /dev/null
+++ b/tools/llvmc/Makefile
@@ -0,0 +1,17 @@
+##===- tools/llvmc/Makefile --------------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open
+# Source License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+
+export LLVMC_BASED_DRIVER_NAME = llvmc
+export LLVMC_BUILTIN_PLUGINS = Base Clang
+
+DIRS = plugins driver
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/doc/LLVMC-Reference.rst b/tools/llvmc/doc/LLVMC-Reference.rst
new file mode 100644
index 0000000..d99fa0c
--- /dev/null
+++ b/tools/llvmc/doc/LLVMC-Reference.rst
@@ -0,0 +1,667 @@
+===================================
+Customizing LLVMC: Reference Manual
+===================================
+..
+ This file was automatically generated by rst2html.
+ Please do not edit directly!
+ The ReST source lives in the directory 'tools/llvmc/doc'.
+
+.. contents::
+
+.. raw:: html
+
+ <div class="doc_author">
+ <p>Written by <a href="mailto:foldr@codedgers.com">Mikhail Glushenkov</a></p>
+ </div>
+
+Introduction
+============
+
+LLVMC is a generic compiler driver, designed to be customizable and
+extensible. It plays the same role for LLVM as the ``gcc`` program
+does for GCC - LLVMC's job is essentially to transform a set of input
+files into a set of targets depending on configuration rules and user
+options. What makes LLVMC different is that these transformation rules
+are completely customizable - in fact, LLVMC knows nothing about the
+specifics of transformation (even the command-line options are mostly
+not hard-coded) and regards the transformation structure as an
+abstract graph. The structure of this graph is completely determined
+by plugins, which can be either statically or dynamically linked. This
+makes it possible to easily adapt LLVMC for other purposes - for
+example, as a build tool for game resources.
+
+Because LLVMC employs TableGen_ as its configuration language, you
+need to be familiar with it to customize LLVMC.
+
+.. _TableGen: http://llvm.cs.uiuc.edu/docs/TableGenFundamentals.html
+
+
+Compiling with LLVMC
+====================
+
+LLVMC tries hard to be as compatible with ``gcc`` as possible,
+although there are some small differences. Most of the time, however,
+you shouldn't be able to notice them::
+
+ $ # This works as expected:
+ $ llvmc -O3 -Wall hello.cpp
+ $ ./a.out
+ hello
+
+One nice feature of LLVMC is that one doesn't have to distinguish
+between different compilers for different languages (think ``g++`` and
+``gcc``) - the right toolchain is chosen automatically based on input
+language names (which are, in turn, determined from file
+extensions). If you want to force files ending with ".c" to compile as
+C++, use the ``-x`` option, just like you would do it with ``gcc``::
+
+ $ # hello.c is really a C++ file
+ $ llvmc -x c++ hello.c
+ $ ./a.out
+ hello
+
+On the other hand, when using LLVMC as a linker to combine several C++
+object files you should provide the ``--linker`` option since it's
+impossible for LLVMC to choose the right linker in that case::
+
+ $ llvmc -c hello.cpp
+ $ llvmc hello.o
+ [A lot of link-time errors skipped]
+ $ llvmc --linker=c++ hello.o
+ $ ./a.out
+ hello
+
+By default, LLVMC uses ``llvm-gcc`` to compile the source code. It is
+also possible to choose the work-in-progress ``clang`` compiler with
+the ``-clang`` option.
+
+
+Predefined options
+==================
+
+LLVMC has some built-in options that can't be overridden in the
+configuration libraries:
+
+* ``-o FILE`` - Output file name.
+
+* ``-x LANGUAGE`` - Specify the language of the following input files
+ until the next -x option.
+
+* ``-load PLUGIN_NAME`` - Load the specified plugin DLL. Example:
+ ``-load $LLVM_DIR/Release/lib/LLVMCSimple.so``.
+
+* ``-v`` - Enable verbose mode, i.e. print out all executed commands.
+
+* ``--check-graph`` - Check the compilation for common errors like mismatched
+ output/input language names, multiple default edges and cycles. Because of
+ plugins, these checks can't be performed at compile-time. Exit with code zero if
+ no errors were found, and return the number of found errors otherwise. Hidden
+ option, useful for debugging LLVMC plugins.
+
+* ``--view-graph`` - Show a graphical representation of the compilation graph
+ and exit. Requires that you have ``dot`` and ``gv`` programs installed. Hidden
+ option, useful for debugging LLVMC plugins.
+
+* ``--write-graph`` - Write a ``compilation-graph.dot`` file in the current
+ directory with the compilation graph description in Graphviz format (identical
+ to the file used by the ``--view-graph`` option). The ``-o`` option can be used
+ to set the output file name. Hidden option, useful for debugging LLVMC plugins.
+
+* ``--save-temps`` - Write temporary files to the current directory
+ and do not delete them on exit. Hidden option, useful for debugging.
+
+* ``--help``, ``--help-hidden``, ``--version`` - These options have
+ their standard meaning.
+
+
+Compiling LLVMC plugins
+=======================
+
+It's easiest to start working on your own LLVMC plugin by copying the
+skeleton project which lives under ``$LLVMC_DIR/plugins/Simple``::
+
+ $ cd $LLVMC_DIR/plugins
+ $ cp -r Simple MyPlugin
+ $ cd MyPlugin
+ $ ls
+ Makefile PluginMain.cpp Simple.td
+
+As you can see, our basic plugin consists of only two files (not
+counting the build script). ``Simple.td`` contains TableGen
+description of the compilation graph; its format is documented in the
+following sections. ``PluginMain.cpp`` is just a helper file used to
+compile the auto-generated C++ code produced from TableGen source. It
+can also contain hook definitions (see `below`__).
+
+__ hooks_
+
+The first thing that you should do is to change the ``LLVMC_PLUGIN``
+variable in the ``Makefile`` to avoid conflicts (since this variable
+is used to name the resulting library)::
+
+ LLVMC_PLUGIN=MyPlugin
+
+It is also a good idea to rename ``Simple.td`` to something less
+generic::
+
+ $ mv Simple.td MyPlugin.td
+
+Note that the plugin source directory must be placed under
+``$LLVMC_DIR/plugins`` to make use of the existing build
+infrastructure. To build a version of the LLVMC executable called
+``mydriver`` with your plugin compiled in, use the following command::
+
+ $ cd $LLVMC_DIR
+ $ make BUILTIN_PLUGINS=MyPlugin DRIVER_NAME=mydriver
+
+To build your plugin as a dynamic library, just ``cd`` to its source
+directory and run ``make``. The resulting file will be called
+``LLVMC$(LLVMC_PLUGIN).$(DLL_EXTENSION)`` (in our case,
+``LLVMCMyPlugin.so``). This library can be then loaded in with the
+``-load`` option. Example::
+
+ $ cd $LLVMC_DIR/plugins/Simple
+ $ make
+ $ llvmc -load $LLVM_DIR/Release/lib/LLVMCSimple.so
+
+Sometimes, you will want a 'bare-bones' version of LLVMC that has no
+built-in plugins. It can be compiled with the following command::
+
+ $ cd $LLVMC_DIR
+ $ make BUILTIN_PLUGINS=""
+
+
+Customizing LLVMC: the compilation graph
+========================================
+
+Each TableGen configuration file should include the common
+definitions::
+
+ include "llvm/CompilerDriver/Common.td"
+
+Internally, LLVMC stores information about possible source
+transformations in form of a graph. Nodes in this graph represent
+tools, and edges between two nodes represent a transformation path. A
+special "root" node is used to mark entry points for the
+transformations. LLVMC also assigns a weight to each edge (more on
+this later) to choose between several alternative edges.
+
+The definition of the compilation graph (see file
+``plugins/Base/Base.td`` for an example) is just a list of edges::
+
+ def CompilationGraph : CompilationGraph<[
+ Edge<"root", "llvm_gcc_c">,
+ Edge<"root", "llvm_gcc_assembler">,
+ ...
+
+ Edge<"llvm_gcc_c", "llc">,
+ Edge<"llvm_gcc_cpp", "llc">,
+ ...
+
+ OptionalEdge<"llvm_gcc_c", "opt", (case (switch_on "opt"),
+ (inc_weight))>,
+ OptionalEdge<"llvm_gcc_cpp", "opt", (case (switch_on "opt"),
+ (inc_weight))>,
+ ...
+
+ OptionalEdge<"llvm_gcc_assembler", "llvm_gcc_cpp_linker",
+ (case (input_languages_contain "c++"), (inc_weight),
+ (or (parameter_equals "linker", "g++"),
+ (parameter_equals "linker", "c++")), (inc_weight))>,
+ ...
+
+ ]>;
+
+As you can see, the edges can be either default or optional, where
+optional edges are differentiated by an additional ``case`` expression
+used to calculate the weight of this edge. Notice also that we refer
+to tools via their names (as strings). This makes it possible to add
+edges to an existing compilation graph in plugins without having to
+know about all tool definitions used in the graph.
+
+The default edges are assigned a weight of 1, and optional edges get a
+weight of 0 + 2*N where N is the number of tests that evaluated to
+true in the ``case`` expression. It is also possible to provide an
+integer parameter to ``inc_weight`` and ``dec_weight`` - in this case,
+the weight is increased (or decreased) by the provided value instead
+of the default 2. It is also possible to change the default weight of
+an optional edge by using the ``default`` clause of the ``case``
+construct.
+
+When passing an input file through the graph, LLVMC picks the edge
+with the maximum weight. To avoid ambiguity, there should be only one
+default edge between two nodes (with the exception of the root node,
+which gets a special treatment - there you are allowed to specify one
+default edge *per language*).
+
+When multiple plugins are loaded, their compilation graphs are merged
+together. Since multiple edges that have the same end nodes are not
+allowed (i.e. the graph is not a multigraph), an edge defined in
+several plugins will be replaced by the definition from the plugin
+that was loaded last. Plugin load order can be controlled by using the
+plugin priority feature described above.
+
+To get a visual representation of the compilation graph (useful for
+debugging), run ``llvmc --view-graph``. You will need ``dot`` and
+``gsview`` installed for this to work properly.
+
+Describing options
+==================
+
+Command-line options that the plugin supports are defined by using an
+``OptionList``::
+
+ def Options : OptionList<[
+ (switch_option "E", (help "Help string")),
+ (alias_option "quiet", "q")
+ ...
+ ]>;
+
+As you can see, the option list is just a list of DAGs, where each DAG
+is an option description consisting of the option name and some
+properties. A plugin can define more than one option list (they are
+all merged together in the end), which can be handy if one wants to
+separate option groups syntactically.
+
+* Possible option types:
+
+ - ``switch_option`` - a simple boolean switch without arguments, for example
+ ``-O2`` or ``-time``. At most one occurrence is allowed.
+
+ - ``parameter_option`` - option that takes one argument, for example
+ ``-std=c99``. It is also allowed to use spaces instead of the equality
+ sign: ``-std c99``. At most one occurrence is allowed.
+
+ - ``parameter_list_option`` - same as the above, but more than one option
+ occurence is allowed.
+
+ - ``prefix_option`` - same as the parameter_option, but the option name and
+ argument do not have to be separated. Example: ``-ofile``. This can be also
+ specified as ``-o file``; however, ``-o=file`` will be parsed incorrectly
+ (``=file`` will be interpreted as option value). At most one occurrence is
+ allowed.
+
+ - ``prefix_list_option`` - same as the above, but more than one occurence of
+ the option is allowed; example: ``-lm -lpthread``.
+
+ - ``alias_option`` - a special option type for creating aliases. Unlike other
+ option types, aliases are not allowed to have any properties besides the
+ aliased option name. Usage example: ``(alias_option "preprocess", "E")``
+
+
+* Possible option properties:
+
+ - ``help`` - help string associated with this option. Used for ``--help``
+ output.
+
+ - ``required`` - this option must be specified exactly once (or, in case of
+ the list options without the ``multi_val`` property, at least
+ once). Incompatible with ``zero_or_one`` and ``one_or_more``.
+
+ - ``one_or_more`` - the option must be specified at least one time. Useful
+ only for list options in conjunction with ``multi_val``; for ordinary lists
+ it is synonymous with ``required``. Incompatible with ``required`` and
+ ``zero_or_one``.
+
+ - ``zero_or_one`` - the option can be specified zero or one times. Useful
+ only for list options in conjunction with ``multi_val``. Incompatible with
+ ``required`` and ``one_or_more``.
+
+ - ``hidden`` - the description of this option will not appear in
+ the ``--help`` output (but will appear in the ``--help-hidden``
+ output).
+
+ - ``really_hidden`` - the option will not be mentioned in any help
+ output.
+
+ - ``multi_val n`` - this option takes *n* arguments (can be useful in some
+ special cases). Usage example: ``(parameter_list_option "foo", (multi_val
+ 3))``. Only list options can have this attribute; you can, however, use
+ the ``one_or_more`` and ``zero_or_one`` properties.
+
+ - ``extern`` - this option is defined in some other plugin, see below.
+
+External options
+----------------
+
+Sometimes, when linking several plugins together, one plugin needs to
+access options defined in some other plugin. Because of the way
+options are implemented, such options must be marked as
+``extern``. This is what the ``extern`` option property is
+for. Example::
+
+ ...
+ (switch_option "E", (extern))
+ ...
+
+See also the section on plugin `priorities`__.
+
+__ priorities_
+
+.. _case:
+
+Conditional evaluation
+======================
+
+The 'case' construct is the main means by which programmability is
+achieved in LLVMC. It can be used to calculate edge weights, program
+actions and modify the shell commands to be executed. The 'case'
+expression is designed after the similarly-named construct in
+functional languages and takes the form ``(case (test_1), statement_1,
+(test_2), statement_2, ... (test_N), statement_N)``. The statements
+are evaluated only if the corresponding tests evaluate to true.
+
+Examples::
+
+ // Edge weight calculation
+
+ // Increases edge weight by 5 if "-A" is provided on the
+ // command-line, and by 5 more if "-B" is also provided.
+ (case
+ (switch_on "A"), (inc_weight 5),
+ (switch_on "B"), (inc_weight 5))
+
+
+ // Tool command line specification
+
+ // Evaluates to "cmdline1" if the option "-A" is provided on the
+ // command line; to "cmdline2" if "-B" is provided;
+ // otherwise to "cmdline3".
+
+ (case
+ (switch_on "A"), "cmdline1",
+ (switch_on "B"), "cmdline2",
+ (default), "cmdline3")
+
+Note the slight difference in 'case' expression handling in contexts
+of edge weights and command line specification - in the second example
+the value of the ``"B"`` switch is never checked when switch ``"A"`` is
+enabled, and the whole expression always evaluates to ``"cmdline1"`` in
+that case.
+
+Case expressions can also be nested, i.e. the following is legal::
+
+ (case (switch_on "E"), (case (switch_on "o"), ..., (default), ...)
+ (default), ...)
+
+You should, however, try to avoid doing that because it hurts
+readability. It is usually better to split tool descriptions and/or
+use TableGen inheritance instead.
+
+* Possible tests are:
+
+ - ``switch_on`` - Returns true if a given command-line switch is
+ provided by the user. Example: ``(switch_on "opt")``.
+
+ - ``parameter_equals`` - Returns true if a command-line parameter equals
+ a given value.
+ Example: ``(parameter_equals "W", "all")``.
+
+ - ``element_in_list`` - Returns true if a command-line parameter
+ list contains a given value.
+ Example: ``(parameter_in_list "l", "pthread")``.
+
+ - ``input_languages_contain`` - Returns true if a given language
+ belongs to the current input language set.
+ Example: ``(input_languages_contain "c++")``.
+
+ - ``in_language`` - Evaluates to true if the input file language
+ equals to the argument. At the moment works only with ``cmd_line``
+ and ``actions`` (on non-join nodes).
+ Example: ``(in_language "c++")``.
+
+ - ``not_empty`` - Returns true if a given option (which should be
+ either a parameter or a parameter list) is set by the
+ user.
+ Example: ``(not_empty "o")``.
+
+ - ``empty`` - The opposite of ``not_empty``. Equivalent to ``(not (not_empty
+ X))``. Provided for convenience.
+
+ - ``default`` - Always evaluates to true. Should always be the last
+ test in the ``case`` expression.
+
+ - ``and`` - A standard logical combinator that returns true iff all
+ of its arguments return true. Used like this: ``(and (test1),
+ (test2), ... (testN))``. Nesting of ``and`` and ``or`` is allowed,
+ but not encouraged.
+
+ - ``or`` - Another logical combinator that returns true only if any
+ one of its arguments returns true. Example: ``(or (test1),
+ (test2), ... (testN))``.
+
+
+Writing a tool description
+==========================
+
+As was said earlier, nodes in the compilation graph represent tools,
+which are described separately. A tool definition looks like this
+(taken from the ``include/llvm/CompilerDriver/Tools.td`` file)::
+
+ def llvm_gcc_cpp : Tool<[
+ (in_language "c++"),
+ (out_language "llvm-assembler"),
+ (output_suffix "bc"),
+ (cmd_line "llvm-g++ -c $INFILE -o $OUTFILE -emit-llvm"),
+ (sink)
+ ]>;
+
+This defines a new tool called ``llvm_gcc_cpp``, which is an alias for
+``llvm-g++``. As you can see, a tool definition is just a list of
+properties; most of them should be self-explanatory. The ``sink``
+property means that this tool should be passed all command-line
+options that aren't mentioned in the option list.
+
+The complete list of all currently implemented tool properties follows.
+
+* Possible tool properties:
+
+ - ``in_language`` - input language name. Can be either a string or a
+ list, in case the tool supports multiple input languages.
+
+ - ``out_language`` - output language name. Tools are not allowed to
+ have multiple output languages.
+
+ - ``output_suffix`` - output file suffix. Can also be changed
+ dynamically, see documentation on actions.
+
+ - ``cmd_line`` - the actual command used to run the tool. You can
+ use ``$INFILE`` and ``$OUTFILE`` variables, output redirection
+ with ``>``, hook invocations (``$CALL``), environment variables
+ (via ``$ENV``) and the ``case`` construct.
+
+ - ``join`` - this tool is a "join node" in the graph, i.e. it gets a
+ list of input files and joins them together. Used for linkers.
+
+ - ``sink`` - all command-line options that are not handled by other
+ tools are passed to this tool.
+
+ - ``actions`` - A single big ``case`` expression that specifies how
+ this tool reacts on command-line options (described in more detail
+ below).
+
+Actions
+-------
+
+A tool often needs to react to command-line options, and this is
+precisely what the ``actions`` property is for. The next example
+illustrates this feature::
+
+ def llvm_gcc_linker : Tool<[
+ (in_language "object-code"),
+ (out_language "executable"),
+ (output_suffix "out"),
+ (cmd_line "llvm-gcc $INFILE -o $OUTFILE"),
+ (join),
+ (actions (case (not_empty "L"), (forward "L"),
+ (not_empty "l"), (forward "l"),
+ (not_empty "dummy"),
+ [(append_cmd "-dummy1"), (append_cmd "-dummy2")])
+ ]>;
+
+The ``actions`` tool property is implemented on top of the omnipresent
+``case`` expression. It associates one or more different *actions*
+with given conditions - in the example, the actions are ``forward``,
+which forwards a given option unchanged, and ``append_cmd``, which
+appends a given string to the tool execution command. Multiple actions
+can be associated with a single condition by using a list of actions
+(used in the example to append some dummy options). The same ``case``
+construct can also be used in the ``cmd_line`` property to modify the
+tool command line.
+
+The "join" property used in the example means that this tool behaves
+like a linker.
+
+The list of all possible actions follows.
+
+* Possible actions:
+
+ - ``append_cmd`` - append a string to the tool invocation
+ command.
+ Example: ``(case (switch_on "pthread"), (append_cmd
+ "-lpthread"))``
+
+ - ``error` - exit with error.
+ Example: ``(error "Mixing -c and -S is not allowed!")``.
+
+ - ``forward`` - forward an option unchanged.
+ Example: ``(forward "Wall")``.
+
+ - ``forward_as`` - Change the name of an option, but forward the
+ argument unchanged.
+ Example: ``(forward_as "O0", "--disable-optimization")``.
+
+ - ``output_suffix`` - modify the output suffix of this
+ tool.
+ Example: ``(output_suffix "i")``.
+
+ - ``stop_compilation`` - stop compilation after this tool processes
+ its input. Used without arguments.
+
+ - ``unpack_values`` - used for for splitting and forwarding
+ comma-separated lists of options, e.g. ``-Wa,-foo=bar,-baz`` is
+ converted to ``-foo=bar -baz`` and appended to the tool invocation
+ command.
+ Example: ``(unpack_values "Wa,")``.
+
+Language map
+============
+
+If you are adding support for a new language to LLVMC, you'll need to
+modify the language map, which defines mappings from file extensions
+to language names. It is used to choose the proper toolchain(s) for a
+given input file set. Language map definition looks like this::
+
+ def LanguageMap : LanguageMap<
+ [LangToSuffixes<"c++", ["cc", "cp", "cxx", "cpp", "CPP", "c++", "C"]>,
+ LangToSuffixes<"c", ["c"]>,
+ ...
+ ]>;
+
+For example, without those definitions the following command wouldn't work::
+
+ $ llvmc hello.cpp
+ llvmc: Unknown suffix: cpp
+
+The language map entries should be added only for tools that are
+linked with the root node. Since tools are not allowed to have
+multiple output languages, for nodes "inside" the graph the input and
+output languages should match. This is enforced at compile-time.
+
+
+More advanced topics
+====================
+
+.. _hooks:
+
+Hooks and environment variables
+-------------------------------
+
+Normally, LLVMC executes programs from the system ``PATH``. Sometimes,
+this is not sufficient: for example, we may want to specify tool paths
+or names in the configuration file. This can be easily achieved via
+the hooks mechanism. To write your own hooks, just add their
+definitions to the ``PluginMain.cpp`` or drop a ``.cpp`` file into the
+your plugin directory. Hooks should live in the ``hooks`` namespace
+and have the signature ``std::string hooks::MyHookName ([const char*
+Arg0 [ const char* Arg2 [, ...]]])``. They can be used from the
+``cmd_line`` tool property::
+
+ (cmd_line "$CALL(MyHook)/path/to/file -o $CALL(AnotherHook)")
+
+To pass arguments to hooks, use the following syntax::
+
+ (cmd_line "$CALL(MyHook, 'Arg1', 'Arg2', 'Arg # 3')/path/to/file -o1 -o2")
+
+It is also possible to use environment variables in the same manner::
+
+ (cmd_line "$ENV(VAR1)/path/to/file -o $ENV(VAR2)")
+
+To change the command line string based on user-provided options use
+the ``case`` expression (documented `above`__)::
+
+ (cmd_line
+ (case
+ (switch_on "E"),
+ "llvm-g++ -E -x c $INFILE -o $OUTFILE",
+ (default),
+ "llvm-g++ -c -x c $INFILE -o $OUTFILE -emit-llvm"))
+
+__ case_
+
+.. _priorities:
+
+How plugins are loaded
+----------------------
+
+It is possible for LLVMC plugins to depend on each other. For example,
+one can create edges between nodes defined in some other plugin. To
+make this work, however, that plugin should be loaded first. To
+achieve this, the concept of plugin priority was introduced. By
+default, every plugin has priority zero; to specify the priority
+explicitly, put the following line in your plugin's TableGen file::
+
+ def Priority : PluginPriority<$PRIORITY_VALUE>;
+ # Where PRIORITY_VALUE is some integer > 0
+
+Plugins are loaded in order of their (increasing) priority, starting
+with 0. Therefore, the plugin with the highest priority value will be
+loaded last.
+
+Debugging
+---------
+
+When writing LLVMC plugins, it can be useful to get a visual view of
+the resulting compilation graph. This can be achieved via the command
+line option ``--view-graph``. This command assumes that Graphviz_ and
+Ghostview_ are installed. There is also a ``--write-graph`` option that
+creates a Graphviz source file (``compilation-graph.dot``) in the
+current directory.
+
+Another useful ``llvmc`` option is ``--check-graph``. It checks the
+compilation graph for common errors like mismatched output/input
+language names, multiple default edges and cycles. These checks can't
+be performed at compile-time because the plugins can load code
+dynamically. When invoked with ``--check-graph``, ``llvmc`` doesn't
+perform any compilation tasks and returns the number of encountered
+errors as its status code.
+
+.. _Graphviz: http://www.graphviz.org/
+.. _Ghostview: http://pages.cs.wisc.edu/~ghost/
+
+.. raw:: html
+
+ <hr />
+ <address>
+ <a href="http://jigsaw.w3.org/css-validator/check/referer">
+ <img src="http://jigsaw.w3.org/css-validator/images/vcss-blue"
+ alt="Valid CSS" /></a>
+ <a href="http://validator.w3.org/check?uri=referer">
+ <img src="http://www.w3.org/Icons/valid-xhtml10-blue"
+ alt="Valid XHTML 1.0 Transitional"/></a>
+
+ <a href="mailto:foldr@codedgers.com">Mikhail Glushenkov</a><br />
+ <a href="http://llvm.org">LLVM Compiler Infrastructure</a><br />
+
+ Last modified: $Date: 2008-12-11 11:34:48 -0600 (Thu, 11 Dec 2008) $
+ </address>
diff --git a/tools/llvmc/doc/LLVMC-Tutorial.rst b/tools/llvmc/doc/LLVMC-Tutorial.rst
new file mode 100644
index 0000000..6f06477
--- /dev/null
+++ b/tools/llvmc/doc/LLVMC-Tutorial.rst
@@ -0,0 +1,124 @@
+======================
+Tutorial - Using LLVMC
+======================
+..
+ This file was automatically generated by rst2html.
+ Please do not edit directly!
+ The ReST source lives in the directory 'tools/llvmc/doc'.
+
+.. contents::
+
+.. raw:: html
+
+ <div class="doc_author">
+ <p>Written by <a href="mailto:foldr@codedgers.com">Mikhail Glushenkov</a></p>
+ </div>
+
+Introduction
+============
+
+LLVMC is a generic compiler driver, which plays the same role for LLVM
+as the ``gcc`` program does for GCC - the difference being that LLVMC
+is designed to be more adaptable and easier to customize. Most of
+LLVMC functionality is implemented via plugins, which can be loaded
+dynamically or compiled in. This tutorial describes the basic usage
+and configuration of LLVMC.
+
+
+Compiling with LLVMC
+====================
+
+In general, LLVMC tries to be command-line compatible with ``gcc`` as
+much as possible, so most of the familiar options work::
+
+ $ llvmc -O3 -Wall hello.cpp
+ $ ./a.out
+ hello
+
+This will invoke ``llvm-g++`` under the hood (you can see which
+commands are executed by using the ``-v`` option). For further help on
+command-line LLVMC usage, refer to the ``llvmc --help`` output.
+
+
+Using LLVMC to generate toolchain drivers
+=========================================
+
+LLVMC plugins are written mostly using TableGen_, so you need to
+be familiar with it to get anything done.
+
+.. _TableGen: http://llvm.cs.uiuc.edu/docs/TableGenFundamentals.html
+
+Start by compiling ``plugins/Simple/Simple.td``, which is a primitive
+wrapper for ``gcc``::
+
+ $ cd $LLVM_DIR/tools/llvmc
+ $ make DRIVER_NAME=mygcc BUILTIN_PLUGINS=Simple
+ $ cat > hello.c
+ [...]
+ $ mygcc hello.c
+ $ ./hello.out
+ Hello
+
+Here we link our plugin with the LLVMC core statically to form an
+executable file called ``mygcc``. It is also possible to build our
+plugin as a standalone dynamic library; this is described in the
+reference manual.
+
+Contents of the file ``Simple.td`` look like this::
+
+ // Include common definitions
+ include "llvm/CompilerDriver/Common.td"
+
+ // Tool descriptions
+ def gcc : Tool<
+ [(in_language "c"),
+ (out_language "executable"),
+ (output_suffix "out"),
+ (cmd_line "gcc $INFILE -o $OUTFILE"),
+ (sink)
+ ]>;
+
+ // Language map
+ def LanguageMap : LanguageMap<[LangToSuffixes<"c", ["c"]>]>;
+
+ // Compilation graph
+ def CompilationGraph : CompilationGraph<[Edge<"root", "gcc">]>;
+
+As you can see, this file consists of three parts: tool descriptions,
+language map, and the compilation graph definition.
+
+At the heart of LLVMC is the idea of a compilation graph: vertices in
+this graph are tools, and edges represent a transformation path
+between two tools (for example, assembly source produced by the
+compiler can be transformed into executable code by an assembler). The
+compilation graph is basically a list of edges; a special node named
+``root`` is used to mark graph entry points.
+
+Tool descriptions are represented as property lists: most properties
+in the example above should be self-explanatory; the ``sink`` property
+means that all options lacking an explicit description should be
+forwarded to this tool.
+
+The ``LanguageMap`` associates a language name with a list of suffixes
+and is used for deciding which toolchain corresponds to a given input
+file.
+
+To learn more about LLVMC customization, refer to the reference
+manual and plugin source code in the ``plugins`` directory.
+
+.. raw:: html
+
+ <hr />
+ <address>
+ <a href="http://jigsaw.w3.org/css-validator/check/referer">
+ <img src="http://jigsaw.w3.org/css-validator/images/vcss-blue"
+ alt="Valid CSS" /></a>
+ <a href="http://validator.w3.org/check?uri=referer">
+ <img src="http://www.w3.org/Icons/valid-xhtml10-blue"
+ alt="Valid XHTML 1.0 Transitional"/></a>
+
+ <a href="mailto:foldr@codedgers.com">Mikhail Glushenkov</a><br />
+ <a href="http://llvm.org">LLVM Compiler Infrastructure</a><br />
+
+ Last modified: $Date: 2008-12-11 11:34:48 -0600 (Thu, 11 Dec 2008) $
+ </address>
diff --git a/tools/llvmc/doc/Makefile b/tools/llvmc/doc/Makefile
new file mode 100644
index 0000000..65e6b9b
--- /dev/null
+++ b/tools/llvmc/doc/Makefile
@@ -0,0 +1,27 @@
+##===- tools/llvmc/doc/Makefile ----------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL=../../..
+include $(LEVEL)/Makefile.config
+
+DOC_DIR=../../../docs
+RST2HTML=rst2html --stylesheet=llvm.css --link-stylesheet
+
+all : LLVMC-Reference.html LLVMC-Tutorial.html
+ $(CP) LLVMC-Reference.html $(DOC_DIR)/CompilerDriver.html
+ $(CP) LLVMC-Tutorial.html $(DOC_DIR)/CompilerDriverTutorial.html
+
+LLVMC-Tutorial.html : LLVMC-Tutorial.rst
+ $(RST2HTML) $< $@
+
+LLVMC-Reference.html : LLVMC-Reference.rst
+ $(RST2HTML) $< $@
+
+clean :
+ $(RM) LLVMC-Tutorial.html LLVMC-Reference.html
diff --git a/tools/llvmc/doc/img/lines.gif b/tools/llvmc/doc/img/lines.gif
new file mode 100644
index 0000000..88f491e
--- /dev/null
+++ b/tools/llvmc/doc/img/lines.gif
Binary files differ
diff --git a/tools/llvmc/driver/Main.cpp b/tools/llvmc/driver/Main.cpp
new file mode 100644
index 0000000..b1f5b67
--- /dev/null
+++ b/tools/llvmc/driver/Main.cpp
@@ -0,0 +1,14 @@
+//===--- Main.cpp - The LLVM Compiler Driver -------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open
+// Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Just include CompilerDriver/Main.inc.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CompilerDriver/Main.inc"
diff --git a/tools/llvmc/driver/Makefile b/tools/llvmc/driver/Makefile
new file mode 100644
index 0000000..3dd373a
--- /dev/null
+++ b/tools/llvmc/driver/Makefile
@@ -0,0 +1,22 @@
+##===- tools/llvmc/driver/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 = $(LLVMC_BASED_DRIVER_NAME)
+LLVMLIBS = CompilerDriver
+
+ifneq ($(LLVMC_BUILTIN_PLUGINS),)
+USEDLIBS += $(patsubst %,plugin_llvmc_%,$(LLVMC_BUILTIN_PLUGINS))
+endif
+
+LINK_COMPONENTS = support system
+REQUIRES_EH := 1
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/example/Hello/Hello.cpp b/tools/llvmc/example/Hello/Hello.cpp
new file mode 100644
index 0000000..23a13a5
--- /dev/null
+++ b/tools/llvmc/example/Hello/Hello.cpp
@@ -0,0 +1,30 @@
+//===- Hello.cpp - Example code from "Writing an LLVMC Plugin" ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Test plugin for LLVMC. Shows how to write plugins without using TableGen.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CompilerDriver/CompilationGraph.h"
+#include "llvm/CompilerDriver/Plugin.h"
+
+#include <iostream>
+
+namespace {
+struct MyPlugin : public llvmc::BasePlugin {
+ void PopulateLanguageMap(llvmc::LanguageMap&) const
+ { std::cout << "Hello!\n"; }
+
+ void PopulateCompilationGraph(llvmc::CompilationGraph&) const
+ {}
+};
+
+static llvmc::RegisterPlugin<MyPlugin> RP("Hello", "Hello World plugin");
+
+}
diff --git a/tools/llvmc/example/Hello/Makefile b/tools/llvmc/example/Hello/Makefile
new file mode 100644
index 0000000..10325e6
--- /dev/null
+++ b/tools/llvmc/example/Hello/Makefile
@@ -0,0 +1,14 @@
+##===- tools/llvmc/plugins/Hello/Makefile ------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../../..
+
+LLVMC_PLUGIN = Hello
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/example/Simple/Makefile b/tools/llvmc/example/Simple/Makefile
new file mode 100644
index 0000000..d7adb5d
--- /dev/null
+++ b/tools/llvmc/example/Simple/Makefile
@@ -0,0 +1,15 @@
+##===- tools/llvmc/plugins/Simple/Makefile -----------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../../..
+
+LLVMC_PLUGIN = Simple
+BUILT_SOURCES = AutoGenerated.inc
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/example/Simple/PluginMain.cpp b/tools/llvmc/example/Simple/PluginMain.cpp
new file mode 100644
index 0000000..add8acb
--- /dev/null
+++ b/tools/llvmc/example/Simple/PluginMain.cpp
@@ -0,0 +1 @@
+#include "AutoGenerated.inc"
diff --git a/tools/llvmc/example/Simple/Simple.td b/tools/llvmc/example/Simple/Simple.td
new file mode 100644
index 0000000..87bc385
--- /dev/null
+++ b/tools/llvmc/example/Simple/Simple.td
@@ -0,0 +1,37 @@
+//===- Simple.td - A simple plugin for LLVMC ------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// A simple LLVMC-based gcc wrapper that shows how to write LLVMC plugins.
+//
+// To compile, use this command:
+//
+// $ cd $LLVMC_DIR/example/Simple
+// $ make
+//
+// Run as:
+//
+// $ llvmc -load $LLVM_DIR/Release/lib/plugin_llvmc_Simple.so
+//
+// For instructions on how to build your own LLVMC-based driver, see
+// the 'example/Skeleton' directory.
+//===----------------------------------------------------------------------===//
+
+include "llvm/CompilerDriver/Common.td"
+
+def gcc : Tool<
+[(in_language "c"),
+ (out_language "executable"),
+ (output_suffix "out"),
+ (cmd_line "gcc $INFILE -o $OUTFILE"),
+ (sink)
+]>;
+
+def LanguageMap : LanguageMap<[LangToSuffixes<"c", ["c"]>]>;
+
+def CompilationGraph : CompilationGraph<[Edge<"root", "gcc">]>;
diff --git a/tools/llvmc/example/Skeleton/Makefile b/tools/llvmc/example/Skeleton/Makefile
new file mode 100644
index 0000000..2e4cbb9
--- /dev/null
+++ b/tools/llvmc/example/Skeleton/Makefile
@@ -0,0 +1,24 @@
+##===- llvmc/example/Skeleton/Makefile ---------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open
+# Source License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+# Change this so that $(BASE_LEVEL)/Makefile.common refers to
+# $LLVM_DIR/Makefile.common.
+export LLVMC_BASE_LEVEL = ../../../..
+
+# Change this to the name of your LLVMC-based driver.
+export LLVMC_BASED_DRIVER_NAME = llvmc-skeleton
+
+# List your plugin names here
+export LLVMC_BUILTIN_PLUGINS = # Plugin
+
+LEVEL = $(LLVMC_BASE_LEVEL)
+
+DIRS = plugins driver
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/example/Skeleton/README b/tools/llvmc/example/Skeleton/README
new file mode 100644
index 0000000..92216ae
--- /dev/null
+++ b/tools/llvmc/example/Skeleton/README
@@ -0,0 +1,6 @@
+
+This is a template that can be used to create your own LLVMC-based drivers. Just
+copy the `Skeleton` directory to the location of your preference and edit
+`Skeleton/Makefile` and `Skeleton/plugins/Plugin`.
+
+The build system assumes that your project is based on LLVM.
diff --git a/tools/llvmc/example/Skeleton/driver/Main.cpp b/tools/llvmc/example/Skeleton/driver/Main.cpp
new file mode 100644
index 0000000..b1f5b67
--- /dev/null
+++ b/tools/llvmc/example/Skeleton/driver/Main.cpp
@@ -0,0 +1,14 @@
+//===--- Main.cpp - The LLVM Compiler Driver -------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open
+// Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Just include CompilerDriver/Main.inc.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CompilerDriver/Main.inc"
diff --git a/tools/llvmc/example/Skeleton/driver/Makefile b/tools/llvmc/example/Skeleton/driver/Makefile
new file mode 100644
index 0000000..bf6d7a5
--- /dev/null
+++ b/tools/llvmc/example/Skeleton/driver/Makefile
@@ -0,0 +1,22 @@
+##===- llvmc/example/Skeleton/driver/Makefile --------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open
+# Source License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = $(LLVMC_BASE_LEVEL)/..
+
+TOOLNAME = $(LLVMC_BASED_DRIVER_NAME)
+LLVMLIBS = CompilerDriver
+
+ifneq ($(LLVMC_BUILTIN_PLUGINS),)
+USEDLIBS += $(patsubst %,plugin_llvmc_%,$(LLVMC_BUILTIN_PLUGINS))
+endif
+
+LINK_COMPONENTS = support system
+REQUIRES_EH := 1
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/example/Skeleton/plugins/Makefile b/tools/llvmc/example/Skeleton/plugins/Makefile
new file mode 100644
index 0000000..fb07f23
--- /dev/null
+++ b/tools/llvmc/example/Skeleton/plugins/Makefile
@@ -0,0 +1,18 @@
+##===- llvmc/example/Skeleton/plugins/Makefile -------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open
+# Source License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = $(LLVMC_BASE_LEVEL)/..
+
+ifneq ($(LLVMC_BUILTIN_PLUGINS),)
+DIRS = $(LLVMC_BUILTIN_PLUGINS)
+endif
+
+export LLVMC_BUILTIN_PLUGIN=1
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/example/Skeleton/plugins/Plugin/Makefile b/tools/llvmc/example/Skeleton/plugins/Plugin/Makefile
new file mode 100644
index 0000000..54f7221
--- /dev/null
+++ b/tools/llvmc/example/Skeleton/plugins/Plugin/Makefile
@@ -0,0 +1,17 @@
+##===- llvmc/example/Skeleton/plugins/Plugin/Makefile ------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = $(LLVMC_BASE_LEVEL)/../..
+
+# Change this to the name of your plugin.
+LLVMC_PLUGIN = Plugin
+
+BUILT_SOURCES = AutoGenerated.inc
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/example/Skeleton/plugins/Plugin/Plugin.td b/tools/llvmc/example/Skeleton/plugins/Plugin/Plugin.td
new file mode 100644
index 0000000..febb9ad
--- /dev/null
+++ b/tools/llvmc/example/Skeleton/plugins/Plugin/Plugin.td
@@ -0,0 +1,7 @@
+//===- Plugin.td - A skeleton plugin for LLVMC -------------*- tablegen -*-===//
+//
+// Write the code for your plugin here.
+//
+//===----------------------------------------------------------------------===//
+
+include "llvm/CompilerDriver/Common.td"
diff --git a/tools/llvmc/example/Skeleton/plugins/Plugin/PluginMain.cpp b/tools/llvmc/example/Skeleton/plugins/Plugin/PluginMain.cpp
new file mode 100644
index 0000000..add8acb
--- /dev/null
+++ b/tools/llvmc/example/Skeleton/plugins/Plugin/PluginMain.cpp
@@ -0,0 +1 @@
+#include "AutoGenerated.inc"
diff --git a/tools/llvmc/plugins/Base/Base.td.in b/tools/llvmc/plugins/Base/Base.td.in
new file mode 100644
index 0000000..757078a
--- /dev/null
+++ b/tools/llvmc/plugins/Base/Base.td.in
@@ -0,0 +1,202 @@
+//===- Base.td - LLVMC2 toolchain descriptions -------------*- tablegen -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains compilation graph description used by llvmc2.
+//
+//===----------------------------------------------------------------------===//
+
+include "llvm/CompilerDriver/Common.td"
+
+// Options
+
+def OptList : OptionList<[
+ (switch_option "emit-llvm",
+ (help "Emit LLVM .ll files instead of native object files")),
+ (switch_option "E",
+ (help "Stop after the preprocessing stage, do not run the compiler")),
+ (switch_option "fsyntax-only",
+ (help "Stop after checking the input for syntax errors")),
+ (switch_option "opt",
+ (help "Enable opt")),
+ (switch_option "S",
+ (help "Stop after compilation, do not assemble")),
+ (switch_option "c",
+ (help "Compile and assemble, but do not link")),
+ (switch_option "pthread",
+ (help "Enable threads")),
+ (parameter_option "linker",
+ (help "Choose linker (possible values: gcc, g++)")),
+ (parameter_list_option "include",
+ (help "Include the named file prior to preprocessing")),
+ (prefix_list_option "I",
+ (help "Add a directory to include path")),
+ (prefix_list_option "Wa,",
+ (help "Pass options to assembler")),
+ (prefix_list_option "Wllc,",
+ (help "Pass options to llc")),
+ (prefix_list_option "L",
+ (help "Add a directory to link path")),
+ (prefix_list_option "l",
+ (help "Search a library when linking")),
+ (prefix_list_option "Wl,",
+ (help "Pass options to linker")),
+ (prefix_list_option "Wo,",
+ (help "Pass options to opt"))
+]>;
+
+// Tools
+
+class llvm_gcc_based <string cmd_prefix, string in_lang, string E_ext> : Tool<
+[(in_language in_lang),
+ (out_language "llvm-bitcode"),
+ (output_suffix "bc"),
+ (cmd_line (case
+ (switch_on "E"),
+ (case (not_empty "o"),
+ !strconcat(cmd_prefix, " -E $INFILE -o $OUTFILE"),
+ (default),
+ !strconcat(cmd_prefix, " -E $INFILE")),
+ (switch_on "fsyntax-only"),
+ !strconcat(cmd_prefix, " -fsyntax-only $INFILE"),
+ (and (switch_on "S"), (switch_on "emit-llvm")),
+ !strconcat(cmd_prefix, " -S $INFILE -o $OUTFILE -emit-llvm"),
+ (default),
+ !strconcat(cmd_prefix, " -c $INFILE -o $OUTFILE -emit-llvm"))),
+ (actions
+ (case
+ (switch_on "E"), [(stop_compilation), (output_suffix E_ext)],
+ (and (switch_on "emit-llvm"), (switch_on "S")),
+ [(output_suffix "ll"), (stop_compilation)],
+ (and (switch_on "emit-llvm"), (switch_on "c")), (stop_compilation),
+ (switch_on "fsyntax-only"), (stop_compilation),
+ (not_empty "include"), (forward "include"),
+ (not_empty "I"), (forward "I"))),
+ (sink)
+]>;
+
+def llvm_gcc_c : llvm_gcc_based<"@LLVMGCCCOMMAND@ -x c", "c", "i">;
+def llvm_gcc_cpp : llvm_gcc_based<"@LLVMGXXCOMMAND@ -x c++", "c++", "i">;
+def llvm_gcc_m : llvm_gcc_based<"@LLVMGCCCOMMAND@ -x objective-c", "objective-c", "mi">;
+def llvm_gcc_mxx : llvm_gcc_based<"@LLVMGCCCOMMAND@ -x objective-c++",
+ "objective-c++", "mi">;
+
+def opt : Tool<
+[(in_language "llvm-bitcode"),
+ (out_language "llvm-bitcode"),
+ (output_suffix "bc"),
+ (actions (case (not_empty "Wo,"), (unpack_values "Wo,"))),
+ (cmd_line "opt -f $INFILE -o $OUTFILE")
+]>;
+
+def llvm_as : Tool<
+[(in_language "llvm-assembler"),
+ (out_language "llvm-bitcode"),
+ (output_suffix "bc"),
+ (cmd_line "llvm-as $INFILE -o $OUTFILE")
+]>;
+
+def llvm_gcc_assembler : Tool<
+[(in_language "assembler"),
+ (out_language "object-code"),
+ (output_suffix "o"),
+ (cmd_line "@LLVMGCCCOMMAND@ -c -x assembler $INFILE -o $OUTFILE"),
+ (actions (case
+ (switch_on "c"), (stop_compilation),
+ (not_empty "Wa,"), (unpack_values "Wa,")))
+]>;
+
+def llc : Tool<
+[(in_language "llvm-bitcode"),
+ (out_language "assembler"),
+ (output_suffix "s"),
+ (cmd_line "llc -f $INFILE -o $OUTFILE"),
+ (actions (case
+ (switch_on "S"), (stop_compilation),
+ (not_empty "Wllc,"), (unpack_values "Wllc,")))
+]>;
+
+// Base class for linkers
+class llvm_gcc_based_linker <string cmd_prefix> : Tool<
+[(in_language "object-code"),
+ (out_language "executable"),
+ (output_suffix "out"),
+ (cmd_line !strconcat(cmd_prefix, " $INFILE -o $OUTFILE")),
+ (join),
+ (actions (case
+ (switch_on "pthread"), (append_cmd "-lpthread"),
+ (not_empty "L"), (forward "L"),
+ (not_empty "l"), (forward "l"),
+ (not_empty "Wl,"), (unpack_values "Wl,")))
+]>;
+
+// Default linker
+def llvm_gcc_linker : llvm_gcc_based_linker<"@LLVMGCCCOMMAND@">;
+// Alternative linker for C++
+def llvm_gcc_cpp_linker : llvm_gcc_based_linker<"@LLVMGXXCOMMAND@">;
+
+// Language map
+
+def LanguageMap : LanguageMap<
+ [LangToSuffixes<"c++", ["cc", "cp", "cxx", "cpp", "CPP", "c++", "C"]>,
+ LangToSuffixes<"c", ["c"]>,
+ LangToSuffixes<"c-cpp-output", ["i"]>,
+ LangToSuffixes<"objective-c-cpp-output", ["mi"]>,
+ LangToSuffixes<"objective-c++", ["mm"]>,
+ LangToSuffixes<"objective-c", ["m"]>,
+ LangToSuffixes<"assembler", ["s"]>,
+ LangToSuffixes<"assembler-with-cpp", ["S"]>,
+ LangToSuffixes<"llvm-assembler", ["ll"]>,
+ LangToSuffixes<"llvm-bitcode", ["bc"]>,
+ LangToSuffixes<"object-code", ["o"]>,
+ LangToSuffixes<"executable", ["out"]>
+ ]>;
+
+// Compilation graph
+
+def CompilationGraph : CompilationGraph<[
+ Edge<"root", "llvm_gcc_c">,
+ Edge<"root", "llvm_gcc_assembler">,
+ Edge<"root", "llvm_gcc_cpp">,
+ Edge<"root", "llvm_gcc_m">,
+ Edge<"root", "llvm_gcc_mxx">,
+ Edge<"root", "llvm_as">,
+
+ Edge<"llvm_gcc_c", "llc">,
+ Edge<"llvm_gcc_cpp", "llc">,
+ Edge<"llvm_gcc_m", "llc">,
+ Edge<"llvm_gcc_mxx", "llc">,
+ Edge<"llvm_as", "llc">,
+
+ OptionalEdge<"llvm_gcc_c", "opt", (case (switch_on "opt"), (inc_weight))>,
+ OptionalEdge<"llvm_gcc_cpp", "opt", (case (switch_on "opt"), (inc_weight))>,
+ OptionalEdge<"llvm_gcc_m", "opt", (case (switch_on "opt"), (inc_weight))>,
+ OptionalEdge<"llvm_gcc_mxx", "opt", (case (switch_on "opt"), (inc_weight))>,
+ OptionalEdge<"llvm_as", "opt", (case (switch_on "opt"), (inc_weight))>,
+ Edge<"opt", "llc">,
+
+ Edge<"llc", "llvm_gcc_assembler">,
+ Edge<"llvm_gcc_assembler", "llvm_gcc_linker">,
+ OptionalEdge<"llvm_gcc_assembler", "llvm_gcc_cpp_linker",
+ (case
+ (or (input_languages_contain "c++"),
+ (input_languages_contain "objective-c++")),
+ (inc_weight),
+ (or (parameter_equals "linker", "g++"),
+ (parameter_equals "linker", "c++")), (inc_weight))>,
+
+
+ Edge<"root", "llvm_gcc_linker">,
+ OptionalEdge<"root", "llvm_gcc_cpp_linker",
+ (case
+ (or (input_languages_contain "c++"),
+ (input_languages_contain "objective-c++")),
+ (inc_weight),
+ (or (parameter_equals "linker", "g++"),
+ (parameter_equals "linker", "c++")), (inc_weight))>
+ ]>;
diff --git a/tools/llvmc/plugins/Base/Makefile b/tools/llvmc/plugins/Base/Makefile
new file mode 100644
index 0000000..ebc4335
--- /dev/null
+++ b/tools/llvmc/plugins/Base/Makefile
@@ -0,0 +1,15 @@
+##===- tools/llvmc/plugins/Base/Makefile -------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../../..
+
+LLVMC_PLUGIN = Base
+BUILT_SOURCES = AutoGenerated.inc
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/plugins/Base/PluginMain.cpp b/tools/llvmc/plugins/Base/PluginMain.cpp
new file mode 100644
index 0000000..add8acb
--- /dev/null
+++ b/tools/llvmc/plugins/Base/PluginMain.cpp
@@ -0,0 +1 @@
+#include "AutoGenerated.inc"
diff --git a/tools/llvmc/plugins/Clang/Clang.td b/tools/llvmc/plugins/Clang/Clang.td
new file mode 100644
index 0000000..a179c53
--- /dev/null
+++ b/tools/llvmc/plugins/Clang/Clang.td
@@ -0,0 +1,116 @@
+// A replacement for the Clang's ccc script.
+// Depends on the Base plugin.
+// To compile, use this command:
+//
+// cd $LLVMC2_DIR
+// make DRIVER_NAME=ccc2 BUILTIN_PLUGINS=Clang
+//
+// Or just use the default llvmc, which now has this plugin enabled.
+
+include "llvm/CompilerDriver/Common.td"
+
+def Priority : PluginPriority<1>;
+
+def Options : OptionList<[
+// Extern options
+(switch_option "E", (extern)),
+(switch_option "S", (extern)),
+(switch_option "c", (extern)),
+(switch_option "fsyntax-only", (extern)),
+(switch_option "emit-llvm", (extern)),
+(switch_option "pthread", (extern)),
+(parameter_list_option "I", (extern)),
+(parameter_list_option "include", (extern)),
+(parameter_list_option "L", (extern)),
+(parameter_list_option "l", (extern)),
+(prefix_list_option "Wa,", (extern)),
+(prefix_list_option "Wl,", (extern)),
+
+(switch_option "clang", (help "Use Clang instead of llvm-gcc"))
+]>;
+
+class clang_based<string language, string cmd, string ext_E> : Tool<
+[(in_language language),
+ (out_language "llvm-bitcode"),
+ (output_suffix "bc"),
+ (cmd_line (case
+ (switch_on "E"),
+ (case
+ (not_empty "o"),
+ !strconcat(cmd, " -E $INFILE -o $OUTFILE"),
+ (default),
+ !strconcat(cmd, " -E $INFILE")),
+ (and (switch_on "S"), (switch_on "emit-llvm")),
+ !strconcat(cmd, " -emit-llvm $INFILE -o $OUTFILE"),
+ (default),
+ !strconcat(cmd, " -emit-llvm-bc $INFILE -o $OUTFILE"))),
+ (actions (case (switch_on "E"),
+ [(stop_compilation), (output_suffix ext_E)],
+ (switch_on "fsyntax-only"), (stop_compilation),
+ (and (switch_on "S"), (switch_on "emit-llvm")),
+ [(stop_compilation), (output_suffix "ll")],
+ (and (switch_on "c"), (switch_on "emit-llvm")),
+ (stop_compilation),
+ (not_empty "include"), (forward "include"),
+ (not_empty "I"), (forward "I"))),
+ (sink)
+]>;
+
+def clang_c : clang_based<"c", "clang -x c", "i">;
+def clang_cpp : clang_based<"c++", "clang -x c++", "i">;
+def clang_objective_c : clang_based<"objective-c",
+ "clang -x objective-c", "mi">;
+def clang_objective_cpp : clang_based<"objective-c++",
+ "clang -x objective-c++", "mi">;
+
+def as : Tool<
+[(in_language "assembler"),
+ (out_language "object-code"),
+ (output_suffix "o"),
+ (cmd_line "as $INFILE -o $OUTFILE"),
+ (actions (case (not_empty "Wa,"), (unpack_values "Wa,"),
+ (switch_on "c"), (stop_compilation)))
+]>;
+
+// Default linker
+def llvm_ld : Tool<
+[(in_language "object-code"),
+ (out_language "executable"),
+ (output_suffix "out"),
+ (cmd_line "llvm-ld -native -disable-internalize $INFILE -o $OUTFILE"),
+ (actions (case
+ (switch_on "pthread"), (append_cmd "-lpthread"),
+ (not_empty "L"), (forward "L"),
+ (not_empty "l"), (forward "l"),
+ (not_empty "Wl,"), (unpack_values "Wl,"))),
+ (join)
+]>;
+
+// Language map
+
+def LanguageMap : LanguageMap<[
+ LangToSuffixes<"c++", ["cc", "cp", "cxx", "cpp", "CPP", "c++", "C"]>,
+ LangToSuffixes<"c", ["c"]>,
+ LangToSuffixes<"objective-c", ["m"]>,
+ LangToSuffixes<"c-cpp-output", ["i"]>,
+ LangToSuffixes<"objective-c-cpp-output", ["mi"]>
+]>;
+
+// Compilation graph
+
+def CompilationGraph : CompilationGraph<[
+ OptionalEdge<"root", "clang_c",
+ (case (switch_on "clang"), (inc_weight))>,
+ OptionalEdge<"root", "clang_cpp",
+ (case (switch_on "clang"), (inc_weight))>,
+ OptionalEdge<"root", "clang_objective_c",
+ (case (switch_on "clang"), (inc_weight))>,
+ OptionalEdge<"root", "clang_objective_cpp",
+ (case (switch_on "clang"), (inc_weight))>,
+ Edge<"clang_c", "llc">,
+ Edge<"clang_cpp", "llc">,
+ Edge<"clang_objective_c", "llc">,
+ Edge<"clang_objective_cpp", "llc">,
+ OptionalEdge<"llc", "as", (case (switch_on "clang"), (inc_weight))>,
+ Edge<"as", "llvm_ld">
+]>;
diff --git a/tools/llvmc/plugins/Clang/Makefile b/tools/llvmc/plugins/Clang/Makefile
new file mode 100644
index 0000000..5e5b88a
--- /dev/null
+++ b/tools/llvmc/plugins/Clang/Makefile
@@ -0,0 +1,15 @@
+##===- tools/llvmc/plugins/Clang/Makefile ------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../../..
+
+LLVMC_PLUGIN = Clang
+BUILT_SOURCES = AutoGenerated.inc
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/plugins/Clang/PluginMain.cpp b/tools/llvmc/plugins/Clang/PluginMain.cpp
new file mode 100644
index 0000000..add8acb
--- /dev/null
+++ b/tools/llvmc/plugins/Clang/PluginMain.cpp
@@ -0,0 +1 @@
+#include "AutoGenerated.inc"
diff --git a/tools/llvmc/plugins/Makefile b/tools/llvmc/plugins/Makefile
new file mode 100644
index 0000000..37dac6f
--- /dev/null
+++ b/tools/llvmc/plugins/Makefile
@@ -0,0 +1,18 @@
+##===- tools/llvmc/plugins/Makefile ------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open
+# Source License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../..
+
+ifneq ($(LLVMC_BUILTIN_PLUGINS),)
+DIRS = $(LLVMC_BUILTIN_PLUGINS)
+endif
+
+export LLVMC_BUILTIN_PLUGIN=1
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp
new file mode 100644
index 0000000..d3a3f7f
--- /dev/null
+++ b/tools/lto/LTOCodeGenerator.cpp
@@ -0,0 +1,506 @@
+//===-LTOCodeGenerator.cpp - LLVM Link Time Optimizer ---------------------===//
+//
+// 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 Link Time Optimization library. This library is
+// intended to be used by linker to optimize code at link time.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LTOModule.h"
+#include "LTOCodeGenerator.h"
+
+
+#include "llvm/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Linker.h"
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/ModuleProvider.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/SystemUtils.h"
+#include "llvm/Support/Mangler.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Signals.h"
+#include "llvm/Analysis/Passes.h"
+#include "llvm/Analysis/LoopPass.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/CodeGen/FileWriters.h"
+#include "llvm/Target/SubtargetFeature.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetMachineRegistry.h"
+#include "llvm/Target/TargetAsmInfo.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Config/config.h"
+
+
+#include <fstream>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+
+
+using namespace llvm;
+
+static cl::opt<bool> DisableInline("disable-inlining",
+ cl::desc("Do not run the inliner pass"));
+
+
+const char* LTOCodeGenerator::getVersionString()
+{
+#ifdef LLVM_VERSION_INFO
+ return PACKAGE_NAME " version " PACKAGE_VERSION ", " LLVM_VERSION_INFO;
+#else
+ return PACKAGE_NAME " version " PACKAGE_VERSION;
+#endif
+}
+
+
+LTOCodeGenerator::LTOCodeGenerator()
+ : _linker("LinkTimeOptimizer", "ld-temp.o"), _target(NULL),
+ _emitDwarfDebugInfo(false), _scopeRestrictionsDone(false),
+ _codeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC),
+ _nativeObjectFile(NULL), _gccPath(NULL)
+{
+
+}
+
+LTOCodeGenerator::~LTOCodeGenerator()
+{
+ delete _target;
+ delete _nativeObjectFile;
+}
+
+
+
+bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg)
+{
+ return _linker.LinkInModule(mod->getLLVVMModule(), &errMsg);
+}
+
+
+bool LTOCodeGenerator::setDebugInfo(lto_debug_model debug, std::string& errMsg)
+{
+ switch (debug) {
+ case LTO_DEBUG_MODEL_NONE:
+ _emitDwarfDebugInfo = false;
+ return false;
+
+ case LTO_DEBUG_MODEL_DWARF:
+ _emitDwarfDebugInfo = true;
+ return false;
+ }
+ errMsg = "unknown debug format";
+ return true;
+}
+
+
+bool LTOCodeGenerator::setCodePICModel(lto_codegen_model model,
+ std::string& errMsg)
+{
+ switch (model) {
+ case LTO_CODEGEN_PIC_MODEL_STATIC:
+ case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
+ case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
+ _codeModel = model;
+ return false;
+ }
+ errMsg = "unknown pic model";
+ return true;
+}
+
+void LTOCodeGenerator::setGccPath(const char* path)
+{
+ if ( _gccPath )
+ delete _gccPath;
+ _gccPath = new sys::Path(path);
+}
+
+void LTOCodeGenerator::addMustPreserveSymbol(const char* sym)
+{
+ _mustPreserveSymbols[sym] = 1;
+}
+
+
+bool LTOCodeGenerator::writeMergedModules(const char* path, std::string& errMsg)
+{
+ if ( this->determineTarget(errMsg) )
+ return true;
+
+ // mark which symbols can not be internalized
+ this->applyScopeRestrictions();
+
+ // create output file
+ std::ofstream out(path, std::ios_base::out|std::ios::trunc|std::ios::binary);
+ if ( out.fail() ) {
+ errMsg = "could not open bitcode file for writing: ";
+ errMsg += path;
+ return true;
+ }
+
+ // write bitcode to it
+ WriteBitcodeToFile(_linker.getModule(), out);
+ if ( out.fail() ) {
+ errMsg = "could not write bitcode file: ";
+ errMsg += path;
+ return true;
+ }
+
+ return false;
+}
+
+
+const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg)
+{
+ // make unique temp .s file to put generated assembly code
+ sys::Path uniqueAsmPath("lto-llvm.s");
+ if ( uniqueAsmPath.createTemporaryFileOnDisk(true, &errMsg) )
+ return NULL;
+ sys::RemoveFileOnSignal(uniqueAsmPath);
+
+ // generate assembly code
+ bool genResult = false;
+ {
+ raw_fd_ostream asmFile(uniqueAsmPath.c_str(), false, errMsg);
+ if (!errMsg.empty())
+ return NULL;
+ genResult = this->generateAssemblyCode(asmFile, errMsg);
+ }
+ if ( genResult ) {
+ if ( uniqueAsmPath.exists() )
+ uniqueAsmPath.eraseFromDisk();
+ return NULL;
+ }
+
+ // make unique temp .o file to put generated object file
+ sys::PathWithStatus uniqueObjPath("lto-llvm.o");
+ if ( uniqueObjPath.createTemporaryFileOnDisk(true, &errMsg) ) {
+ if ( uniqueAsmPath.exists() )
+ uniqueAsmPath.eraseFromDisk();
+ return NULL;
+ }
+ sys::RemoveFileOnSignal(uniqueObjPath);
+
+ // assemble the assembly code
+ const std::string& uniqueObjStr = uniqueObjPath.toString();
+ bool asmResult = this->assemble(uniqueAsmPath.toString(),
+ uniqueObjStr, errMsg);
+ if ( !asmResult ) {
+ // remove old buffer if compile() called twice
+ delete _nativeObjectFile;
+
+ // read .o file into memory buffer
+ _nativeObjectFile = MemoryBuffer::getFile(uniqueObjStr.c_str(),&errMsg);
+ }
+
+ // remove temp files
+ uniqueAsmPath.eraseFromDisk();
+ uniqueObjPath.eraseFromDisk();
+
+ // return buffer, unless error
+ if ( _nativeObjectFile == NULL )
+ return NULL;
+ *length = _nativeObjectFile->getBufferSize();
+ return _nativeObjectFile->getBufferStart();
+}
+
+
+bool LTOCodeGenerator::assemble(const std::string& asmPath,
+ const std::string& objPath, std::string& errMsg)
+{
+ sys::Path gcc;
+ if ( _gccPath ) {
+ gcc = *_gccPath;
+ } else {
+ // find compiler driver
+ gcc = sys::Program::FindProgramByName("gcc");
+ if ( gcc.isEmpty() ) {
+ errMsg = "can't locate gcc";
+ return true;
+ }
+ }
+
+ // build argument list
+ std::vector<const char*> args;
+ std::string targetTriple = _linker.getModule()->getTargetTriple();
+ args.push_back(gcc.c_str());
+ if ( targetTriple.find("darwin") != targetTriple.size() ) {
+ if (strncmp(targetTriple.c_str(), "i386-apple-", 11) == 0) {
+ args.push_back("-arch");
+ args.push_back("i386");
+ }
+ else if (strncmp(targetTriple.c_str(), "x86_64-apple-", 13) == 0) {
+ args.push_back("-arch");
+ args.push_back("x86_64");
+ }
+ else if (strncmp(targetTriple.c_str(), "powerpc-apple-", 14) == 0) {
+ args.push_back("-arch");
+ args.push_back("ppc");
+ }
+ else if (strncmp(targetTriple.c_str(), "powerpc64-apple-", 16) == 0) {
+ args.push_back("-arch");
+ args.push_back("ppc64");
+ }
+ else if (strncmp(targetTriple.c_str(), "arm-apple-", 10) == 0) {
+ args.push_back("-arch");
+ args.push_back("arm");
+ }
+ else if ((strncmp(targetTriple.c_str(), "armv4t-apple-", 13) == 0) ||
+ (strncmp(targetTriple.c_str(), "thumbv4t-apple-", 15) == 0)) {
+ args.push_back("-arch");
+ args.push_back("armv4t");
+ }
+ else if ((strncmp(targetTriple.c_str(), "armv5-apple-", 12) == 0) ||
+ (strncmp(targetTriple.c_str(), "armv5e-apple-", 13) == 0) ||
+ (strncmp(targetTriple.c_str(), "thumbv5-apple-", 14) == 0) ||
+ (strncmp(targetTriple.c_str(), "thumbv5e-apple-", 15) == 0)) {
+ args.push_back("-arch");
+ args.push_back("armv5");
+ }
+ else if ((strncmp(targetTriple.c_str(), "armv6-apple-", 12) == 0) ||
+ (strncmp(targetTriple.c_str(), "thumbv6-apple-", 14) == 0)) {
+ args.push_back("-arch");
+ args.push_back("armv6");
+ }
+ }
+ args.push_back("-c");
+ args.push_back("-x");
+ args.push_back("assembler");
+ args.push_back("-o");
+ args.push_back(objPath.c_str());
+ args.push_back(asmPath.c_str());
+ args.push_back(0);
+
+ // invoke assembler
+ if ( sys::Program::ExecuteAndWait(gcc, &args[0], 0, 0, 0, 0, &errMsg) ) {
+ errMsg = "error in assembly";
+ return true;
+ }
+ return false; // success
+}
+
+
+
+bool LTOCodeGenerator::determineTarget(std::string& errMsg)
+{
+ if ( _target == NULL ) {
+ // create target machine from info for merged modules
+ Module* mergedModule = _linker.getModule();
+ const TargetMachineRegistry::entry* march =
+ TargetMachineRegistry::getClosestStaticTargetForModule(
+ *mergedModule, errMsg);
+ if ( march == NULL )
+ return true;
+
+ // construct LTModule, hand over ownership of module and target
+ std::string FeatureStr =
+ getFeatureString(_linker.getModule()->getTargetTriple().c_str());
+ _target = march->CtorFn(*mergedModule, FeatureStr.c_str());
+ }
+ return false;
+}
+
+void LTOCodeGenerator::applyScopeRestrictions()
+{
+ if ( !_scopeRestrictionsDone ) {
+ Module* mergedModule = _linker.getModule();
+
+ // Start off with a verification pass.
+ PassManager passes;
+ passes.add(createVerifierPass());
+
+ // mark which symbols can not be internalized
+ if ( !_mustPreserveSymbols.empty() ) {
+ Mangler mangler(*mergedModule,
+ _target->getTargetAsmInfo()->getGlobalPrefix());
+ std::vector<const char*> mustPreserveList;
+ for (Module::iterator f = mergedModule->begin(),
+ e = mergedModule->end(); f != e; ++f) {
+ if ( !f->isDeclaration()
+ && _mustPreserveSymbols.count(mangler.getValueName(f)) )
+ mustPreserveList.push_back(::strdup(f->getName().c_str()));
+ }
+ for (Module::global_iterator v = mergedModule->global_begin(),
+ e = mergedModule->global_end(); v != e; ++v) {
+ if ( !v->isDeclaration()
+ && _mustPreserveSymbols.count(mangler.getValueName(v)) )
+ mustPreserveList.push_back(::strdup(v->getName().c_str()));
+ }
+ passes.add(createInternalizePass(mustPreserveList));
+ }
+ // apply scope restrictions
+ passes.run(*mergedModule);
+
+ _scopeRestrictionsDone = true;
+ }
+}
+
+/// Optimize merged modules using various IPO passes
+bool LTOCodeGenerator::generateAssemblyCode(raw_ostream& out,
+ std::string& errMsg)
+{
+ if ( this->determineTarget(errMsg) )
+ return true;
+
+ // mark which symbols can not be internalized
+ this->applyScopeRestrictions();
+
+ Module* mergedModule = _linker.getModule();
+
+ // If target supports exception handling then enable it now.
+ if ( _target->getTargetAsmInfo()->doesSupportExceptionHandling() )
+ llvm::ExceptionHandling = true;
+
+ // set codegen model
+ switch( _codeModel ) {
+ case LTO_CODEGEN_PIC_MODEL_STATIC:
+ _target->setRelocationModel(Reloc::Static);
+ break;
+ case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
+ _target->setRelocationModel(Reloc::PIC_);
+ break;
+ case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
+ _target->setRelocationModel(Reloc::DynamicNoPIC);
+ break;
+ }
+
+ // if options were requested, set them
+ if ( !_codegenOptions.empty() )
+ cl::ParseCommandLineOptions(_codegenOptions.size(),
+ (char**)&_codegenOptions[0]);
+
+ // Instantiate the pass manager to organize the passes.
+ PassManager passes;
+
+ // Start off with a verification pass.
+ passes.add(createVerifierPass());
+
+ // Add an appropriate TargetData instance for this module...
+ passes.add(new TargetData(*_target->getTargetData()));
+
+ // Propagate constants at call sites into the functions they call. This
+ // opens opportunities for globalopt (and inlining) by substituting function
+ // pointers passed as arguments to direct uses of functions.
+ passes.add(createIPSCCPPass());
+
+ // Now that we internalized some globals, see if we can hack on them!
+ passes.add(createGlobalOptimizerPass());
+
+ // Linking modules together can lead to duplicated global constants, only
+ // keep one copy of each constant...
+ passes.add(createConstantMergePass());
+
+ // Remove unused arguments from functions...
+ passes.add(createDeadArgEliminationPass());
+
+ // Reduce the code after globalopt and ipsccp. Both can open up significant
+ // simplification opportunities, and both can propagate functions through
+ // function pointers. When this happens, we often have to resolve varargs
+ // calls, etc, so let instcombine do this.
+ passes.add(createInstructionCombiningPass());
+ if (!DisableInline)
+ passes.add(createFunctionInliningPass()); // Inline small functions
+ passes.add(createPruneEHPass()); // Remove dead EH info
+ passes.add(createGlobalDCEPass()); // Remove dead functions
+
+ // If we didn't decide to inline a function, check to see if we can
+ // transform it to pass arguments by value instead of by reference.
+ passes.add(createArgumentPromotionPass());
+
+ // The IPO passes may leave cruft around. Clean up after them.
+ passes.add(createInstructionCombiningPass());
+ passes.add(createJumpThreadingPass()); // Thread jumps.
+ passes.add(createScalarReplAggregatesPass()); // Break up allocas
+
+ // Run a few AA driven optimizations here and now, to cleanup the code.
+ passes.add(createFunctionAttrsPass()); // Add nocapture
+ passes.add(createGlobalsModRefPass()); // IP alias analysis
+ passes.add(createLICMPass()); // Hoist loop invariants
+ passes.add(createGVNPass()); // Remove common subexprs
+ passes.add(createMemCpyOptPass()); // Remove dead memcpy's
+ passes.add(createDeadStoreEliminationPass()); // Nuke dead stores
+
+ // Cleanup and simplify the code after the scalar optimizations.
+ passes.add(createInstructionCombiningPass());
+ passes.add(createJumpThreadingPass()); // Thread jumps.
+ passes.add(createPromoteMemoryToRegisterPass()); // Cleanup after threading.
+
+
+ // Delete basic blocks, which optimization passes may have killed...
+ passes.add(createCFGSimplificationPass());
+
+ // Now that we have optimized the program, discard unreachable functions...
+ passes.add(createGlobalDCEPass());
+
+ // Make sure everything is still good.
+ passes.add(createVerifierPass());
+
+ FunctionPassManager* codeGenPasses =
+ new FunctionPassManager(new ExistingModuleProvider(mergedModule));
+
+ codeGenPasses->add(new TargetData(*_target->getTargetData()));
+
+ MachineCodeEmitter* mce = NULL;
+
+ switch (_target->addPassesToEmitFile(*codeGenPasses, out,
+ TargetMachine::AssemblyFile,
+ CodeGenOpt::Aggressive)) {
+ case FileModel::MachOFile:
+ mce = AddMachOWriter(*codeGenPasses, out, *_target);
+ break;
+ case FileModel::ElfFile:
+ mce = AddELFWriter(*codeGenPasses, out, *_target);
+ break;
+ case FileModel::AsmFile:
+ break;
+ case FileModel::Error:
+ case FileModel::None:
+ errMsg = "target file type not supported";
+ return true;
+ }
+
+ if (_target->addPassesToEmitFileFinish(*codeGenPasses, mce,
+ CodeGenOpt::Aggressive)) {
+ errMsg = "target does not support generation of this file type";
+ return true;
+ }
+
+ // Run our queue of passes all at once now, efficiently.
+ passes.run(*mergedModule);
+
+ // Run the code generator, and write assembly file
+ codeGenPasses->doInitialization();
+
+ for (Module::iterator
+ it = mergedModule->begin(), e = mergedModule->end(); it != e; ++it)
+ if (!it->isDeclaration())
+ codeGenPasses->run(*it);
+
+ codeGenPasses->doFinalization();
+ return false; // success
+}
+
+
+/// Optimize merged modules using various IPO passes
+void LTOCodeGenerator::setCodeGenDebugOptions(const char* options)
+{
+ std::string ops(options);
+ for (std::string o = getToken(ops); !o.empty(); o = getToken(ops)) {
+ // ParseCommandLineOptions() expects argv[0] to be program name.
+ // Lazily add that.
+ if ( _codegenOptions.empty() )
+ _codegenOptions.push_back("libLTO");
+ _codegenOptions.push_back(strdup(o.c_str()));
+ }
+}
diff --git a/tools/lto/LTOCodeGenerator.h b/tools/lto/LTOCodeGenerator.h
new file mode 100644
index 0000000..57398b0
--- /dev/null
+++ b/tools/lto/LTOCodeGenerator.h
@@ -0,0 +1,67 @@
+//===-LTOCodeGenerator.h - LLVM Link Time Optimizer -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the LTOCodeGenerator class.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef LTO_CODE_GENERATOR_H
+#define LTO_CODE_GENERATOR_H
+
+#include "llvm/Linker.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/SmallVector.h"
+
+#include <string>
+
+
+//
+// C++ class which implements the opaque lto_code_gen_t
+//
+
+class LTOCodeGenerator {
+public:
+ static const char* getVersionString();
+
+ LTOCodeGenerator();
+ ~LTOCodeGenerator();
+
+ bool addModule(class LTOModule*, std::string& errMsg);
+ bool setDebugInfo(lto_debug_model, std::string& errMsg);
+ bool setCodePICModel(lto_codegen_model, std::string& errMsg);
+ void setGccPath(const char* path);
+ void addMustPreserveSymbol(const char* sym);
+ bool writeMergedModules(const char* path,
+ std::string& errMsg);
+ const void* compile(size_t* length, std::string& errMsg);
+ void setCodeGenDebugOptions(const char *opts);
+private:
+ bool generateAssemblyCode(llvm::raw_ostream& out,
+ std::string& errMsg);
+ bool assemble(const std::string& asmPath,
+ const std::string& objPath, std::string& errMsg);
+ void applyScopeRestrictions();
+ bool determineTarget(std::string& errMsg);
+
+ typedef llvm::StringMap<uint8_t> StringSet;
+
+ llvm::Linker _linker;
+ llvm::TargetMachine* _target;
+ bool _emitDwarfDebugInfo;
+ bool _scopeRestrictionsDone;
+ lto_codegen_model _codeModel;
+ StringSet _mustPreserveSymbols;
+ llvm::MemoryBuffer* _nativeObjectFile;
+ std::vector<const char*> _codegenOptions;
+ llvm::sys::Path* _gccPath;
+};
+
+#endif // LTO_CODE_GENERATOR_H
+
diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp
new file mode 100644
index 0000000..939d0ea
--- /dev/null
+++ b/tools/lto/LTOModule.cpp
@@ -0,0 +1,538 @@
+//===-LTOModule.cpp - LLVM Link Time Optimizer ----------------------------===//
+//
+// 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 Link Time Optimization library. This library is
+// intended to be used by linker to optimize code at link time.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LTOModule.h"
+
+#include "llvm/Constants.h"
+#include "llvm/Module.h"
+#include "llvm/ModuleProvider.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Support/SystemUtils.h"
+#include "llvm/Support/Mangler.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/System/Path.h"
+#include "llvm/System/Process.h"
+#include "llvm/Target/SubtargetFeature.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetMachineRegistry.h"
+#include "llvm/Target/TargetAsmInfo.h"
+
+#include <fstream>
+
+using namespace llvm;
+
+bool LTOModule::isBitcodeFile(const void* mem, size_t length)
+{
+ return ( llvm::sys::IdentifyFileType((char*)mem, length)
+ == llvm::sys::Bitcode_FileType );
+}
+
+bool LTOModule::isBitcodeFile(const char* path)
+{
+ return llvm::sys::Path(path).isBitcodeFile();
+}
+
+bool LTOModule::isBitcodeFileForTarget(const void* mem, size_t length,
+ const char* triplePrefix)
+{
+ MemoryBuffer* buffer = makeBuffer(mem, length);
+ if ( buffer == NULL )
+ return false;
+ return isTargetMatch(buffer, triplePrefix);
+}
+
+
+bool LTOModule::isBitcodeFileForTarget(const char* path,
+ const char* triplePrefix)
+{
+ MemoryBuffer *buffer = MemoryBuffer::getFile(path);
+ if (buffer == NULL)
+ return false;
+ return isTargetMatch(buffer, triplePrefix);
+}
+
+// takes ownership of buffer
+bool LTOModule::isTargetMatch(MemoryBuffer* buffer, const char* triplePrefix)
+{
+ OwningPtr<ModuleProvider> mp(getBitcodeModuleProvider(buffer));
+ // on success, mp owns buffer and both are deleted at end of this method
+ if ( !mp ) {
+ delete buffer;
+ return false;
+ }
+ std::string actualTarget = mp->getModule()->getTargetTriple();
+ return ( strncmp(actualTarget.c_str(), triplePrefix,
+ strlen(triplePrefix)) == 0);
+}
+
+
+LTOModule::LTOModule(Module* m, TargetMachine* t)
+ : _module(m), _target(t), _symbolsParsed(false)
+{
+}
+
+LTOModule* LTOModule::makeLTOModule(const char* path, std::string& errMsg)
+{
+ OwningPtr<MemoryBuffer> buffer(MemoryBuffer::getFile(path, &errMsg));
+ if ( !buffer )
+ return NULL;
+ return makeLTOModule(buffer.get(), errMsg);
+}
+
+/// makeBuffer - create a MemoryBuffer from a memory range.
+/// MemoryBuffer requires the byte past end of the buffer to be a zero.
+/// We might get lucky and already be that way, otherwise make a copy.
+/// Also if next byte is on a different page, don't assume it is readable.
+MemoryBuffer* LTOModule::makeBuffer(const void* mem, size_t length)
+{
+ const char* startPtr = (char*)mem;
+ const char* endPtr = startPtr+length;
+ if ( (((uintptr_t)endPtr & (sys::Process::GetPageSize()-1)) == 0)
+ || (*endPtr != 0) )
+ return MemoryBuffer::getMemBufferCopy(startPtr, endPtr);
+ else
+ return MemoryBuffer::getMemBuffer(startPtr, endPtr);
+}
+
+
+LTOModule* LTOModule::makeLTOModule(const void* mem, size_t length,
+ std::string& errMsg)
+{
+ OwningPtr<MemoryBuffer> buffer(makeBuffer(mem, length));
+ if ( !buffer )
+ return NULL;
+ return makeLTOModule(buffer.get(), errMsg);
+}
+
+/// getFeatureString - Return a string listing the features associated with the
+/// target triple.
+///
+/// FIXME: This is an inelegant way of specifying the features of a
+/// subtarget. It would be better if we could encode this information into the
+/// IR. See <rdar://5972456>.
+std::string getFeatureString(const char *TargetTriple) {
+ SubtargetFeatures Features;
+
+ if (strncmp(TargetTriple, "powerpc-apple-", 14) == 0) {
+ Features.AddFeature("altivec", true);
+ } else if (strncmp(TargetTriple, "powerpc64-apple-", 16) == 0) {
+ Features.AddFeature("64bit", true);
+ Features.AddFeature("altivec", true);
+ }
+
+ return Features.getString();
+}
+
+LTOModule* LTOModule::makeLTOModule(MemoryBuffer* buffer, std::string& errMsg)
+{
+ // parse bitcode buffer
+ OwningPtr<Module> m(ParseBitcodeFile(buffer, &errMsg));
+ if ( !m )
+ return NULL;
+ // find machine architecture for this module
+ const TargetMachineRegistry::entry* march =
+ TargetMachineRegistry::getClosestStaticTargetForModule(*m, errMsg);
+
+ if ( march == NULL )
+ return NULL;
+
+ // construct LTModule, hand over ownership of module and target
+ std::string FeatureStr = getFeatureString(m->getTargetTriple().c_str());
+ TargetMachine* target = march->CtorFn(*m, FeatureStr);
+ return new LTOModule(m.take(), target);
+}
+
+
+const char* LTOModule::getTargetTriple()
+{
+ return _module->getTargetTriple().c_str();
+}
+
+void LTOModule::addDefinedFunctionSymbol(Function* f, Mangler &mangler)
+{
+ // add to list of defined symbols
+ addDefinedSymbol(f, mangler, true);
+
+ // add external symbols referenced by this function.
+ for (Function::iterator b = f->begin(); b != f->end(); ++b) {
+ for (BasicBlock::iterator i = b->begin(); i != b->end(); ++i) {
+ for (unsigned count = 0, total = i->getNumOperands();
+ count != total; ++count) {
+ findExternalRefs(i->getOperand(count), mangler);
+ }
+ }
+ }
+}
+
+// get string that data pointer points to
+bool LTOModule::objcClassNameFromExpression(Constant* c, std::string& name)
+{
+ if (ConstantExpr* ce = dyn_cast<ConstantExpr>(c)) {
+ Constant* op = ce->getOperand(0);
+ if (GlobalVariable* gvn = dyn_cast<GlobalVariable>(op)) {
+ Constant* cn = gvn->getInitializer();
+ if (ConstantArray* ca = dyn_cast<ConstantArray>(cn)) {
+ if ( ca->isCString() ) {
+ name = ".objc_class_name_" + ca->getAsString();
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+// parse i386/ppc ObjC class data structure
+void LTOModule::addObjCClass(GlobalVariable* clgv)
+{
+ if (ConstantStruct* c = dyn_cast<ConstantStruct>(clgv->getInitializer())) {
+ // second slot in __OBJC,__class is pointer to superclass name
+ std::string superclassName;
+ if ( objcClassNameFromExpression(c->getOperand(1), superclassName) ) {
+ NameAndAttributes info;
+ if ( _undefines.find(superclassName.c_str()) == _undefines.end() ) {
+ const char* symbolName = ::strdup(superclassName.c_str());
+ info.name = ::strdup(symbolName);
+ info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
+ // string is owned by _undefines
+ _undefines[info.name] = info;
+ }
+ }
+ // third slot in __OBJC,__class is pointer to class name
+ std::string className;
+ if ( objcClassNameFromExpression(c->getOperand(2), className) ) {
+ const char* symbolName = ::strdup(className.c_str());
+ NameAndAttributes info;
+ info.name = symbolName;
+ info.attributes = (lto_symbol_attributes)
+ (LTO_SYMBOL_PERMISSIONS_DATA |
+ LTO_SYMBOL_DEFINITION_REGULAR |
+ LTO_SYMBOL_SCOPE_DEFAULT);
+ _symbols.push_back(info);
+ _defines[info.name] = 1;
+ }
+ }
+}
+
+
+// parse i386/ppc ObjC category data structure
+void LTOModule::addObjCCategory(GlobalVariable* clgv)
+{
+ if (ConstantStruct* c = dyn_cast<ConstantStruct>(clgv->getInitializer())) {
+ // second slot in __OBJC,__category is pointer to target class name
+ std::string targetclassName;
+ if ( objcClassNameFromExpression(c->getOperand(1), targetclassName) ) {
+ NameAndAttributes info;
+ if ( _undefines.find(targetclassName.c_str()) == _undefines.end() ){
+ const char* symbolName = ::strdup(targetclassName.c_str());
+ info.name = ::strdup(symbolName);
+ info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
+ // string is owned by _undefines
+ _undefines[info.name] = info;
+ }
+ }
+ }
+}
+
+
+// parse i386/ppc ObjC class list data structure
+void LTOModule::addObjCClassRef(GlobalVariable* clgv)
+{
+ std::string targetclassName;
+ if ( objcClassNameFromExpression(clgv->getInitializer(), targetclassName) ){
+ NameAndAttributes info;
+ if ( _undefines.find(targetclassName.c_str()) == _undefines.end() ) {
+ const char* symbolName = ::strdup(targetclassName.c_str());
+ info.name = ::strdup(symbolName);
+ info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
+ // string is owned by _undefines
+ _undefines[info.name] = info;
+ }
+ }
+}
+
+
+void LTOModule::addDefinedDataSymbol(GlobalValue* v, Mangler& mangler)
+{
+ // add to list of defined symbols
+ addDefinedSymbol(v, mangler, false);
+
+ // Special case i386/ppc ObjC data structures in magic sections:
+ // The issue is that the old ObjC object format did some strange
+ // contortions to avoid real linker symbols. For instance, the
+ // ObjC class data structure is allocated statically in the executable
+ // that defines that class. That data structures contains a pointer to
+ // its superclass. But instead of just initializing that part of the
+ // struct to the address of its superclass, and letting the static and
+ // dynamic linkers do the rest, the runtime works by having that field
+ // instead point to a C-string that is the name of the superclass.
+ // At runtime the objc initialization updates that pointer and sets
+ // it to point to the actual super class. As far as the linker
+ // knows it is just a pointer to a string. But then someone wanted the
+ // linker to issue errors at build time if the superclass was not found.
+ // So they figured out a way in mach-o object format to use an absolute
+ // symbols (.objc_class_name_Foo = 0) and a floating reference
+ // (.reference .objc_class_name_Bar) to cause the linker into erroring when
+ // a class was missing.
+ // The following synthesizes the implicit .objc_* symbols for the linker
+ // from the ObjC data structures generated by the front end.
+ if ( v->hasSection() /* && isTargetDarwin */ ) {
+ // special case if this data blob is an ObjC class definition
+ if ( v->getSection().compare(0, 15, "__OBJC,__class,") == 0 ) {
+ if (GlobalVariable* gv = dyn_cast<GlobalVariable>(v)) {
+ addObjCClass(gv);
+ }
+ }
+
+ // special case if this data blob is an ObjC category definition
+ else if ( v->getSection().compare(0, 18, "__OBJC,__category,") == 0 ) {
+ if (GlobalVariable* gv = dyn_cast<GlobalVariable>(v)) {
+ addObjCCategory(gv);
+ }
+ }
+
+ // special case if this data blob is the list of referenced classes
+ else if ( v->getSection().compare(0, 18, "__OBJC,__cls_refs,") == 0 ) {
+ if (GlobalVariable* gv = dyn_cast<GlobalVariable>(v)) {
+ addObjCClassRef(gv);
+ }
+ }
+ }
+
+ // add external symbols referenced by this data.
+ for (unsigned count = 0, total = v->getNumOperands();
+ count != total; ++count) {
+ findExternalRefs(v->getOperand(count), mangler);
+ }
+}
+
+
+void LTOModule::addDefinedSymbol(GlobalValue* def, Mangler &mangler,
+ bool isFunction)
+{
+ // ignore all llvm.* symbols
+ if ( strncmp(def->getNameStart(), "llvm.", 5) == 0 )
+ return;
+
+ // string is owned by _defines
+ const char* symbolName = ::strdup(mangler.getValueName(def).c_str());
+
+ // set alignment part log2() can have rounding errors
+ uint32_t align = def->getAlignment();
+ uint32_t attr = align ? CountTrailingZeros_32(def->getAlignment()) : 0;
+
+ // set permissions part
+ if ( isFunction )
+ attr |= LTO_SYMBOL_PERMISSIONS_CODE;
+ else {
+ GlobalVariable* gv = dyn_cast<GlobalVariable>(def);
+ if ( (gv != NULL) && gv->isConstant() )
+ attr |= LTO_SYMBOL_PERMISSIONS_RODATA;
+ else
+ attr |= LTO_SYMBOL_PERMISSIONS_DATA;
+ }
+
+ // set definition part
+ if ( def->hasWeakLinkage() || def->hasLinkOnceLinkage() ) {
+ attr |= LTO_SYMBOL_DEFINITION_WEAK;
+ }
+ else if ( def->hasCommonLinkage()) {
+ attr |= LTO_SYMBOL_DEFINITION_TENTATIVE;
+ }
+ else {
+ attr |= LTO_SYMBOL_DEFINITION_REGULAR;
+ }
+
+ // set scope part
+ if ( def->hasHiddenVisibility() )
+ attr |= LTO_SYMBOL_SCOPE_HIDDEN;
+ else if ( def->hasProtectedVisibility() )
+ attr |= LTO_SYMBOL_SCOPE_PROTECTED;
+ else if ( def->hasExternalLinkage() || def->hasWeakLinkage()
+ || def->hasLinkOnceLinkage() || def->hasCommonLinkage() )
+ attr |= LTO_SYMBOL_SCOPE_DEFAULT;
+ else
+ attr |= LTO_SYMBOL_SCOPE_INTERNAL;
+
+ // add to table of symbols
+ NameAndAttributes info;
+ info.name = symbolName;
+ info.attributes = (lto_symbol_attributes)attr;
+ _symbols.push_back(info);
+ _defines[info.name] = 1;
+}
+
+void LTOModule::addAsmGlobalSymbol(const char *name) {
+ // only add new define if not already defined
+ if ( _defines.count(name, &name[strlen(name)+1]) == 0 )
+ return;
+
+ // string is owned by _defines
+ const char *symbolName = ::strdup(name);
+ uint32_t attr = LTO_SYMBOL_DEFINITION_REGULAR;
+ attr |= LTO_SYMBOL_SCOPE_DEFAULT;
+ NameAndAttributes info;
+ info.name = symbolName;
+ info.attributes = (lto_symbol_attributes)attr;
+ _symbols.push_back(info);
+ _defines[info.name] = 1;
+}
+
+void LTOModule::addPotentialUndefinedSymbol(GlobalValue* decl, Mangler &mangler)
+{
+ // ignore all llvm.* symbols
+ if ( strncmp(decl->getNameStart(), "llvm.", 5) == 0 )
+ return;
+
+ const char* name = mangler.getValueName(decl).c_str();
+
+ // we already have the symbol
+ if (_undefines.find(name) != _undefines.end())
+ return;
+
+ NameAndAttributes info;
+ // string is owned by _undefines
+ info.name = ::strdup(name);
+ if (decl->hasExternalWeakLinkage())
+ info.attributes = LTO_SYMBOL_DEFINITION_WEAKUNDEF;
+ else
+ info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
+ _undefines[name] = info;
+}
+
+
+
+// Find exeternal symbols referenced by VALUE. This is a recursive function.
+void LTOModule::findExternalRefs(Value* value, Mangler &mangler) {
+
+ if (GlobalValue* gv = dyn_cast<GlobalValue>(value)) {
+ if ( !gv->hasExternalLinkage() )
+ addPotentialUndefinedSymbol(gv, mangler);
+ // If this is a variable definition, do not recursively process
+ // initializer. It might contain a reference to this variable
+ // and cause an infinite loop. The initializer will be
+ // processed in addDefinedDataSymbol().
+ return;
+ }
+
+ // GlobalValue, even with InternalLinkage type, may have operands with
+ // ExternalLinkage type. Do not ignore these operands.
+ if (Constant* c = dyn_cast<Constant>(value)) {
+ // Handle ConstantExpr, ConstantStruct, ConstantArry etc..
+ for (unsigned i = 0, e = c->getNumOperands(); i != e; ++i)
+ findExternalRefs(c->getOperand(i), mangler);
+ }
+}
+
+void LTOModule::lazyParseSymbols()
+{
+ if ( !_symbolsParsed ) {
+ _symbolsParsed = true;
+
+ // Use mangler to add GlobalPrefix to names to match linker names.
+ Mangler mangler(*_module, _target->getTargetAsmInfo()->getGlobalPrefix());
+ // add chars used in ObjC method names so method names aren't mangled
+ mangler.markCharAcceptable('[');
+ mangler.markCharAcceptable(']');
+ mangler.markCharAcceptable('(');
+ mangler.markCharAcceptable(')');
+ mangler.markCharAcceptable('-');
+ mangler.markCharAcceptable('+');
+ mangler.markCharAcceptable(' ');
+
+ // add functions
+ for (Module::iterator f = _module->begin(); f != _module->end(); ++f) {
+ if ( f->isDeclaration() )
+ addPotentialUndefinedSymbol(f, mangler);
+ else
+ addDefinedFunctionSymbol(f, mangler);
+ }
+
+ // add data
+ for (Module::global_iterator v = _module->global_begin(),
+ e = _module->global_end(); v != e; ++v) {
+ if ( v->isDeclaration() )
+ addPotentialUndefinedSymbol(v, mangler);
+ else
+ addDefinedDataSymbol(v, mangler);
+ }
+
+ // add asm globals
+ const std::string &inlineAsm = _module->getModuleInlineAsm();
+ const std::string glbl = ".globl";
+ std::string asmSymbolName;
+ std::string::size_type pos = inlineAsm.find(glbl, 0);
+ while (pos != std::string::npos) {
+ // eat .globl
+ pos = pos + 6;
+
+ // skip white space between .globl and symbol name
+ std::string::size_type pbegin = inlineAsm.find_first_not_of(' ', pos);
+ if (pbegin == std::string::npos)
+ break;
+
+ // find end-of-line
+ std::string::size_type pend = inlineAsm.find_first_of('\n', pbegin);
+ if (pend == std::string::npos)
+ break;
+
+ asmSymbolName.assign(inlineAsm, pbegin, pend - pbegin);
+ addAsmGlobalSymbol(asmSymbolName.c_str());
+
+ // search next .globl
+ pos = inlineAsm.find(glbl, pend);
+ }
+
+ // make symbols for all undefines
+ for (StringMap<NameAndAttributes>::iterator it=_undefines.begin();
+ it != _undefines.end(); ++it) {
+ // if this symbol also has a definition, then don't make an undefine
+ // because it is a tentative definition
+ if ( _defines.count(it->getKeyData(), it->getKeyData()+
+ it->getKeyLength()) == 0 ) {
+ NameAndAttributes info = it->getValue();
+ _symbols.push_back(info);
+ }
+ }
+ }
+}
+
+
+uint32_t LTOModule::getSymbolCount()
+{
+ lazyParseSymbols();
+ return _symbols.size();
+}
+
+
+lto_symbol_attributes LTOModule::getSymbolAttributes(uint32_t index)
+{
+ lazyParseSymbols();
+ if ( index < _symbols.size() )
+ return _symbols[index].attributes;
+ else
+ return lto_symbol_attributes(0);
+}
+
+const char* LTOModule::getSymbolName(uint32_t index)
+{
+ lazyParseSymbols();
+ if ( index < _symbols.size() )
+ return _symbols[index].name;
+ else
+ return NULL;
+}
+
diff --git a/tools/lto/LTOModule.h b/tools/lto/LTOModule.h
new file mode 100644
index 0000000..9de02a2
--- /dev/null
+++ b/tools/lto/LTOModule.h
@@ -0,0 +1,112 @@
+//===-LTOModule.h - LLVM Link Time Optimizer ------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the LTOModule class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LTO_MODULE_H
+#define LTO_MODULE_H
+
+#include "llvm/Module.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/ADT/StringMap.h"
+
+#include "llvm-c/lto.h"
+
+#include <vector>
+#include <string>
+
+
+// forward references to llvm classes
+namespace llvm {
+ class Mangler;
+ class MemoryBuffer;
+ class GlobalValue;
+ class Value;
+ class Function;
+}
+
+
+//
+// C++ class which implements the opaque lto_module_t
+//
+class LTOModule {
+public:
+
+ static bool isBitcodeFile(const void* mem, size_t length);
+ static bool isBitcodeFile(const char* path);
+
+ static bool isBitcodeFileForTarget(const void* mem,
+ size_t length, const char* triplePrefix);
+
+ static bool isBitcodeFileForTarget(const char* path,
+ const char* triplePrefix);
+
+ static LTOModule* makeLTOModule(const char* path, std::string& errMsg);
+ static LTOModule* makeLTOModule(const void* mem, size_t length,
+ std::string& errMsg);
+
+ const char* getTargetTriple();
+ uint32_t getSymbolCount();
+ lto_symbol_attributes getSymbolAttributes(uint32_t index);
+ const char* getSymbolName(uint32_t index);
+
+ llvm::Module * getLLVVMModule() { return _module.get(); }
+
+private:
+ LTOModule(llvm::Module* m, llvm::TargetMachine* t);
+
+ void lazyParseSymbols();
+ void addDefinedSymbol(llvm::GlobalValue* def,
+ llvm::Mangler& mangler,
+ bool isFunction);
+ void addPotentialUndefinedSymbol(llvm::GlobalValue* decl,
+ llvm::Mangler &mangler);
+ void findExternalRefs(llvm::Value* value,
+ llvm::Mangler& mangler);
+ void addDefinedFunctionSymbol(llvm::Function* f,
+ llvm::Mangler &mangler);
+ void addDefinedDataSymbol(llvm::GlobalValue* v,
+ llvm::Mangler &mangler);
+ void addAsmGlobalSymbol(const char *);
+ void addObjCClass(llvm::GlobalVariable* clgv);
+ void addObjCCategory(llvm::GlobalVariable* clgv);
+ void addObjCClassRef(llvm::GlobalVariable* clgv);
+ bool objcClassNameFromExpression(llvm::Constant* c,
+ std::string& name);
+
+ static bool isTargetMatch(llvm::MemoryBuffer* memBuffer,
+ const char* triplePrefix);
+
+ static LTOModule* makeLTOModule(llvm::MemoryBuffer* buffer,
+ std::string& errMsg);
+ static llvm::MemoryBuffer* makeBuffer(const void* mem, size_t length);
+
+ typedef llvm::StringMap<uint8_t> StringSet;
+
+ struct NameAndAttributes {
+ const char* name;
+ lto_symbol_attributes attributes;
+ };
+
+ llvm::OwningPtr<llvm::Module> _module;
+ llvm::OwningPtr<llvm::TargetMachine> _target;
+ bool _symbolsParsed;
+ std::vector<NameAndAttributes> _symbols;
+ // _defines and _undefines only needed to disambiguate tentative definitions
+ StringSet _defines;
+ llvm::StringMap<NameAndAttributes> _undefines;
+};
+
+extern std::string getFeatureString(const char *TargetTriple);
+
+#endif // LTO_MODULE_H
+
diff --git a/tools/lto/Makefile b/tools/lto/Makefile
new file mode 100644
index 0000000..f0f6da7
--- /dev/null
+++ b/tools/lto/Makefile
@@ -0,0 +1,47 @@
+##===- tools/lto/Makefile ----------------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+LIBRARYNAME = LTO
+
+# Include this here so we can get the configuration of the targets
+# that have been configured for construction. We have to do this
+# early so we can set up LINK_COMPONENTS before including Makefile.rules
+include $(LEVEL)/Makefile.config
+
+LINK_LIBS_IN_SHARED = 1
+SHARED_LIBRARY = 1
+DONT_BUILD_RELINKED = 1
+
+LINK_COMPONENTS := $(TARGETS_TO_BUILD) ipo scalaropts linker bitreader bitwriter
+
+include $(LEVEL)/Makefile.common
+
+ifeq ($(OS),Darwin)
+ # set dylib internal version number to llvmCore submission number
+ ifdef LLVM_SUBMIT_VERSION
+ LLVMLibsOptions := $(LLVMLibsOptions) -Wl,-current_version \
+ -Wl,$(LLVM_SUBMIT_VERSION).$(LLVM_SUBMIT_SUBVERSION) \
+ -Wl,-compatibility_version -Wl,1
+ endif
+ # extra options to override libtool defaults
+ LLVMLibsOptions := $(LLVMLibsOptions) \
+ -no-undefined -avoid-version \
+ -Wl,-exported_symbols_list -Wl,$(PROJ_SRC_DIR)/lto.exports \
+ -Wl,-dead_strip \
+ -Wl,-seg1addr -Wl,0xE0000000
+
+ # Mac OS X 10.4 and earlier tools do not allow a second -install_name on command line
+ DARWIN_VERS := $(shell echo $(TARGET_TRIPLE) | sed 's/.*darwin\([0-9]*\).*/\1/')
+ ifneq ($(DARWIN_VERS),8)
+ LLVMLibsOptions := $(LLVMLibsOptions) \
+ -Wl,-install_name \
+ -Wl,"@executable_path/../lib/lib$(LIBRARYNAME)$(SHLIBEXT)"
+ endif
+endif
diff --git a/tools/lto/lto.cpp b/tools/lto/lto.cpp
new file mode 100644
index 0000000..5c3f90a
--- /dev/null
+++ b/tools/lto/lto.cpp
@@ -0,0 +1,259 @@
+//===-lto.cpp - LLVM Link Time Optimizer ----------------------------------===//
+//
+// 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 Link Time Optimization library. This library is
+// intended to be used by linker to optimize code at link time.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm-c/lto.h"
+
+#include "LTOModule.h"
+#include "LTOCodeGenerator.h"
+
+
+// holds most recent error string
+// *** not thread safe ***
+static std::string sLastErrorString;
+
+
+
+//
+// returns a printable string
+//
+extern const char* lto_get_version()
+{
+ return LTOCodeGenerator::getVersionString();
+}
+
+//
+// returns the last error string or NULL if last operation was successful
+//
+const char* lto_get_error_message()
+{
+ return sLastErrorString.c_str();
+}
+
+
+
+//
+// validates if a file is a loadable object file
+//
+bool lto_module_is_object_file(const char* path)
+{
+ return LTOModule::isBitcodeFile(path);
+}
+
+
+//
+// validates if a file is a loadable object file compilable for requested target
+//
+bool lto_module_is_object_file_for_target(const char* path,
+ const char* target_triplet_prefix)
+{
+ return LTOModule::isBitcodeFileForTarget(path, target_triplet_prefix);
+}
+
+
+//
+// validates if a buffer is a loadable object file
+//
+bool lto_module_is_object_file_in_memory(const void* mem, size_t length)
+{
+ return LTOModule::isBitcodeFile(mem, length);
+}
+
+
+//
+// validates if a buffer is a loadable object file compilable for the target
+//
+bool lto_module_is_object_file_in_memory_for_target(const void* mem,
+ size_t length, const char* target_triplet_prefix)
+{
+ return LTOModule::isBitcodeFileForTarget(mem, length, target_triplet_prefix);
+}
+
+
+
+//
+// loads an object file from disk
+// returns NULL on error (check lto_get_error_message() for details)
+//
+lto_module_t lto_module_create(const char* path)
+{
+ return LTOModule::makeLTOModule(path, sLastErrorString);
+}
+
+
+//
+// loads an object file from memory
+// returns NULL on error (check lto_get_error_message() for details)
+//
+lto_module_t lto_module_create_from_memory(const void* mem, size_t length)
+{
+ return LTOModule::makeLTOModule(mem, length, sLastErrorString);
+}
+
+
+//
+// frees all memory for a module
+// upon return the lto_module_t is no longer valid
+//
+void lto_module_dispose(lto_module_t mod)
+{
+ delete mod;
+}
+
+
+//
+// returns triplet string which the object module was compiled under
+//
+const char* lto_module_get_target_triple(lto_module_t mod)
+{
+ return mod->getTargetTriple();
+}
+
+
+//
+// returns the number of symbols in the object module
+//
+uint32_t lto_module_get_num_symbols(lto_module_t mod)
+{
+ return mod->getSymbolCount();
+}
+
+//
+// returns the name of the ith symbol in the object module
+//
+const char* lto_module_get_symbol_name(lto_module_t mod, uint32_t index)
+{
+ return mod->getSymbolName(index);
+}
+
+
+//
+// returns the attributes of the ith symbol in the object module
+//
+lto_symbol_attributes lto_module_get_symbol_attribute(lto_module_t mod,
+ uint32_t index)
+{
+ return mod->getSymbolAttributes(index);
+}
+
+
+
+
+
+//
+// instantiates a code generator
+// returns NULL if there is an error
+//
+lto_code_gen_t lto_codegen_create()
+{
+ return new LTOCodeGenerator();
+}
+
+
+
+//
+// frees all memory for a code generator
+// upon return the lto_code_gen_t is no longer valid
+//
+void lto_codegen_dispose(lto_code_gen_t cg)
+{
+ delete cg;
+}
+
+
+
+//
+// add an object module to the set of modules for which code will be generated
+// returns true on error (check lto_get_error_message() for details)
+//
+bool lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod)
+{
+ return cg->addModule(mod, sLastErrorString);
+}
+
+
+//
+// sets what if any format of debug info should be generated
+// returns true on error (check lto_get_error_message() for details)
+//
+bool lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model debug)
+{
+ return cg->setDebugInfo(debug, sLastErrorString);
+}
+
+
+//
+// sets what code model to generated
+// returns true on error (check lto_get_error_message() for details)
+//
+bool lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model model)
+{
+ return cg->setCodePICModel(model, sLastErrorString);
+}
+
+//
+// sets the path to gcc
+//
+void lto_codegen_set_gcc_path(lto_code_gen_t cg, const char* path)
+{
+ cg->setGccPath(path);
+}
+
+//
+// adds to a list of all global symbols that must exist in the final
+// generated code. If a function is not listed there, it might be
+// inlined into every usage and optimized away.
+//
+void lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, const char* symbol)
+{
+ cg->addMustPreserveSymbol(symbol);
+}
+
+
+//
+// writes a new file at the specified path that contains the
+// merged contents of all modules added so far.
+// returns true on error (check lto_get_error_message() for details)
+//
+bool lto_codegen_write_merged_modules(lto_code_gen_t cg, const char* path)
+{
+ return cg->writeMergedModules(path, sLastErrorString);
+}
+
+
+//
+// Generates code for all added modules into one native object file.
+// On sucess returns a pointer to a generated mach-o/ELF buffer and
+// length set to the buffer size. The buffer is owned by the
+// lto_code_gen_t and will be freed when lto_codegen_dispose()
+// is called, or lto_codegen_compile() is called again.
+// On failure, returns NULL (check lto_get_error_message() for details).
+//
+extern const void*
+lto_codegen_compile(lto_code_gen_t cg, size_t* length)
+{
+ return cg->compile(length, sLastErrorString);
+}
+
+
+//
+// Used to pass extra options to the code generator
+//
+extern void
+lto_codegen_debug_options(lto_code_gen_t cg, const char * opt)
+{
+ cg->setCodeGenDebugOptions(opt);
+}
+
+
+
diff --git a/tools/lto/lto.exports b/tools/lto/lto.exports
new file mode 100644
index 0000000..aff7559
--- /dev/null
+++ b/tools/lto/lto.exports
@@ -0,0 +1,23 @@
+_lto_get_error_message
+_lto_get_version
+_lto_module_create
+_lto_module_create_from_memory
+_lto_module_get_num_symbols
+_lto_module_get_symbol_attribute
+_lto_module_get_symbol_name
+_lto_module_get_target_triple
+_lto_module_is_object_file
+_lto_module_is_object_file_for_target
+_lto_module_is_object_file_in_memory
+_lto_module_is_object_file_in_memory_for_target
+_lto_module_dispose
+_lto_codegen_add_module
+_lto_codegen_add_must_preserve_symbol
+_lto_codegen_compile
+_lto_codegen_create
+_lto_codegen_dispose
+_lto_codegen_set_debug_model
+_lto_codegen_set_pic_model
+_lto_codegen_write_merged_modules
+_lto_codegen_debug_options
+
diff --git a/tools/opt/AnalysisWrappers.cpp b/tools/opt/AnalysisWrappers.cpp
new file mode 100644
index 0000000..631a0dd
--- /dev/null
+++ b/tools/opt/AnalysisWrappers.cpp
@@ -0,0 +1,88 @@
+//===- AnalysisWrappers.cpp - Wrappers around non-pass analyses -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines pass wrappers around LLVM analyses that don't make sense to
+// be passes. It provides a nice standard pass interface to these classes so
+// that they can be printed out by analyze.
+//
+// These classes are separated out of analyze.cpp so that it is more clear which
+// code is the integral part of the analyze tool, and which part of the code is
+// just making it so more passes are available.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/CallSite.h"
+#include "llvm/Analysis/CallGraph.h"
+#include <iostream>
+using namespace llvm;
+
+namespace {
+ /// ExternalFunctionsPassedConstants - This pass prints out call sites to
+ /// external functions that are called with constant arguments. This can be
+ /// useful when looking for standard library functions we should constant fold
+ /// or handle in alias analyses.
+ struct ExternalFunctionsPassedConstants : public ModulePass {
+ static char ID; // Pass ID, replacement for typeid
+ ExternalFunctionsPassedConstants() : ModulePass(&ID) {}
+ virtual bool runOnModule(Module &M) {
+ for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
+ if (I->isDeclaration()) {
+ bool PrintedFn = false;
+ for (Value::use_iterator UI = I->use_begin(), E = I->use_end();
+ UI != E; ++UI)
+ if (Instruction *User = dyn_cast<Instruction>(*UI)) {
+ CallSite CS = CallSite::get(User);
+ if (CS.getInstruction()) {
+ for (CallSite::arg_iterator AI = CS.arg_begin(),
+ E = CS.arg_end(); AI != E; ++AI)
+ if (isa<Constant>(*AI)) {
+ if (!PrintedFn) {
+ std::cerr << "Function '" << I->getName() << "':\n";
+ PrintedFn = true;
+ }
+ std::cerr << *User;
+ break;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ }
+ };
+
+ char ExternalFunctionsPassedConstants::ID = 0;
+ RegisterPass<ExternalFunctionsPassedConstants>
+ P1("print-externalfnconstants",
+ "Print external fn callsites passed constants");
+
+ struct CallGraphPrinter : public ModulePass {
+ static char ID; // Pass ID, replacement for typeid
+ CallGraphPrinter() : ModulePass(&ID) {}
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ AU.addRequiredTransitive<CallGraph>();
+ }
+ virtual bool runOnModule(Module &M) {
+ getAnalysis<CallGraph>().print(std::cerr, &M);
+ return false;
+ }
+ };
+
+ char CallGraphPrinter::ID = 0;
+ RegisterPass<CallGraphPrinter>
+ P2("print-callgraph", "Print a call graph");
+}
diff --git a/tools/opt/CMakeLists.txt b/tools/opt/CMakeLists.txt
new file mode 100644
index 0000000..efcca80
--- /dev/null
+++ b/tools/opt/CMakeLists.txt
@@ -0,0 +1,9 @@
+set(LLVM_REQUIRES_EH 1)
+set(LLVM_LINK_COMPONENTS bitreader bitwriter instrumentation scalaropts ipo)
+
+add_llvm_tool(opt
+ AnalysisWrappers.cpp
+ GraphPrinters.cpp
+ PrintSCC.cpp
+ opt.cpp
+ )
diff --git a/tools/opt/GraphPrinters.cpp b/tools/opt/GraphPrinters.cpp
new file mode 100644
index 0000000..a52baf7
--- /dev/null
+++ b/tools/opt/GraphPrinters.cpp
@@ -0,0 +1,115 @@
+//===- GraphPrinters.cpp - DOT printers for various graph types -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines several printers for various different types of graphs used
+// by the LLVM infrastructure. It uses the generic graph interface to convert
+// the graph into a .dot graph. These graphs can then be processed with the
+// "dot" tool to convert them to postscript or some other suitable format.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/GraphWriter.h"
+#include "llvm/Pass.h"
+#include "llvm/Value.h"
+#include "llvm/Analysis/CallGraph.h"
+#include "llvm/Analysis/Dominators.h"
+#include <iostream>
+#include <fstream>
+using namespace llvm;
+
+template<typename GraphType>
+static void WriteGraphToFile(std::ostream &O, const std::string &GraphName,
+ const GraphType &GT) {
+ std::string Filename = GraphName + ".dot";
+ O << "Writing '" << Filename << "'...";
+ std::ofstream F(Filename.c_str());
+
+ if (F.good())
+ WriteGraph(F, GT);
+ else
+ O << " error opening file for writing!";
+ O << "\n";
+}
+
+
+//===----------------------------------------------------------------------===//
+// Call Graph Printer
+//===----------------------------------------------------------------------===//
+
+namespace llvm {
+ template<>
+ struct DOTGraphTraits<CallGraph*> : public DefaultDOTGraphTraits {
+ static std::string getGraphName(CallGraph *F) {
+ return "Call Graph";
+ }
+
+ static std::string getNodeLabel(CallGraphNode *Node, CallGraph *Graph) {
+ if (Node->getFunction())
+ return ((Value*)Node->getFunction())->getName();
+ else
+ return "Indirect call node";
+ }
+ };
+}
+
+
+namespace {
+ struct CallGraphPrinter : public ModulePass {
+ static char ID; // Pass ID, replacement for typeid
+ CallGraphPrinter() : ModulePass(&ID) {}
+
+ virtual bool runOnModule(Module &M) {
+ WriteGraphToFile(std::cerr, "callgraph", &getAnalysis<CallGraph>());
+ return false;
+ }
+
+ void print(std::ostream &OS) const {}
+ void print(std::ostream &OS, const llvm::Module*) const {}
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<CallGraph>();
+ AU.setPreservesAll();
+ }
+ };
+
+ char CallGraphPrinter::ID = 0;
+ RegisterPass<CallGraphPrinter> P2("dot-callgraph",
+ "Print Call Graph to 'dot' file");
+}
+
+//===----------------------------------------------------------------------===//
+// DomInfoPrinter Pass
+//===----------------------------------------------------------------------===//
+
+namespace {
+ class DomInfoPrinter : public FunctionPass {
+ public:
+ static char ID; // Pass identification, replacement for typeid
+ DomInfoPrinter() : FunctionPass(&ID) {}
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ AU.addRequired<DominatorTree>();
+ AU.addRequired<DominanceFrontier>();
+
+ }
+
+ virtual bool runOnFunction(Function &F) {
+ DominatorTree &DT = getAnalysis<DominatorTree>();
+ DT.dump();
+ DominanceFrontier &DF = getAnalysis<DominanceFrontier>();
+ DF.dump();
+ return false;
+ }
+ };
+
+ char DomInfoPrinter::ID = 0;
+ static RegisterPass<DomInfoPrinter>
+ DIP("print-dom-info", "Dominator Info Printer", true, true);
+}
diff --git a/tools/opt/Makefile b/tools/opt/Makefile
new file mode 100644
index 0000000..0afb002
--- /dev/null
+++ b/tools/opt/Makefile
@@ -0,0 +1,15 @@
+##===- tools/opt/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 = opt
+REQUIRES_EH := 1
+
+LINK_COMPONENTS := bitreader bitwriter instrumentation scalaropts ipo
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/opt/PrintSCC.cpp b/tools/opt/PrintSCC.cpp
new file mode 100644
index 0000000..be65264
--- /dev/null
+++ b/tools/opt/PrintSCC.cpp
@@ -0,0 +1,112 @@
+//===- PrintSCC.cpp - Enumerate SCCs in some key graphs -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides passes to print out SCCs in a CFG or a CallGraph.
+// Normally, you would not use these passes; instead, you would use the
+// scc_iterator directly to enumerate SCCs and process them in some way. These
+// passes serve three purposes:
+//
+// (1) As a reference for how to use the scc_iterator.
+// (2) To print out the SCCs for a CFG or a CallGraph:
+// analyze -print-cfg-sccs to print the SCCs in each CFG of a module.
+// analyze -print-cfg-sccs -stats to print the #SCCs and the maximum SCC size.
+// analyze -print-cfg-sccs -debug > /dev/null to watch the algorithm in action.
+//
+// and similarly:
+// analyze -print-callgraph-sccs [-stats] [-debug] to print SCCs in the CallGraph
+//
+// (3) To test the scc_iterator.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Pass.h"
+#include "llvm/Module.h"
+#include "llvm/Analysis/CallGraph.h"
+#include "llvm/Support/CFG.h"
+#include "llvm/ADT/SCCIterator.h"
+#include <iostream>
+using namespace llvm;
+
+namespace {
+ struct CFGSCC : public FunctionPass {
+ static char ID; // Pass identification, replacement for typeid
+ CFGSCC() : FunctionPass(&ID) {}
+ bool runOnFunction(Function& func);
+
+ void print(std::ostream &O, const Module* = 0) const { }
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ }
+ };
+
+ struct CallGraphSCC : public ModulePass {
+ static char ID; // Pass identification, replacement for typeid
+ CallGraphSCC() : ModulePass(&ID) {}
+
+ // run - Print out SCCs in the call graph for the specified module.
+ bool runOnModule(Module &M);
+
+ void print(std::ostream &O, const Module* = 0) const { }
+
+ // getAnalysisUsage - This pass requires the CallGraph.
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ AU.addRequired<CallGraph>();
+ }
+ };
+
+ char CFGSCC::ID = 0;
+ RegisterPass<CFGSCC>
+ Y("print-cfg-sccs", "Print SCCs of each function CFG");
+
+ char CallGraphSCC::ID = 0;
+ RegisterPass<CallGraphSCC>
+ Z("print-callgraph-sccs", "Print SCCs of the Call Graph");
+}
+
+bool CFGSCC::runOnFunction(Function &F) {
+ unsigned sccNum = 0;
+ std::cout << "SCCs for Function " << F.getName() << " in PostOrder:";
+ for (scc_iterator<Function*> SCCI = scc_begin(&F),
+ E = scc_end(&F); SCCI != E; ++SCCI) {
+ std::vector<BasicBlock*> &nextSCC = *SCCI;
+ std::cout << "\nSCC #" << ++sccNum << " : ";
+ for (std::vector<BasicBlock*>::const_iterator I = nextSCC.begin(),
+ E = nextSCC.end(); I != E; ++I)
+ std::cout << (*I)->getName() << ", ";
+ if (nextSCC.size() == 1 && SCCI.hasLoop())
+ std::cout << " (Has self-loop).";
+ }
+ std::cout << "\n";
+
+ return true;
+}
+
+
+// run - Print out SCCs in the call graph for the specified module.
+bool CallGraphSCC::runOnModule(Module &M) {
+ CallGraphNode* rootNode = getAnalysis<CallGraph>().getRoot();
+ unsigned sccNum = 0;
+ std::cout << "SCCs for the program in PostOrder:";
+ for (scc_iterator<CallGraphNode*> SCCI = scc_begin(rootNode),
+ E = scc_end(rootNode); SCCI != E; ++SCCI) {
+ const std::vector<CallGraphNode*> &nextSCC = *SCCI;
+ std::cout << "\nSCC #" << ++sccNum << " : ";
+ for (std::vector<CallGraphNode*>::const_iterator I = nextSCC.begin(),
+ E = nextSCC.end(); I != E; ++I)
+ std::cout << ((*I)->getFunction() ? (*I)->getFunction()->getName()
+ : std::string("Indirect CallGraph node")) << ", ";
+ if (nextSCC.size() == 1 && SCCI.hasLoop())
+ std::cout << " (Has self-loop).";
+ }
+ std::cout << "\n";
+
+ return true;
+}
diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp
new file mode 100644
index 0000000..680353a
--- /dev/null
+++ b/tools/opt/opt.cpp
@@ -0,0 +1,602 @@
+//===- opt.cpp - The LLVM Modular Optimizer -------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Optimizations may be specified an arbitrary number of times on the command
+// line, They are run in the order specified.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Module.h"
+#include "llvm/ModuleProvider.h"
+#include "llvm/PassManager.h"
+#include "llvm/CallGraphSCCPass.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Assembly/PrintModulePass.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Analysis/LoopPass.h"
+#include "llvm/Analysis/CallGraph.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Support/PassNameParser.h"
+#include "llvm/System/Signals.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PluginLoader.h"
+#include "llvm/Support/Streams.h"
+#include "llvm/Support/SystemUtils.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/LinkAllPasses.h"
+#include "llvm/LinkAllVMCore.h"
+#include <iostream>
+#include <fstream>
+#include <memory>
+#include <algorithm>
+using namespace llvm;
+
+// The OptimizationList is automatically populated with registered Passes by the
+// PassNameParser.
+//
+static cl::list<const PassInfo*, bool, PassNameParser>
+PassList(cl::desc("Optimizations available:"));
+
+// Other command line options...
+//
+static cl::opt<std::string>
+InputFilename(cl::Positional, cl::desc("<input bitcode file>"),
+ cl::init("-"), cl::value_desc("filename"));
+
+static cl::opt<std::string>
+OutputFilename("o", cl::desc("Override output filename"),
+ cl::value_desc("filename"), cl::init("-"));
+
+static cl::opt<bool>
+Force("f", cl::desc("Overwrite output files"));
+
+static cl::opt<bool>
+PrintEachXForm("p", cl::desc("Print module after each transformation"));
+
+static cl::opt<bool>
+NoOutput("disable-output",
+ cl::desc("Do not write result bitcode file"), cl::Hidden);
+
+static cl::opt<bool>
+NoVerify("disable-verify", cl::desc("Do not verify result module"), cl::Hidden);
+
+static cl::opt<bool>
+VerifyEach("verify-each", cl::desc("Verify after each transform"));
+
+static cl::opt<bool>
+StripDebug("strip-debug",
+ cl::desc("Strip debugger symbol info from translation unit"));
+
+static cl::opt<bool>
+DisableInline("disable-inlining", cl::desc("Do not run the inliner pass"));
+
+static cl::opt<bool>
+DisableOptimizations("disable-opt",
+ cl::desc("Do not run any optimization passes"));
+
+static cl::opt<bool>
+StandardCompileOpts("std-compile-opts",
+ cl::desc("Include the standard compile 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<bool>
+UnitAtATime("funit-at-a-time",
+ cl::desc("Enable IPO. This is same as llvm-gcc's -funit-at-a-time"));
+
+static cl::opt<bool>
+DisableSimplifyLibCalls("disable-simplify-libcalls",
+ cl::desc("Disable simplify-libcalls"));
+
+static cl::opt<bool>
+Quiet("q", cl::desc("Obsolete option"), cl::Hidden);
+
+static cl::alias
+QuietA("quiet", cl::desc("Alias for -q"), cl::aliasopt(Quiet));
+
+static cl::opt<bool>
+AnalyzeOnly("analyze", cl::desc("Only perform analysis, no optimization"));
+
+// ---------- Define Printers for module and function passes ------------
+namespace {
+
+struct CallGraphSCCPassPrinter : public CallGraphSCCPass {
+ static char ID;
+ const PassInfo *PassToPrint;
+ CallGraphSCCPassPrinter(const PassInfo *PI) :
+ CallGraphSCCPass(&ID), PassToPrint(PI) {}
+
+ virtual bool runOnSCC(const std::vector<CallGraphNode *>&SCC) {
+ if (!Quiet) {
+ cout << "Printing analysis '" << PassToPrint->getPassName() << "':\n";
+
+ for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
+ Function *F = SCC[i]->getFunction();
+ if (F)
+ getAnalysisID<Pass>(PassToPrint).print(cout, F->getParent());
+ }
+ }
+ // Get and print pass...
+ return false;
+ }
+
+ virtual const char *getPassName() const { return "'Pass' Printer"; }
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequiredID(PassToPrint);
+ AU.setPreservesAll();
+ }
+};
+
+char CallGraphSCCPassPrinter::ID = 0;
+
+struct ModulePassPrinter : public ModulePass {
+ static char ID;
+ const PassInfo *PassToPrint;
+ ModulePassPrinter(const PassInfo *PI) : ModulePass(&ID),
+ PassToPrint(PI) {}
+
+ virtual bool runOnModule(Module &M) {
+ if (!Quiet) {
+ cout << "Printing analysis '" << PassToPrint->getPassName() << "':\n";
+ getAnalysisID<Pass>(PassToPrint).print(cout, &M);
+ }
+
+ // Get and print pass...
+ return false;
+ }
+
+ virtual const char *getPassName() const { return "'Pass' Printer"; }
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequiredID(PassToPrint);
+ AU.setPreservesAll();
+ }
+};
+
+char ModulePassPrinter::ID = 0;
+struct FunctionPassPrinter : public FunctionPass {
+ const PassInfo *PassToPrint;
+ static char ID;
+ FunctionPassPrinter(const PassInfo *PI) : FunctionPass(&ID),
+ PassToPrint(PI) {}
+
+ virtual bool runOnFunction(Function &F) {
+ if (!Quiet) {
+ cout << "Printing analysis '" << PassToPrint->getPassName()
+ << "' for function '" << F.getName() << "':\n";
+ }
+ // Get and print pass...
+ getAnalysisID<Pass>(PassToPrint).print(cout, F.getParent());
+ return false;
+ }
+
+ virtual const char *getPassName() const { return "FunctionPass Printer"; }
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequiredID(PassToPrint);
+ AU.setPreservesAll();
+ }
+};
+
+char FunctionPassPrinter::ID = 0;
+
+struct LoopPassPrinter : public LoopPass {
+ static char ID;
+ const PassInfo *PassToPrint;
+ LoopPassPrinter(const PassInfo *PI) :
+ LoopPass(&ID), PassToPrint(PI) {}
+
+ virtual bool runOnLoop(Loop *L, LPPassManager &LPM) {
+ if (!Quiet) {
+ cout << "Printing analysis '" << PassToPrint->getPassName() << "':\n";
+ getAnalysisID<Pass>(PassToPrint).print(cout,
+ L->getHeader()->getParent()->getParent());
+ }
+ // Get and print pass...
+ return false;
+ }
+
+ virtual const char *getPassName() const { return "'Pass' Printer"; }
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequiredID(PassToPrint);
+ AU.setPreservesAll();
+ }
+};
+
+char LoopPassPrinter::ID = 0;
+
+struct BasicBlockPassPrinter : public BasicBlockPass {
+ const PassInfo *PassToPrint;
+ static char ID;
+ BasicBlockPassPrinter(const PassInfo *PI)
+ : BasicBlockPass(&ID), PassToPrint(PI) {}
+
+ virtual bool runOnBasicBlock(BasicBlock &BB) {
+ if (!Quiet) {
+ cout << "Printing Analysis info for BasicBlock '" << BB.getName()
+ << "': Pass " << PassToPrint->getPassName() << ":\n";
+ }
+
+ // Get and print pass...
+ getAnalysisID<Pass>(PassToPrint).print(cout, BB.getParent()->getParent());
+ return false;
+ }
+
+ virtual const char *getPassName() const { return "BasicBlockPass Printer"; }
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequiredID(PassToPrint);
+ AU.setPreservesAll();
+ }
+};
+
+char BasicBlockPassPrinter::ID = 0;
+inline void addPass(PassManager &PM, Pass *P) {
+ // Add the pass to the pass manager...
+ PM.add(P);
+
+ // If we are verifying all of the intermediate steps, add the verifier...
+ if (VerifyEach) PM.add(createVerifierPass());
+}
+
+/// AddOptimizationPasses - This routine adds optimization passes
+/// based on selected optimization level, OptLevel. This routine
+/// duplicates llvm-gcc behaviour.
+///
+/// OptLevel - Optimization Level
+void AddOptimizationPasses(PassManager &MPM, FunctionPassManager &FPM,
+ unsigned OptLevel) {
+
+ if (OptLevel == 0)
+ return;
+
+ FPM.add(createCFGSimplificationPass());
+ if (OptLevel == 1)
+ FPM.add(createPromoteMemoryToRegisterPass());
+ else
+ FPM.add(createScalarReplAggregatesPass());
+ FPM.add(createInstructionCombiningPass());
+
+ if (UnitAtATime)
+ MPM.add(createRaiseAllocationsPass()); // call %malloc -> malloc inst
+ MPM.add(createCFGSimplificationPass()); // Clean up disgusting code
+ MPM.add(createPromoteMemoryToRegisterPass()); // Kill useless allocas
+ if (UnitAtATime) {
+ MPM.add(createGlobalOptimizerPass()); // OptLevel out global vars
+ MPM.add(createGlobalDCEPass()); // Remove unused fns and globs
+ MPM.add(createIPConstantPropagationPass()); // IP Constant Propagation
+ MPM.add(createDeadArgEliminationPass()); // Dead argument elimination
+ }
+ MPM.add(createInstructionCombiningPass()); // Clean up after IPCP & DAE
+ MPM.add(createCFGSimplificationPass()); // Clean up after IPCP & DAE
+ if (UnitAtATime) {
+ MPM.add(createPruneEHPass()); // Remove dead EH info
+ MPM.add(createFunctionAttrsPass()); // Deduce function attrs
+ }
+ if (OptLevel > 1)
+ MPM.add(createFunctionInliningPass()); // Inline small functions
+ if (OptLevel > 2)
+ MPM.add(createArgumentPromotionPass()); // Scalarize uninlined fn args
+ if (!DisableSimplifyLibCalls)
+ MPM.add(createSimplifyLibCallsPass()); // Library Call Optimizations
+ MPM.add(createInstructionCombiningPass()); // Cleanup for scalarrepl.
+ MPM.add(createJumpThreadingPass()); // Thread jumps.
+ MPM.add(createCFGSimplificationPass()); // Merge & remove BBs
+ MPM.add(createScalarReplAggregatesPass()); // Break up aggregate allocas
+ MPM.add(createInstructionCombiningPass()); // Combine silly seq's
+ MPM.add(createCondPropagationPass()); // Propagate conditionals
+ MPM.add(createTailCallEliminationPass()); // Eliminate tail calls
+ MPM.add(createCFGSimplificationPass()); // Merge & remove BBs
+ MPM.add(createReassociatePass()); // Reassociate expressions
+ MPM.add(createLoopRotatePass()); // Rotate Loop
+ MPM.add(createLICMPass()); // Hoist loop invariants
+ MPM.add(createLoopUnswitchPass());
+ MPM.add(createLoopIndexSplitPass()); // Split loop index
+ MPM.add(createInstructionCombiningPass());
+ MPM.add(createIndVarSimplifyPass()); // Canonicalize indvars
+ MPM.add(createLoopDeletionPass()); // Delete dead loops
+ if (OptLevel > 1)
+ MPM.add(createLoopUnrollPass()); // Unroll small loops
+ MPM.add(createInstructionCombiningPass()); // Clean up after the unroller
+ MPM.add(createGVNPass()); // Remove redundancies
+ MPM.add(createMemCpyOptPass()); // Remove memcpy / form memset
+ MPM.add(createSCCPPass()); // Constant prop with SCCP
+
+ // Run instcombine after redundancy elimination to exploit opportunities
+ // opened up by them.
+ MPM.add(createInstructionCombiningPass());
+ MPM.add(createCondPropagationPass()); // Propagate conditionals
+ MPM.add(createDeadStoreEliminationPass()); // Delete dead stores
+ MPM.add(createAggressiveDCEPass()); // Delete dead instructions
+ MPM.add(createCFGSimplificationPass()); // Merge & remove BBs
+
+ if (UnitAtATime) {
+ MPM.add(createStripDeadPrototypesPass()); // Get rid of dead prototypes
+ MPM.add(createDeadTypeEliminationPass()); // Eliminate dead types
+ }
+
+ if (OptLevel > 1 && UnitAtATime)
+ MPM.add(createConstantMergePass()); // Merge dup global constants
+
+ return;
+}
+
+void AddStandardCompilePasses(PassManager &PM) {
+ PM.add(createVerifierPass()); // Verify that input is correct
+
+ addPass(PM, createLowerSetJmpPass()); // Lower llvm.setjmp/.longjmp
+
+ // If the -strip-debug command line option was specified, do it.
+ if (StripDebug)
+ addPass(PM, createStripSymbolsPass(true));
+
+ if (DisableOptimizations) return;
+
+ addPass(PM, createRaiseAllocationsPass()); // call %malloc -> malloc inst
+ addPass(PM, createCFGSimplificationPass()); // Clean up disgusting code
+ addPass(PM, createPromoteMemoryToRegisterPass());// Kill useless allocas
+ addPass(PM, createGlobalOptimizerPass()); // Optimize out global vars
+ addPass(PM, createGlobalDCEPass()); // Remove unused fns and globs
+ addPass(PM, createIPConstantPropagationPass());// IP Constant Propagation
+ addPass(PM, createDeadArgEliminationPass()); // Dead argument elimination
+ addPass(PM, createInstructionCombiningPass()); // Clean up after IPCP & DAE
+ addPass(PM, createCFGSimplificationPass()); // Clean up after IPCP & DAE
+
+ addPass(PM, createPruneEHPass()); // Remove dead EH info
+ addPass(PM, createFunctionAttrsPass()); // Deduce function attrs
+
+ if (!DisableInline)
+ addPass(PM, createFunctionInliningPass()); // Inline small functions
+ addPass(PM, createArgumentPromotionPass()); // Scalarize uninlined fn args
+
+ addPass(PM, createSimplifyLibCallsPass()); // Library Call Optimizations
+ addPass(PM, createInstructionCombiningPass()); // Cleanup for scalarrepl.
+ addPass(PM, createJumpThreadingPass()); // Thread jumps.
+ addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs
+ addPass(PM, createScalarReplAggregatesPass()); // Break up aggregate allocas
+ addPass(PM, createInstructionCombiningPass()); // Combine silly seq's
+ addPass(PM, createCondPropagationPass()); // Propagate conditionals
+
+ addPass(PM, createTailCallEliminationPass()); // Eliminate tail calls
+ addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs
+ addPass(PM, createReassociatePass()); // Reassociate expressions
+ addPass(PM, createLoopRotatePass());
+ addPass(PM, createLICMPass()); // Hoist loop invariants
+ addPass(PM, createLoopUnswitchPass()); // Unswitch loops.
+ addPass(PM, createLoopIndexSplitPass()); // Index split loops.
+ // FIXME : Removing instcombine causes nestedloop regression.
+ addPass(PM, createInstructionCombiningPass());
+ addPass(PM, createIndVarSimplifyPass()); // Canonicalize indvars
+ addPass(PM, createLoopDeletionPass()); // Delete dead loops
+ addPass(PM, createLoopUnrollPass()); // Unroll small loops
+ addPass(PM, createInstructionCombiningPass()); // Clean up after the unroller
+ addPass(PM, createGVNPass()); // Remove redundancies
+ addPass(PM, createMemCpyOptPass()); // Remove memcpy / form memset
+ addPass(PM, createSCCPPass()); // Constant prop with SCCP
+
+ // Run instcombine after redundancy elimination to exploit opportunities
+ // opened up by them.
+ addPass(PM, createInstructionCombiningPass());
+ addPass(PM, createCondPropagationPass()); // Propagate conditionals
+
+ addPass(PM, createDeadStoreEliminationPass()); // Delete dead stores
+ addPass(PM, createAggressiveDCEPass()); // Delete dead instructions
+ addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs
+ addPass(PM, createStripDeadPrototypesPass()); // Get rid of dead prototypes
+ addPass(PM, createDeadTypeEliminationPass()); // Eliminate dead types
+ addPass(PM, createConstantMergePass()); // Merge dup global constants
+}
+
+} // anonymous namespace
+
+
+//===----------------------------------------------------------------------===//
+// main for opt
+//
+int main(int argc, char **argv) {
+ llvm_shutdown_obj X; // Call llvm_shutdown() on exit.
+ try {
+ cl::ParseCommandLineOptions(argc, argv,
+ "llvm .bc -> .bc modular optimizer and analysis printer\n");
+ sys::PrintStackTraceOnErrorSignal();
+
+ // Allocate a full target machine description only if necessary.
+ // FIXME: The choice of target should be controllable on the command line.
+ std::auto_ptr<TargetMachine> target;
+
+ std::string ErrorMessage;
+
+ // Load the input module...
+ std::auto_ptr<Module> M;
+ if (MemoryBuffer *Buffer
+ = MemoryBuffer::getFileOrSTDIN(InputFilename, &ErrorMessage)) {
+ M.reset(ParseBitcodeFile(Buffer, &ErrorMessage));
+ delete Buffer;
+ }
+
+ if (M.get() == 0) {
+ cerr << argv[0] << ": ";
+ if (ErrorMessage.size())
+ cerr << ErrorMessage << "\n";
+ else
+ cerr << "bitcode didn't read correctly.\n";
+ return 1;
+ }
+
+ // Figure out what stream we are supposed to write to...
+ // FIXME: cout is not binary!
+ std::ostream *Out = &std::cout; // Default to printing to stdout...
+ if (OutputFilename != "-") {
+ if (!Force && std::ifstream(OutputFilename.c_str())) {
+ // If force is not specified, make sure not to overwrite a file!
+ cerr << argv[0] << ": error opening '" << OutputFilename
+ << "': file exists!\n"
+ << "Use -f command line argument to force output\n";
+ return 1;
+ }
+ std::ios::openmode io_mode = std::ios::out | std::ios::trunc |
+ std::ios::binary;
+ Out = new std::ofstream(OutputFilename.c_str(), io_mode);
+
+ if (!Out->good()) {
+ cerr << argv[0] << ": error opening " << OutputFilename << "!\n";
+ return 1;
+ }
+
+ // Make sure that the Output file gets unlinked from the disk if we get a
+ // SIGINT
+ sys::RemoveFileOnSignal(sys::Path(OutputFilename));
+ }
+
+ // If the output is set to be emitted to standard out, and standard out is a
+ // console, print out a warning message and refuse to do it. We don't
+ // impress anyone by spewing tons of binary goo to a terminal.
+ if (!Force && !NoOutput && CheckBitcodeOutputToConsole(Out,!Quiet)) {
+ NoOutput = true;
+ }
+
+ // Create a PassManager to hold and optimize the collection of passes we are
+ // about to build...
+ //
+ PassManager Passes;
+
+ // Add an appropriate TargetData instance for this module...
+ Passes.add(new TargetData(M.get()));
+
+ FunctionPassManager *FPasses = NULL;
+ if (OptLevelO1 || OptLevelO2 || OptLevelO3) {
+ FPasses = new FunctionPassManager(new ExistingModuleProvider(M.get()));
+ FPasses->add(new TargetData(M.get()));
+ }
+
+ // If the -strip-debug command line option was specified, add it. If
+ // -std-compile-opts was also specified, it will handle StripDebug.
+ if (StripDebug && !StandardCompileOpts)
+ addPass(Passes, createStripSymbolsPass(true));
+
+ // Create a new optimization pass for each one specified on the command line
+ for (unsigned i = 0; i < PassList.size(); ++i) {
+ // Check to see if -std-compile-opts was specified before this option. If
+ // so, handle it.
+ if (StandardCompileOpts &&
+ StandardCompileOpts.getPosition() < PassList.getPosition(i)) {
+ AddStandardCompilePasses(Passes);
+ StandardCompileOpts = false;
+ }
+
+ if (OptLevelO1 && OptLevelO1.getPosition() < PassList.getPosition(i)) {
+ AddOptimizationPasses(Passes, *FPasses, 1);
+ OptLevelO1 = false;
+ }
+
+ if (OptLevelO2 && OptLevelO2.getPosition() < PassList.getPosition(i)) {
+ AddOptimizationPasses(Passes, *FPasses, 2);
+ OptLevelO2 = false;
+ }
+
+ if (OptLevelO3 && OptLevelO3.getPosition() < PassList.getPosition(i)) {
+ AddOptimizationPasses(Passes, *FPasses, 3);
+ OptLevelO3 = false;
+ }
+
+ const PassInfo *PassInf = PassList[i];
+ Pass *P = 0;
+ if (PassInf->getNormalCtor())
+ P = PassInf->getNormalCtor()();
+ else
+ cerr << argv[0] << ": cannot create pass: "
+ << PassInf->getPassName() << "\n";
+ if (P) {
+ bool isBBPass = dynamic_cast<BasicBlockPass*>(P) != 0;
+ bool isLPass = !isBBPass && dynamic_cast<LoopPass*>(P) != 0;
+ bool isFPass = !isLPass && dynamic_cast<FunctionPass*>(P) != 0;
+ bool isCGSCCPass = !isFPass && dynamic_cast<CallGraphSCCPass*>(P) != 0;
+
+ addPass(Passes, P);
+
+ if (AnalyzeOnly) {
+ if (isBBPass)
+ Passes.add(new BasicBlockPassPrinter(PassInf));
+ else if (isLPass)
+ Passes.add(new LoopPassPrinter(PassInf));
+ else if (isFPass)
+ Passes.add(new FunctionPassPrinter(PassInf));
+ else if (isCGSCCPass)
+ Passes.add(new CallGraphSCCPassPrinter(PassInf));
+ else
+ Passes.add(new ModulePassPrinter(PassInf));
+ }
+ }
+
+ if (PrintEachXForm)
+ Passes.add(createPrintModulePass(&errs()));
+ }
+
+ // If -std-compile-opts was specified at the end of the pass list, add them.
+ if (StandardCompileOpts) {
+ AddStandardCompilePasses(Passes);
+ StandardCompileOpts = false;
+ }
+
+ if (OptLevelO1) {
+ AddOptimizationPasses(Passes, *FPasses, 1);
+ }
+
+ if (OptLevelO2) {
+ AddOptimizationPasses(Passes, *FPasses, 2);
+ }
+
+ if (OptLevelO3) {
+ AddOptimizationPasses(Passes, *FPasses, 3);
+ }
+
+ if (OptLevelO1 || OptLevelO2 || OptLevelO3) {
+ for (Module::iterator I = M.get()->begin(), E = M.get()->end();
+ I != E; ++I)
+ FPasses->run(*I);
+ }
+
+ // Check that the module is well formed on completion of optimization
+ if (!NoVerify && !VerifyEach)
+ Passes.add(createVerifierPass());
+
+ // Write bitcode out to disk or cout as the last step...
+ if (!NoOutput && !AnalyzeOnly)
+ Passes.add(CreateBitcodeWriterPass(*Out));
+
+ // Now that we have all of the passes ready, run them.
+ Passes.run(*M.get());
+
+ // Delete the ofstream.
+ if (Out != &std::cout)
+ delete Out;
+ return 0;
+
+ } catch (const std::string& msg) {
+ cerr << argv[0] << ": " << msg << "\n";
+ } catch (...) {
+ cerr << argv[0] << ": Unexpected unknown exception occurred.\n";
+ }
+ llvm_shutdown();
+ return 1;
+}
OpenPOWER on IntegriCloud