From cbb70ce070d220642b038ea101d9c0f9fbf860d6 Mon Sep 17 00:00:00 2001 From: dim Date: Sun, 20 Feb 2011 12:57:14 +0000 Subject: Vendor import of llvm trunk r126079: http://llvm.org/svn/llvm-project/llvm/trunk@126079 --- tools/CMakeLists.txt | 16 +- tools/Makefile | 48 ++-- tools/bugpoint-passes/CMakeLists.txt | 2 + tools/bugpoint/BugDriver.cpp | 2 +- tools/bugpoint/BugDriver.h | 3 +- tools/bugpoint/CrashDebugger.cpp | 8 +- tools/bugpoint/ExecutionDriver.cpp | 44 ++-- tools/bugpoint/ExtractFunction.cpp | 12 +- tools/bugpoint/Miscompilation.cpp | 12 +- tools/bugpoint/OptimizerDriver.cpp | 28 ++- tools/bugpoint/ToolRunner.cpp | 206 +++++++++++----- tools/bugpoint/ToolRunner.h | 13 +- tools/bugpoint/bugpoint.cpp | 31 ++- tools/edis/CMakeLists.txt | 2 - tools/edis/Makefile | 4 +- tools/gold/Makefile | 3 +- tools/gold/gold-plugin.cpp | 139 ++++++----- tools/llc/llc.cpp | 22 +- tools/lli/CMakeLists.txt | 2 +- tools/lli/Makefile | 2 +- tools/lli/lli.cpp | 40 ++- tools/llvm-ar/llvm-ar.cpp | 78 +++--- tools/llvm-as/llvm-as.cpp | 4 +- tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp | 30 ++- tools/llvm-config/CMakeLists.txt | 19 +- tools/llvm-config/llvm-config.in.in | 5 +- tools/llvm-diff/llvm-diff.cpp | 75 +++--- tools/llvm-dis/llvm-dis.cpp | 37 +-- tools/llvm-extract/llvm-extract.cpp | 45 +++- tools/llvm-ld/CMakeLists.txt | 2 + tools/llvm-ld/Optimize.cpp | 2 +- tools/llvm-ld/llvm-ld.cpp | 62 ++--- tools/llvm-link/llvm-link.cpp | 6 +- tools/llvm-mc/Disassembler.cpp | 3 +- tools/llvm-mc/llvm-mc.cpp | 193 +++++++++------ tools/llvm-nm/CMakeLists.txt | 2 +- tools/llvm-nm/Makefile | 2 +- tools/llvm-nm/llvm-nm.cpp | 228 ++++++++++++++--- tools/llvm-objdump/CMakeLists.txt | 11 + tools/llvm-objdump/Makefile | 17 ++ tools/llvm-objdump/llvm-objdump.cpp | 255 +++++++++++++++++++ tools/llvm-prof/llvm-prof.cpp | 14 +- tools/llvm-ranlib/llvm-ranlib.cpp | 14 +- tools/llvm-shlib/Makefile | 15 +- tools/llvm-stub/llvm-stub.c | 10 +- tools/llvmc/doc/LLVMC-Reference.rst | 71 +++--- tools/llvmc/examples/mcc16/Hooks.cpp | 2 +- tools/llvmc/examples/mcc16/Main.cpp | 2 +- tools/llvmc/src/Base.td.in | 227 +++++++++++------ tools/llvmc/src/Clang.td | 6 +- tools/llvmc/src/Hooks.cpp | 181 +++++++++++++- tools/lto/LTOCodeGenerator.cpp | 38 ++- tools/lto/LTOModule.cpp | 83 ++++--- tools/lto/LTOModule.h | 3 + tools/lto/Makefile | 4 + tools/lto/lto.cpp | 14 +- tools/lto/lto.exports | 1 + tools/macho-dump/CMakeLists.txt | 5 + tools/macho-dump/Makefile | 23 ++ tools/macho-dump/macho-dump.cpp | 391 ++++++++++++++++++++++++++++++ tools/opt/GraphPrinters.cpp | 13 +- tools/opt/opt.cpp | 223 +++++++++++++---- 62 files changed, 2346 insertions(+), 709 deletions(-) create mode 100644 tools/llvm-objdump/CMakeLists.txt create mode 100644 tools/llvm-objdump/Makefile create mode 100644 tools/llvm-objdump/llvm-objdump.cpp create mode 100644 tools/macho-dump/CMakeLists.txt create mode 100644 tools/macho-dump/Makefile create mode 100644 tools/macho-dump/macho-dump.cpp (limited to 'tools') diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 7ed10e9..2f37911 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,6 +1,14 @@ -# 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. +# NOTE: The tools are organized into 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 polly exists and is not disabled compile it and add it to the LLVM tools. +option(LLVM_BUILD_POLLY "Compile polly" ON) +if( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/polly/CMakeLists.txt ) + if (LLVM_BUILD_POLLY) + add_subdirectory( ${CMAKE_CURRENT_SOURCE_DIR}/polly) + endif (LLVM_BUILD_POLLY) +endif( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/polly/CMakeLists.txt ) if( NOT WIN32 OR MSYS OR CYGWIN ) # It is useful to build llvm-config before the other tools, so we @@ -28,6 +36,8 @@ add_subdirectory(lli) add_subdirectory(llvm-extract) add_subdirectory(llvm-diff) +add_subdirectory(macho-dump) +add_subdirectory(llvm-objdump) add_subdirectory(bugpoint) add_subdirectory(bugpoint-passes) diff --git a/tools/Makefile b/tools/Makefile index aa07a2b..7310247 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -12,6 +12,10 @@ LEVEL := .. # Build clang if present. OPTIONAL_PARALLEL_DIRS := clang +# Build LLDB if present. Note LLDB must be built last as it depends on the +# wider LLVM infrastructure (including Clang). +OPTIONAL_DIRS := lldb + # 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. @@ -21,12 +25,13 @@ PARALLEL_DIRS := opt llvm-as llvm-dis \ llvm-ld llvm-prof llvm-link \ lli llvm-extract llvm-mc \ bugpoint llvm-bcanalyzer llvm-stub \ - llvmc llvm-diff + llvmc llvm-diff macho-dump llvm-objdump # Let users override the set of tools to build from the command line. ifdef ONLY_TOOLS OPTIONAL_PARALLEL_DIRS := - PARALLEL_DIRS := $(ONLY_TOOLS) + OPTIONAL_DIRS := $(findstring lldb,$(ONLY_TOOLS)) + PARALLEL_DIRS := $(filter-out lldb,$(ONLY_TOOLS)) endif include $(LEVEL)/Makefile.config @@ -34,26 +39,37 @@ include $(LEVEL)/Makefile.config # These libraries build as dynamic libraries (.dylib /.so), they can only be # built if ENABLE_PIC is set. +ifndef ONLY_TOOLS ifeq ($(ENABLE_PIC),1) - # No support for dynamic libraries on windows targets. - ifneq ($(TARGET_OS), $(filter $(TARGET_OS), Cygwin MingW)) - # gold only builds if binutils is around. It requires "lto" to build before - # it so it is added to DIRS. - ifdef BINUTILS_INCDIR - DIRS += lto gold - else - PARALLEL_DIRS += lto - endif + # gold only builds if binutils is around. It requires "lto" to build before + # it so it is added to DIRS. + ifdef BINUTILS_INCDIR + DIRS += lto gold + else + PARALLEL_DIRS += lto + endif - PARALLEL_DIRS += bugpoint-passes + PARALLEL_DIRS += bugpoint-passes - # The edis library is only supported if ARM and/or X86 are enabled, and if - # LLVM is being built PIC on platforms that support dylibs. - ifneq ($(DISABLE_EDIS),1) + # The edis library is only supported if ARM and/or X86 are enabled, and if + # LLVM is being built PIC on platforms that support dylibs. + ifneq ($(DISABLE_EDIS),1) ifneq ($(filter $(TARGETS_TO_BUILD), X86 ARM),) PARALLEL_DIRS += edis endif - endif + endif +endif + +ifdef LLVM_HAS_POLLY + PARALLEL_DIRS += polly +endif +endif + +# On Win32, loadable modules can be built with ENABLE_SHARED. +ifneq ($(ENABLE_SHARED),1) + ifneq (,$(filter $(HOST_OS), Cygwin MingW)) + PARALLEL_DIRS := $(filter-out bugpoint-passes, \ + $(PARALLEL_DIRS)) endif endif diff --git a/tools/bugpoint-passes/CMakeLists.txt b/tools/bugpoint-passes/CMakeLists.txt index 50109a5..b2f1bb5 100644 --- a/tools/bugpoint-passes/CMakeLists.txt +++ b/tools/bugpoint-passes/CMakeLists.txt @@ -1,3 +1,5 @@ add_llvm_loadable_module( BugpointPasses TestPasses.cpp ) + +add_dependencies(BugpointPasses bugpoint) diff --git a/tools/bugpoint/BugDriver.cpp b/tools/bugpoint/BugDriver.cpp index 6966671..1cbf632 100644 --- a/tools/bugpoint/BugDriver.cpp +++ b/tools/bugpoint/BugDriver.cpp @@ -23,7 +23,7 @@ #include "llvm/Support/FileUtilities.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/System/Host.h" +#include "llvm/Support/Host.h" #include using namespace llvm; diff --git a/tools/bugpoint/BugDriver.h b/tools/bugpoint/BugDriver.h index e48806a..cc78489 100644 --- a/tools/bugpoint/BugDriver.h +++ b/tools/bugpoint/BugDriver.h @@ -17,6 +17,7 @@ #define BUGDRIVER_H #include "llvm/ADT/ValueMap.h" +#include "llvm/Transforms/Utils/ValueMapper.h" #include #include @@ -322,7 +323,7 @@ void DeleteFunctionBody(Function *F); /// module, split the functions OUT of the specified module, and place them in /// the new module. Module *SplitFunctionsOutOfModule(Module *M, const std::vector &F, - ValueMap &VMap); + ValueToValueMapTy &VMap); } // End llvm namespace diff --git a/tools/bugpoint/CrashDebugger.cpp b/tools/bugpoint/CrashDebugger.cpp index 57dc1c8..f19ef62 100644 --- a/tools/bugpoint/CrashDebugger.cpp +++ b/tools/bugpoint/CrashDebugger.cpp @@ -130,7 +130,7 @@ bool ReduceCrashingGlobalVariables::TestGlobalVariables( std::vector &GVs) { // Clone the program to try hacking it apart... - ValueMap VMap; + ValueToValueMapTy VMap; Module *M = CloneModule(BD.getProgram(), VMap); // Convert list to set for fast lookup... @@ -204,7 +204,7 @@ bool ReduceCrashingFunctions::TestFuncs(std::vector &Funcs) { return false; // Clone the program to try hacking it apart... - ValueMap VMap; + ValueToValueMapTy VMap; Module *M = CloneModule(BD.getProgram(), VMap); // Convert list to set for fast lookup... @@ -271,7 +271,7 @@ namespace { bool ReduceCrashingBlocks::TestBlocks(std::vector &BBs) { // Clone the program to try hacking it apart... - ValueMap VMap; + ValueToValueMapTy VMap; Module *M = CloneModule(BD.getProgram(), VMap); // Convert list to set for fast lookup... @@ -381,7 +381,7 @@ namespace { bool ReduceCrashingInstructions::TestInsts(std::vector &Insts) { // Clone the program to try hacking it apart... - ValueMap VMap; + ValueToValueMapTy VMap; Module *M = CloneModule(BD.getProgram(), VMap); // Convert list to set for fast lookup... diff --git a/tools/bugpoint/ExecutionDriver.cpp b/tools/bugpoint/ExecutionDriver.cpp index 7312484..f1601cd 100644 --- a/tools/bugpoint/ExecutionDriver.cpp +++ b/tools/bugpoint/ExecutionDriver.cpp @@ -28,7 +28,8 @@ namespace { // for miscompilation. // enum OutputType { - AutoPick, RunLLI, RunJIT, RunLLC, RunLLCIA, RunCBE, CBE_bug, LLC_Safe,Custom + AutoPick, RunLLI, RunJIT, RunLLC, RunLLCIA, RunCBE, CBE_bug, LLC_Safe, + CompileCustom, Custom }; cl::opt @@ -50,6 +51,9 @@ namespace { clEnumValN(RunCBE, "run-cbe", "Compile with CBE"), clEnumValN(CBE_bug,"cbe-bug", "Find CBE bugs"), clEnumValN(LLC_Safe, "llc-safe", "Use LLC for all"), + clEnumValN(CompileCustom, "compile-custom", + "Use -compile-command to define a command to " + "compile the bitcode. Useful to avoid linking."), clEnumValN(Custom, "run-custom", "Use -exec-command to define a command to execute " "the bitcode. Useful for cross-compilation."), @@ -87,10 +91,15 @@ namespace { "into executing programs")); cl::list - AdditionalLinkerArgs("Xlinker", + AdditionalLinkerArgs("Xlinker", cl::desc("Additional arguments to pass to the linker")); cl::opt + CustomCompileCommand("compile-command", cl::init("llc"), + cl::desc("Command to compile the bitcode (use with -compile-custom) " + "(default: llc)")); + + cl::opt CustomExecCommand("exec-command", cl::init("simulate"), cl::desc("Command to execute the bitcode (use with -run-custom) " "(default: simulate)")); @@ -119,7 +128,7 @@ namespace { cl::ZeroOrMore, cl::PositionalEatsArgs); cl::opt - GCCBinary("gcc", cl::init("gcc"), + GCCBinary("gcc", cl::init("gcc"), cl::desc("The gcc binary to use. (default 'gcc')")); cl::list @@ -157,7 +166,7 @@ bool BugDriver::initializeExecutionEnvironment() { if (!Interpreter) { InterpreterSel = RunLLC; Interpreter = AbstractInterpreter::createLLC(getToolName(), Message, - GCCBinary, &ToolArgv, + GCCBinary, &ToolArgv, &GCCToolArgv); } if (!Interpreter) { @@ -178,7 +187,7 @@ bool BugDriver::initializeExecutionEnvironment() { case RunLLCIA: case LLC_Safe: Interpreter = AbstractInterpreter::createLLC(getToolName(), Message, - GCCBinary, &ToolArgv, + GCCBinary, &ToolArgv, &GCCToolArgv, InterpreterSel == RunLLCIA); break; @@ -189,11 +198,16 @@ bool BugDriver::initializeExecutionEnvironment() { case RunCBE: case CBE_bug: Interpreter = AbstractInterpreter::createCBE(getToolName(), Message, - GCCBinary, &ToolArgv, + GCCBinary, &ToolArgv, &GCCToolArgv); break; + case CompileCustom: + Interpreter = + AbstractInterpreter::createCustomCompiler(Message, CustomCompileCommand); + break; case Custom: - Interpreter = AbstractInterpreter::createCustom(Message, CustomExecCommand); + Interpreter = + AbstractInterpreter::createCustomExecutor(Message, CustomExecCommand); break; default: Message = "Sorry, this back-end is not supported by bugpoint right now!\n"; @@ -216,7 +230,7 @@ bool BugDriver::initializeExecutionEnvironment() { SafeInterpreterSel = RunLLC; SafeToolArgs.push_back("--relocation-model=pic"); SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, - GCCBinary, + GCCBinary, &SafeToolArgs, &GCCToolArgv); } @@ -227,7 +241,7 @@ bool BugDriver::initializeExecutionEnvironment() { SafeInterpreterSel = RunLLC; SafeToolArgs.push_back("--relocation-model=pic"); SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, - GCCBinary, + GCCBinary, &SafeToolArgs, &GCCToolArgv); } @@ -249,7 +263,7 @@ bool BugDriver::initializeExecutionEnvironment() { SafeInterpreterSel = RunLLC; SafeToolArgs.push_back("--relocation-model=pic"); SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, - GCCBinary, + GCCBinary, &SafeToolArgs, &GCCToolArgv); } @@ -272,8 +286,8 @@ bool BugDriver::initializeExecutionEnvironment() { &GCCToolArgv); break; case Custom: - SafeInterpreter = AbstractInterpreter::createCustom(Message, - CustomExecCommand); + SafeInterpreter = + AbstractInterpreter::createCustomExecutor(Message, CustomExecCommand); break; default: Message = "Sorry, this back-end is not supported by bugpoint as the " @@ -281,7 +295,7 @@ bool BugDriver::initializeExecutionEnvironment() { break; } if (!SafeInterpreter) { outs() << Message << "\nExiting.\n"; exit(1); } - + gcc = GCC::create(Message, GCCBinary, &GCCToolArgv); if (!gcc) { outs() << Message << "\nExiting.\n"; exit(1); } @@ -298,7 +312,7 @@ void BugDriver::compileProgram(Module *M, std::string *Error) const { sys::Path BitcodeFile (OutputPrefix + "-test-program.bc"); std::string ErrMsg; if (BitcodeFile.makeUnique(true, &ErrMsg)) { - errs() << ToolName << ": Error making unique filename: " << ErrMsg + errs() << ToolName << ": Error making unique filename: " << ErrMsg << "\n"; exit(1); } @@ -432,7 +446,7 @@ std::string BugDriver::compileSharedObject(const std::string &BitcodeFile, } /// createReferenceFile - calls compileProgram and then records the output -/// into ReferenceOutputFile. Returns true if reference file created, false +/// into ReferenceOutputFile. Returns true if reference file created, false /// otherwise. Note: initializeExecutionEnvironment should be called BEFORE /// this function. /// diff --git a/tools/bugpoint/ExtractFunction.cpp b/tools/bugpoint/ExtractFunction.cpp index 524f130..593765c 100644 --- a/tools/bugpoint/ExtractFunction.cpp +++ b/tools/bugpoint/ExtractFunction.cpp @@ -29,9 +29,9 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileUtilities.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/System/Path.h" -#include "llvm/System/Signals.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Signals.h" #include using namespace llvm; @@ -193,7 +193,7 @@ static Constant *GetTorInit(std::vector > &TorList) { /// static ctors/dtors, we need to add an llvm.global_[cd]tors global to M2, and /// prune appropriate entries out of M1s list. static void SplitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2, - ValueMap &VMap) { + ValueToValueMapTy &VMap) { GlobalVariable *GV = M1->getNamedGlobal(GlobalName); if (!GV || GV->isDeclaration() || GV->hasLocalLinkage() || !GV->use_empty()) return; @@ -256,7 +256,7 @@ static void SplitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2, Module * llvm::SplitFunctionsOutOfModule(Module *M, const std::vector &F, - ValueMap &VMap) { + ValueToValueMapTy &VMap) { // Make sure functions & globals are all external so that linkage // between the two modules will work. for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) @@ -268,7 +268,7 @@ llvm::SplitFunctionsOutOfModule(Module *M, I->setLinkage(GlobalValue::ExternalLinkage); } - ValueMap NewVMap; + ValueToValueMapTy NewVMap; Module *New = CloneModule(M, NewVMap); // Make sure global initializers exist only in the safe module (CBE->.so) diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp index 3f2b696..3a5f143 100644 --- a/tools/bugpoint/Miscompilation.cpp +++ b/tools/bugpoint/Miscompilation.cpp @@ -261,7 +261,7 @@ bool ReduceMiscompilingFunctions::TestFuncs(const std::vector &Funcs, // a function, we want to continue with the original function. Otherwise // we can conclude that a function triggers the bug when in fact one // needs a larger set of original functions to do so. - ValueMap VMap; + ValueToValueMapTy VMap; Module *Clone = CloneModule(BD.getProgram(), VMap); Module *Orig = BD.swapProgramIn(Clone); @@ -310,7 +310,7 @@ static bool ExtractLoops(BugDriver &BD, while (1) { if (BugpointIsInterrupted) return MadeChange; - ValueMap VMap; + ValueToValueMapTy VMap; Module *ToNotOptimize = CloneModule(BD.getProgram(), VMap); Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, MiscompiledFunctions, @@ -476,7 +476,7 @@ bool ReduceMiscompiledBlocks::TestFuncs(const std::vector &BBs, outs() << '\n'; // Split the module into the two halves of the program we want. - ValueMap VMap; + ValueToValueMapTy VMap; Module *Clone = CloneModule(BD.getProgram(), VMap); Module *Orig = BD.swapProgramIn(Clone); std::vector FuncsOnClone; @@ -551,7 +551,7 @@ static bool ExtractBlocks(BugDriver &BD, return false; } - ValueMap VMap; + ValueToValueMapTy VMap; Module *ProgClone = CloneModule(BD.getProgram(), VMap); Module *ToExtract = SplitFunctionsOutOfModule(ProgClone, MiscompiledFunctions, @@ -738,7 +738,7 @@ void BugDriver::debugMiscompilation(std::string *Error) { // Output a bunch of bitcode files for the user... outs() << "Outputting reduced bitcode files which expose the problem:\n"; - ValueMap VMap; + ValueToValueMapTy VMap; Module *ToNotOptimize = CloneModule(getProgram(), VMap); Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, MiscompiledFunctions, @@ -1011,7 +1011,7 @@ bool BugDriver::debugCodeGenerator(std::string *Error) { return true; // Split the module into the two halves of the program we want. - ValueMap VMap; + ValueToValueMapTy VMap; Module *ToNotCodeGen = CloneModule(getProgram(), VMap); Module *ToCodeGen = SplitFunctionsOutOfModule(ToNotCodeGen, Funcs, VMap); diff --git a/tools/bugpoint/OptimizerDriver.cpp b/tools/bugpoint/OptimizerDriver.cpp index 3600ca6..2471cc1 100644 --- a/tools/bugpoint/OptimizerDriver.cpp +++ b/tools/bugpoint/OptimizerDriver.cpp @@ -15,10 +15,6 @@ // //===----------------------------------------------------------------------===// -// 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" @@ -29,9 +25,9 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/SystemUtils.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/System/Path.h" -#include "llvm/System/Program.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Program.h" #define DONT_GET_PLUGIN_LOADER_OPTION #include "llvm/Support/PluginLoader.h" @@ -130,12 +126,12 @@ bool BugDriver::runPasses(Module *Program, << ErrMsg << "\n"; return(1); } - + std::string ErrInfo; tool_output_file InFile(inputFilename.c_str(), ErrInfo, raw_fd_ostream::F_Binary); - - + + if (!ErrInfo.empty()) { errs() << "Error opening bitcode file: " << inputFilename.str() << "\n"; return 1; @@ -147,11 +143,19 @@ bool BugDriver::runPasses(Module *Program, InFile.os().clear_error(); return 1; } + + sys::Path tool = PrependMainExecutablePath("opt", getToolName(), + (void*)"opt"); + if (tool.empty()) { + errs() << "Cannot find `opt' in executable directory!\n"; + return 1; + } + + // Ok, everything that could go wrong before running opt is done. InFile.keep(); // setup the child process' arguments SmallVector Args; - sys::Path tool = FindExecutable("opt", getToolName(), (void*)"opt"); std::string Opt = tool.str(); if (UseValgrind) { Args.push_back("valgrind"); @@ -192,7 +196,7 @@ bool BugDriver::runPasses(Module *Program, 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}; diff --git a/tools/bugpoint/ToolRunner.cpp b/tools/bugpoint/ToolRunner.cpp index 36dbe14..37cc902 100644 --- a/tools/bugpoint/ToolRunner.cpp +++ b/tools/bugpoint/ToolRunner.cpp @@ -13,7 +13,7 @@ #define DEBUG_TYPE "toolrunner" #include "ToolRunner.h" -#include "llvm/System/Program.h" +#include "llvm/Support/Program.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileUtilities.h" @@ -59,7 +59,8 @@ static int RunProgramWithTimeout(const sys::Path &ProgramPath, const sys::Path &StdOutFile, const sys::Path &StdErrFile, unsigned NumSeconds = 0, - unsigned MemoryLimit = 0) { + unsigned MemoryLimit = 0, + std::string *ErrMsg = 0) { const sys::Path* redirects[3]; redirects[0] = &StdInFile; redirects[1] = &StdOutFile; @@ -76,7 +77,7 @@ static int RunProgramWithTimeout(const sys::Path &ProgramPath, return sys::Program::ExecuteAndWait(ProgramPath, Args, 0, redirects, - NumSeconds, MemoryLimit); + NumSeconds, MemoryLimit, ErrMsg); } /// RunProgramRemotelyWithTimeout - This function runs the given program @@ -141,7 +142,7 @@ static std::string ProcessFailure(sys::Path ProgPath, const char** Args, 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; @@ -206,7 +207,8 @@ int LLI::ExecuteProgram(const std::string &Bitcode, LLIArgs.push_back(LLIPath.c_str()); LLIArgs.push_back("-force-interpreter=true"); - for (std::vector::const_iterator i = SharedLibs.begin(), e = SharedLibs.end(); i != e; ++i) { + for (std::vector::const_iterator i = SharedLibs.begin(), + e = SharedLibs.end(); i != e; ++i) { LLIArgs.push_back("-load"); LLIArgs.push_back((*i).c_str()); } @@ -229,7 +231,7 @@ int LLI::ExecuteProgram(const std::string &Bitcode, ); return RunProgramWithTimeout(sys::Path(LLIPath), &LLIArgs[0], sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), - Timeout, MemoryLimit); + Timeout, MemoryLimit, Error); } // LLI create method - Try to find the LLI executable @@ -237,21 +239,82 @@ AbstractInterpreter *AbstractInterpreter::createLLI(const char *Argv0, std::string &Message, const std::vector *ToolArgs) { std::string LLIPath = - FindExecutable("lli", Argv0, (void *)(intptr_t)&createLLI).str(); + PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t)&createLLI).str(); if (!LLIPath.empty()) { Message = "Found lli: " + LLIPath + "\n"; return new LLI(LLIPath, ToolArgs); } - Message = "Cannot find `lli' in executable directory or PATH!\n"; + Message = "Cannot find `lli' in executable directory!\n"; return 0; } //===---------------------------------------------------------------------===// +// Custom compiler command implementation of AbstractIntepreter interface +// +// Allows using a custom command for compiling the bitcode, thus allows, for +// example, to compile a bitcode fragment without linking or executing, then +// using a custom wrapper script to check for compiler errors. +namespace { + class CustomCompiler : public AbstractInterpreter { + std::string CompilerCommand; + std::vector CompilerArgs; + public: + CustomCompiler( + const std::string &CompilerCmd, std::vector CompArgs) : + CompilerCommand(CompilerCmd), CompilerArgs(CompArgs) {} + + virtual void compileProgram(const std::string &Bitcode, + std::string *Error, + unsigned Timeout = 0, + unsigned MemoryLimit = 0); + + virtual int ExecuteProgram(const std::string &Bitcode, + const std::vector &Args, + const std::string &InputFile, + const std::string &OutputFile, + std::string *Error, + const std::vector &GCCArgs = + std::vector(), + const std::vector &SharedLibs = + std::vector(), + unsigned Timeout = 0, + unsigned MemoryLimit = 0) { + *Error = "Execution not supported with -compile-custom"; + return -1; + } + }; +} + +void CustomCompiler::compileProgram(const std::string &Bitcode, + std::string *Error, + unsigned Timeout, + unsigned MemoryLimit) { + + std::vector ProgramArgs; + ProgramArgs.push_back(CompilerCommand.c_str()); + + for (std::size_t i = 0; i < CompilerArgs.size(); ++i) + ProgramArgs.push_back(CompilerArgs.at(i).c_str()); + ProgramArgs.push_back(Bitcode.c_str()); + ProgramArgs.push_back(0); + + // Add optional parameters to the running program from Argv + for (unsigned i = 0, e = CompilerArgs.size(); i != e; ++i) + ProgramArgs.push_back(CompilerArgs[i].c_str()); + + if (RunProgramWithTimeout( sys::Path(CompilerCommand), &ProgramArgs[0], + sys::Path(), sys::Path(), sys::Path(), + Timeout, MemoryLimit, Error)) + *Error = ProcessFailure(sys::Path(CompilerCommand), &ProgramArgs[0], + Timeout, MemoryLimit); +} + +//===---------------------------------------------------------------------===// // Custom execution command implementation of AbstractIntepreter interface // // Allows using a custom command for executing the bitcode, thus allows, -// for example, to invoke a cross compiler for code generation followed by +// for example, to invoke a cross compiler for code generation followed by // a simulator that executes the generated binary. namespace { class CustomExecutor : public AbstractInterpreter { @@ -299,55 +362,78 @@ int CustomExecutor::ExecuteProgram(const std::string &Bitcode, return RunProgramWithTimeout( sys::Path(ExecutionCommand), - &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), - sys::Path(OutputFile), Timeout, MemoryLimit); + &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), + sys::Path(OutputFile), Timeout, MemoryLimit, Error); } -// Custom execution environment create method, takes the execution command -// as arguments -AbstractInterpreter *AbstractInterpreter::createCustom( - std::string &Message, - const std::string &ExecCommandLine) { +// Tokenize the CommandLine to the command and the args to allow +// defining a full command line as the command instead of just the +// executed program. We cannot just pass the whole string after the command +// as a single argument because then program sees only a single +// command line argument (with spaces in it: "foo bar" instead +// of "foo" and "bar"). +// +// code borrowed from: +// http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html +static void lexCommand(std::string &Message, const std::string &CommandLine, + std::string &CmdPath, std::vector Args) { std::string Command = ""; - std::vector 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); + std::string::size_type lastPos = CommandLine.find_first_not_of(delimiters, 0); + std::string::size_type pos = CommandLine.find_first_of(delimiters, lastPos); while (std::string::npos != pos || std::string::npos != lastPos) { - std::string token = ExecCommandLine.substr(lastPos, pos - lastPos); + std::string token = CommandLine.substr(lastPos, pos - lastPos); if (Command == "") Command = token; else Args.push_back(token); // Skip delimiters. Note the "not_of" - lastPos = ExecCommandLine.find_first_not_of(delimiters, pos); + lastPos = CommandLine.find_first_not_of(delimiters, pos); // Find next "non-delimiter" - pos = ExecCommandLine.find_first_of(delimiters, lastPos); + pos = CommandLine.find_first_of(delimiters, lastPos); } - std::string CmdPath = sys::Program::FindProgramByName(Command).str(); + CmdPath = sys::Program::FindProgramByName(Command).str(); if (CmdPath.empty()) { - Message = - std::string("Cannot find '") + Command + - "' in executable directory or PATH!\n"; - return 0; + Message = + std::string("Cannot find '") + Command + + "' in PATH!\n"; + return; } Message = "Found command in: " + CmdPath + "\n"; +} + +// Custom execution environment create method, takes the execution command +// as arguments +AbstractInterpreter *AbstractInterpreter::createCustomCompiler( + std::string &Message, + const std::string &CompileCommandLine) { + + std::string CmdPath; + std::vector Args; + lexCommand(Message, CompileCommandLine, CmdPath, Args); + if (CmdPath.empty()) + return 0; + + return new CustomCompiler(CmdPath, Args); +} + +// Custom execution environment create method, takes the execution command +// as arguments +AbstractInterpreter *AbstractInterpreter::createCustomExecutor( + std::string &Message, + const std::string &ExecCommandLine) { + + + std::string CmdPath; + std::vector Args; + lexCommand(Message, ExecCommandLine, CmdPath, Args); + if (CmdPath.empty()) + return 0; return new CustomExecutor(CmdPath, Args); } @@ -355,7 +441,7 @@ AbstractInterpreter *AbstractInterpreter::createCustom( //===----------------------------------------------------------------------===// // LLC Implementation of AbstractIntepreter interface // -GCC::FileType LLC::OutputCode(const std::string &Bitcode, +GCC::FileType LLC::OutputCode(const std::string &Bitcode, sys::Path &OutputAsmFile, std::string &Error, unsigned Timeout, unsigned MemoryLimit) { const char *Suffix = (UseIntegratedAssembler ? ".llc.o" : ".llc.s"); @@ -376,10 +462,10 @@ GCC::FileType LLC::OutputCode(const std::string &Bitcode, LLCArgs.push_back("-o"); LLCArgs.push_back(OutputAsmFile.c_str()); // Output to the Asm file LLCArgs.push_back(Bitcode.c_str()); // This is the input bitcode - + if (UseIntegratedAssembler) LLCArgs.push_back("-filetype=obj"); - + LLCArgs.push_back (0); outs() << (UseIntegratedAssembler ? "" : ""); @@ -394,7 +480,7 @@ GCC::FileType LLC::OutputCode(const std::string &Bitcode, Timeout, MemoryLimit)) Error = ProcessFailure(sys::Path(LLCPath), &LLCArgs[0], Timeout, MemoryLimit); - return UseIntegratedAssembler ? GCC::ObjectFile : GCC::AsmFile; + return UseIntegratedAssembler ? GCC::ObjectFile : GCC::AsmFile; } void LLC::compileProgram(const std::string &Bitcode, std::string *Error, @@ -437,9 +523,9 @@ LLC *AbstractInterpreter::createLLC(const char *Argv0, const std::vector *GCCArgs, bool UseIntegratedAssembler) { std::string LLCPath = - FindExecutable("llc", Argv0, (void *)(intptr_t)&createLLC).str(); + PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t)&createLLC).str(); if (LLCPath.empty()) { - Message = "Cannot find `llc' in executable directory or PATH!\n"; + Message = "Cannot find `llc' in executable directory!\n"; return 0; } @@ -474,7 +560,7 @@ namespace { const std::vector &GCCArgs = std::vector(), const std::vector &SharedLibs = - std::vector(), + std::vector(), unsigned Timeout = 0, unsigned MemoryLimit = 0); }; @@ -517,7 +603,7 @@ int JIT::ExecuteProgram(const std::string &Bitcode, DEBUG(errs() << "\nSending output to " << OutputFile << "\n"); return RunProgramWithTimeout(sys::Path(LLIPath), &JITArgs[0], sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), - Timeout, MemoryLimit); + Timeout, MemoryLimit, Error); } /// createJIT - Try to find the LLI executable @@ -525,13 +611,13 @@ int JIT::ExecuteProgram(const std::string &Bitcode, AbstractInterpreter *AbstractInterpreter::createJIT(const char *Argv0, std::string &Message, const std::vector *Args) { std::string LLIPath = - FindExecutable("lli", Argv0, (void *)(intptr_t)&createJIT).str(); + PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t)&createJIT).str(); if (!LLIPath.empty()) { Message = "Found lli: " + LLIPath + "\n"; return new JIT(LLIPath, Args); } - Message = "Cannot find `lli' in executable directory or PATH!\n"; + Message = "Cannot find `lli' in executable directory!\n"; return 0; } @@ -603,14 +689,14 @@ int CBE::ExecuteProgram(const std::string &Bitcode, /// CBE *AbstractInterpreter::createCBE(const char *Argv0, std::string &Message, - const std::string &GCCBinary, + const std::string &GCCBinary, const std::vector *Args, const std::vector *GCCArgs) { sys::Path LLCPath = - FindExecutable("llc", Argv0, (void *)(intptr_t)&createCBE); + PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t)&createCBE); if (LLCPath.isEmpty()) { Message = - "Cannot find `llc' in executable directory or PATH!\n"; + "Cannot find `llc' in executable directory!\n"; return 0; } @@ -677,9 +763,9 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, GCCArgs.push_back("-force_cpusubtype_ALL"); } } - + GCCArgs.push_back(ProgramFile.c_str()); // Specify the input filename. - + GCCArgs.push_back("-x"); GCCArgs.push_back("none"); GCCArgs.push_back("-o"); @@ -771,7 +857,7 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, DEBUG(errs() << ""); return RunProgramWithTimeout(OutputBinary, &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), - Timeout, MemoryLimit); + Timeout, MemoryLimit, Error); } else { outs() << ""; outs().flush(); return RunProgramRemotelyWithTimeout(sys::Path(RemoteClientPath), @@ -793,7 +879,7 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, OutputFile = uniqueFilename.str(); std::vector GCCArgs; - + GCCArgs.push_back(GCCPath.c_str()); if (TargetTriple.getArch() == Triple::x86) @@ -816,7 +902,7 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc else if (TargetTriple.getOS() == Triple::Darwin) { // link all source files into a single module in data segment, rather than - // generating blocks. dynamic_lookup requires that you set + // 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"); @@ -837,8 +923,8 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, 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 @@ -847,7 +933,7 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, GCCArgs.push_back(ArgsForGCC[i].c_str()); GCCArgs.push_back(0); // NULL terminator - + outs() << ""; outs().flush(); DEBUG(errs() << "\nAbout to run:\t"; @@ -870,7 +956,7 @@ GCC *GCC::create(std::string &Message, const std::vector *Args) { sys::Path GCCPath = sys::Program::FindProgramByName(GCCBinary); if (GCCPath.isEmpty()) { - Message = "Cannot find `"+ GCCBinary +"' in executable directory or PATH!\n"; + Message = "Cannot find `"+ GCCBinary +"' in PATH!\n"; return 0; } diff --git a/tools/bugpoint/ToolRunner.h b/tools/bugpoint/ToolRunner.h index cda0ddf..cfa8acf 100644 --- a/tools/bugpoint/ToolRunner.h +++ b/tools/bugpoint/ToolRunner.h @@ -21,7 +21,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/SystemUtils.h" -#include "llvm/System/Path.h" +#include "llvm/Support/Path.h" #include #include @@ -66,7 +66,7 @@ public: const std::string &OutputFile, std::string *Error = 0, const std::vector &GCCArgs = - std::vector(), + std::vector(), unsigned Timeout = 0, unsigned MemoryLimit = 0); @@ -103,8 +103,13 @@ public: static AbstractInterpreter* createJIT(const char *Argv0, std::string &Message, const std::vector *Args=0); - static AbstractInterpreter* createCustom(std::string &Message, - const std::string &ExecCommandLine); + static AbstractInterpreter* + createCustomCompiler(std::string &Message, + const std::string &CompileCommandLine); + + static AbstractInterpreter* + createCustomExecutor(std::string &Message, + const std::string &ExecCommandLine); virtual ~AbstractInterpreter() {} diff --git a/tools/bugpoint/bugpoint.cpp b/tools/bugpoint/bugpoint.cpp index 79cf563..f9c9e18 100644 --- a/tools/bugpoint/bugpoint.cpp +++ b/tools/bugpoint/bugpoint.cpp @@ -23,10 +23,14 @@ #include "llvm/Support/PluginLoader.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/StandardPasses.h" -#include "llvm/System/Process.h" -#include "llvm/System/Signals.h" -#include "llvm/System/Valgrind.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/Valgrind.h" #include "llvm/LinkAllVMCore.h" + +//Enable this macro to debug bugpoint itself. +//#define DEBUG_BUGPOINT 1 + using namespace llvm; static cl::opt @@ -71,9 +75,11 @@ OverrideTriple("mtriple", cl::desc("Override target triple for module")); /// BugpointIsInterrupted - Set to true when the user presses ctrl-c. bool llvm::BugpointIsInterrupted = false; +#ifndef DEBUG_BUGPOINT static void BugpointInterruptFunction() { BugpointIsInterrupted = true; } +#endif // Hack to capture a pass list. namespace { @@ -91,14 +97,31 @@ namespace { } int main(int argc, char **argv) { +#ifndef DEBUG_BUGPOINT llvm::sys::PrintStackTraceOnErrorSignal(); llvm::PrettyStackTraceProgram X(argc, argv); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. +#endif + + // Initialize passes + PassRegistry &Registry = *PassRegistry::getPassRegistry(); + initializeCore(Registry); + initializeScalarOpts(Registry); + initializeIPO(Registry); + initializeAnalysis(Registry); + initializeIPA(Registry); + initializeTransformUtils(Registry); + initializeInstCombine(Registry); + initializeInstrumentation(Registry); + initializeTarget(Registry); + cl::ParseCommandLineOptions(argc, argv, "LLVM automatic testcase reducer. See\nhttp://" "llvm.org/cmds/bugpoint.html" " for more information.\n"); +#ifndef DEBUG_BUGPOINT sys::SetInterruptFunction(BugpointInterruptFunction); +#endif LLVMContext& Context = getGlobalContext(); // If we have an override, set it and then track the triple we want Modules @@ -147,7 +170,9 @@ int main(int argc, char **argv) { // Bugpoint has the ability of generating a plethora of core files, so to // avoid filling up the disk, we prevent it +#ifndef DEBUG_BUGPOINT sys::Process::PreventCoreFiles(); +#endif std::string Error; bool Failure = D.run(Error); diff --git a/tools/edis/CMakeLists.txt b/tools/edis/CMakeLists.txt index 2019995..5037f9f 100644 --- a/tools/edis/CMakeLists.txt +++ b/tools/edis/CMakeLists.txt @@ -1,5 +1,3 @@ -set(LLVM_NO_RTTI 1) - include_directories(${CMAKE_CURRENT_BINARY_DIR}) add_llvm_library(EnhancedDisassembly diff --git a/tools/edis/Makefile b/tools/edis/Makefile index 92484bf..b5557fc 100644 --- a/tools/edis/Makefile +++ b/tools/edis/Makefile @@ -1,4 +1,4 @@ -##===- tools/ed/Makefile -----------------------------------*- Makefile -*-===## +##===- tools/edis/Makefile -----------------------------------*- Makefile -*-===## # # The LLVM Compiler Infrastructure # @@ -26,7 +26,7 @@ ifneq ($(filter $(TARGETS_TO_BUILD), X86),) LINK_COMPONENTS += x86asmprinter x86disassembler endif -# If the X86 target is enabled, link in the asmprinter and disassembler. +# If the ARM target is enabled, link in the asmprinter and disassembler. ifneq ($(filter $(TARGETS_TO_BUILD), ARM),) LINK_COMPONENTS += armasmprinter armdisassembler endif diff --git a/tools/gold/Makefile b/tools/gold/Makefile index 1627346..66a0271 100644 --- a/tools/gold/Makefile +++ b/tools/gold/Makefile @@ -19,10 +19,9 @@ include $(LEVEL)/Makefile.config LINK_LIBS_IN_SHARED=1 SHARED_LIBRARY = 1 -BUILD_ARCHIVE = 0 LOADABLE_MODULE = 1 -LINK_COMPONENTS := support system +LINK_COMPONENTS := support LIBS += -llto # Because off_t is used in the public API, the largefile parts are required for diff --git a/tools/gold/gold-plugin.cpp b/tools/gold/gold-plugin.cpp index 4b58fae..ad2774a 100644 --- a/tools/gold/gold-plugin.cpp +++ b/tools/gold/gold-plugin.cpp @@ -17,10 +17,10 @@ #include "llvm-c/lto.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/System/Errno.h" -#include "llvm/System/Path.h" -#include "llvm/System/Program.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/Errno.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Program.h" #include #include @@ -29,6 +29,13 @@ #include #include +// Support Windows/MinGW crazyness. +#ifdef _WIN32 +# include +# define lseek _lseek +# define read _read +#endif + using namespace llvm; namespace { @@ -49,7 +56,6 @@ namespace { int gold_version = 0; struct claimed_file { - lto_module_t M; void *handle; std::vector syms; }; @@ -58,6 +64,7 @@ namespace { std::string output_name = ""; std::list Modules; std::vector Cleanup; + lto_code_gen_t code_gen; } namespace options { @@ -65,6 +72,7 @@ namespace options { static bool generate_api_file = false; static generate_bc generate_bc_file = BC_NO; static std::string bc_path; + static std::string obj_path; static std::string as_path; static std::vector as_args; static std::vector pass_through; @@ -105,6 +113,8 @@ namespace options { pass_through.push_back(item.str()); } else if (opt.startswith("mtriple=")) { triple = opt.substr(strlen("mtriple=")); + } else if (opt.startswith("obj-path=")) { + obj_path = opt.substr(strlen("obj-path=")); } else if (opt == "emit-llvm") { generate_bc_file = BC_ONLY; } else if (opt == "also-emit-llvm") { @@ -226,6 +236,8 @@ ld_plugin_status onload(ld_plugin_tv *tv) { return LDPS_ERR; } + code_gen = lto_codegen_create(); + return LDPS_OK; } @@ -234,7 +246,8 @@ ld_plugin_status onload(ld_plugin_tv *tv) { /// with add_symbol if possible. static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, int *claimed) { - void *buf = NULL; + lto_module_t M; + if (file->offset) { // Gold has found what might be IR part-way inside of a file, such as // an .a archive. @@ -245,7 +258,7 @@ static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, file->offset, sys::StrError(errno).c_str()); return LDPS_ERR; } - buf = malloc(file->filesize); + void *buf = malloc(file->filesize); if (!buf) { (*message)(LDPL_ERROR, "Failed to allocate buffer for archive member of size: %d\n", @@ -265,37 +278,50 @@ static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, free(buf); return LDPS_OK; } - } else if (!lto_module_is_object_file(file->name)) - return LDPS_OK; + M = lto_module_create_from_memory(buf, file->filesize); + if (!M) { + (*message)(LDPL_ERROR, "Failed to create LLVM module: %s", + lto_get_error_message()); + return LDPS_ERR; + } + free(buf); + } else { + // FIXME: We should not need to pass -1 as the file size, but there + // is a bug in BFD that causes it to pass 0 to us. Remove this once + // that is fixed. + off_t size = file->filesize ? file->filesize : -1; + + // FIXME: We should not need to reset the position in the file, but there + // is a bug in BFD. Remove this once that is fixed. + off_t old_pos = lseek(file->fd, 0, SEEK_CUR); + + lseek(file->fd, 0, SEEK_SET); + M = lto_module_create_from_fd(file->fd, file->name, size); + + lseek(file->fd, old_pos, SEEK_SET); + if (!M) + 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; - } - if (!options::triple.empty()) - lto_module_set_target_triple(cf.M, options::triple.c_str()); + lto_module_set_target_triple(M, options::triple.c_str()); cf.handle = file->handle; - unsigned sym_count = lto_module_get_num_symbols(cf.M); + unsigned sym_count = lto_module_get_num_symbols(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); + lto_symbol_attributes attrs = lto_module_get_symbol_attribute(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(lto_module_get_symbol_name(cf.M, i)); + sym.name = const_cast(lto_module_get_symbol_name(M, i)); sym.version = NULL; int scope = attrs & LTO_SYMBOL_SCOPE_MASK; @@ -316,6 +342,7 @@ static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, } int definition = attrs & LTO_SYMBOL_DEFINITION_MASK; + sym.comdat_key = NULL; switch (definition) { case LTO_SYMBOL_DEFINITION_REGULAR: sym.def = LDPK_DEF; @@ -327,6 +354,7 @@ static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, sym.def = LDPK_COMMON; break; case LTO_SYMBOL_DEFINITION_WEAK: + sym.comdat_key = sym.name; sym.def = LDPK_WEAKDEF; break; case LTO_SYMBOL_DEFINITION_WEAKUNDEF: @@ -337,9 +365,7 @@ static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, return LDPS_ERR; } - // LLVM never emits COMDAT. sym.size = 0; - sym.comdat_key = NULL; sym.resolution = LDPR_UNKNOWN; } @@ -353,6 +379,7 @@ static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, } } + lto_codegen_add_module(code_gen, M); return LDPS_OK; } @@ -361,12 +388,6 @@ static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, /// been overridden by a native object file. Then, perform optimization and /// codegen. static ld_plugin_status all_symbols_read_hook(void) { - lto_code_gen_t cg = lto_codegen_create(); - - for (std::list::iterator I = Modules.begin(), - E = Modules.end(); I != E; ++I) - lto_codegen_add_module(cg, I->M); - std::ofstream api_file; if (options::generate_api_file) { api_file.open("apifile.txt", std::ofstream::out | std::ofstream::trunc); @@ -384,7 +405,7 @@ static ld_plugin_status all_symbols_read_hook(void) { (*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) { - lto_codegen_add_must_preserve_symbol(cg, I->syms[i].name); + lto_codegen_add_must_preserve_symbol(code_gen, I->syms[i].name); anySymbolsPreserved = true; if (options::generate_api_file) @@ -398,15 +419,15 @@ static ld_plugin_status all_symbols_read_hook(void) { if (!anySymbolsPreserved) { // All of the IL is unnecessary! - lto_codegen_dispose(cg); + lto_codegen_dispose(code_gen); return LDPS_OK; } - lto_codegen_set_pic_model(cg, output_type); - lto_codegen_set_debug_model(cg, LTO_DEBUG_MODEL_DWARF); + lto_codegen_set_pic_model(code_gen, output_type); + lto_codegen_set_debug_model(code_gen, LTO_DEBUG_MODEL_DWARF); if (!options::as_path.empty()) { sys::Path p = sys::Program::FindProgramByName(options::as_path); - lto_codegen_set_assembler_path(cg, p.c_str()); + lto_codegen_set_assembler_path(code_gen, p.c_str()); } if (!options::as_args.empty()) { std::vector as_args_p; @@ -414,20 +435,19 @@ static ld_plugin_status all_symbols_read_hook(void) { E = options::as_args.end(); I != E; ++I) { as_args_p.push_back(I->c_str()); } - lto_codegen_set_assembler_args(cg, &as_args_p[0], as_args_p.size()); + lto_codegen_set_assembler_args(code_gen, &as_args_p[0], as_args_p.size()); } if (!options::mcpu.empty()) - lto_codegen_set_cpu(cg, options::mcpu.c_str()); + lto_codegen_set_cpu(code_gen, options::mcpu.c_str()); // Pass through extra options to the code generator. if (!options::extra.empty()) { for (std::vector::iterator it = options::extra.begin(); it != options::extra.end(); ++it) { - lto_codegen_debug_options(cg, (*it).c_str()); + lto_codegen_debug_options(code_gen, (*it).c_str()); } } - if (options::generate_bc_file != options::BC_NO) { std::string path; if (options::generate_bc_file == options::BC_ONLY) @@ -436,45 +456,51 @@ static ld_plugin_status all_symbols_read_hook(void) { path = options::bc_path; else path = output_name + ".bc"; - bool err = lto_codegen_write_merged_modules(cg, path.c_str()); + bool err = lto_codegen_write_merged_modules(code_gen, path.c_str()); if (err) (*message)(LDPL_FATAL, "Failed to write the output file."); if (options::generate_bc_file == options::BC_ONLY) exit(0); } size_t bufsize = 0; - const char *buffer = static_cast(lto_codegen_compile(cg, + const char *buffer = static_cast(lto_codegen_compile(code_gen, &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; - } - tool_output_file objFile(uniqueObjPath.c_str(), ErrMsg, - raw_fd_ostream::F_Binary); - if (!ErrMsg.empty()) { - (*message)(LDPL_ERROR, "%s", ErrMsg.c_str()); - return LDPS_ERR; + const char *objPath; + if (!options::obj_path.empty()) { + objPath = options::obj_path.c_str(); + } else { + sys::Path uniqueObjPath("/tmp/llvmgold.o"); + if (uniqueObjPath.createTemporaryFileOnDisk(true, &ErrMsg)) { + (*message)(LDPL_ERROR, "%s", ErrMsg.c_str()); + return LDPS_ERR; + } + objPath = uniqueObjPath.c_str(); } + tool_output_file objFile(objPath, ErrMsg, + raw_fd_ostream::F_Binary); + if (!ErrMsg.empty()) { + (*message)(LDPL_ERROR, "%s", ErrMsg.c_str()); + return LDPS_ERR; + } objFile.os().write(buffer, bufsize); objFile.os().close(); if (objFile.os().has_error()) { (*message)(LDPL_ERROR, "Error writing output file '%s'", - uniqueObjPath.c_str()); + objPath); objFile.os().clear_error(); return LDPS_ERR; } objFile.keep(); - lto_codegen_dispose(cg); + lto_codegen_dispose(code_gen); - if ((*add_input_file)(uniqueObjPath.c_str()) != LDPS_OK) { + if ((*add_input_file)(objPath) != LDPS_OK) { (*message)(LDPL_ERROR, "Unable to add .o file to the link."); - (*message)(LDPL_ERROR, "File left behind in: %s", uniqueObjPath.c_str()); + (*message)(LDPL_ERROR, "File left behind in: %s", objPath); return LDPS_ERR; } @@ -502,7 +528,8 @@ static ld_plugin_status all_symbols_read_hook(void) { } } - Cleanup.push_back(uniqueObjPath); + if (options::obj_path.empty()) + Cleanup.push_back(sys::Path(objPath)); return LDPS_OK; } diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index 8bcc2d8..bb426a9 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -28,8 +28,9 @@ #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PluginLoader.h" #include "llvm/Support/PrettyStackTrace.h" -#include "llvm/System/Host.h" -#include "llvm/System/Signals.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/Signals.h" #include "llvm/Target/SubtargetFeature.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" @@ -95,6 +96,8 @@ FileType("filetype", cl::init(TargetMachine::CGFT_AssemblyFile), cl::opt NoVerify("disable-verify", cl::Hidden, cl::desc("Do not verify input module")); +cl::opt DisableDotLoc("disable-dot-loc", cl::Hidden, + cl::desc("Do not use .loc entries")); static cl::opt DisableRedZone("disable-red-zone", @@ -273,6 +276,21 @@ int main(int argc, char **argv) { assert(target.get() && "Could not allocate target machine!"); TargetMachine &Target = *target.get(); + if (DisableDotLoc) + Target.setMCUseLoc(false); + if (TheTriple.getOS() == Triple::Darwin) { + switch (TheTriple.getDarwinMajorNumber()) { + case 7: + case 8: + case 9: + // disable .loc support for older darwin OS. + Target.setMCUseLoc(false); + break; + default: + break; + } + } + // Figure out where we are going to send the output... OwningPtr Out (GetOutputStream(TheTarget->getName(), TheTriple.getOS(), argv[0])); diff --git a/tools/lli/CMakeLists.txt b/tools/lli/CMakeLists.txt index ce70d46e..9378ef2 100644 --- a/tools/lli/CMakeLists.txt +++ b/tools/lli/CMakeLists.txt @@ -1,4 +1,4 @@ -set(LLVM_LINK_COMPONENTS jit interpreter nativecodegen bitreader selectiondag) +set(LLVM_LINK_COMPONENTS mcjit jit interpreter nativecodegen bitreader asmparser selectiondag) add_llvm_tool(lli lli.cpp diff --git a/tools/lli/Makefile b/tools/lli/Makefile index 8f6eeed..80aa82b 100644 --- a/tools/lli/Makefile +++ b/tools/lli/Makefile @@ -9,7 +9,7 @@ LEVEL := ../.. TOOLNAME := lli -LINK_COMPONENTS := jit interpreter nativecodegen bitreader selectiondag +LINK_COMPONENTS := mcjit jit interpreter nativecodegen bitreader asmparser selectiondag # Enable JIT support include $(LEVEL)/Makefile.common diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp index 4c37780..a756459 100644 --- a/tools/lli/lli.cpp +++ b/tools/lli/lli.cpp @@ -23,16 +23,26 @@ #include "llvm/ExecutionEngine/Interpreter.h" #include "llvm/ExecutionEngine/JIT.h" #include "llvm/ExecutionEngine/JITEventListener.h" +#include "llvm/ExecutionEngine/MCJIT.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/IRReader.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PluginLoader.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/System/Process.h" -#include "llvm/System/Signals.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Signals.h" #include "llvm/Target/TargetSelect.h" #include + +#ifdef __CYGWIN__ +#include +#if defined(CYGWIN_VERSION_DLL_MAJOR) && CYGWIN_VERSION_DLL_MAJOR<1007 +#define DO_NOTHING_ATEXIT 1 +#endif +#endif + using namespace llvm; namespace { @@ -46,6 +56,10 @@ namespace { cl::desc("Force interpretation: disable JIT"), cl::init(false)); + cl::opt UseMCJIT( + "use-mcjit", cl::desc("Enable use of the MC-based JIT (if available)"), + cl::init(false)); + // Determine optimization level. cl::opt OptLevel("O", @@ -99,8 +113,11 @@ namespace { static ExecutionEngine *EE = 0; static void do_shutdown() { + // Cygwin-1.5 invokes DLL's dtors before atexit handler. +#ifndef DO_NOTHING_ATEXIT delete EE; llvm_shutdown(); +#endif } //===----------------------------------------------------------------------===// @@ -125,20 +142,15 @@ int main(int argc, char **argv, char * const *envp) { sys::Process::PreventCoreFiles(); // Load the bitcode... - std::string ErrorMsg; - Module *Mod = NULL; - if (MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFile,&ErrorMsg)){ - Mod = getLazyBitcodeModule(Buffer, Context, &ErrorMsg); - if (!Mod) delete Buffer; - } - + SMDiagnostic Err; + Module *Mod = ParseIRFile(InputFile, Err, Context); if (!Mod) { - errs() << argv[0] << ": error loading program '" << InputFile << "': " - << ErrorMsg << "\n"; - exit(1); + Err.Print(argv[0], errs()); + return 1; } // If not jitting lazily, load the whole bitcode file eagerly too. + std::string ErrorMsg; if (NoLazyCompilation) { if (Mod->MaterializeAllPermanently(&ErrorMsg)) { errs() << argv[0] << ": bitcode didn't read correctly.\n"; @@ -160,6 +172,10 @@ int main(int argc, char **argv, char * const *envp) { if (!TargetTriple.empty()) Mod->setTargetTriple(Triple::normalize(TargetTriple)); + // Enable MCJIT, if desired. + if (UseMCJIT) + builder.setUseMCJIT(true); + CodeGenOpt::Level OLvl = CodeGenOpt::Default; switch (OptLevel) { default: diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp index 021a369..c1c8b24 100644 --- a/tools/llvm-ar/llvm-ar.cpp +++ b/tools/llvm-ar/llvm-ar.cpp @@ -16,13 +16,13 @@ #include "llvm/Module.h" #include "llvm/Bitcode/Archive.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/System/Signals.h" -#include +#include "llvm/Support/Signals.h" #include -#include #include #include using namespace llvm; @@ -274,7 +274,7 @@ ArchiveOperation parseCommandLine() { // 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, +recurseDirectories(const sys::Path& path, std::set& result, std::string* ErrMsg) { result.clear(); if (RecurseDirectories) { @@ -311,7 +311,8 @@ bool buildPaths(bool checkExistence, std::string* ErrMsg) { if (!aPath.set(Members[i])) throw std::string("File member name invalid: ") + Members[i]; if (checkExistence) { - if (!aPath.exists()) + bool Exists; + if (sys::fs::exists(aPath.str(), Exists) || !Exists) throw std::string("File does not exist: ") + Members[i]; std::string Err; sys::PathWithStatus PwS(aPath); @@ -335,12 +336,12 @@ bool buildPaths(bool checkExistence, std::string* ErrMsg) { // printSymbolTable - print out the archive's symbol table. void printSymbolTable() { - std::cout << "\nArchive Symbol Table:\n"; + outs() << "\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"; + outs() << " " << format("%9u", offset) << "\t" << I->first <<"\n"; } } @@ -365,10 +366,10 @@ bool doPrint(std::string* ErrMsg) { continue; if (Verbose) - std::cout << "Printing " << I->getPath().str() << "\n"; + outs() << "Printing " << I->getPath().str() << "\n"; unsigned len = I->getSize(); - std::cout.write(data, len); + outs().write(data, len); } else { countDown--; } @@ -379,27 +380,27 @@ bool doPrint(std::string* ErrMsg) { // putMode - utility function for printing out the file mode when the 't' // operation is in verbose mode. -void +void printMode(unsigned mode) { if (mode & 004) - std::cout << "r"; + outs() << "r"; else - std::cout << "-"; + outs() << "-"; if (mode & 002) - std::cout << "w"; + outs() << "w"; else - std::cout << "-"; + outs() << "-"; if (mode & 001) - std::cout << "x"; + outs() << "x"; else - std::cout << "-"; + outs() << "-"; } // 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 +bool doDisplayTable(std::string* ErrMsg) { if (buildPaths(false, ErrMsg)) return true; @@ -411,22 +412,22 @@ doDisplayTable(std::string* ErrMsg) { // FIXME: Output should be this format: // Zrw-r--r-- 500/ 500 525 Nov 8 17:42 2004 Makefile if (I->isBitcode()) - std::cout << "b"; + outs() << "b"; else if (I->isCompressed()) - std::cout << "Z"; + outs() << "Z"; else - std::cout << " "; + outs() << " "; 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().str().substr(4); - std::cout << " " << I->getPath().str() << "\n"; + outs() << " " << format("%4u", I->getUser()); + outs() << "/" << format("%4u", I->getGroup()); + outs() << " " << format("%8u", I->getSize()); + outs() << " " << format("%20s", I->getModTime().str().substr(4).c_str()); + outs() << " " << I->getPath().str() << "\n"; } else { - std::cout << I->getPath().str() << "\n"; + outs() << I->getPath().str() << "\n"; } } } @@ -437,7 +438,7 @@ doDisplayTable(std::string* ErrMsg) { // doExtract - Implement the 'x' operation. This function extracts files back to // the file system, making sure to uncompress any that were compressed -bool +bool doExtract(std::string* ErrMsg) { if (buildPaths(false, ErrMsg)) return true; @@ -450,7 +451,7 @@ doExtract(std::string* ErrMsg) { if (I->hasPath()) { sys::Path dirs(I->getPath()); dirs.eraseComponent(); - if (dirs.createDirectoryOnDisk(/*create_parents=*/true, ErrMsg)) + if (dirs.createDirectoryOnDisk(/*create_parents=*/true, ErrMsg)) return true; } @@ -480,11 +481,11 @@ doExtract(std::string* ErrMsg) { // 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 +bool doDelete(std::string* ErrMsg) { if (buildPaths(false, ErrMsg)) return true; - if (Paths.empty()) + if (Paths.empty()) return false; unsigned countDown = Count; for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); @@ -513,9 +514,9 @@ doDelete(std::string* ErrMsg) { // 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 +bool doMove(std::string* ErrMsg) { - if (buildPaths(false, ErrMsg)) + if (buildPaths(false, ErrMsg)) return true; // By default and convention the place to move members to is the end of the @@ -566,12 +567,12 @@ doMove(std::string* ErrMsg) { // doQuickAppend - Implements the 'q' operation. This function just // indiscriminantly adds the members to the archive and rebuilds it. -bool +bool doQuickAppend(std::string* ErrMsg) { // Get the list of paths to append. if (buildPaths(true, ErrMsg)) return true; - if (Paths.empty()) + if (Paths.empty()) return false; // Append them quickly. @@ -591,13 +592,13 @@ doQuickAppend(std::string* ErrMsg) { // doReplaceOrInsert - Implements the 'r' operation. This function will replace // any existing files or insert new ones into the archive. -bool +bool doReplaceOrInsert(std::string* ErrMsg) { // Build the list of files to be added/replaced. if (buildPaths(true, ErrMsg)) return true; - if (Paths.empty()) + if (Paths.empty()) return false; // Keep track of the paths that remain to be inserted. @@ -637,7 +638,7 @@ doReplaceOrInsert(std::string* ErrMsg) { if (found != remaining.end()) { std::string Err; - sys::PathWithStatus PwS(*found); + sys::PathWithStatus PwS(*found); const sys::FileStatus *si = PwS.getFileStatus(false, &Err); if (!si) return true; @@ -716,7 +717,8 @@ int main(int argc, char **argv) { throw std::string("Archive name invalid: ") + ArchiveName; // Create or open the archive object. - if (!ArchivePath.exists()) { + bool Exists; + if (llvm::sys::fs::exists(ArchivePath.str(), Exists) || !Exists) { // Produce a warning if we should and we're creating the archive if (!Create) errs() << argv[0] << ": creating " << ArchivePath.str() << "\n"; diff --git a/tools/llvm-as/llvm-as.cpp b/tools/llvm-as/llvm-as.cpp index 1eaa4b3..c1661cd 100644 --- a/tools/llvm-as/llvm-as.cpp +++ b/tools/llvm-as/llvm-as.cpp @@ -25,8 +25,8 @@ #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/SystemUtils.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/System/Signals.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/Signals.h" #include using namespace llvm; diff --git a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp index 9c0d675..980f278 100644 --- a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp +++ b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp @@ -27,6 +27,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/OwningPtr.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Bitcode/BitstreamReader.h" #include "llvm/Bitcode/LLVMBitCodes.h" @@ -37,7 +38,8 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/System/Signals.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/system_error.h" #include #include #include @@ -57,15 +59,22 @@ static cl::opt NoHistogram("disable-histogram", static cl::opt NonSymbolic("non-symbolic", - cl::desc("Emit numberic info in dump even if" + cl::desc("Emit numeric 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 { +namespace { + +/// CurStreamTypeType - A type for CurStreamType +enum CurStreamTypeType { UnknownBitstream, LLVMIRBitstream -} CurStreamType; +}; + +} + +/// CurStreamType - If we can sniff the flavor of this stream, we can produce +/// better dump info. +static CurStreamTypeType CurStreamType; /// GetBlockName - Return a symbolic block name if known, otherwise return @@ -254,6 +263,7 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, switch(CodeID) { default:return 0; case bitc::METADATA_ATTACHMENT: return "METADATA_ATTACHMENT"; + case bitc::METADATA_ATTACHMENT2: return "METADATA_ATTACHMENT2"; } case bitc::METADATA_BLOCK_ID: switch(CodeID) { @@ -268,7 +278,6 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, case bitc::METADATA_NODE2: return "METADATA_NODE2"; case bitc::METADATA_FN_NODE2: return "METADATA_FN_NODE2"; case bitc::METADATA_NAMED_NODE2: return "METADATA_NAMED_NODE2"; - case bitc::METADATA_ATTACHMENT2: return "METADATA_ATTACHMENT2"; } } } @@ -473,10 +482,11 @@ static void PrintSize(uint64_t Bits) { /// AnalyzeBitcode - Analyze the bitcode file specified by InputFilename. static int AnalyzeBitcode() { // Read the input file. - MemoryBuffer *MemBuf = MemoryBuffer::getFileOrSTDIN(InputFilename.c_str()); + OwningPtr MemBuf; - if (MemBuf == 0) - return Error("Error reading '" + InputFilename + "'."); + if (error_code ec = + MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), MemBuf)) + return Error("Error reading '" + InputFilename + "': " + ec.message()); if (MemBuf->getBufferSize() & 3) return Error("Bitcode stream should be a multiple of 4 bytes in length"); diff --git a/tools/llvm-config/CMakeLists.txt b/tools/llvm-config/CMakeLists.txt index 663cae5..d33ff0d 100644 --- a/tools/llvm-config/CMakeLists.txt +++ b/tools/llvm-config/CMakeLists.txt @@ -70,6 +70,8 @@ if( NOT NM_PATH ) message(FATAL_ERROR "`nm' not found") endif() +get_property(llvm_libs GLOBAL PROPERTY LLVM_LIBS) + 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} @@ -80,8 +82,11 @@ add_custom_command(OUTPUT ${LIBDEPS} DEPENDS ${LIBDEPS_TMP} COMMENT "Updating ${LIBDEPS} if necessary...") +# This must stop the build if find-cycles.pl returns error: 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} + COMMAND ${CMAKE_COMMAND} -E remove -f ${FINAL_LIBDEPS} ${FINAL_LIBDEPS}.tmp + COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/find-cycles.pl < ${LIBDEPS} > ${FINAL_LIBDEPS}.tmp + COMMAND ${CMAKE_COMMAND} -E copy ${FINAL_LIBDEPS}.tmp ${FINAL_LIBDEPS} DEPENDS ${LIBDEPS} COMMENT "Checking for cyclic dependencies between LLVM libraries.") @@ -89,6 +94,17 @@ 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}") +# We don't want certain flags on the output of +# llvm-config --cflags --cxxflags +macro(remove_option_from_llvm_config option) + llvm_replace_compiler_option(C_FLGS "${option}" "") + llvm_replace_compiler_option(CXX_FLGS "${option}" "") + llvm_replace_compiler_option(CPP_FLGS "${option}" "") +endmacro(remove_option_from_llvm_config) +remove_option_from_llvm_config("-pedantic") +remove_option_from_llvm_config("-Wall") +remove_option_from_llvm_config("-W") + add_custom_command(OUTPUT ${LLVM_CONFIG} COMMAND echo 's!@LLVM_CPPFLAGS@!${CPP_FLGS}!' > temp.sed COMMAND echo 's!@LLVM_CFLAGS@!${C_FLGS}!' >> temp.sed @@ -108,6 +124,7 @@ add_custom_command(OUTPUT ${LLVM_CONFIG} add_custom_target(llvm-config.target ALL DEPENDS ${LLVM_CONFIG}) +get_property(llvm_lib_targets GLOBAL PROPERTY LLVM_LIB_TARGETS) add_dependencies(llvm-config.target ${llvm_lib_targets}) # Make sure that llvm-config builds before the llvm tools, so we have diff --git a/tools/llvm-config/llvm-config.in.in b/tools/llvm-config/llvm-config.in.in index d435d57..840a10e 100644 --- a/tools/llvm-config/llvm-config.in.in +++ b/tools/llvm-config/llvm-config.in.in @@ -197,7 +197,7 @@ Options: 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. + engine Either a native JIT or a bitcode interpreter. __EOD__ exit(1); } @@ -320,6 +320,9 @@ sub build_name_map { $NAME_MAP{$target} = [$target.'info', $target.'asmprinter', $target.'codegen'] + } elsif (defined $NAME_MAP{$target.'codegen'}) { + $NAME_MAP{$target} = [$target.'info', + $target.'codegen'] } else { $NAME_MAP{$target} = [$target.'info', $NAME_MAP{$target}[0]] diff --git a/tools/llvm-diff/llvm-diff.cpp b/tools/llvm-diff/llvm-diff.cpp index 16a990f..b932ccc 100644 --- a/tools/llvm-diff/llvm-diff.cpp +++ b/tools/llvm-diff/llvm-diff.cpp @@ -17,13 +17,12 @@ #include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/Type.h" -#include "llvm/Assembly/Parser.h" -#include "llvm/Bitcode/ReaderWriter.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/IRReader.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/SourceMgr.h" @@ -34,47 +33,30 @@ using namespace llvm; -/// Reads a module from a file. If the filename ends in .ll, it is -/// interpreted as an assembly file; otherwise, it is interpreted as -/// bitcode. On error, messages are written to stderr and null is -/// returned. +/// Reads a module from a file. On error, messages are written to stderr +/// and null is returned. static Module *ReadModule(LLVMContext &Context, StringRef Name) { - // LLVM assembly path. - if (Name.endswith(".ll")) { - SMDiagnostic Diag; - Module *M = ParseAssemblyFile(Name, Diag, Context); - if (M) return M; - + SMDiagnostic Diag; + Module *M = ParseIRFile(Name, Diag, Context); + if (!M) Diag.Print("llvmdiff", errs()); - return 0; - } - - // Bitcode path. - MemoryBuffer *Buffer = MemoryBuffer::getFile(Name); - - // ParseBitcodeFile takes ownership of the buffer if it succeeds. - std::string Error; - Module *M = ParseBitcodeFile(Buffer, Context, &Error); - if (M) return M; - - errs() << "error parsing " << Name << ": " << Error; - delete Buffer; - return 0; + return M; } namespace { -struct DiffContext { - DiffContext(Value *L, Value *R) - : L(L), R(R), Differences(false), IsFunction(isa(L)) {} - Value *L; - Value *R; - bool Differences; - bool IsFunction; - DenseMap LNumbering; - DenseMap RNumbering; -}; + struct DiffContext { + DiffContext(Value *L, Value *R) + : L(L), R(R), Differences(false), IsFunction(isa(L)) {} + Value *L; + Value *R; + bool Differences; + bool IsFunction; + DenseMap LNumbering; + DenseMap RNumbering; + }; +} -void ComputeNumbering(Function *F, DenseMap &Numbering) { +static void ComputeNumbering(Function *F, DenseMap &Numbering){ unsigned IN = 0; // Arguments get the first numbers. @@ -98,6 +80,7 @@ void ComputeNumbering(Function *F, DenseMap &Numbering) { assert(!Numbering.empty() && "asked for numbering but numbering was no-op"); } +namespace { class DiffConsumer : public DifferenceEngine::Consumer { private: raw_ostream &out; @@ -273,7 +256,7 @@ public: } }; -} +} // end anonymous namespace static void diffGlobal(DifferenceEngine &Engine, Module *L, Module *R, StringRef Name) { @@ -292,14 +275,14 @@ static void diffGlobal(DifferenceEngine &Engine, Module *L, Module *R, errs() << "No function named @" << Name << " in right module\n"; } -cl::opt LeftFilename(cl::Positional, - cl::desc(""), - cl::Required); -cl::opt RightFilename(cl::Positional, - cl::desc(""), - cl::Required); -cl::list GlobalsToCompare(cl::Positional, - cl::desc("")); +static cl::opt LeftFilename(cl::Positional, + cl::desc(""), + cl::Required); +static cl::opt RightFilename(cl::Positional, + cl::desc(""), + cl::Required); +static cl::list GlobalsToCompare(cl::Positional, + cl::desc("")); int main(int argc, char **argv) { cl::ParseCommandLineOptions(argc, argv); diff --git a/tools/llvm-dis/llvm-dis.cpp b/tools/llvm-dis/llvm-dis.cpp index 9d2d31d..b4977ce 100644 --- a/tools/llvm-dis/llvm-dis.cpp +++ b/tools/llvm-dis/llvm-dis.cpp @@ -26,8 +26,9 @@ #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 "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/system_error.h" using namespace llvm; static cl::opt @@ -48,7 +49,7 @@ ShowAnnotations("show-annotations", cl::desc("Add informational comments to the .ll file")); namespace { - + class CommentWriter : public AssemblyAnnotationWriter { public: void emitFunctionAnnot(const Function *F, @@ -58,32 +59,34 @@ public: } void printInfoComment(const Value &V, formatted_raw_ostream &OS) { if (V.getType()->isVoidTy()) return; - + OS.PadToColumn(50); OS << "; [#uses=" << V.getNumUses() << ']'; // Output # uses } }; - + } // end anon namespace int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); - + LLVMContext &Context = getGlobalContext(); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. - - + + cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n"); std::string ErrorMessage; std::auto_ptr M; - - if (MemoryBuffer *Buffer - = MemoryBuffer::getFileOrSTDIN(InputFilename, &ErrorMessage)) { - M.reset(ParseBitcodeFile(Buffer, Context, &ErrorMessage)); - delete Buffer; + + { + OwningPtr BufferPtr; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, BufferPtr)) + ErrorMessage = ec.message(); + else + M.reset(ParseBitcodeFile(BufferPtr.get(), Context, &ErrorMessage)); } if (M.get() == 0) { @@ -94,11 +97,11 @@ int main(int argc, char **argv) { errs() << "bitcode didn't read correctly.\n"; return 1; } - + // Just use stdout. We won't actually print anything on it. if (DontPrint) OutputFilename = "-"; - + if (OutputFilename.empty()) { // Unspecified output, infer it. if (InputFilename == "-") { OutputFilename = "-"; @@ -114,7 +117,7 @@ int main(int argc, char **argv) { } std::string ErrorInfo; - OwningPtr + OwningPtr Out(new tool_output_file(OutputFilename.c_str(), ErrorInfo, raw_fd_ostream::F_Binary)); if (!ErrorInfo.empty()) { @@ -125,7 +128,7 @@ int main(int argc, char **argv) { OwningPtr Annotator; if (ShowAnnotations) Annotator.reset(new CommentWriter()); - + // All that llvm-dis does is write the assembly to a file. if (!DontPrint) M->print(Out->os(), Annotator.get()); diff --git a/tools/llvm-extract/llvm-extract.cpp b/tools/llvm-extract/llvm-extract.cpp index 91a59e5..8c2f43a 100644 --- a/tools/llvm-extract/llvm-extract.cpp +++ b/tools/llvm-extract/llvm-extract.cpp @@ -23,9 +23,10 @@ #include "llvm/Support/IRReader.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/SystemUtils.h" -#include "llvm/System/Signals.h" +#include "llvm/Support/Signals.h" +#include "llvm/ADT/SmallPtrSet.h" #include using namespace llvm; @@ -102,13 +103,39 @@ int main(int argc, char **argv) { } // Materialize requisite global values. - for (size_t i = 0, e = GVs.size(); i != e; ++i) { - GlobalValue *GV = GVs[i]; - if (GV->isMaterializable()) { - std::string ErrInfo; - if (GV->Materialize(&ErrInfo)) { - errs() << argv[0] << ": error reading input: " << ErrInfo << "\n"; - return 1; + if (!DeleteFn) + for (size_t i = 0, e = GVs.size(); i != e; ++i) { + GlobalValue *GV = GVs[i]; + if (GV->isMaterializable()) { + std::string ErrInfo; + if (GV->Materialize(&ErrInfo)) { + errs() << argv[0] << ": error reading input: " << ErrInfo << "\n"; + return 1; + } + } + } + else { + // Deleting. Materialize every GV that's *not* in GVs. + SmallPtrSet GVSet(GVs.begin(), GVs.end()); + for (Module::global_iterator I = M->global_begin(), E = M->global_end(); + I != E; ++I) { + GlobalVariable *G = I; + if (!GVSet.count(G) && G->isMaterializable()) { + std::string ErrInfo; + if (G->Materialize(&ErrInfo)) { + errs() << argv[0] << ": error reading input: " << ErrInfo << "\n"; + return 1; + } + } + } + for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) { + Function *F = I; + if (!GVSet.count(F) && F->isMaterializable()) { + std::string ErrInfo; + if (F->Materialize(&ErrInfo)) { + errs() << argv[0] << ": error reading input: " << ErrInfo << "\n"; + return 1; + } } } } diff --git a/tools/llvm-ld/CMakeLists.txt b/tools/llvm-ld/CMakeLists.txt index 2ae4a1d..370bcb4 100644 --- a/tools/llvm-ld/CMakeLists.txt +++ b/tools/llvm-ld/CMakeLists.txt @@ -4,3 +4,5 @@ add_llvm_tool(llvm-ld Optimize.cpp llvm-ld.cpp ) + +add_dependencies(llvm-ld llvm-stub) diff --git a/tools/llvm-ld/Optimize.cpp b/tools/llvm-ld/Optimize.cpp index 3fb0079..ef4502b 100644 --- a/tools/llvm-ld/Optimize.cpp +++ b/tools/llvm-ld/Optimize.cpp @@ -16,7 +16,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/StandardPasses.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/System/DynamicLibrary.h" +#include "llvm/Support/DynamicLibrary.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Support/PassNameParser.h" diff --git a/tools/llvm-ld/llvm-ld.cpp b/tools/llvm-ld/llvm-ld.cpp index 3bbea9d..cd6ce25 100644 --- a/tools/llvm-ld/llvm-ld.cpp +++ b/tools/llvm-ld/llvm-ld.cpp @@ -23,7 +23,7 @@ #include "llvm/LinkAllVMCore.h" #include "llvm/Linker.h" #include "llvm/LLVMContext.h" -#include "llvm/System/Program.h" +#include "llvm/Support/Program.h" #include "llvm/Module.h" #include "llvm/PassManager.h" #include "llvm/Bitcode/ReaderWriter.h" @@ -35,8 +35,8 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/SystemUtils.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/System/Signals.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/Signals.h" #include "llvm/Config/config.h" #include #include @@ -98,7 +98,7 @@ static cl::list PostLinkOpts("post-link-opts", static cl::list 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 options that llvm-ld ignores but are supported for // compatibility with LD static cl::opt CO3("soname", cl::Hidden, cl::desc("Compatibility option: ignored")); @@ -112,13 +112,13 @@ static cl::opt CO5("eh-frame-hdr", cl::Hidden, static cl::opt CO6("h", cl::Hidden, cl::desc("Compatibility option: ignored")); -static cl::opt CO7("start-group", cl::Hidden, +static cl::opt CO7("start-group", cl::Hidden, cl::desc("Compatibility option: ignored")); -static cl::opt CO8("end-group", cl::Hidden, +static cl::opt CO8("end-group", cl::Hidden, cl::desc("Compatibility option: ignored")); -static cl::opt CO9("m", cl::Hidden, +static cl::opt CO9("m", cl::Hidden, cl::desc("Compatibility option: ignored")); /// This is just for convenience so it doesn't have to be passed around @@ -142,7 +142,7 @@ static void PrintAndExit(const std::string &Message, Module *M, int errcode = 1) } static void PrintCommand(const std::vector &args) { - std::vector::const_iterator I = args.begin(), E = args.end(); + std::vector::const_iterator I = args.begin(), E = args.end(); for (; I != E; ++I) if (*I) errs() << "'" << *I << "'" << " "; @@ -178,7 +178,7 @@ static char ** CopyEnv(char ** const envp) { // Allocate a new environment list. char **newenv = new char* [entries]; - if ((newenv = new char* [entries]) == NULL) + if (newenv == NULL) return NULL; // Make a copy of the list. Don't forget the NULL that ends the list. @@ -384,7 +384,7 @@ static int GenerateNative(const std::string &OutputFilename, 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. @@ -410,13 +410,13 @@ static int GenerateNative(const std::string &OutputFilename, static void EmitShellScript(char **argv, Module *M) { if (Verbose) errs() << "Emitting Shell Script\n"; -#if defined(_WIN32) || defined(__CYGWIN__) +#if defined(_WIN32) // 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], - (void *)(intptr_t)&Optimize); + std::string ErrMsg; + sys::Path llvmstub = PrependMainExecutablePath("llvm-stub", argv[0], + (void *)(intptr_t)&Optimize); if (llvmstub.isEmpty()) PrintAndExit("Could not find llvm-stub.exe executable!", M); @@ -455,7 +455,7 @@ static void EmitShellScript(char **argv, Module *M) { E = LibPaths.end(); P != E; ++P) { FullLibraryPath = *P; FullLibraryPath.appendComponent("lib" + *i); - FullLibraryPath.appendSuffix(&(LTDL_SHLIB_EXT[1])); + FullLibraryPath.appendSuffix(sys::Path::GetDLLSuffix()); if (!FullLibraryPath.isEmpty()) { if (!FullLibraryPath.isDynamicLibrary()) { // Not a native shared library; mark as invalid @@ -513,9 +513,20 @@ int main(int argc, char **argv, char **envp) { LLVMContext &Context = getGlobalContext(); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. - + + // Initialize passes + PassRegistry &Registry = *PassRegistry::getPassRegistry(); + initializeCore(Registry); + initializeScalarOpts(Registry); + initializeIPO(Registry); + initializeAnalysis(Registry); + initializeIPA(Registry); + initializeTransformUtils(Registry); + initializeInstCombine(Registry); + initializeTarget(Registry); + // Initial global variable above for convenience printing of program name. - progname = sys::Path(argv[0]).getBasename(); + progname = sys::path::stem(argv[0]); // Parse the command line options cl::ParseCommandLineOptions(argc, argv, "llvm linker\n"); @@ -527,11 +538,8 @@ int main(int argc, char **argv, char **envp) { OutputFilename = "a.exe"; // If there is no suffix add an "exe" one. - sys::Path ExeFile( OutputFilename ); - if (ExeFile.getSuffix() == "") { - ExeFile.appendSuffix("exe"); - OutputFilename = ExeFile.str(); - } + if (sys::path::extension(OutputFilename).empty()) + OutputFilename.append(".exe"); } #endif @@ -653,8 +661,8 @@ int main(int argc, char **argv, char **envp) { sys::RemoveFileOnSignal(AssemblyFile); // Determine the locations of the llc and gcc programs. - sys::Path llc = FindExecutable("llc", argv[0], - (void *)(intptr_t)&Optimize); + sys::Path llc = PrependMainExecutablePath("llc", argv[0], + (void *)(intptr_t)&Optimize); if (llc.isEmpty()) PrintAndExit("Failed to find llc", Composite.get()); @@ -680,8 +688,8 @@ int main(int argc, char **argv, char **envp) { sys::RemoveFileOnSignal(CFile); // Determine the locations of the llc and gcc programs. - sys::Path llc = FindExecutable("llc", argv[0], - (void *)(intptr_t)&Optimize); + sys::Path llc = PrependMainExecutablePath("llc", argv[0], + (void *)(intptr_t)&Optimize); if (llc.isEmpty()) PrintAndExit("Failed to find llc", Composite.get()); @@ -694,7 +702,7 @@ int main(int argc, char **argv, char **envp) { if (GenerateCFile(CFile.str(), BitcodeOutputFilename, llc, ErrMsg)) PrintAndExit(ErrMsg, Composite.get()); - if (GenerateNative(OutputFilename, CFile.str(), + if (GenerateNative(OutputFilename, CFile.str(), NativeLinkItems, gcc, envp, ErrMsg)) PrintAndExit(ErrMsg, Composite.get()); } else { diff --git a/tools/llvm-link/llvm-link.cpp b/tools/llvm-link/llvm-link.cpp index e55d0de..3fb7ba4 100644 --- a/tools/llvm-link/llvm-link.cpp +++ b/tools/llvm-link/llvm-link.cpp @@ -20,11 +20,11 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/SystemUtils.h" #include "llvm/Support/IRReader.h" -#include "llvm/System/Signals.h" -#include "llvm/System/Path.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/Path.h" #include using namespace llvm; diff --git a/tools/llvm-mc/Disassembler.cpp b/tools/llvm-mc/Disassembler.cpp index 13080b4..c29d82a 100644 --- a/tools/llvm-mc/Disassembler.cpp +++ b/tools/llvm-mc/Disassembler.cpp @@ -24,6 +24,7 @@ #include "llvm/Target/TargetRegistry.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/Triple.h" +#include "llvm/ADT/Twine.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryObject.h" #include "llvm/Support/raw_ostream.h" @@ -43,7 +44,7 @@ public: uint64_t getExtent() const { return Bytes.size(); } int readByte(uint64_t Addr, uint8_t *Byte) const { - if (Addr > getExtent()) + if (Addr >= getExtent()) return -1; *Byte = Bytes[Addr].first; return 0; diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index aef0a3d..2c22bed 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -23,6 +23,10 @@ #include "llvm/Target/TargetAsmParser.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetRegistry.h" +#include "llvm/Target/SubtargetFeature.h" // FIXME. +#include "llvm/Target/TargetAsmInfo.h" // FIXME. +#include "llvm/Target/TargetLowering.h" // FIXME. +#include "llvm/Target/TargetLoweringObjectFile.h" // FIXME. #include "llvm/Target/TargetMachine.h" // FIXME. #include "llvm/Target/TargetSelect.h" #include "llvm/ADT/OwningPtr.h" @@ -33,9 +37,10 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/SourceMgr.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/System/Host.h" -#include "llvm/System/Signals.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/system_error.h" #include "Disassembler.h" using namespace llvm; @@ -64,6 +69,9 @@ static cl::opt RelaxAll("mc-relax-all", cl::desc("Relax all fixups")); static cl::opt +NoExecStack("mc-no-exec-stack", cl::desc("File doesn't need an exec stack")); + +static cl::opt EnableLogging("enable-api-logging", cl::desc("Enable MC API logging")); enum OutputFileType { @@ -95,6 +103,12 @@ static cl::opt TripleName("triple", cl::desc("Target triple to assemble for, " "see -version for available targets")); +static cl::opt +MCPU("mcpu", + cl::desc("Target a specific cpu type (-mcpu=help for details)"), + cl::value_desc("cpu-name"), + cl::init("")); + static cl::opt NoInitialTextSection("n", cl::desc( "Don't assume assembly file starts in the text section")); @@ -157,17 +171,12 @@ static tool_output_file *GetOutputStream() { } static int AsLexInput(const char *ProgName) { - std::string ErrorMessage; - MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFilename, - &ErrorMessage); - if (Buffer == 0) { - errs() << ProgName << ": "; - if (ErrorMessage.size()) - errs() << ErrorMessage << "\n"; - else - errs() << "input file didn't read correctly.\n"; + OwningPtr BufferPtr; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, BufferPtr)) { + errs() << ProgName << ": " << ec.message() << '\n'; return 1; } + MemoryBuffer *Buffer = BufferPtr.take(); SourceMgr SrcMgr; @@ -194,7 +203,9 @@ static int AsLexInput(const char *ProgName) { bool Error = false; while (Lexer.Lex().isNot(AsmToken::Eof)) { - switch (Lexer.getKind()) { + AsmToken Tok = Lexer.getTok(); + + switch (Tok.getKind()) { default: SrcMgr.PrintMessage(Lexer.getLoc(), "unknown token", "warning"); Error = true; @@ -203,45 +214,63 @@ static int AsLexInput(const char *ProgName) { Error = true; // error already printed. break; case AsmToken::Identifier: - Out->os() << "identifier: " << Lexer.getTok().getString() << '\n'; - break; - case AsmToken::String: - Out->os() << "string: " << Lexer.getTok().getString() << '\n'; + Out->os() << "identifier: " << Lexer.getTok().getString(); break; case AsmToken::Integer: - Out->os() << "int: " << Lexer.getTok().getString() << '\n'; + Out->os() << "int: " << Lexer.getTok().getString(); + break; + case AsmToken::Real: + Out->os() << "real: " << Lexer.getTok().getString(); + break; + case AsmToken::Register: + Out->os() << "register: " << Lexer.getTok().getRegVal(); + break; + case AsmToken::String: + Out->os() << "string: " << Lexer.getTok().getString(); break; - case AsmToken::Amp: Out->os() << "Amp\n"; break; - case AsmToken::AmpAmp: Out->os() << "AmpAmp\n"; break; - case AsmToken::Caret: Out->os() << "Caret\n"; break; - case AsmToken::Colon: Out->os() << "Colon\n"; break; - case AsmToken::Comma: Out->os() << "Comma\n"; break; - case AsmToken::Dollar: Out->os() << "Dollar\n"; break; - case AsmToken::EndOfStatement: Out->os() << "EndOfStatement\n"; break; - case AsmToken::Eof: Out->os() << "Eof\n"; break; - case AsmToken::Equal: Out->os() << "Equal\n"; break; - case AsmToken::EqualEqual: Out->os() << "EqualEqual\n"; break; - case AsmToken::Exclaim: Out->os() << "Exclaim\n"; break; - case AsmToken::ExclaimEqual: Out->os() << "ExclaimEqual\n"; break; - case AsmToken::Greater: Out->os() << "Greater\n"; break; - case AsmToken::GreaterEqual: Out->os() << "GreaterEqual\n"; break; - case AsmToken::GreaterGreater: Out->os() << "GreaterGreater\n"; break; - case AsmToken::LParen: Out->os() << "LParen\n"; break; - case AsmToken::Less: Out->os() << "Less\n"; break; - case AsmToken::LessEqual: Out->os() << "LessEqual\n"; break; - case AsmToken::LessGreater: Out->os() << "LessGreater\n"; break; - case AsmToken::LessLess: Out->os() << "LessLess\n"; break; - case AsmToken::Minus: Out->os() << "Minus\n"; break; - case AsmToken::Percent: Out->os() << "Percent\n"; break; - case AsmToken::Pipe: Out->os() << "Pipe\n"; break; - case AsmToken::PipePipe: Out->os() << "PipePipe\n"; break; - case AsmToken::Plus: Out->os() << "Plus\n"; break; - case AsmToken::RParen: Out->os() << "RParen\n"; break; - case AsmToken::Slash: Out->os() << "Slash\n"; break; - case AsmToken::Star: Out->os() << "Star\n"; break; - case AsmToken::Tilde: Out->os() << "Tilde\n"; break; + case AsmToken::Amp: Out->os() << "Amp"; break; + case AsmToken::AmpAmp: Out->os() << "AmpAmp"; break; + case AsmToken::At: Out->os() << "At"; break; + case AsmToken::Caret: Out->os() << "Caret"; break; + case AsmToken::Colon: Out->os() << "Colon"; break; + case AsmToken::Comma: Out->os() << "Comma"; break; + case AsmToken::Dollar: Out->os() << "Dollar"; break; + case AsmToken::Dot: Out->os() << "Dot"; break; + case AsmToken::EndOfStatement: Out->os() << "EndOfStatement"; break; + case AsmToken::Eof: Out->os() << "Eof"; break; + case AsmToken::Equal: Out->os() << "Equal"; break; + case AsmToken::EqualEqual: Out->os() << "EqualEqual"; break; + case AsmToken::Exclaim: Out->os() << "Exclaim"; break; + case AsmToken::ExclaimEqual: Out->os() << "ExclaimEqual"; break; + case AsmToken::Greater: Out->os() << "Greater"; break; + case AsmToken::GreaterEqual: Out->os() << "GreaterEqual"; break; + case AsmToken::GreaterGreater: Out->os() << "GreaterGreater"; break; + case AsmToken::Hash: Out->os() << "Hash"; break; + case AsmToken::LBrac: Out->os() << "LBrac"; break; + case AsmToken::LCurly: Out->os() << "LCurly"; break; + case AsmToken::LParen: Out->os() << "LParen"; break; + case AsmToken::Less: Out->os() << "Less"; break; + case AsmToken::LessEqual: Out->os() << "LessEqual"; break; + case AsmToken::LessGreater: Out->os() << "LessGreater"; break; + case AsmToken::LessLess: Out->os() << "LessLess"; break; + case AsmToken::Minus: Out->os() << "Minus"; break; + case AsmToken::Percent: Out->os() << "Percent"; break; + case AsmToken::Pipe: Out->os() << "Pipe"; break; + case AsmToken::PipePipe: Out->os() << "PipePipe"; break; + case AsmToken::Plus: Out->os() << "Plus"; break; + case AsmToken::RBrac: Out->os() << "RBrac"; break; + case AsmToken::RCurly: Out->os() << "RCurly"; break; + case AsmToken::RParen: Out->os() << "RParen"; break; + case AsmToken::Slash: Out->os() << "Slash"; break; + case AsmToken::Star: Out->os() << "Star"; break; + case AsmToken::Tilde: Out->os() << "Tilde"; break; } + + // Print the token string. + Out->os() << " (\""; + Out->os().write_escaped(Tok.getString()); + Out->os() << "\")\n"; } // Keep output if no errors. @@ -255,16 +284,12 @@ static int AssembleInput(const char *ProgName) { if (!TheTarget) return 1; - std::string Error; - MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFilename, &Error); - if (Buffer == 0) { - errs() << ProgName << ": "; - if (Error.size()) - errs() << Error << "\n"; - else - errs() << "input file didn't read correctly.\n"; + OwningPtr BufferPtr; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, BufferPtr)) { + errs() << ProgName << ": " << ec.message() << '\n'; return 1; } + MemoryBuffer *Buffer = BufferPtr.take(); SourceMgr SrcMgr; @@ -279,10 +304,20 @@ static int AssembleInput(const char *ProgName) { llvm::OwningPtr MAI(TheTarget->createAsmInfo(TripleName)); assert(MAI && "Unable to create target asm info!"); - MCContext Ctx(*MAI); + // Package up features to be passed to target/subtarget + std::string FeaturesStr; + if (MCPU.size()) { + SubtargetFeatures Features; + Features.setCPU(MCPU); + FeaturesStr = Features.getString(); + } // FIXME: We shouldn't need to do this (and link in codegen). - OwningPtr TM(TheTarget->createTargetMachine(TripleName, "")); + // When we split this out, we should do it in a way that makes + // it straightforward to switch subtargets on the fly (.e.g, + // the .cpu and .code16 directives). + OwningPtr TM(TheTarget->createTargetMachine(TripleName, + FeaturesStr)); if (!TM) { errs() << ProgName << ": error: could not create target for triple '" @@ -290,6 +325,9 @@ static int AssembleInput(const char *ProgName) { return 1; } + const TargetAsmInfo *tai = new TargetAsmInfo(*TM); + MCContext Ctx(*MAI, tai); + OwningPtr Out(GetOutputStream()); if (!Out) return 1; @@ -297,15 +335,23 @@ static int AssembleInput(const char *ProgName) { formatted_raw_ostream FOS(Out->os()); OwningPtr Str; + const TargetLoweringObjectFile &TLOF = + TM->getTargetLowering()->getObjFileLowering(); + const_cast(TLOF).Initialize(Ctx, *TM); + + // FIXME: There is a bit of code duplication with addPassesToEmitFile. if (FileType == OFT_AssemblyFile) { MCInstPrinter *IP = TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI); MCCodeEmitter *CE = 0; - if (ShowEncoding) + TargetAsmBackend *TAB = 0; + if (ShowEncoding) { CE = TheTarget->createCodeEmitter(*TM, Ctx); - Str.reset(createAsmStreamer(Ctx, FOS, - TM->getTargetData()->isLittleEndian(), - /*asmverbose*/true, IP, CE, ShowInst)); + TAB = TheTarget->createAsmBackend(TripleName); + } + Str.reset(TheTarget->createAsmStreamer(Ctx, FOS, /*asmverbose*/true, + /*useLoc*/ true, IP, CE, TAB, + ShowInst)); } else if (FileType == OFT_Null) { Str.reset(createNullStreamer(Ctx)); } else { @@ -313,7 +359,8 @@ static int AssembleInput(const char *ProgName) { MCCodeEmitter *CE = TheTarget->createCodeEmitter(*TM, Ctx); TargetAsmBackend *TAB = TheTarget->createAsmBackend(TripleName); Str.reset(TheTarget->createObjectStreamer(TripleName, Ctx, *TAB, - FOS, CE, RelaxAll)); + FOS, CE, RelaxAll, + NoExecStack)); } if (EnableLogging) { @@ -344,18 +391,10 @@ static int DisassembleInput(const char *ProgName, bool Enhanced) { const Target *TheTarget = GetTarget(ProgName); if (!TheTarget) return 0; - - std::string ErrorMessage; - - MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFilename, - &ErrorMessage); - - if (Buffer == 0) { - errs() << ProgName << ": "; - if (ErrorMessage.size()) - errs() << ErrorMessage << "\n"; - else - errs() << "input file didn't read correctly.\n"; + + OwningPtr Buffer; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, Buffer)) { + errs() << ProgName << ": " << ec.message() << '\n'; return 1; } @@ -365,9 +404,11 @@ static int DisassembleInput(const char *ProgName, bool Enhanced) { int Res; if (Enhanced) - Res = Disassembler::disassembleEnhanced(TripleName, *Buffer, Out->os()); + Res = + Disassembler::disassembleEnhanced(TripleName, *Buffer.take(), Out->os()); else - Res = Disassembler::disassemble(*TheTarget, TripleName, *Buffer, Out->os()); + Res = Disassembler::disassemble(*TheTarget, TripleName, + *Buffer.take(), Out->os()); // Keep output if no errors. if (Res == 0) Out->keep(); diff --git a/tools/llvm-nm/CMakeLists.txt b/tools/llvm-nm/CMakeLists.txt index 45cf1b6..b6cd80b 100644 --- a/tools/llvm-nm/CMakeLists.txt +++ b/tools/llvm-nm/CMakeLists.txt @@ -1,4 +1,4 @@ -set(LLVM_LINK_COMPONENTS archive bitreader) +set(LLVM_LINK_COMPONENTS archive bitreader object) add_llvm_tool(llvm-nm llvm-nm.cpp diff --git a/tools/llvm-nm/Makefile b/tools/llvm-nm/Makefile index ecf5f8c..6bb4cd4 100644 --- a/tools/llvm-nm/Makefile +++ b/tools/llvm-nm/Makefile @@ -9,7 +9,7 @@ LEVEL = ../.. TOOLNAME = llvm-nm -LINK_COMPONENTS = archive bitreader +LINK_COMPONENTS = archive bitreader object # This tool has no plugins, optimize startup time. TOOL_NO_EXPORTS = 1 diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp index daa8571..1afa503 100644 --- a/tools/llvm-nm/llvm-nm.cpp +++ b/tools/llvm-nm/llvm-nm.cpp @@ -20,17 +20,23 @@ #include "llvm/Module.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/Bitcode/Archive.h" +#include "llvm/Object/ObjectFile.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.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 "llvm/Support/Signals.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/system_error.h" #include #include #include #include +#include using namespace llvm; +using namespace object; namespace { enum OutputFormatTy { bsd, sysv, posix }; @@ -64,11 +70,148 @@ namespace { cl::opt BSDFormat("B", cl::desc("Alias for --format=bsd")); cl::opt POSIXFormat("P", cl::desc("Alias for --format=posix")); + cl::opt PrintFileName("print-file-name", + cl::desc("Precede each symbol with the object file it came from")); + + cl::alias PrintFileNameA("A", cl::desc("Alias for --print-file-name"), + cl::aliasopt(PrintFileName)); + cl::alias PrintFileNameo("o", cl::desc("Alias for --print-file-name"), + cl::aliasopt(PrintFileName)); + + cl::opt DebugSyms("debug-syms", + cl::desc("Show all symbols, even debugger only")); + cl::alias DebugSymsa("a", cl::desc("Alias for --debug-syms"), + cl::aliasopt(DebugSyms)); + + cl::opt NumericSort("numeric-sort", + cl::desc("Sort symbols by address")); + cl::alias NumericSortn("n", cl::desc("Alias for --numeric-sort"), + cl::aliasopt(NumericSort)); + cl::alias NumericSortv("v", cl::desc("Alias for --numeric-sort"), + cl::aliasopt(NumericSort)); + + cl::opt NoSort("no-sort", + cl::desc("Show symbols in order encountered")); + cl::alias NoSortp("p", cl::desc("Alias for --no-sort"), + cl::aliasopt(NoSort)); + + cl::opt PrintSize("print-size", + cl::desc("Show symbol size instead of address")); + cl::alias PrintSizeS("S", cl::desc("Alias for --print-size"), + cl::aliasopt(PrintSize)); + + cl::opt SizeSort("size-sort", cl::desc("Sort symbols by size")); + + bool PrintAddress = true; + bool MultipleFiles = false; std::string ToolName; } +namespace { + struct NMSymbol { + uint64_t Address; + uint64_t Size; + char TypeChar; + StringRef Name; + }; + + static bool CompareSymbolAddress(const NMSymbol &a, const NMSymbol &b) { + if (a.Address < b.Address) + return true; + else if (a.Address == b.Address && a.Name < b.Name) + return true; + else + return false; + + } + + static bool CompareSymbolSize(const NMSymbol &a, const NMSymbol &b) { + if (a.Size < b.Size) + return true; + else if (a.Size == b.Size && a.Name < b.Name) + return true; + else + return false; + } + + static bool CompareSymbolName(const NMSymbol &a, const NMSymbol &b) { + return a.Name < b.Name; + } + + StringRef CurrentFilename; + typedef std::vector SymbolListT; + SymbolListT SymbolList; +} + +static void SortAndPrintSymbolList() { + if (!NoSort) { + if (NumericSort) + std::sort(SymbolList.begin(), SymbolList.end(), CompareSymbolAddress); + else if (SizeSort) + std::sort(SymbolList.begin(), SymbolList.end(), CompareSymbolSize); + else + std::sort(SymbolList.begin(), SymbolList.end(), CompareSymbolName); + } + + if (OutputFormat == posix && MultipleFiles) { + outs() << '\n' << CurrentFilename << ":\n"; + } else if (OutputFormat == bsd && MultipleFiles) { + outs() << "\n" << CurrentFilename << ":\n"; + } else if (OutputFormat == sysv) { + outs() << "\n\nSymbols from " << CurrentFilename << ":\n\n" + << "Name Value Class Type" + << " Size Line Section\n"; + } + + for (SymbolListT::iterator i = SymbolList.begin(), + e = SymbolList.end(); i != e; ++i) { + if ((i->TypeChar != 'U') && UndefinedOnly) + continue; + if ((i->TypeChar == 'U') && DefinedOnly) + continue; + if (SizeSort && !PrintAddress && i->Size == UnknownAddressOrSize) + continue; + + char SymbolAddrStr[10] = ""; + char SymbolSizeStr[10] = ""; + + if (OutputFormat == sysv || i->Address == object::UnknownAddressOrSize) + strcpy(SymbolAddrStr, " "); + if (OutputFormat == sysv) + strcpy(SymbolSizeStr, " "); + + if (i->Address != object::UnknownAddressOrSize) + format("%08x", i->Address).print(SymbolAddrStr, sizeof(SymbolAddrStr)); + if (i->Size != object::UnknownAddressOrSize) + format("%08x", i->Size).print(SymbolSizeStr, sizeof(SymbolSizeStr)); + + if (OutputFormat == posix) { + outs() << i->Name << " " << i->TypeChar << " " + << SymbolAddrStr << SymbolSizeStr << "\n"; + } else if (OutputFormat == bsd) { + if (PrintAddress) + outs() << SymbolAddrStr << ' '; + if (PrintSize) { + outs() << SymbolSizeStr; + if (i->Size != object::UnknownAddressOrSize) + outs() << ' '; + } + outs() << i->TypeChar << " " << i->Name << "\n"; + } else if (OutputFormat == sysv) { + std::string PaddedName (i->Name); + while (PaddedName.length () < 20) + PaddedName += " "; + outs() << PaddedName << "|" << SymbolAddrStr << "| " + << i->TypeChar + << " | |" << SymbolSizeStr << "| |\n"; + } + } + + SymbolList.clear(); +} + static char TypeCharForSymbol(GlobalValue &GV) { if (GV.isDeclaration()) return 'U'; if (GV.hasLinkOnceLinkage()) return 'C'; @@ -94,57 +237,62 @@ static void DumpSymbolNameForGlobalValue(GlobalValue &GV) { GV.hasLinkerPrivateWeakDefAutoLinkage() || 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) { - outs() << GV.getName () << " " << TypeCharForSymbol(GV) << " " - << SymbolAddrStr << "\n"; - } else if (OutputFormat == bsd) { - outs() << SymbolAddrStr << " " << TypeCharForSymbol(GV) << " " - << GV.getName () << "\n"; - } else if (OutputFormat == sysv) { - std::string PaddedName (GV.getName ()); - while (PaddedName.length () < 20) - PaddedName += " "; - outs() << PaddedName << "|" << SymbolAddrStr << "| " - << TypeCharForSymbol(GV) - << " | | | |\n"; - } + + NMSymbol s; + s.Address = object::UnknownAddressOrSize; + s.Size = object::UnknownAddressOrSize; + s.TypeChar = TypeChar; + s.Name = GV.getName(); + SymbolList.push_back(s); } static void DumpSymbolNamesFromModule(Module *M) { - const std::string &Filename = M->getModuleIdentifier (); - if (OutputFormat == posix && MultipleFiles) { - outs() << Filename << ":\n"; - } else if (OutputFormat == bsd && MultipleFiles) { - outs() << "\n" << Filename << ":\n"; - } else if (OutputFormat == sysv) { - outs() << "\n\nSymbols from " << Filename << ":\n\n" - << "Name Value Class Type" - << " Size Line Section\n"; - } + CurrentFilename = M->getModuleIdentifier(); 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); + + SortAndPrintSymbolList(); +} + +static void DumpSymbolNamesFromObject(ObjectFile *obj) { + for (ObjectFile::symbol_iterator i = obj->begin_symbols(), + e = obj->end_symbols(); i != e; ++i) { + if (!DebugSyms && i->isInternal()) + continue; + NMSymbol s; + s.Size = object::UnknownAddressOrSize; + s.Address = object::UnknownAddressOrSize; + if (PrintSize || SizeSort) + s.Size = i->getSize(); + if (PrintAddress) + s.Address = i->getAddress(); + s.TypeChar = i->getNMTypeChar(); + s.Name = i->getName(); + SymbolList.push_back(s); + } + + CurrentFilename = obj->getFilename(); + SortAndPrintSymbolList(); } static void DumpSymbolNamesFromFile(std::string &Filename) { LLVMContext &Context = getGlobalContext(); std::string ErrorMessage; sys::Path aPath(Filename); + bool exists; + if (sys::fs::exists(aPath.str(), exists) || !exists) + errs() << ToolName << ": '" << Filename << "': " << "No such file\n"; // Note: Currently we do not support reading an archive from stdin. if (Filename == "-" || aPath.isBitcodeFile()) { - std::auto_ptr Buffer( - MemoryBuffer::getFileOrSTDIN(Filename, &ErrorMessage)); + OwningPtr Buffer; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buffer)) + ErrorMessage = ec.message(); Module *Result = 0; if (Buffer.get()) Result = ParseBitcodeFile(Buffer.get(), Context, &ErrorMessage); @@ -168,6 +316,14 @@ static void DumpSymbolNamesFromFile(std::string &Filename) { } MultipleFiles = true; std::for_each (Modules.begin(), Modules.end(), DumpSymbolNamesFromModule); + } else if (aPath.isObjectFile()) { + std::auto_ptr obj(ObjectFile::createObjectFile(aPath.str())); + if (!obj.get()) { + errs() << ToolName << ": " << Filename << ": " + << "Failed to open object file\n"; + return; + } + DumpSymbolNamesFromObject(obj.get()); } else { errs() << ToolName << ": " << Filename << ": " << "unrecognizable file type\n"; @@ -187,6 +343,12 @@ int main(int argc, char **argv) { if (BSDFormat) OutputFormat = bsd; if (POSIXFormat) OutputFormat = posix; + // The relative order of these is important. If you pass --size-sort it should + // only print out the size. However, if you pass -S --size-sort, it should + // print out both the size and address. + if (SizeSort && !PrintSize) PrintAddress = false; + if (OutputFormat == sysv || SizeSort) PrintSize = true; + switch (InputFilenames.size()) { case 0: InputFilenames.push_back("-"); case 1: break; diff --git a/tools/llvm-objdump/CMakeLists.txt b/tools/llvm-objdump/CMakeLists.txt new file mode 100644 index 0000000..4181b32 --- /dev/null +++ b/tools/llvm-objdump/CMakeLists.txt @@ -0,0 +1,11 @@ +set(LLVM_LINK_COMPONENTS + ${LLVM_TARGETS_TO_BUILD} + MC + MCParser + MCDisassembler + Object + ) + +add_llvm_tool(llvm-objdump + llvm-objdump.cpp + ) diff --git a/tools/llvm-objdump/Makefile b/tools/llvm-objdump/Makefile new file mode 100644 index 0000000..4d7cd34 --- /dev/null +++ b/tools/llvm-objdump/Makefile @@ -0,0 +1,17 @@ +##===- tools/llvm-objdump/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-objdump +LINK_COMPONENTS = $(TARGETS_TO_BUILD) MC MCParser MCDisassembler Object + +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS = 1 + +include $(LEVEL)/Makefile.common diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp new file mode 100644 index 0000000..1fef8b6 --- /dev/null +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -0,0 +1,255 @@ +//===-- llvm-objdump.cpp - Object file 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 binutils "objdump", that is, it +// dumps out a plethora of information about an object file depending on the +// flags. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/ObjectFile.h" +// This config must be included before llvm-config.h. +#include "llvm/Config/config.h" +#include "../../lib/MC/MCDisassembler/EDDisassembler.h" +#include "../../lib/MC/MCDisassembler/EDInst.h" +#include "../../lib/MC/MCDisassembler/EDOperand.h" +#include "../../lib/MC/MCDisassembler/EDToken.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/Triple.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCDisassembler.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstPrinter.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/MemoryObject.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/system_error.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Target/TargetSelect.h" +#include +#include +#include +#include +#include +using namespace llvm; +using namespace object; + +namespace { + cl::list + InputFilenames(cl::Positional, cl::desc(""), + cl::ZeroOrMore); + + cl::opt + Disassemble("disassemble", + cl::desc("Display assembler mnemonics for the machine instructions")); + cl::alias + Disassembled("d", cl::desc("Alias for --disassemble"), + cl::aliasopt(Disassemble)); + + cl::opt + TripleName("triple", cl::desc("Target triple to disassemble for, " + "see -version for available targets")); + + cl::opt + ArchName("arch", cl::desc("Target arch to disassemble for, " + "see -version for available targets")); + + StringRef ToolName; +} + +static const Target *GetTarget(const ObjectFile *Obj = NULL) { + // Figure out the target triple. + llvm::Triple TT("unknown-unknown-unknown"); + if (TripleName.empty()) { + if (Obj) + TT.setArch(Triple::ArchType(Obj->getArch())); + } else + TT.setTriple(Triple::normalize(TripleName)); + + if (!ArchName.empty()) + TT.setArchName(ArchName); + + TripleName = TT.str(); + + // Get the target specific parser. + std::string Error; + const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error); + if (TheTarget) + return TheTarget; + + errs() << ToolName << ": error: unable to get target for '" << TripleName + << "', see --version and --triple.\n"; + return 0; +} + +namespace { +class StringRefMemoryObject : public MemoryObject { +private: + StringRef Bytes; +public: + StringRefMemoryObject(StringRef bytes) : Bytes(bytes) {} + + uint64_t getBase() const { return 0; } + uint64_t getExtent() const { return Bytes.size(); } + + int readByte(uint64_t Addr, uint8_t *Byte) const { + if (Addr > getExtent()) + return -1; + *Byte = Bytes[Addr]; + return 0; + } +}; +} + +static void DumpBytes(StringRef bytes) { + static char hex_rep[] = "0123456789abcdef"; + // FIXME: The real way to do this is to figure out the longest instruction + // and align to that size before printing. I'll fix this when I get + // around to outputting relocations. + // 15 is the longest x86 instruction + // 3 is for the hex rep of a byte + a space. + // 1 is for the null terminator. + enum { OutputSize = (15 * 3) + 1 }; + char output[OutputSize]; + + assert(bytes.size() <= 15 + && "DumpBytes only supports instructions of up to 15 bytes"); + memset(output, ' ', sizeof(output)); + unsigned index = 0; + for (StringRef::iterator i = bytes.begin(), + e = bytes.end(); i != e; ++i) { + output[index] = hex_rep[(*i & 0xF0) >> 4]; + output[index + 1] = hex_rep[*i & 0xF]; + index += 3; + } + + output[sizeof(output) - 1] = 0; + outs() << output; +} + +static void DisassembleInput(const StringRef &Filename) { + OwningPtr Buff; + + if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) { + errs() << ToolName << ": " << Filename << ": " << ec.message() << "\n"; + return; + } + + OwningPtr Obj(ObjectFile::createObjectFile(Buff.take())); + + const Target *TheTarget = GetTarget(Obj.get()); + if (!TheTarget) { + // GetTarget prints out stuff. + return; + } + + outs() << '\n'; + outs() << Filename + << ":\tfile format " << Obj->getFileFormatName() << "\n\n\n"; + + for (ObjectFile::section_iterator i = Obj->begin_sections(), + e = Obj->end_sections(); + i != e; ++i) { + if (!i->isText()) + continue; + outs() << "Disassembly of section " << i->getName() << ":\n\n"; + + // Set up disassembler. + OwningPtr AsmInfo(TheTarget->createAsmInfo(TripleName)); + + if (!AsmInfo) { + errs() << "error: no assembly info for target " << TripleName << "\n"; + return; + } + + OwningPtr DisAsm(TheTarget->createMCDisassembler()); + if (!DisAsm) { + errs() << "error: no disassembler for target " << TripleName << "\n"; + return; + } + + int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); + OwningPtr IP(TheTarget->createMCInstPrinter( + AsmPrinterVariant, *AsmInfo)); + if (!IP) { + errs() << "error: no instruction printer for target " << TripleName << '\n'; + return; + } + + StringRef Bytes = i->getContents(); + StringRefMemoryObject memoryObject(Bytes); + uint64_t Size; + uint64_t Index; + + for (Index = 0; Index < Bytes.size(); Index += Size) { + MCInst Inst; + +# ifndef NDEBUG + raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls(); +# else + raw_ostream &DebugOut = nulls(); +# endif + + if (DisAsm->getInstruction(Inst, Size, memoryObject, Index, DebugOut)) { + outs() << format("%8x:\t", i->getAddress() + Index); + DumpBytes(StringRef(Bytes.data() + Index, Size)); + IP->printInst(&Inst, outs()); + outs() << "\n"; + } else { + errs() << ToolName << ": warning: invalid instruction encoding\n"; + if (Size == 0) + Size = 1; // skip illegible bytes + } + } + } +} + +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. + + // Initialize targets and assembly printers/parsers. + llvm::InitializeAllTargetInfos(); + // FIXME: We shouldn't need to initialize the Target(Machine)s. + llvm::InitializeAllTargets(); + llvm::InitializeAllAsmPrinters(); + llvm::InitializeAllAsmParsers(); + llvm::InitializeAllDisassemblers(); + + cl::ParseCommandLineOptions(argc, argv, "llvm object file dumper\n"); + TripleName = Triple::normalize(TripleName); + + ToolName = argv[0]; + + // Defaults to a.out if no filenames specified. + if (InputFilenames.size() == 0) + InputFilenames.push_back("a.out"); + + // -d is the only flag that is currently implemented, so just print help if + // it is not set. + if (!Disassemble) { + cl::PrintHelpMessage(); + return 2; + } + + std::for_each(InputFilenames.begin(), InputFilenames.end(), + DisassembleInput); + + return 0; +} diff --git a/tools/llvm-prof/llvm-prof.cpp b/tools/llvm-prof/llvm-prof.cpp index 1c63d97..9d0b468 100644 --- a/tools/llvm-prof/llvm-prof.cpp +++ b/tools/llvm-prof/llvm-prof.cpp @@ -29,7 +29,8 @@ #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Format.h" -#include "llvm/System/Signals.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/system_error.h" #include #include #include @@ -263,12 +264,13 @@ int main(int argc, char **argv) { // Read in the bitcode file... std::string ErrorMessage; + OwningPtr Buffer; + error_code ec; Module *M = 0; - if (MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(BitcodeFile, - &ErrorMessage)) { - M = ParseBitcodeFile(Buffer, Context, &ErrorMessage); - delete Buffer; - } + if (!(ec = MemoryBuffer::getFileOrSTDIN(BitcodeFile, Buffer))) { + M = ParseBitcodeFile(Buffer.get(), Context, &ErrorMessage); + } else + ErrorMessage = ec.message(); if (M == 0) { errs() << argv[0] << ": " << BitcodeFile << ": " << ErrorMessage << "\n"; diff --git a/tools/llvm-ranlib/llvm-ranlib.cpp b/tools/llvm-ranlib/llvm-ranlib.cpp index dffe3ad..64f795f 100644 --- a/tools/llvm-ranlib/llvm-ranlib.cpp +++ b/tools/llvm-ranlib/llvm-ranlib.cpp @@ -15,14 +15,13 @@ #include "llvm/Module.h" #include "llvm/Bitcode/Archive.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/System/Signals.h" -#include -#include +#include "llvm/Support/Signals.h" #include - using namespace llvm; // llvm-ar operation code and modifier flags @@ -35,12 +34,12 @@ Verbose("verbose",cl::Optional,cl::init(false), // printSymbolTable - print out the archive's symbol table. void printSymbolTable(Archive* TheArchive) { - std::cout << "\nArchive Symbol Table:\n"; + outs() << "\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"; + outs() << " " << format("%9u", offset) << "\t" << I->first <<"\n"; } } @@ -71,7 +70,8 @@ int main(int argc, char **argv) { throw std::string("Archive name invalid: ") + ArchiveName; // Make sure it exists, we don't create empty archives - if (!ArchivePath.exists()) + bool Exists; + if (llvm::sys::fs::exists(ArchivePath.str(), Exists) || !Exists) throw std::string("Archive file does not exist"); std::string err_msg; diff --git a/tools/llvm-shlib/Makefile b/tools/llvm-shlib/Makefile index 5238130..9e6faca 100644 --- a/tools/llvm-shlib/Makefile +++ b/tools/llvm-shlib/Makefile @@ -18,11 +18,12 @@ SHARED_LIBRARY = 1 include $(LEVEL)/Makefile.config ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) - EXPORTED_SYMBOL_FILE = $(ObjDir)/$(LIBRARYNAME).exports + EXPORTED_SYMBOL_FILE = $(ObjDir)/$(LIBRARYNAME).exports + ifeq (1,$(ENABLE_EMBED_STDCXX)) # It is needed to force static-stdc++.a linked. - # FIXME: It should be omitted when configure detects system's stdc++.dll. SHLIB_FRAG_NAMES += stdc++.a.o + endif endif @@ -61,14 +62,22 @@ ifeq ($(HOST_OS),Darwin) endif endif -ifeq ($(HOST_OS), Linux) +ifeq ($(HOST_OS), $(filter $(HOST_OS), Linux FreeBSD OpenBSD)) # Include everything from the .a's into the shared library. LLVMLibsOptions := -Wl,--whole-archive $(LLVMLibsOptions) \ -Wl,--no-whole-archive +endif + +ifeq ($(HOST_OS),Linux) # Don't allow unresolved symbols. LLVMLibsOptions += -Wl,--no-undefined endif +ifeq ($(HOST_OS),SunOS) + # add -z allextract ahead of other libraries on Solaris + LLVMLibsOptions := -Wl,-z -Wl,allextract $(LLVMLibsOptions) +endif + ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) SHLIB_STUBS := $(addprefix $(ObjDir)/, $(SHLIB_FRAG_NAMES)) diff --git a/tools/llvm-stub/llvm-stub.c b/tools/llvm-stub/llvm-stub.c index f2e478e..31c2d09 100644 --- a/tools/llvm-stub/llvm-stub.c +++ b/tools/llvm-stub/llvm-stub.c @@ -1,10 +1,10 @@ /*===- 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 @@ -64,7 +64,11 @@ int main(int argc, char** argv) { memcpy((char **)Args+2, argv+1, sizeof(char*)*argc); /* Run the JIT. */ - execvp(Interp, (char **)Args); +#ifndef _WIN32 + execvp(Interp, (char **)Args); /* POSIX execvp takes a char *const[]. */ +#else + execvp(Interp, Args); /* windows execvp takes a const char *const *. */ +#endif /* 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 " diff --git a/tools/llvmc/doc/LLVMC-Reference.rst b/tools/llvmc/doc/LLVMC-Reference.rst index d160e75..ec9098b 100644 --- a/tools/llvmc/doc/LLVMC-Reference.rst +++ b/tools/llvmc/doc/LLVMC-Reference.rst @@ -319,7 +319,8 @@ separate option groups syntactically. - ``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")`` + aliased option name. + Usage example: ``(alias_option "preprocess", "E")`` - ``switch_list_option`` - like ``switch_option`` with the ``zero_or_more`` property, but remembers how many times the switch was turned on. Useful @@ -456,22 +457,22 @@ use TableGen inheritance instead. * Possible tests are: - ``switch_on`` - Returns true if a given command-line switch is provided by - the user. Can be given a list as argument, in that case ``(switch_on ["foo", - "bar", "baz"])`` is equivalent to ``(and (switch_on "foo"), (switch_on + the user. Can be given multiple arguments, in that case ``(switch_on "foo", + "bar", "baz")`` is equivalent to ``(and (switch_on "foo"), (switch_on "bar"), (switch_on "baz"))``. Example: ``(switch_on "opt")``. - - ``any_switch_on`` - Given a list of switch options, returns true if any of + - ``any_switch_on`` - Given a number of switch options, returns true if any of the switches is turned on. - Example: ``(any_switch_on ["foo", "bar", "baz"])`` is equivalent to ``(or + Example: ``(any_switch_on "foo", "bar", "baz")`` is equivalent to ``(or (switch_on "foo"), (switch_on "bar"), (switch_on "baz"))``. - - ``parameter_equals`` - Returns true if a command-line parameter equals - a given value. + - ``parameter_equals`` - Returns true if a command-line parameter (first + argument) equals a given value (second argument). Example: ``(parameter_equals "W", "all")``. - - ``element_in_list`` - Returns true if a command-line parameter - list contains a given value. + - ``element_in_list`` - Returns true if a command-line parameter list (first + argument) contains a given value (second argument). Example: ``(element_in_list "l", "pthread")``. - ``input_languages_contain`` - Returns true if a given language @@ -479,27 +480,27 @@ use TableGen inheritance instead. Example: ``(input_languages_contain "c++")``. - ``in_language`` - Evaluates to true if the input file language is equal to - the argument. At the moment works only with ``cmd_line`` and ``actions`` (on + the argument. At the moment works only with ``command`` 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. Like ``switch_on``, can - be also given a list as argument. - Example: ``(not_empty "o")``. + be also given multiple arguments. + Examples: ``(not_empty "o")``, ``(not_empty "o", "l")``. - ``any_not_empty`` - Returns true if ``not_empty`` returns true for any of - the options in the list. - Example: ``(any_not_empty ["foo", "bar", "baz"])`` is equivalent to ``(or + the provided options. + Example: ``(any_not_empty "foo", "bar", "baz")`` is equivalent to ``(or (not_empty "foo"), (not_empty "bar"), (not_empty "baz"))``. - ``empty`` - The opposite of ``not_empty``. Equivalent to ``(not (not_empty - X))``. Provided for convenience. Can be given a list as argument. + X))``. Can be given multiple arguments. - ``any_not_empty`` - Returns true if ``not_empty`` returns true for any of - the options in the list. - Example: ``(any_empty ["foo", "bar", "baz"])`` is equivalent to ``(not (and - (not_empty "foo"), (not_empty "bar"), (not_empty "baz")))``. + the provided options. + Example: ``(any_empty "foo", "bar", "baz")`` is equivalent to ``(or + (not_empty "foo"), (not_empty "bar"), (not_empty "baz"))``. - ``single_input_file`` - Returns true if there was only one input file provided on the command-line. Used without arguments: @@ -511,16 +512,18 @@ use TableGen inheritance instead. - ``default`` - Always evaluates to true. Should always be the last test in the ``case`` expression. - - ``and`` - A standard binary logical combinator that returns true iff all of + - ``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`` - A binary logical combinator that returns true iff any of its - arguments returns true. Example: ``(or (test1), (test2), ... (testN))``. + - ``or`` - A logical combinator that returns true iff any of its arguments + return true. + Example: ``(or (test1), (test2), ... (testN))``. - ``not`` - Standard unary logical combinator that negates its - argument. Example: ``(not (or (test1), (test2), ... (testN)))``. + argument. + Example: ``(not (or (test1), (test2), ... (testN)))``. @@ -549,10 +552,10 @@ 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. + - ``in_language`` - input language name. Can be given multiple arguments, in + case the tool supports multiple input languages. - - ``out_language`` - output language name. Multiple output languages are not + - ``out_language`` - output language name. Multiple output languages are allowed. - ``output_suffix`` - output file suffix. Can also be changed @@ -687,12 +690,12 @@ occasions. Example (adapted from the built-in Base plugin):: def Preprocess : OptionPreprocessor< - (case (not (any_switch_on ["O0", "O1", "O2", "O3"])), + (case (not (any_switch_on "O0", "O1", "O2", "O3")), (set_option "O2"), - (and (switch_on "O3"), (any_switch_on ["O0", "O1", "O2"])), - (unset_option ["O0", "O1", "O2"]), - (and (switch_on "O2"), (any_switch_on ["O0", "O1"])), - (unset_option ["O0", "O1"]), + (and (switch_on "O3"), (any_switch_on "O0", "O1", "O2")), + (unset_option "O0", "O1", "O2"), + (and (switch_on "O2"), (any_switch_on "O0", "O1")), + (unset_option "O0", "O1"), (and (switch_on "O1"), (switch_on "O0")), (unset_option "O0")) >; @@ -709,10 +712,10 @@ set or unset a given option. To set an option with ``set_option``, use the two-argument form: ``(set_option "parameter", VALUE)``. Here, ``VALUE`` can be either a string, a string list, or a boolean constant. -For convenience, ``set_option`` and ``unset_option`` also work on lists. That -is, instead of ``[(unset_option "A"), (unset_option "B")]`` you can use -``(unset_option ["A", "B"])``. Obviously, ``(set_option ["A", "B"])`` is valid -only if both ``A`` and ``B`` are switches. +For convenience, ``set_option`` and ``unset_option`` also work with multiple +arguments. That is, instead of ``[(unset_option "A"), (unset_option "B")]`` you +can use ``(unset_option "A", "B")``. Obviously, ``(set_option "A", "B")`` is +only valid if both ``A`` and ``B`` are switches. More advanced topics diff --git a/tools/llvmc/examples/mcc16/Hooks.cpp b/tools/llvmc/examples/mcc16/Hooks.cpp index edb91e1..95158ef 100644 --- a/tools/llvmc/examples/mcc16/Hooks.cpp +++ b/tools/llvmc/examples/mcc16/Hooks.cpp @@ -1,4 +1,4 @@ -#include "llvm/System/Path.h" +#include "llvm/Support/Path.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/raw_ostream.h" diff --git a/tools/llvmc/examples/mcc16/Main.cpp b/tools/llvmc/examples/mcc16/Main.cpp index 55ae912..5d4992d 100644 --- a/tools/llvmc/examples/mcc16/Main.cpp +++ b/tools/llvmc/examples/mcc16/Main.cpp @@ -16,7 +16,7 @@ #include "llvm/CompilerDriver/BuiltinOptions.h" #include "llvm/CompilerDriver/Main.h" -#include "llvm/System/Path.h" +#include "llvm/Support/Path.h" #include "llvm/Config/config.h" #include diff --git a/tools/llvmc/src/Base.td.in b/tools/llvmc/src/Base.td.in index 0c4de4c..50533f1 100644 --- a/tools/llvmc/src/Base.td.in +++ b/tools/llvmc/src/Base.td.in @@ -11,7 +11,6 @@ // //===----------------------------------------------------------------------===// - // Options def OptList : OptionList<[ @@ -35,8 +34,6 @@ def OptList : OptionList<[ (help "Stop after compilation, do not assemble")), (switch_option "c", (help "Compile and assemble, but do not link")), - (switch_option "pthread", - (help "Enable threads")), (switch_option "m32", (help "Generate code for a 32-bit environment"), (hidden)), (switch_option "m64", @@ -45,22 +42,21 @@ def OptList : OptionList<[ (help "Relocation model: PIC"), (hidden)), (switch_option "mdynamic-no-pic", (help "Relocation model: dynamic-no-pic"), (hidden)), - (switch_option "shared", - (help "Create a DLL instead of the regular executable")), (parameter_option "linker", (help "Choose linker (possible values: gcc, g++)")), (parameter_option "mtune", - (help "Target a specific CPU type"), (hidden), (forward_not_split)), - - // TODO: Add a conditional compilation mechanism to make Darwin-only options - // like '-arch' really Darwin-only. - - (parameter_option "arch", - (help "Compile for the specified target architecture"), (hidden)), - (parameter_option "march", - (help "A synonym for -mtune"), (hidden), (forward_not_split)), + (help "Target a specific CPU type"), (forward_not_split)), + (parameter_list_option "march", + (help "Generate code for the specified machine type")), (parameter_option "mcpu", (help "A deprecated synonym for -mtune"), (hidden), (forward_not_split)), + (parameter_option "mfpu", + (help "Specify type of floating point unit"), + (hidden), (forward_not_split)), + (parameter_option "mabi", + (help "Generate code for the specified ABI"), (hidden)), + (parameter_option "mfloat-abi", + (help "Specifies which floating-point ABI to use"), (hidden)), (switch_option "mfix-and-continue", (help "Needed by gdb to load .o files dynamically"), (hidden)), (parameter_option "MF", @@ -73,14 +69,6 @@ def OptList : OptionList<[ (parameter_list_option "iquote", (help "Search dir only for files requested with #inlcude \"file\""), (hidden)), - (parameter_list_option "framework", - (help "Specifies a framework to link against")), - (parameter_list_option "weak_framework", - (help "Specifies a framework to weakly link against"), (hidden)), - (parameter_option "filelist", (hidden), - (help "Link the files listed in file")), - (prefix_list_option "F", - (help "Add a directory to framework search path")), (prefix_list_option "I", (help "Add a directory to include path")), (prefix_list_option "D", @@ -93,10 +81,6 @@ def OptList : OptionList<[ (help "Pass options to assembler")), (prefix_list_option "Wllc,", (comma_separated), (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")), (parameter_list_option "Xlinker", (hidden), @@ -105,7 +89,56 @@ def OptList : OptionList<[ (help "Pass options to opt")), (prefix_list_option "m", (help "Enable or disable various extensions (-mmmx, -msse, etc.)"), - (hidden)), + (hidden)) +]>; + +def LinkerOptList : OptionList<[ + (prefix_list_option "L", + (help "Add a directory to link path")), + (prefix_list_option "l", + (help "Search a library when linking")), + (parameter_option "filelist", (hidden), + (help "Link the files listed in file")), + (switch_option "nostartfiles", + (help "Do not use the standard system startup files when linking"), + (hidden)), + (switch_option "nodefaultlibs", + (help "Do not use the standard system libraries when linking"), (hidden)), + (switch_option "nostdlib", + (help + "Do not use the standard system startup files or libraries when linking"), + (hidden)), + (switch_option "pie", + (help "Produce a position independent executable"), (hidden)), + (switch_option "rdynamic", + (help "Add all symbols to the dynamic export table"), (hidden)), + (switch_option "s", + (help "Strip all symbols"), (hidden)), + (switch_option "static", + (help "Do not link against shared libraries"), (hidden)), + (switch_option "static-libgcc", + (help "Use static libgcc"), (hidden)), + (switch_option "shared", + (help "Create a DLL instead of the regular executable")), + (switch_option "shared-libgcc", + (help "Use shared libgcc"), (hidden)), + (parameter_option "T", + (help "Read linker script"), (hidden)), + (parameter_option "u", + (help "Start with undefined reference to SYMBOL"), (hidden)), + (switch_option "pthread", + (help "Enable threads")), + + // TODO: Add a conditional compilation mechanism to make Darwin-only options + // like '-arch' really Darwin-only. + (parameter_option "arch", + (help "Compile for the specified target architecture"), (hidden)), + (prefix_list_option "F", + (help "Add a directory to framework search path")), + (parameter_list_option "framework", + (help "Specifies a framework to link against")), + (parameter_list_option "weak_framework", + (help "Specifies a framework to weakly link against"), (hidden)), (switch_option "dynamiclib", (hidden), (help "Produce a dynamic library")), (switch_option "prebind", (hidden), @@ -125,24 +158,24 @@ def OptList : OptionList<[ // Option preprocessor. def Preprocess : OptionPreprocessor< -(case (not (any_switch_on ["O0", "O1", "O2", "O3"])), +(case (not (any_switch_on "O0", "O1", "O2", "O3")), (set_option "O2"), - (and (switch_on "O3"), (any_switch_on ["O0", "O1", "O2"])), - (unset_option ["O0", "O1", "O2"]), - (and (switch_on "O2"), (any_switch_on ["O0", "O1"])), - (unset_option ["O0", "O1"]), - (switch_on ["O1", "O0"]), + (and (switch_on "O3"), (any_switch_on "O0", "O1", "O2")), + (unset_option "O0", "O1", "O2"), + (and (switch_on "O2"), (any_switch_on "O0", "O1")), + (unset_option "O0", "O1"), + (switch_on "O1", "O0"), (unset_option "O0")) >; // Tools -class llvm_gcc_based : Tool< +class llvm_gcc_based : Tool< [(in_language in_lang), - (out_language "llvm-bitcode"), - (output_suffix out_lang), - (command cmd_prefix), + out_lang, + (output_suffix out_ext), + (command cmd), (actions (case (and (not_empty "o"), @@ -151,14 +184,20 @@ class llvm_gcc_based stop compilation + (and (switch_on "emit-llvm"), (not (switch_on "opt"))), + (stop_compilation), + // ('-S' && '-emit-llvm') && !('opt') -> output .ll + (and (switch_on "emit-llvm", "S"), (not (switch_on "opt"))), + [(forward "S"), (output_suffix "ll")], + // Ususally just output .bc + (not (switch_on "fsyntax-only")), + [(append_cmd "-c"), (append_cmd "-emit-llvm")], + + // -fsyntax-only (switch_on "fsyntax-only"), [(forward "fsyntax-only"), (no_out_file), (stop_compilation)], - (switch_on ["S", "emit-llvm"]), [(forward "S"), (forward "emit-llvm")], - (not (or (switch_on ["S", "emit-llvm"]), (switch_on "fsyntax-only"))), - [(append_cmd "-c"), (append_cmd "-emit-llvm")], // Forwards (not_empty "Xpreprocessor"), (forward "Xpreprocessor"), @@ -170,8 +209,11 @@ class llvm_gcc_based ; -def llvm_gcc_c : llvm_gcc_based<"@LLVMGCCCOMMAND@ -x c", "c", "i", "bc">; -def llvm_gcc_cpp : llvm_gcc_based<"@LLVMGXXCOMMAND@ -x c++", "c++", "i", "bc">; -def llvm_gcc_m : llvm_gcc_based<"@LLVMGCCCOMMAND@ -x objective-c", - "objective-c", "mi", "bc">; -def llvm_gcc_mxx : llvm_gcc_based<"@LLVMGCCCOMMAND@ -x objective-c++", - "objective-c++", "mi", "bc">; +class llvm_gcc_comp_based +: llvm_gcc_based; + +class llvm_gcc_pch_based +: llvm_gcc_based; -def llvm_gcc_c_pch : llvm_gcc_based<"@LLVMGCCCOMMAND@ -x c-header", - "c-header", "i", "gch">; -def llvm_gcc_cpp_pch : llvm_gcc_based<"@LLVMGXXCOMMAND@ -x c++-header", - "c++-header", - "i", "gch">; -def llvm_gcc_m_pch : llvm_gcc_based<"@LLVMGCCCOMMAND@ -x objective-c-header", - "objective-c-header", - "mi", "gch">; -def llvm_gcc_mxx_pch - : llvm_gcc_based<"@LLVMGCCCOMMAND@ -x objective-c++-header", - "objective-c++-header", "mi", "gch">; +def llvm_gcc_c : llvm_gcc_comp_based + <"@LLVMGCCCOMMAND@ -x c", "c", "i">; +def llvm_gcc_cpp : llvm_gcc_comp_based + <"@LLVMGXXCOMMAND@ -x c++", "c++", "i">; +def llvm_gcc_m : llvm_gcc_comp_based + <"@LLVMGCCCOMMAND@ -x objective-c", "objective-c", "mi">; +def llvm_gcc_mxx : llvm_gcc_comp_based + <"@LLVMGCCCOMMAND@ -x objective-c++", "objective-c++", "mi">; + +def llvm_gcc_c_pch : llvm_gcc_pch_based + <"@LLVMGCCCOMMAND@ -x c-header", "c-header", "i">; +def llvm_gcc_cpp_pch : llvm_gcc_pch_based + <"@LLVMGXXCOMMAND@ -x c++-header", "c++-header", "i">; +def llvm_gcc_m_pch : llvm_gcc_pch_based + <"@LLVMGCCCOMMAND@ -x objective-c-header", "objective-c-header", "mi">; +def llvm_gcc_mxx_pch : llvm_gcc_pch_based + <"@LLVMGCCCOMMAND@ -x objective-c++-header", "objective-c++-header", "mi">; def opt : Tool< [(in_language "llvm-bitcode"), (out_language "llvm-bitcode"), - (output_suffix "bc"), - (actions (case (not_empty "Wo,"), (forward_value "Wo,"), + (output_suffix "opt.bc"), + (actions (case (switch_on "emit-llvm"), (stop_compilation), + (switch_on "emit-llvm", "S"), + [(append_cmd "-S"), (output_suffix "ll")], + (not_empty "Wo,"), (forward_value "Wo,"), (switch_on "O1"), (forward "O1"), (switch_on "O2"), (forward "O2"), (switch_on "O3"), (forward "O3"))), @@ -222,7 +274,8 @@ def llvm_as : Tool< (out_language "llvm-bitcode"), (output_suffix "bc"), (command "llvm-as"), - (actions (case (switch_on "emit-llvm"), (stop_compilation))) + (actions (case (and (switch_on "emit-llvm"), (not (switch_on "opt"))), + (stop_compilation))) ]>; def llvm_gcc_assembler : Tool< @@ -234,13 +287,18 @@ def llvm_gcc_assembler : Tool< (switch_on "c"), (stop_compilation), (not_empty "arch"), (forward "arch"), (not_empty "Xassembler"), (forward "Xassembler"), + (not_empty "march"), (forward "march"), + (not_empty "mcpu"), (forward "mcpu"), + (not_empty "mtune"), (forward "mtune"), + (not_empty "mabi"), (forward "mabi"), + (not_empty "mfloat-abi"), (forward "mfloat-abi"), (switch_on "m32"), (forward "m32"), (switch_on "m64"), (forward "m64"), (not_empty "Wa,"), (forward "Wa,"))) ]>; def llc : Tool< -[(in_language ["llvm-bitcode", "llvm-assembler"]), +[(in_language "llvm-bitcode", "llvm-assembler"), (out_language "assembler"), (output_suffix "s"), (command "llc"), @@ -253,19 +311,22 @@ def llc : Tool< (switch_on "fPIC"), (append_cmd "-relocation-model=pic"), (switch_on "mdynamic-no-pic"), (append_cmd "-relocation-model=dynamic-no-pic"), - (not_empty "march"), (forward_as "mtune", "-mcpu"), - (not_empty "mtune"), (forward_as "mtune", "-mcpu"), - (not_empty "mcpu"), (forward "mcpu"), + (not_empty "march"), (forward_transformed_value + "march", "ConvertMArchToMAttr"), + (not_empty "mcpu"), (forward_transformed_value "mcpu", "ConvertMCpu"), + (and (not_empty "mtune"), (empty "mcpu")), + (forward_as "mtune", "-mcpu"), + (not_empty "mfpu"), (forward_transformed_value "mfpu", "ConvertMFpu"), (not_empty "m"), (forward_transformed_value "m", "ConvertToMAttr"), (not_empty "Wllc,"), (forward_value "Wllc,"))) ]>; // Base class for linkers -class llvm_gcc_based_linker : Tool< -[(in_language ["object-code", "static-library", "dynamic-library"]), +class llvm_gcc_based_linker : Tool< +[(in_language "object-code", "static-library", "dynamic-library"), (out_language "executable"), (output_suffix "out"), - (command cmd_prefix), + (command cmd), (works_on_empty (case (and (not_empty "filelist"), on_empty), true, (default), false)), (join), @@ -277,12 +338,28 @@ class llvm_gcc_based_linker : Tool< (not_empty "framework"), (forward "framework"), (not_empty "weak_framework"), (forward "weak_framework"), (not_empty "filelist"), (forward "filelist"), + (not_empty "march"), (forward "march"), + (not_empty "mcpu"), (forward "mcpu"), + (not_empty "mtune"), (forward "mtune"), + (not_empty "mabi"), (forward "mabi"), + (not_empty "mfloat-abi"), (forward "mfloat-abi"), (switch_on "m32"), (forward "m32"), (switch_on "m64"), (forward "m64"), (not_empty "l"), (forward "l"), (not_empty "Xlinker"), (forward "Xlinker"), (not_empty "Wl,"), (forward "Wl,"), + (switch_on "nostartfiles"), (forward "nostartfiles"), + (switch_on "nodefaultlibs"), (forward "nodefaultlibs"), + (switch_on "nostdlib"), (forward "nostdlib"), + (switch_on "pie"), (forward "pie"), + (switch_on "rdynamic"), (forward "rdynamic"), + (switch_on "s"), (forward "s"), + (switch_on "static"), (forward "static"), + (switch_on "static-libgcc"), (forward "static-libgcc"), (switch_on "shared"), (forward "shared"), + (switch_on "shared-libgcc"), (forward "shared-libgcc"), + (not_empty "T"), (forward "T"), + (not_empty "u"), (forward "u"), (switch_on "dynamiclib"), (forward "dynamiclib"), (switch_on "prebind"), (forward "prebind"), (switch_on "dead_strip"), (forward "dead_strip"), @@ -305,6 +382,7 @@ def llvm_gcc_cpp_linker : llvm_gcc_based_linker<"@LLVMGXXCOMMAND@", // Language map def LanguageMap : LanguageMap<[ + (lang_to_suffixes "precompiled-header", ["gch", "pch"]), (lang_to_suffixes "c++", ["cc", "cp", "cxx", "cpp", "CPP", "c++", "C"]), (lang_to_suffixes "c++-header", "hpp"), (lang_to_suffixes "c", "c"), @@ -322,7 +400,7 @@ def LanguageMap : LanguageMap<[ (lang_to_suffixes "object-code", ["o", "*empty*"]), (lang_to_suffixes "static-library", ["a", "lib"]), (lang_to_suffixes "dynamic-library", ["so", "dylib", "dll"]), - (lang_to_suffixes "executable", ["out"]) + (lang_to_suffixes "executable", "out") ]>; // Compilation graph @@ -347,7 +425,8 @@ def CompilationGraph : CompilationGraph<[ (edge "llvm_as", "llc"), (optional_edge "root", "llvm_as", - (case (switch_on "emit-llvm"), (inc_weight))), + (case (or (switch_on "emit-llvm"), + (switch_on "opt")), (inc_weight))), (optional_edge "llvm_gcc_c", "opt", (case (switch_on "opt"), (inc_weight))), (optional_edge "llvm_gcc_cpp", "opt", diff --git a/tools/llvmc/src/Clang.td b/tools/llvmc/src/Clang.td index 1d75743..e2d32e8 100644 --- a/tools/llvmc/src/Clang.td +++ b/tools/llvmc/src/Clang.td @@ -25,12 +25,12 @@ class clang_based : Tool< [(forward "E"), (stop_compilation), (output_suffix ext_E)], (and (switch_on "E"), (empty "o")), (no_out_file), (switch_on "fsyntax-only"), (stop_compilation), - (switch_on ["S", "emit-llvm"]), + (switch_on "S", "emit-llvm"), [(append_cmd "-emit-llvm"), (stop_compilation), (output_suffix "ll")], - (not (switch_on ["S", "emit-llvm"])), + (not (switch_on "S", "emit-llvm")), (append_cmd "-emit-llvm-bc"), - (switch_on ["c", "emit-llvm"]), + (switch_on "c", "emit-llvm"), (stop_compilation), (not_empty "include"), (forward "include"), (not_empty "I"), (forward "I"))), diff --git a/tools/llvmc/src/Hooks.cpp b/tools/llvmc/src/Hooks.cpp index 661a914..5aa250e 100644 --- a/tools/llvmc/src/Hooks.cpp +++ b/tools/llvmc/src/Hooks.cpp @@ -1,14 +1,182 @@ +#include "llvm/ADT/StringMap.h" + #include #include namespace hooks { + +/// NUM_KEYS - Calculate the size of a const char* array. +#define NUM_KEYS(Keys) sizeof(Keys) / sizeof(const char*) + +// See http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 +inline unsigned NextHighestPowerOf2 (unsigned i) { + --i; + i |= i >> 1; + i |= i >> 2; + i |= i >> 4; + i |= i >> 8; + i |= i >> 16; + ++i; + return i; +} + typedef std::vector StrVec; +typedef llvm::StringMap ArgMap; + +/// AddPlusOrMinus - Convert 'no-foo' to '-foo' and 'foo' to '+foo'. +void AddPlusOrMinus (const std::string& Arg, std::string& out) { + if (Arg.find("no-") == 0 && Arg[3] != 0) { + out += '-'; + out += Arg.c_str() + 3; + } + else { + out += '+'; + out += Arg; + } +} + +// -march values that need to be special-cased. +const char* MArchKeysARM[] = { "armv4t", "armv5t", "armv5te", "armv6", + "armv6-m", "armv6t2", "armv7-a", "armv7-m" }; +const char* MArchValuesARM[] = { "v4t", "v5t", "v5te", "v6", "v6m", "v6t2", + "v7a", "v7m" }; +const unsigned MArchNumKeysARM = NUM_KEYS(MArchKeysARM); +const unsigned MArchMapSize = NextHighestPowerOf2(MArchNumKeysARM); + +// -march values that should be forwarded as -mcpu +const char* MArchMCpuKeysARM[] = { "iwmmxt", "ep9312" }; +const char* MArchMCpuValuesARM[] = { "iwmmxt", "ep9312"}; +const unsigned MArchMCpuNumKeysARM = NUM_KEYS(MArchMCpuKeysARM); +const unsigned MArchMCpuMapSize = NextHighestPowerOf2(MArchMCpuNumKeysARM); + + +void FillInArgMap(ArgMap& Args, const char* Keys[], + const char* Values[], unsigned NumKeys) +{ + for (unsigned i = 0; i < NumKeys; ++i) { + // Explicit cast to StringRef here is necessary to pick up the right + // overload. + Args.GetOrCreateValue(llvm::StringRef(Keys[i]), Values[i]); + } +} + +/// ConvertMArchToMAttr - Convert -march from the gcc dialect to +/// something llc can understand. +std::string ConvertMArchToMAttr(const StrVec& Opts) { + static ArgMap MArchMap(MArchMapSize); + static ArgMap MArchMCpuMap(MArchMapSize); + static bool StaticDataInitialized = false; + + if (!StaticDataInitialized) { + FillInArgMap(MArchMap, MArchKeysARM, MArchValuesARM, MArchNumKeysARM); + FillInArgMap(MArchMCpuMap, MArchMCpuKeysARM, + MArchMCpuValuesARM, MArchMCpuNumKeysARM); + StaticDataInitialized = true; + } + + std::string mattr("-mattr="); + std::string mcpu("-mcpu="); + bool mattrTouched = false; + bool mcpuTouched = false; + + for (StrVec::const_iterator B = Opts.begin(), E = Opts.end(); B!=E; ++B) { + const std::string& Arg = *B; + + // Check if the argument should be forwarded to -mcpu instead of -mattr. + { + ArgMap::const_iterator I = MArchMCpuMap.find(Arg); + + if (I != MArchMCpuMap.end()) { + mcpuTouched = true; + mcpu += I->getValue(); + continue; + } + } + + if (mattrTouched) + mattr += ","; + + // Check if the argument is a special case. + { + ArgMap::const_iterator I = MArchMap.find(Arg); -/// ConvertToMAttr - Convert -m* and -mno-* to -mattr=+*,-* + if (I != MArchMap.end()) { + mattrTouched = true; + mattr += '+'; + mattr += I->getValue(); + continue; + } + } + + AddPlusOrMinus(Arg, mattr); + } + + std::string out; + if (mattrTouched) + out += mattr; + if (mcpuTouched) + out += (mattrTouched ? " " : "") + mcpu; + + return out; +} + +// -mcpu values that need to be special-cased. +const char* MCpuKeysPPC[] = { "G3", "G4", "G5", "powerpc", "powerpc64"}; +const char* MCpuValuesPPC[] = { "g3", "g4", "g5", "ppc", "ppc64"}; +const unsigned MCpuNumKeysPPC = NUM_KEYS(MCpuKeysPPC); +const unsigned MCpuMapSize = NextHighestPowerOf2(MCpuNumKeysPPC); + +/// ConvertMCpu - Convert -mcpu value from the gcc to the llc dialect. +std::string ConvertMCpu(const char* Val) { + static ArgMap MCpuMap(MCpuMapSize); + static bool StaticDataInitialized = false; + + if (!StaticDataInitialized) { + FillInArgMap(MCpuMap, MCpuKeysPPC, MCpuValuesPPC, MCpuNumKeysPPC); + StaticDataInitialized = true; + } + + std::string ret = "-mcpu="; + ArgMap::const_iterator I = MCpuMap.find(Val); + if (I != MCpuMap.end()) { + return ret + I->getValue(); + } + return ret + Val; +} + +// -mfpu values that need to be special-cased. +const char* MFpuKeysARM[] = { "vfp", "vfpv3", + "vfpv3-fp16", "vfpv3-d16", "vfpv3-d16-fp16", + "neon", "neon-fp16" }; +const char* MFpuValuesARM[] = { "vfp2", "vfp3", + "+vfp3,+fp16", "+vfp3,+d16", "+vfp3,+d16,+fp16", + "+neon", "+neon,+neonfp" }; +const unsigned MFpuNumKeysARM = NUM_KEYS(MFpuKeysARM); +const unsigned MFpuMapSize = NextHighestPowerOf2(MFpuNumKeysARM); + +/// ConvertMFpu - Convert -mfpu value from the gcc to the llc dialect. +std::string ConvertMFpu(const char* Val) { + static ArgMap MFpuMap(MFpuMapSize); + static bool StaticDataInitialized = false; + + if (!StaticDataInitialized) { + FillInArgMap(MFpuMap, MFpuKeysARM, MFpuValuesARM, MFpuNumKeysARM); + StaticDataInitialized = true; + } + + std::string ret = "-mattr="; + ArgMap::const_iterator I = MFpuMap.find(Val); + if (I != MFpuMap.end()) { + return ret + I->getValue(); + } + return ret + '+' + Val; +} + +/// ConvertToMAttr - Convert '-mfoo' and '-mno-bar' to '-mattr=+foo,-bar'. std::string ConvertToMAttr(const StrVec& Opts) { std::string out("-mattr="); - bool firstIter = true; + for (StrVec::const_iterator B = Opts.begin(), E = Opts.end(); B!=E; ++B) { const std::string& Arg = *B; @@ -17,14 +185,7 @@ std::string ConvertToMAttr(const StrVec& Opts) { else out += ","; - if (Arg.find("no-") == 0 && Arg[3] != 0) { - out += '-'; - out += Arg.c_str() + 3; - } - else { - out += '+'; - out += Arg; - } + AddPlusOrMinus(Arg, out); } return out; diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp index 671348c..adb7102 100644 --- a/tools/lto/LTOCodeGenerator.cpp +++ b/tools/lto/LTOCodeGenerator.cpp @@ -39,9 +39,11 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/StandardPasses.h" #include "llvm/Support/SystemUtils.h" -#include "llvm/System/Host.h" -#include "llvm/System/Program.h" -#include "llvm/System/Signals.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/system_error.h" #include "llvm/Config/config.h" #include #include @@ -183,7 +185,7 @@ 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) ) + if ( uniqueAsmPath.createTemporaryFileOnDisk(false, &errMsg) ) return NULL; sys::RemoveFileOnSignal(uniqueAsmPath); @@ -208,7 +210,7 @@ const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) // make unique temp .o file to put generated object file sys::PathWithStatus uniqueObjPath("lto-llvm.o"); - if ( uniqueObjPath.createTemporaryFileOnDisk(true, &errMsg) ) { + if ( uniqueObjPath.createTemporaryFileOnDisk(false, &errMsg) ) { uniqueAsmPath.eraseFromDisk(); return NULL; } @@ -220,9 +222,12 @@ const void* LTOCodeGenerator::compile(size_t* length, std::string& 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); + OwningPtr BuffPtr; + if (error_code ec = MemoryBuffer::getFile(uniqueObjStr.c_str(),BuffPtr)) + errMsg = ec.message(); + _nativeObjectFile = BuffPtr.take(); } // remove temp files @@ -342,21 +347,34 @@ void LTOCodeGenerator::applyScopeRestrictions() { // mark which symbols can not be internalized if (!_mustPreserveSymbols.empty()) { - MCContext Context(*_target->getMCAsmInfo()); + MCContext Context(*_target->getMCAsmInfo(), NULL); Mangler mangler(Context, *_target->getTargetData()); std::vector mustPreserveList; + SmallString<64> Buffer; for (Module::iterator f = mergedModule->begin(), e = mergedModule->end(); f != e; ++f) { + Buffer.clear(); + mangler.getNameWithPrefix(Buffer, f, false); if (!f->isDeclaration() && - _mustPreserveSymbols.count(mangler.getNameWithPrefix(f))) + _mustPreserveSymbols.count(Buffer)) mustPreserveList.push_back(::strdup(f->getNameStr().c_str())); } for (Module::global_iterator v = mergedModule->global_begin(), e = mergedModule->global_end(); v != e; ++v) { + Buffer.clear(); + mangler.getNameWithPrefix(Buffer, v, false); if (!v->isDeclaration() && - _mustPreserveSymbols.count(mangler.getNameWithPrefix(v))) + _mustPreserveSymbols.count(Buffer)) mustPreserveList.push_back(::strdup(v->getNameStr().c_str())); } + for (Module::alias_iterator a = mergedModule->alias_begin(), + e = mergedModule->alias_end(); a != e; ++a) { + Buffer.clear(); + mangler.getNameWithPrefix(Buffer, a, false); + if (!a->isDeclaration() && + _mustPreserveSymbols.count(Buffer)) + mustPreserveList.push_back(::strdup(a->getNameStr().c_str())); + } passes.add(createInternalizePass(mustPreserveList)); } diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp index c7cd585..8562f74 100644 --- a/tools/lto/LTOModule.cpp +++ b/tools/lto/LTOModule.cpp @@ -23,9 +23,10 @@ #include "llvm/Support/SystemUtils.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MathExtras.h" -#include "llvm/System/Host.h" -#include "llvm/System/Path.h" -#include "llvm/System/Process.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/system_error.h" #include "llvm/Target/Mangler.h" #include "llvm/Target/SubtargetFeature.h" #include "llvm/MC/MCAsmInfo.h" @@ -56,23 +57,18 @@ bool LTOModule::isBitcodeFileForTarget(const void *mem, size_t length, bool LTOModule::isBitcodeFileForTarget(const char *path, const char *triplePrefix) { - MemoryBuffer *buffer = MemoryBuffer::getFile(path); - if (buffer == NULL) + OwningPtr buffer; + if (MemoryBuffer::getFile(path, buffer)) return false; - return isTargetMatch(buffer, triplePrefix); + return isTargetMatch(buffer.take(), triplePrefix); } // Takes ownership of buffer. bool LTOModule::isTargetMatch(MemoryBuffer *buffer, const char *triplePrefix) { - OwningPtr m(getLazyBitcodeModule(buffer, getGlobalContext())); - // On success, m owns buffer and both are deleted at end of this method. - if (!m) { - delete buffer; - return false; - } - std::string actualTarget = m->getTargetTriple(); - return (strncmp(actualTarget.c_str(), triplePrefix, - strlen(triplePrefix)) == 0); + std::string Triple = getBitcodeTargetTriple(buffer, getGlobalContext()); + delete buffer; + return (strncmp(Triple.c_str(), triplePrefix, + strlen(triplePrefix)) == 0); } @@ -83,9 +79,22 @@ LTOModule::LTOModule(Module *m, TargetMachine *t) LTOModule *LTOModule::makeLTOModule(const char *path, std::string &errMsg) { - OwningPtr buffer(MemoryBuffer::getFile(path, &errMsg)); - if (!buffer) + OwningPtr buffer; + if (error_code ec = MemoryBuffer::getFile(path, buffer)) { + errMsg = ec.message(); return NULL; + } + return makeLTOModule(buffer.get(), errMsg); +} + +LTOModule *LTOModule::makeLTOModule(int fd, const char *path, + off_t size, + std::string &errMsg) { + OwningPtr buffer; + if (error_code ec = MemoryBuffer::getOpenFile(fd, path, buffer, size)) { + errMsg = ec.message(); + return NULL; + } return makeLTOModule(buffer.get(), errMsg); } @@ -306,8 +315,14 @@ void LTOModule::addDefinedSymbol(GlobalValue *def, Mangler &mangler, if (def->getName().startswith("llvm.")) return; + // ignore available_externally + if (def->hasAvailableExternallyLinkage()) + return; + // string is owned by _defines - const char *symbolName = ::strdup(mangler.getNameWithPrefix(def).c_str()); + SmallString<64> Buffer; + mangler.getNameWithPrefix(Buffer, def, false); + const char *symbolName = ::strdup(Buffer.c_str()); // set alignment part log2() can have rounding errors uint32_t align = def->getAlignment(); @@ -325,24 +340,26 @@ void LTOModule::addDefinedSymbol(GlobalValue *def, Mangler &mangler, } // set definition part - if (def->hasWeakLinkage() || def->hasLinkOnceLinkage()) { + if (def->hasWeakLinkage() || def->hasLinkOnceLinkage() || + def->hasLinkerPrivateWeakLinkage() || + def->hasLinkerPrivateWeakDefAutoLinkage()) attr |= LTO_SYMBOL_DEFINITION_WEAK; - } - else if (def->hasCommonLinkage()) { + else if (def->hasCommonLinkage()) attr |= LTO_SYMBOL_DEFINITION_TENTATIVE; - } - else { + 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()) + else if (def->hasExternalLinkage() || def->hasWeakLinkage() || + def->hasLinkOnceLinkage() || def->hasCommonLinkage() || + def->hasLinkerPrivateWeakLinkage()) attr |= LTO_SYMBOL_SCOPE_DEFAULT; + else if (def->hasLinkerPrivateWeakDefAutoLinkage()) + attr |= LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN; else attr |= LTO_SYMBOL_SCOPE_INTERNAL; @@ -380,7 +397,8 @@ void LTOModule::addPotentialUndefinedSymbol(GlobalValue *decl, if (isa(decl)) return; - std::string name = mangler.getNameWithPrefix(decl); + SmallString<64> name; + mangler.getNameWithPrefix(name, decl, false); // we already have the symbol if (_undefines.find(name) != _undefines.end()) @@ -426,7 +444,7 @@ void LTOModule::lazyParseSymbols() { _symbolsParsed = true; // Use mangler to add GlobalPrefix to names to match linker names. - MCContext Context(*_target->getMCAsmInfo()); + MCContext Context(*_target->getMCAsmInfo(), NULL); Mangler mangler(Context, *_target->getTargetData()); // add functions @@ -472,6 +490,15 @@ void LTOModule::lazyParseSymbols() { pos = inlineAsm.find(glbl, pend); } + // add aliases + for (Module::alias_iterator i = _module->alias_begin(), + e = _module->alias_end(); i != e; ++i) { + if (i->isDeclaration()) + addPotentialUndefinedSymbol(i, mangler); + else + addDefinedDataSymbol(i, mangler); + } + // make symbols for all undefines for (StringMap::iterator it=_undefines.begin(); it != _undefines.end(); ++it) { diff --git a/tools/lto/LTOModule.h b/tools/lto/LTOModule.h index a19acc0..1794d81 100644 --- a/tools/lto/LTOModule.h +++ b/tools/lto/LTOModule.h @@ -51,6 +51,9 @@ struct LTOModule { static LTOModule* makeLTOModule(const char* path, std::string& errMsg); + static LTOModule* makeLTOModule(int fd, const char *path, + off_t size, + std::string& errMsg); static LTOModule* makeLTOModule(const void* mem, size_t length, std::string& errMsg); diff --git a/tools/lto/Makefile b/tools/lto/Makefile index e157a4c..294c81b 100644 --- a/tools/lto/Makefile +++ b/tools/lto/Makefile @@ -24,6 +24,10 @@ LINK_COMPONENTS := $(TARGETS_TO_BUILD) ipo scalaropts linker bitreader bitwriter include $(LEVEL)/Makefile.common +ifdef LLVM_VERSION_INFO +CXX.Flags += -DLLVM_VERSION_INFO='"$(LLVM_VERSION_INFO)"' +endif + ifeq ($(HOST_OS),Darwin) # Special hack to allow libLTO to have an offset version number. ifdef LLVM_LTO_VERSION_OFFSET diff --git a/tools/lto/lto.cpp b/tools/lto/lto.cpp index 3d7ef0a..7d4871d 100644 --- a/tools/lto/lto.cpp +++ b/tools/lto/lto.cpp @@ -91,6 +91,14 @@ lto_module_t lto_module_create(const char* path) return LTOModule::makeLTOModule(path, sLastErrorString); } +// +// loads an object file from disk +// returns NULL on error (check lto_get_error_message() for details) +// +lto_module_t lto_module_create_from_fd(int fd, const char *path, off_t size) +{ + return LTOModule::makeLTOModule(fd, path, size, sLastErrorString); +} // // loads an object file from memory @@ -132,7 +140,7 @@ void lto_module_set_target_triple(lto_module_t mod, const char *triple) // // returns the number of symbols in the object module // -uint32_t lto_module_get_num_symbols(lto_module_t mod) +unsigned int lto_module_get_num_symbols(lto_module_t mod) { return mod->getSymbolCount(); } @@ -140,7 +148,7 @@ uint32_t lto_module_get_num_symbols(lto_module_t mod) // // 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) +const char* lto_module_get_symbol_name(lto_module_t mod, unsigned int index) { return mod->getSymbolName(index); } @@ -150,7 +158,7 @@ const char* lto_module_get_symbol_name(lto_module_t mod, uint32_t 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) + unsigned int index) { return mod->getSymbolAttributes(index); } diff --git a/tools/lto/lto.exports b/tools/lto/lto.exports index 4dbf760..a374091 100644 --- a/tools/lto/lto.exports +++ b/tools/lto/lto.exports @@ -1,6 +1,7 @@ lto_get_error_message lto_get_version lto_module_create +lto_module_create_from_fd lto_module_create_from_memory lto_module_get_num_symbols lto_module_get_symbol_attribute diff --git a/tools/macho-dump/CMakeLists.txt b/tools/macho-dump/CMakeLists.txt new file mode 100644 index 0000000..d55e1d5 --- /dev/null +++ b/tools/macho-dump/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} support object) + +add_llvm_tool(macho-dump + macho-dump.cpp + ) diff --git a/tools/macho-dump/Makefile b/tools/macho-dump/Makefile new file mode 100644 index 0000000..638015e --- /dev/null +++ b/tools/macho-dump/Makefile @@ -0,0 +1,23 @@ +##===- tools/macho-dump/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 = macho-dump + +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS = 1 + +# 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 := support object + +include $(LLVM_SRC_ROOT)/Makefile.rules diff --git a/tools/macho-dump/macho-dump.cpp b/tools/macho-dump/macho-dump.cpp new file mode 100644 index 0000000..c4c558d --- /dev/null +++ b/tools/macho-dump/macho-dump.cpp @@ -0,0 +1,391 @@ +//===-- macho-dump.cpp - Mach Object Dumping Tool -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is a testing tool for use with the MC/Mach-O LLVM components. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/MachOObject.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/system_error.h" +using namespace llvm; +using namespace llvm::object; + +static cl::opt +InputFile(cl::Positional, cl::desc(""), cl::init("-")); + +static cl::opt +ShowSectionData("dump-section-data", cl::desc("Dump the contents of sections"), + cl::init(false)); + +/// + +static const char *ProgramName; + +static void Message(const char *Type, const Twine &Msg) { + errs() << ProgramName << ": " << Type << ": " << Msg << "\n"; +} + +static int Error(const Twine &Msg) { + Message("error", Msg); + return 1; +} + +static void Warning(const Twine &Msg) { + Message("warning", Msg); +} + +/// + +static int DumpHeader(MachOObject &Obj) { + // Read the header. + const macho::Header &Hdr = Obj.getHeader(); + outs() << "('cputype', " << Hdr.CPUType << ")\n"; + outs() << "('cpusubtype', " << Hdr.CPUSubtype << ")\n"; + outs() << "('filetype', " << Hdr.FileType << ")\n"; + outs() << "('num_load_commands', " << Hdr.NumLoadCommands << ")\n"; + outs() << "('load_commands_size', " << Hdr.SizeOfLoadCommands << ")\n"; + outs() << "('flag', " << Hdr.Flags << ")\n"; + + // Print extended header if 64-bit. + if (Obj.is64Bit()) { + const macho::Header64Ext &Hdr64 = Obj.getHeader64Ext(); + outs() << "('reserved', " << Hdr64.Reserved << ")\n"; + } + + return 0; +} + +static void DumpSegmentCommandData(StringRef Name, + uint64_t VMAddr, uint64_t VMSize, + uint64_t FileOffset, uint64_t FileSize, + uint32_t MaxProt, uint32_t InitProt, + uint32_t NumSections, uint32_t Flags) { + outs() << " ('segment_name', '"; + outs().write_escaped(Name, /*UseHexEscapes=*/true) << "')\n"; + outs() << " ('vm_addr', " << VMAddr << ")\n"; + outs() << " ('vm_size', " << VMSize << ")\n"; + outs() << " ('file_offset', " << FileOffset << ")\n"; + outs() << " ('file_size', " << FileSize << ")\n"; + outs() << " ('maxprot', " << MaxProt << ")\n"; + outs() << " ('initprot', " << InitProt << ")\n"; + outs() << " ('num_sections', " << NumSections << ")\n"; + outs() << " ('flags', " << Flags << ")\n"; +} + +static int DumpSectionData(MachOObject &Obj, unsigned Index, StringRef Name, + StringRef SegmentName, uint64_t Address, + uint64_t Size, uint32_t Offset, + uint32_t Align, uint32_t RelocationTableOffset, + uint32_t NumRelocationTableEntries, + uint32_t Flags, uint32_t Reserved1, + uint32_t Reserved2, uint64_t Reserved3 = ~0ULL) { + outs() << " # Section " << Index << "\n"; + outs() << " (('section_name', '"; + outs().write_escaped(Name, /*UseHexEscapes=*/true) << "')\n"; + outs() << " ('segment_name', '"; + outs().write_escaped(SegmentName, /*UseHexEscapes=*/true) << "')\n"; + outs() << " ('address', " << Address << ")\n"; + outs() << " ('size', " << Size << ")\n"; + outs() << " ('offset', " << Offset << ")\n"; + outs() << " ('alignment', " << Align << ")\n"; + outs() << " ('reloc_offset', " << RelocationTableOffset << ")\n"; + outs() << " ('num_reloc', " << NumRelocationTableEntries << ")\n"; + outs() << " ('flags', " << format("0x%x", Flags) << ")\n"; + outs() << " ('reserved1', " << Reserved1 << ")\n"; + outs() << " ('reserved2', " << Reserved2 << ")\n"; + if (Reserved3 != ~0ULL) + outs() << " ('reserved3', " << Reserved3 << ")\n"; + outs() << " ),\n"; + + // Dump the relocation entries. + int Res = 0; + outs() << " ('_relocations', [\n"; + for (unsigned i = 0; i != NumRelocationTableEntries; ++i) { + InMemoryStruct RE; + Obj.ReadRelocationEntry(RelocationTableOffset, i, RE); + if (!RE) { + Res = Error("unable to read relocation table entry '" + Twine(i) + "'"); + break; + } + + outs() << " # Relocation " << i << "\n"; + outs() << " (('word-0', " << format("0x%x", RE->Word0) << "),\n"; + outs() << " ('word-1', " << format("0x%x", RE->Word1) << ")),\n"; + } + outs() << " ])\n"; + + // Dump the section data, if requested. + if (ShowSectionData) { + outs() << " ('_section_data', '"; + StringRef Data = Obj.getData(Offset, Size); + for (unsigned i = 0; i != Data.size(); ++i) { + if (i && (i % 4) == 0) + outs() << ' '; + outs() << hexdigit((Data[i] >> 4) & 0xF, /*LowerCase=*/true); + outs() << hexdigit((Data[i] >> 0) & 0xF, /*LowerCase=*/true); + } + outs() << "')\n"; + } + + return Res; +} + +static int DumpSegmentCommand(MachOObject &Obj, + const MachOObject::LoadCommandInfo &LCI) { + InMemoryStruct SLC; + Obj.ReadSegmentLoadCommand(LCI, SLC); + if (!SLC) + return Error("unable to read segment load command"); + + DumpSegmentCommandData(StringRef(SLC->Name, 16), SLC->VMAddress, + SLC->VMSize, SLC->FileOffset, SLC->FileSize, + SLC->MaxVMProtection, SLC->InitialVMProtection, + SLC->NumSections, SLC->Flags); + + // Dump the sections. + int Res = 0; + outs() << " ('sections', [\n"; + for (unsigned i = 0; i != SLC->NumSections; ++i) { + InMemoryStruct Sect; + Obj.ReadSection(LCI, i, Sect); + if (!SLC) { + Res = Error("unable to read section '" + Twine(i) + "'"); + break; + } + + if ((Res = DumpSectionData(Obj, i, StringRef(Sect->Name, 16), + StringRef(Sect->SegmentName, 16), Sect->Address, + Sect->Size, Sect->Offset, Sect->Align, + Sect->RelocationTableOffset, + Sect->NumRelocationTableEntries, Sect->Flags, + Sect->Reserved1, Sect->Reserved2))) + break; + } + outs() << " ])\n"; + + return Res; +} + +static int DumpSegment64Command(MachOObject &Obj, + const MachOObject::LoadCommandInfo &LCI) { + InMemoryStruct SLC; + Obj.ReadSegment64LoadCommand(LCI, SLC); + if (!SLC) + return Error("unable to read segment load command"); + + DumpSegmentCommandData(StringRef(SLC->Name, 16), SLC->VMAddress, + SLC->VMSize, SLC->FileOffset, SLC->FileSize, + SLC->MaxVMProtection, SLC->InitialVMProtection, + SLC->NumSections, SLC->Flags); + + // Dump the sections. + int Res = 0; + outs() << " ('sections', [\n"; + for (unsigned i = 0; i != SLC->NumSections; ++i) { + InMemoryStruct Sect; + Obj.ReadSection64(LCI, i, Sect); + if (!SLC) { + Res = Error("unable to read section '" + Twine(i) + "'"); + break; + } + + if ((Res = DumpSectionData(Obj, i, StringRef(Sect->Name, 16), + StringRef(Sect->SegmentName, 16), Sect->Address, + Sect->Size, Sect->Offset, Sect->Align, + Sect->RelocationTableOffset, + Sect->NumRelocationTableEntries, Sect->Flags, + Sect->Reserved1, Sect->Reserved2, + Sect->Reserved3))) + break; + } + outs() << " ])\n"; + + return 0; +} + +static void DumpSymbolTableEntryData(MachOObject &Obj, + unsigned Index, uint32_t StringIndex, + uint8_t Type, uint8_t SectionIndex, + uint16_t Flags, uint64_t Value) { + outs() << " # Symbol " << Index << "\n"; + outs() << " (('n_strx', " << StringIndex << ")\n"; + outs() << " ('n_type', " << format("0x%x", Type) << ")\n"; + outs() << " ('n_sect', " << uint32_t(SectionIndex) << ")\n"; + outs() << " ('n_desc', " << Flags << ")\n"; + outs() << " ('n_value', " << Value << ")\n"; + outs() << " ('_string', '" << Obj.getStringAtIndex(StringIndex) << "')\n"; + outs() << " ),\n"; +} + +static int DumpSymtabCommand(MachOObject &Obj, + const MachOObject::LoadCommandInfo &LCI) { + InMemoryStruct SLC; + Obj.ReadSymtabLoadCommand(LCI, SLC); + if (!SLC) + return Error("unable to read segment load command"); + + outs() << " ('symoff', " << SLC->SymbolTableOffset << ")\n"; + outs() << " ('nsyms', " << SLC->NumSymbolTableEntries << ")\n"; + outs() << " ('stroff', " << SLC->StringTableOffset << ")\n"; + outs() << " ('strsize', " << SLC->StringTableSize << ")\n"; + + // Cache the string table data. + Obj.RegisterStringTable(*SLC); + + // Dump the string data. + outs() << " ('_string_data', '"; + outs().write_escaped(Obj.getStringTableData(), + /*UseHexEscapes=*/true) << "')\n"; + + // Dump the symbol table. + int Res = 0; + outs() << " ('_symbols', [\n"; + for (unsigned i = 0; i != SLC->NumSymbolTableEntries; ++i) { + if (Obj.is64Bit()) { + InMemoryStruct STE; + Obj.ReadSymbol64TableEntry(SLC->SymbolTableOffset, i, STE); + if (!STE) { + Res = Error("unable to read symbol: '" + Twine(i) + "'"); + break; + } + + DumpSymbolTableEntryData(Obj, i, STE->StringIndex, STE->Type, + STE->SectionIndex, STE->Flags, STE->Value); + } else { + InMemoryStruct STE; + Obj.ReadSymbolTableEntry(SLC->SymbolTableOffset, i, STE); + if (!SLC) { + Res = Error("unable to read symbol: '" + Twine(i) + "'"); + break; + } + + DumpSymbolTableEntryData(Obj, i, STE->StringIndex, STE->Type, + STE->SectionIndex, STE->Flags, STE->Value); + } + } + outs() << " ])\n"; + + return Res; +} + +static int DumpDysymtabCommand(MachOObject &Obj, + const MachOObject::LoadCommandInfo &LCI) { + InMemoryStruct DLC; + Obj.ReadDysymtabLoadCommand(LCI, DLC); + if (!DLC) + return Error("unable to read segment load command"); + + outs() << " ('ilocalsym', " << DLC->LocalSymbolsIndex << ")\n"; + outs() << " ('nlocalsym', " << DLC->NumLocalSymbols << ")\n"; + outs() << " ('iextdefsym', " << DLC->ExternalSymbolsIndex << ")\n"; + outs() << " ('nextdefsym', " << DLC->NumExternalSymbols << ")\n"; + outs() << " ('iundefsym', " << DLC->UndefinedSymbolsIndex << ")\n"; + outs() << " ('nundefsym', " << DLC->NumUndefinedSymbols << ")\n"; + outs() << " ('tocoff', " << DLC->TOCOffset << ")\n"; + outs() << " ('ntoc', " << DLC->NumTOCEntries << ")\n"; + outs() << " ('modtaboff', " << DLC->ModuleTableOffset << ")\n"; + outs() << " ('nmodtab', " << DLC->NumModuleTableEntries << ")\n"; + outs() << " ('extrefsymoff', " << DLC->ReferenceSymbolTableOffset << ")\n"; + outs() << " ('nextrefsyms', " + << DLC->NumReferencedSymbolTableEntries << ")\n"; + outs() << " ('indirectsymoff', " << DLC->IndirectSymbolTableOffset << ")\n"; + outs() << " ('nindirectsyms', " + << DLC->NumIndirectSymbolTableEntries << ")\n"; + outs() << " ('extreloff', " << DLC->ExternalRelocationTableOffset << ")\n"; + outs() << " ('nextrel', " << DLC->NumExternalRelocationTableEntries << ")\n"; + outs() << " ('locreloff', " << DLC->LocalRelocationTableOffset << ")\n"; + outs() << " ('nlocrel', " << DLC->NumLocalRelocationTableEntries << ")\n"; + + // Dump the indirect symbol table. + int Res = 0; + outs() << " ('_indirect_symbols', [\n"; + for (unsigned i = 0; i != DLC->NumIndirectSymbolTableEntries; ++i) { + InMemoryStruct ISTE; + Obj.ReadIndirectSymbolTableEntry(*DLC, i, ISTE); + if (!ISTE) { + Res = Error("unable to read segment load command"); + break; + } + + outs() << " # Indirect Symbol " << i << "\n"; + outs() << " (('symbol_index', " + << format("0x%x", ISTE->Index) << "),),\n"; + } + outs() << " ])\n"; + + return Res; +} + +static int DumpLoadCommand(MachOObject &Obj, unsigned Index) { + const MachOObject::LoadCommandInfo &LCI = Obj.getLoadCommandInfo(Index); + int Res = 0; + + outs() << " # Load Command " << Index << "\n" + << " (('command', " << LCI.Command.Type << ")\n" + << " ('size', " << LCI.Command.Size << ")\n"; + switch (LCI.Command.Type) { + case macho::LCT_Segment: + Res = DumpSegmentCommand(Obj, LCI); + break; + case macho::LCT_Segment64: + Res = DumpSegment64Command(Obj, LCI); + break; + case macho::LCT_Symtab: + Res = DumpSymtabCommand(Obj, LCI); + break; + case macho::LCT_Dysymtab: + Res = DumpDysymtabCommand(Obj, LCI); + break; + default: + Warning("unknown load command: " + Twine(LCI.Command.Type)); + break; + } + outs() << " ),\n"; + + return Res; +} + +int main(int argc, char **argv) { + ProgramName = argv[0]; + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + + cl::ParseCommandLineOptions(argc, argv, "llvm Mach-O dumping tool\n"); + + // Load the input file. + std::string ErrorStr; + OwningPtr InputBuffer; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFile, InputBuffer)) + return Error("unable to read input: '" + ec.message() + "'"); + + // Construct the Mach-O wrapper object. + OwningPtr InputObject( + MachOObject::LoadFromBuffer(InputBuffer.take(), &ErrorStr)); + if (!InputObject) + return Error("unable to load object: '" + ErrorStr + "'"); + + if (int Res = DumpHeader(*InputObject)) + return Res; + + // Print the load commands. + int Res = 0; + outs() << "('load_commands', [\n"; + for (unsigned i = 0; i != InputObject->getHeader().NumLoadCommands; ++i) + if ((Res = DumpLoadCommand(*InputObject, i))) + break; + outs() << "])\n"; + + return Res; +} diff --git a/tools/opt/GraphPrinters.cpp b/tools/opt/GraphPrinters.cpp index 9de7d6a..791caf5 100644 --- a/tools/opt/GraphPrinters.cpp +++ b/tools/opt/GraphPrinters.cpp @@ -18,8 +18,8 @@ #include "llvm/Pass.h" #include "llvm/Value.h" #include "llvm/Analysis/CallGraph.h" -#include "llvm/Analysis/Dominators.h" -#include "llvm/Support/raw_ostream.h" +#include "llvm/Analysis/DominanceFrontier.h" +#include "llvm/Support/ToolOutputFile.h" using namespace llvm; template @@ -61,8 +61,7 @@ namespace llvm { static std::string getNodeLabel(CallGraphNode *Node, CallGraph *Graph) { if (Node->getFunction()) return ((Value*)Node->getFunction())->getName(); - else - return "external node"; + return "external node"; } }; } @@ -109,10 +108,8 @@ namespace { } virtual bool runOnFunction(Function &F) { - DominatorTree &DT = getAnalysis(); - DT.dump(); - DominanceFrontier &DF = getAnalysis(); - DF.dump(); + getAnalysis().dump(); + getAnalysis().dump(); return false; } }; diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp index d837185..e55b4b3 100644 --- a/tools/opt/opt.cpp +++ b/tools/opt/opt.cpp @@ -18,13 +18,17 @@ #include "llvm/CallGraphSCCPass.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/Assembly/PrintModulePass.h" +#include "llvm/Analysis/DebugInfo.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/RegionPass.h" #include "llvm/Analysis/CallGraph.h" #include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLibraryInfo.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/Triple.h" #include "llvm/Support/PassNameParser.h" -#include "llvm/System/Signals.h" +#include "llvm/Support/Signals.h" #include "llvm/Support/Debug.h" #include "llvm/Support/IRReader.h" #include "llvm/Support/ManagedStatic.h" @@ -32,7 +36,7 @@ #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/StandardPasses.h" #include "llvm/Support/SystemUtils.h" -#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/ToolOutputFile.h" #include "llvm/LinkAllPasses.h" #include "llvm/LinkAllVMCore.h" #include @@ -127,6 +131,10 @@ QuietA("quiet", cl::desc("Alias for -q"), cl::aliasopt(Quiet)); static cl::opt AnalyzeOnly("analyze", cl::desc("Only perform analysis, no optimization")); +static cl::opt +PrintBreakpoints("print-breakpoints-for-testing", + cl::desc("Print select breakpoints location for testing")); + static cl::opt DefaultDataLayout("default-data-layout", cl::desc("data layout string to use if not specified by module"), @@ -139,25 +147,29 @@ struct CallGraphSCCPassPrinter : public CallGraphSCCPass { static char ID; const PassInfo *PassToPrint; raw_ostream &Out; + std::string PassName; + CallGraphSCCPassPrinter(const PassInfo *PI, raw_ostream &out) : - CallGraphSCCPass(ID), PassToPrint(PI), Out(out) {} + CallGraphSCCPass(ID), PassToPrint(PI), Out(out) { + std::string PassToPrintName = PassToPrint->getPassName(); + PassName = "CallGraphSCCPass Printer: " + PassToPrintName; + } virtual bool runOnSCC(CallGraphSCC &SCC) { - if (!Quiet) { + if (!Quiet) Out << "Printing analysis '" << PassToPrint->getPassName() << "':\n"; - for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) { - Function *F = (*I)->getFunction(); - if (F) - getAnalysisID(PassToPrint->getTypeInfo()).print(Out, - F->getParent()); - } - } // Get and print pass... + for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) { + Function *F = (*I)->getFunction(); + if (F) + getAnalysisID(PassToPrint->getTypeInfo()).print(Out, + F->getParent()); + } return false; } - virtual const char *getPassName() const { return "'Pass' Printer"; } + virtual const char *getPassName() const { return PassName.c_str(); } virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequiredID(PassToPrint->getTypeInfo()); @@ -171,20 +183,24 @@ struct ModulePassPrinter : public ModulePass { static char ID; const PassInfo *PassToPrint; raw_ostream &Out; + std::string PassName; + ModulePassPrinter(const PassInfo *PI, raw_ostream &out) - : ModulePass(ID), PassToPrint(PI), Out(out) {} + : ModulePass(ID), PassToPrint(PI), Out(out) { + std::string PassToPrintName = PassToPrint->getPassName(); + PassName = "ModulePass Printer: " + PassToPrintName; + } virtual bool runOnModule(Module &M) { - if (!Quiet) { + if (!Quiet) Out << "Printing analysis '" << PassToPrint->getPassName() << "':\n"; - getAnalysisID(PassToPrint->getTypeInfo()).print(Out, &M); - } // Get and print pass... + getAnalysisID(PassToPrint->getTypeInfo()).print(Out, &M); return false; } - virtual const char *getPassName() const { return "'Pass' Printer"; } + virtual const char *getPassName() const { return PassName.c_str(); } virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequiredID(PassToPrint->getTypeInfo()); @@ -197,21 +213,26 @@ struct FunctionPassPrinter : public FunctionPass { const PassInfo *PassToPrint; raw_ostream &Out; static char ID; + std::string PassName; + FunctionPassPrinter(const PassInfo *PI, raw_ostream &out) - : FunctionPass(ID), PassToPrint(PI), Out(out) {} + : FunctionPass(ID), PassToPrint(PI), Out(out) { + std::string PassToPrintName = PassToPrint->getPassName(); + PassName = "FunctionPass Printer: " + PassToPrintName; + } virtual bool runOnFunction(Function &F) { - if (!Quiet) { + if (!Quiet) Out << "Printing analysis '" << PassToPrint->getPassName() << "' for function '" << F.getName() << "':\n"; - } + // Get and print pass... getAnalysisID(PassToPrint->getTypeInfo()).print(Out, F.getParent()); return false; } - virtual const char *getPassName() const { return "FunctionPass Printer"; } + virtual const char *getPassName() const { return PassName.c_str(); } virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequiredID(PassToPrint->getTypeInfo()); @@ -225,20 +246,26 @@ struct LoopPassPrinter : public LoopPass { static char ID; const PassInfo *PassToPrint; raw_ostream &Out; + std::string PassName; + LoopPassPrinter(const PassInfo *PI, raw_ostream &out) : - LoopPass(ID), PassToPrint(PI), Out(out) {} + LoopPass(ID), PassToPrint(PI), Out(out) { + std::string PassToPrintName = PassToPrint->getPassName(); + PassName = "LoopPass Printer: " + PassToPrintName; + } + virtual bool runOnLoop(Loop *L, LPPassManager &LPM) { - if (!Quiet) { + if (!Quiet) Out << "Printing analysis '" << PassToPrint->getPassName() << "':\n"; - getAnalysisID(PassToPrint->getTypeInfo()).print(Out, - L->getHeader()->getParent()->getParent()); - } + // Get and print pass... + getAnalysisID(PassToPrint->getTypeInfo()).print(Out, + L->getHeader()->getParent()->getParent()); return false; } - virtual const char *getPassName() const { return "'Pass' Printer"; } + virtual const char *getPassName() const { return PassName.c_str(); } virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequiredID(PassToPrint->getTypeInfo()); @@ -248,18 +275,56 @@ struct LoopPassPrinter : public LoopPass { char LoopPassPrinter::ID = 0; +struct RegionPassPrinter : public RegionPass { + static char ID; + const PassInfo *PassToPrint; + raw_ostream &Out; + std::string PassName; + + RegionPassPrinter(const PassInfo *PI, raw_ostream &out) : RegionPass(ID), + PassToPrint(PI), Out(out) { + std::string PassToPrintName = PassToPrint->getPassName(); + PassName = "RegionPass Printer: " + PassToPrintName; + } + + virtual bool runOnRegion(Region *R, RGPassManager &RGM) { + if (!Quiet) { + Out << "Printing analysis '" << PassToPrint->getPassName() << "' for " + << "region: '" << R->getNameStr() << "' in function '" + << R->getEntry()->getParent()->getNameStr() << "':\n"; + } + // Get and print pass... + getAnalysisID(PassToPrint->getTypeInfo()).print(Out, + R->getEntry()->getParent()->getParent()); + return false; + } + + virtual const char *getPassName() const { return PassName.c_str(); } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequiredID(PassToPrint->getTypeInfo()); + AU.setPreservesAll(); + } +}; + +char RegionPassPrinter::ID = 0; + struct BasicBlockPassPrinter : public BasicBlockPass { const PassInfo *PassToPrint; raw_ostream &Out; static char ID; + std::string PassName; + BasicBlockPassPrinter(const PassInfo *PI, raw_ostream &out) - : BasicBlockPass(ID), PassToPrint(PI), Out(out) {} + : BasicBlockPass(ID), PassToPrint(PI), Out(out) { + std::string PassToPrintName = PassToPrint->getPassName(); + PassName = "BasicBlockPass Printer: " + PassToPrintName; + } virtual bool runOnBasicBlock(BasicBlock &BB) { - if (!Quiet) { + if (!Quiet) Out << "Printing Analysis info for BasicBlock '" << BB.getName() << "': Pass " << PassToPrint->getPassName() << ":\n"; - } // Get and print pass... getAnalysisID(PassToPrint->getTypeInfo()).print(Out, @@ -267,7 +332,7 @@ struct BasicBlockPassPrinter : public BasicBlockPass { return false; } - virtual const char *getPassName() const { return "BasicBlockPass Printer"; } + virtual const char *getPassName() const { return PassName.c_str(); } virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequiredID(PassToPrint->getTypeInfo()); @@ -276,6 +341,39 @@ struct BasicBlockPassPrinter : public BasicBlockPass { }; char BasicBlockPassPrinter::ID = 0; + +struct BreakpointPrinter : public FunctionPass { + raw_ostream &Out; + static char ID; + + BreakpointPrinter(raw_ostream &out) + : FunctionPass(ID), Out(out) { + } + + virtual bool runOnFunction(Function &F) { + BasicBlock &EntryBB = F.getEntryBlock(); + BasicBlock::const_iterator BI = EntryBB.end(); + --BI; + do { + const Instruction *In = BI; + const DebugLoc DL = In->getDebugLoc(); + if (!DL.isUnknown()) { + DIScope S(DL.getScope(getGlobalContext())); + Out << S.getFilename() << " " << DL.getLine() << "\n"; + break; + } + --BI; + } while (BI != EntryBB.begin()); + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } +}; + +char BreakpointPrinter::ID = 0; + inline void addPass(PassManagerBase &PM, Pass *P) { // Add the pass to the pass manager... PM.add(P); @@ -297,9 +395,9 @@ void AddOptimizationPasses(PassManagerBase &MPM, PassManagerBase &FPM, if (DisableInline) { // No inlining pass } else if (OptLevel) { - unsigned Threshold = 200; + unsigned Threshold = 225; if (OptLevel > 2) - Threshold = 250; + Threshold = 275; InliningPass = createFunctionInliningPass(Threshold); } else { InliningPass = createAlwaysInlinerPass(); @@ -331,7 +429,7 @@ void AddStandardCompilePasses(PassManagerBase &PM) { /*OptimizeSize=*/ false, /*UnitAtATime=*/ true, /*UnrollLoops=*/ true, - /*SimplifyLibCalls=*/ true, + !DisableSimplifyLibCalls, /*HaveExceptions=*/ true, InliningPass); } @@ -360,20 +458,32 @@ int main(int argc, char **argv) { sys::PrintStackTraceOnErrorSignal(); llvm::PrettyStackTraceProgram X(argc, argv); - if (AnalyzeOnly && NoOutput) { - errs() << argv[0] << ": analyze mode conflicts with no-output mode.\n"; - return 1; - } - // Enable debug stream buffering. EnableDebugBuffering = true; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. LLVMContext &Context = getGlobalContext(); + // Initialize passes + PassRegistry &Registry = *PassRegistry::getPassRegistry(); + initializeCore(Registry); + initializeScalarOpts(Registry); + initializeIPO(Registry); + initializeAnalysis(Registry); + initializeIPA(Registry); + initializeTransformUtils(Registry); + initializeInstCombine(Registry); + initializeInstrumentation(Registry); + initializeTarget(Registry); + cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .bc modular optimizer and analysis printer\n"); + if (AnalyzeOnly && NoOutput) { + errs() << argv[0] << ": analyze mode conflicts with no-output mode.\n"; + return 1; + } + // Allocate a full target machine description only if necessary. // FIXME: The choice of target should be controllable on the command line. std::auto_ptr target; @@ -417,11 +527,19 @@ int main(int argc, char **argv) { NoOutput = true; // Create a PassManager to hold and optimize the collection of passes we are - // about to build... + // about to build. // PassManager Passes; - // Add an appropriate TargetData instance for this module... + // Add an appropriate TargetLibraryInfo pass for the module's triple. + TargetLibraryInfo *TLI = new TargetLibraryInfo(Triple(M->getTargetTriple())); + + // The -disable-simplify-libcalls flag actually disables all builtin optzns. + if (DisableSimplifyLibCalls) + TLI->disableAllFunctions(); + Passes.add(TLI); + + // Add an appropriate TargetData instance for this module. TargetData *TD = 0; const std::string &ModuleDataLayout = M.get()->getDataLayout(); if (!ModuleDataLayout.empty()) @@ -439,6 +557,24 @@ int main(int argc, char **argv) { FPasses->add(new TargetData(*TD)); } + if (PrintBreakpoints) { + // Default to standard output. + if (!Out) { + if (OutputFilename.empty()) + OutputFilename = "-"; + + std::string ErrorInfo; + Out.reset(new tool_output_file(OutputFilename.c_str(), ErrorInfo, + raw_fd_ostream::F_Binary)); + if (!ErrorInfo.empty()) { + errs() << ErrorInfo << '\n'; + return 1; + } + } + Passes.add(new BreakpointPrinter(Out->os())); + NoOutput = true; + } + // 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) @@ -491,6 +627,9 @@ int main(int argc, char **argv) { case PT_BasicBlock: Passes.add(new BasicBlockPassPrinter(PassInf, Out->os())); break; + case PT_Region: + Passes.add(new RegionPassPrinter(PassInf, Out->os())); + break; case PT_Loop: Passes.add(new LoopPassPrinter(PassInf, Out->os())); break; @@ -550,7 +689,7 @@ int main(int argc, char **argv) { Passes.run(*M.get()); // Declare success. - if (!NoOutput) + if (!NoOutput || PrintBreakpoints) Out->keep(); return 0; -- cgit v1.1