diff options
| author | Stephen Hines <srhines@google.com> | 2013-01-21 13:15:17 -0800 |
|---|---|---|
| committer | Stephen Hines <srhines@google.com> | 2013-01-21 13:15:17 -0800 |
| commit | 059800f9e3fee2852672f846d91a2da14da7783a (patch) | |
| tree | a6ef16b7263252ae1b8069295ea9cbbae0d9467d /tools | |
| parent | cbefa15de4821975bb99fc6d74b3bdb42b2df45c (diff) | |
| parent | b6714227eda5d499f7667fc865f931126a8dc488 (diff) | |
| download | external_llvm-059800f9e3fee2852672f846d91a2da14da7783a.zip external_llvm-059800f9e3fee2852672f846d91a2da14da7783a.tar.gz external_llvm-059800f9e3fee2852672f846d91a2da14da7783a.tar.bz2 | |
Merge remote-tracking branch 'upstream/master' into merge-llvm
Conflicts:
lib/CodeGen/AsmPrinter/AsmPrinter.cpp
lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
lib/MC/MCAssembler.cpp
lib/Support/Atomic.cpp
lib/Support/Memory.cpp
lib/Target/ARM/ARMJITInfo.cpp
Change-Id: Ib339baf88df5b04870c8df1bedcfe1f877ccab8d
Diffstat (limited to 'tools')
88 files changed, 2401 insertions, 1258 deletions
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 1bfc2fe..144e8ec 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -31,11 +31,17 @@ add_subdirectory(llvm-objdump) add_subdirectory(llvm-readobj) add_subdirectory(llvm-rtdyld) add_subdirectory(llvm-dwarfdump) +if( LLVM_USE_INTEL_JITEVENTS ) + add_subdirectory(llvm-jitlistener) +endif( LLVM_USE_INTEL_JITEVENTS ) add_subdirectory(bugpoint) add_subdirectory(bugpoint-passes) add_subdirectory(llvm-bcanalyzer) add_subdirectory(llvm-stress) +add_subdirectory(llvm-mcmarkup) + +add_subdirectory(llvm-symbolizer) if( NOT WIN32 ) add_subdirectory(lto) diff --git a/tools/LLVMBuild.txt b/tools/LLVMBuild.txt index df4aa9f..25aa177 100644 --- a/tools/LLVMBuild.txt +++ b/tools/LLVMBuild.txt @@ -16,7 +16,7 @@ ;===------------------------------------------------------------------------===; [common] -subdirectories = bugpoint llc lli llvm-ar llvm-as llvm-bcanalyzer llvm-cov llvm-diff llvm-dis llvm-dwarfdump llvm-extract llvm-link llvm-mc llvm-nm llvm-objdump llvm-prof llvm-ranlib llvm-rtdyld llvm-size macho-dump opt +subdirectories = bugpoint llc lli llvm-ar llvm-as llvm-bcanalyzer llvm-cov llvm-diff llvm-dis llvm-dwarfdump llvm-extract llvm-jitlistener llvm-link llvm-mc llvm-nm llvm-objdump llvm-prof llvm-ranlib llvm-rtdyld llvm-size macho-dump opt llvm-mcmarkup [component_0] type = Group diff --git a/tools/Makefile b/tools/Makefile index 2b4b9b7..c405868 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -34,7 +34,13 @@ PARALLEL_DIRS := opt llvm-as llvm-dis \ bugpoint llvm-bcanalyzer \ llvm-diff macho-dump llvm-objdump llvm-readobj \ llvm-rtdyld llvm-dwarfdump llvm-cov \ - llvm-size llvm-stress + llvm-size llvm-stress llvm-mcmarkup \ + llvm-symbolizer + +# If Intel JIT Events support is configured, build an extra tool to test it. +ifeq ($(USE_INTEL_JITEVENTS), 1) + PARALLEL_DIRS += llvm-jitlistener +endif # Let users override the set of tools to build from the command line. ifdef ONLY_TOOLS diff --git a/tools/bugpoint-passes/TestPasses.cpp b/tools/bugpoint-passes/TestPasses.cpp index 1535b03..118c98a 100644 --- a/tools/bugpoint-passes/TestPasses.cpp +++ b/tools/bugpoint-passes/TestPasses.cpp @@ -12,12 +12,12 @@ // //===----------------------------------------------------------------------===// -#include "llvm/BasicBlock.h" -#include "llvm/Constant.h" -#include "llvm/Instructions.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Constant.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Type.h" +#include "llvm/InstVisitor.h" #include "llvm/Pass.h" -#include "llvm/Type.h" -#include "llvm/Support/InstVisitor.h" using namespace llvm; diff --git a/tools/bugpoint/BugDriver.cpp b/tools/bugpoint/BugDriver.cpp index 21636ea..cede4ac 100644 --- a/tools/bugpoint/BugDriver.cpp +++ b/tools/bugpoint/BugDriver.cpp @@ -15,15 +15,15 @@ #include "BugDriver.h" #include "ToolRunner.h" +#include "llvm/IR/Module.h" #include "llvm/Linker.h" -#include "llvm/Module.h" #include "llvm/Pass.h" -#include "llvm/Support/IRReader.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileUtilities.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/IRReader.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/Host.h" #include <memory> using namespace llvm; diff --git a/tools/bugpoint/BugDriver.h b/tools/bugpoint/BugDriver.h index cc78489..2b621ec 100644 --- a/tools/bugpoint/BugDriver.h +++ b/tools/bugpoint/BugDriver.h @@ -18,8 +18,8 @@ #include "llvm/ADT/ValueMap.h" #include "llvm/Transforms/Utils/ValueMapper.h" -#include <vector> #include <string> +#include <vector> namespace llvm { diff --git a/tools/bugpoint/CrashDebugger.cpp b/tools/bugpoint/CrashDebugger.cpp index aed16f4..ed211a6 100644 --- a/tools/bugpoint/CrashDebugger.cpp +++ b/tools/bugpoint/CrashDebugger.cpp @@ -12,22 +12,22 @@ //===----------------------------------------------------------------------===// #include "BugDriver.h" -#include "ToolRunner.h" #include "ListReducer.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Instructions.h" -#include "llvm/Module.h" -#include "llvm/Pass.h" -#include "llvm/PassManager.h" -#include "llvm/ValueSymbolTable.h" +#include "ToolRunner.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Analysis/Verifier.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/ValueSymbolTable.h" +#include "llvm/Pass.h" +#include "llvm/PassManager.h" #include "llvm/Support/CFG.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileUtilities.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/Cloning.h" -#include "llvm/Support/FileUtilities.h" -#include "llvm/Support/CommandLine.h" #include <set> using namespace llvm; diff --git a/tools/bugpoint/ExtractFunction.cpp b/tools/bugpoint/ExtractFunction.cpp index 888d2c8..bb27767 100644 --- a/tools/bugpoint/ExtractFunction.cpp +++ b/tools/bugpoint/ExtractFunction.cpp @@ -13,25 +13,25 @@ //===----------------------------------------------------------------------===// #include "BugDriver.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" -#include "llvm/PassManager.h" -#include "llvm/Pass.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Assembly/Writer.h" -#include "llvm/Transforms/IPO.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/Utils/Cloning.h" -#include "llvm/Transforms/Utils/CodeExtractor.h" -#include "llvm/Target/TargetData.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Pass.h" +#include "llvm/PassManager.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileUtilities.h" -#include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/Path.h" #include "llvm/Support/Signals.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/Transforms/Utils/CodeExtractor.h" #include <set> using namespace llvm; diff --git a/tools/bugpoint/ListReducer.h b/tools/bugpoint/ListReducer.h index bd1c5da..8083e2d 100644 --- a/tools/bugpoint/ListReducer.h +++ b/tools/bugpoint/ListReducer.h @@ -15,11 +15,11 @@ #ifndef BUGPOINT_LIST_REDUCER_H #define BUGPOINT_LIST_REDUCER_H -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/ErrorHandling.h" -#include <vector> -#include <cstdlib> +#include "llvm/Support/raw_ostream.h" #include <algorithm> +#include <cstdlib> +#include <vector> namespace llvm { diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp index 82a3a86..c676a05 100644 --- a/tools/bugpoint/Miscompilation.cpp +++ b/tools/bugpoint/Miscompilation.cpp @@ -15,17 +15,17 @@ #include "BugDriver.h" #include "ListReducer.h" #include "ToolRunner.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Instructions.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Config/config.h" // for HAVE_LINK_R +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" #include "llvm/Linker.h" -#include "llvm/Module.h" #include "llvm/Pass.h" -#include "llvm/Analysis/Verifier.h" -#include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileUtilities.h" -#include "llvm/Config/config.h" // for HAVE_LINK_R +#include "llvm/Transforms/Utils/Cloning.h" using namespace llvm; namespace llvm { diff --git a/tools/bugpoint/OptimizerDriver.cpp b/tools/bugpoint/OptimizerDriver.cpp index fb090ee..87dc9f3 100644 --- a/tools/bugpoint/OptimizerDriver.cpp +++ b/tools/bugpoint/OptimizerDriver.cpp @@ -16,18 +16,18 @@ //===----------------------------------------------------------------------===// #include "BugDriver.h" -#include "llvm/Module.h" -#include "llvm/PassManager.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Support/FileUtilities.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Module.h" +#include "llvm/PassManager.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/SystemUtils.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/FileUtilities.h" #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" +#include "llvm/Support/SystemUtils.h" +#include "llvm/Support/ToolOutputFile.h" #define DONT_GET_PLUGIN_LOADER_OPTION #include "llvm/Support/PluginLoader.h" diff --git a/tools/bugpoint/ToolRunner.cpp b/tools/bugpoint/ToolRunner.cpp index d975d68..e7d3978 100644 --- a/tools/bugpoint/ToolRunner.cpp +++ b/tools/bugpoint/ToolRunner.cpp @@ -13,12 +13,12 @@ #define DEBUG_TYPE "toolrunner" #include "ToolRunner.h" -#include "llvm/Support/Program.h" +#include "llvm/Config/config.h" // for HAVE_LINK_R #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileUtilities.h" +#include "llvm/Support/Program.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Config/config.h" // for HAVE_LINK_R #include <fstream> #include <sstream> using namespace llvm; diff --git a/tools/bugpoint/ToolRunner.h b/tools/bugpoint/ToolRunner.h index 7b93394..bb83ce4 100644 --- a/tools/bugpoint/ToolRunner.h +++ b/tools/bugpoint/ToolRunner.h @@ -20,8 +20,8 @@ #include "llvm/ADT/Triple.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/SystemUtils.h" #include "llvm/Support/Path.h" +#include "llvm/Support/SystemUtils.h" #include <exception> #include <vector> diff --git a/tools/bugpoint/bugpoint.cpp b/tools/bugpoint/bugpoint.cpp index 8f15b02..3049421 100644 --- a/tools/bugpoint/bugpoint.cpp +++ b/tools/bugpoint/bugpoint.cpp @@ -15,18 +15,18 @@ #include "BugDriver.h" #include "ToolRunner.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/LinkAllPasses.h" -#include "llvm/LLVMContext.h" +#include "llvm/LinkAllVMCore.h" #include "llvm/PassManager.h" -#include "llvm/Support/PassNameParser.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/PassNameParser.h" #include "llvm/Support/PluginLoader.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Process.h" #include "llvm/Support/Signals.h" #include "llvm/Support/Valgrind.h" -#include "llvm/LinkAllVMCore.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" //Enable this macro to debug bugpoint itself. diff --git a/tools/gold/gold-plugin.cpp b/tools/gold/gold-plugin.cpp index 9c17da6..40f5fd6 100644 --- a/tools/gold/gold-plugin.cpp +++ b/tools/gold/gold-plugin.cpp @@ -14,17 +14,14 @@ #include "llvm/Config/config.h" // plugin-api.h requires HAVE_STDINT_H #include "plugin-api.h" - #include "llvm-c/lto.h" - #include "llvm/ADT/OwningPtr.h" -#include "llvm/Support/system_error.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/Errno.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" - +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/system_error.h" #include <cerrno> #include <cstdlib> #include <cstring> @@ -378,9 +375,6 @@ static ld_plugin_status all_symbols_read_hook(void) { } } - // If we don't preserve any symbols, libLTO will assume that all symbols are - // needed. Keep all symbols unless we're producing a final executable. - bool anySymbolsPreserved = false; for (std::list<claimed_file>::iterator I = Modules.begin(), E = Modules.end(); I != E; ++I) { if (I->syms.empty()) @@ -389,7 +383,6 @@ static ld_plugin_status all_symbols_read_hook(void) { 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(code_gen, I->syms[i].name); - anySymbolsPreserved = true; if (options::generate_api_file) api_file << I->syms[i].name << "\n"; @@ -400,12 +393,6 @@ static ld_plugin_status all_symbols_read_hook(void) { if (options::generate_api_file) api_file.close(); - if (!anySymbolsPreserved) { - // All of the IL is unnecessary! - lto_codegen_dispose(code_gen); - return LDPS_OK; - } - lto_codegen_set_pic_model(code_gen, output_type); lto_codegen_set_debug_model(code_gen, LTO_DEBUG_MODEL_DWARF); if (!options::mcpu.empty()) diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index 81f297f..aa65223 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -13,28 +13,29 @@ // //===----------------------------------------------------------------------===// -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" -#include "llvm/PassManager.h" -#include "llvm/Pass.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/ADT/Triple.h" #include "llvm/Assembly/PrintModulePass.h" -#include "llvm/Support/IRReader.h" +#include "llvm/CodeGen/CommandFlags.h" #include "llvm/CodeGen/LinkAllAsmWriterComponents.h" #include "llvm/CodeGen/LinkAllCodegenComponents.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Module.h" #include "llvm/MC/SubtargetFeature.h" +#include "llvm/Pass.h" +#include "llvm/PassManager.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FormattedStream.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/IRReader.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PluginLoader.h" #include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/ToolOutputFile.h" -#include "llvm/Support/Host.h" #include "llvm/Support/Signals.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" -#include "llvm/Target/TargetData.h" +#include "llvm/Support/ToolOutputFile.h" #include "llvm/Target/TargetLibraryInfo.h" #include "llvm/Target/TargetMachine.h" #include <memory> @@ -50,6 +51,11 @@ InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-")); static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename")); +static cl::opt<unsigned> +TimeCompilations("time-compilations", cl::Hidden, cl::init(1u), + cl::value_desc("N"), + cl::desc("Repeat compilation N times for timing")); + // Determine optimization level. static cl::opt<char> OptLevel("O", @@ -62,216 +68,15 @@ OptLevel("O", static cl::opt<std::string> TargetTriple("mtriple", cl::desc("Override target triple for module")); -static cl::opt<std::string> -MArch("march", cl::desc("Architecture to generate code for (see --version)")); - -static cl::opt<std::string> -MCPU("mcpu", - cl::desc("Target a specific cpu type (-mcpu=help for details)"), - cl::value_desc("cpu-name"), - cl::init("")); - -static cl::list<std::string> -MAttrs("mattr", - cl::CommaSeparated, - cl::desc("Target specific attributes (-mattr=help for details)"), - cl::value_desc("a1,+a2,-a3,...")); - -static cl::opt<Reloc::Model> -RelocModel("relocation-model", - cl::desc("Choose relocation model"), - cl::init(Reloc::Default), - cl::values( - clEnumValN(Reloc::Default, "default", - "Target default relocation model"), - clEnumValN(Reloc::Static, "static", - "Non-relocatable code"), - clEnumValN(Reloc::PIC_, "pic", - "Fully relocatable, position independent code"), - clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic", - "Relocatable external references, non-relocatable code"), - clEnumValEnd)); - -static cl::opt<llvm::CodeModel::Model> -CMModel("code-model", - cl::desc("Choose code model"), - cl::init(CodeModel::Default), - cl::values(clEnumValN(CodeModel::Default, "default", - "Target default code model"), - clEnumValN(CodeModel::Small, "small", - "Small code model"), - clEnumValN(CodeModel::Kernel, "kernel", - "Kernel code model"), - clEnumValN(CodeModel::Medium, "medium", - "Medium code model"), - clEnumValN(CodeModel::Large, "large", - "Large code model"), - clEnumValEnd)); - -static cl::opt<bool> -RelaxAll("mc-relax-all", - cl::desc("When used with filetype=obj, " - "relax all fixups in the emitted object file")); - -cl::opt<TargetMachine::CodeGenFileType> -FileType("filetype", cl::init(TargetMachine::CGFT_AssemblyFile), - cl::desc("Choose a file type (not all types are supported by all targets):"), - cl::values( - clEnumValN(TargetMachine::CGFT_AssemblyFile, "asm", - "Emit an assembly ('.s') file"), - clEnumValN(TargetMachine::CGFT_ObjectFile, "obj", - "Emit a native object ('.o') file"), - clEnumValN(TargetMachine::CGFT_Null, "null", - "Emit nothing, for performance testing"), - clEnumValEnd)); - cl::opt<bool> NoVerify("disable-verify", cl::Hidden, cl::desc("Do not verify input module")); -cl::opt<bool> DisableDotLoc("disable-dot-loc", cl::Hidden, - cl::desc("Do not use .loc entries")); - -cl::opt<bool> DisableCFI("disable-cfi", cl::Hidden, - cl::desc("Do not use .cfi_* directives")); - -cl::opt<bool> EnableDwarfDirectory("enable-dwarf-directory", cl::Hidden, - cl::desc("Use .file directives with an explicit directory.")); - -static cl::opt<bool> -DisableRedZone("disable-red-zone", - cl::desc("Do not emit code that uses the red zone."), - cl::init(false)); - -static cl::opt<bool> -EnableFPMAD("enable-fp-mad", - cl::desc("Enable less precise MAD instructions to be generated"), - cl::init(false)); - -static cl::opt<bool> -DisableFPElim("disable-fp-elim", - cl::desc("Disable frame pointer elimination optimization"), - cl::init(false)); - -static cl::opt<bool> -DisableFPElimNonLeaf("disable-non-leaf-fp-elim", - cl::desc("Disable frame pointer elimination optimization for non-leaf funcs"), - cl::init(false)); - -static cl::opt<bool> -EnableUnsafeFPMath("enable-unsafe-fp-math", - cl::desc("Enable optimizations that may decrease FP precision"), - cl::init(false)); - -static cl::opt<bool> -EnableNoInfsFPMath("enable-no-infs-fp-math", - cl::desc("Enable FP math optimizations that assume no +-Infs"), - cl::init(false)); - -static cl::opt<bool> -EnableNoNaNsFPMath("enable-no-nans-fp-math", - cl::desc("Enable FP math optimizations that assume no NaNs"), - cl::init(false)); - -static cl::opt<bool> -EnableHonorSignDependentRoundingFPMath("enable-sign-dependent-rounding-fp-math", - cl::Hidden, - cl::desc("Force codegen to assume rounding mode can change dynamically"), - cl::init(false)); - -static cl::opt<bool> -GenerateSoftFloatCalls("soft-float", - cl::desc("Generate software floating point library calls"), - cl::init(false)); - -static cl::opt<llvm::FloatABI::ABIType> -FloatABIForCalls("float-abi", - cl::desc("Choose float ABI type"), - cl::init(FloatABI::Default), - cl::values( - clEnumValN(FloatABI::Default, "default", - "Target default float ABI type"), - clEnumValN(FloatABI::Soft, "soft", - "Soft float ABI (implied by -soft-float)"), - clEnumValN(FloatABI::Hard, "hard", - "Hard float ABI (uses FP registers)"), - clEnumValEnd)); - -static cl::opt<llvm::FPOpFusion::FPOpFusionMode> -FuseFPOps("fp-contract", - cl::desc("Enable aggresive formation of fused FP ops"), - cl::init(FPOpFusion::Standard), - cl::values( - clEnumValN(FPOpFusion::Fast, "fast", - "Fuse FP ops whenever profitable"), - clEnumValN(FPOpFusion::Standard, "on", - "Only fuse 'blessed' FP ops."), - clEnumValN(FPOpFusion::Strict, "off", - "Only fuse FP ops when the result won't be effected."), - clEnumValEnd)); - -static cl::opt<bool> -DontPlaceZerosInBSS("nozero-initialized-in-bss", - cl::desc("Don't place zero-initialized symbols into bss section"), - cl::init(false)); - -static cl::opt<bool> +cl::opt<bool> DisableSimplifyLibCalls("disable-simplify-libcalls", - cl::desc("Disable simplify-libcalls"), - cl::init(false)); - -static cl::opt<bool> -EnableGuaranteedTailCallOpt("tailcallopt", - cl::desc("Turn fastcc calls into tail calls by (potentially) changing ABI."), - cl::init(false)); - -static cl::opt<bool> -DisableTailCalls("disable-tail-calls", - cl::desc("Never emit tail calls"), - cl::init(false)); - -static cl::opt<unsigned> -OverrideStackAlignment("stack-alignment", - cl::desc("Override default stack alignment"), - cl::init(0)); - -static cl::opt<bool> -EnableRealignStack("realign-stack", - cl::desc("Realign stack if needed"), - cl::init(true)); + cl::desc("Disable simplify-libcalls"), + cl::init(false)); -static cl::opt<std::string> -TrapFuncName("trap-func", cl::Hidden, - cl::desc("Emit a call to trap function rather than a trap instruction"), - cl::init("")); - -static cl::opt<bool> -EnablePIE("enable-pie", - cl::desc("Assume the creation of a position independent executable."), - cl::init(false)); - -static cl::opt<bool> -SegmentedStacks("segmented-stacks", - cl::desc("Use segmented stacks if possible."), - cl::init(false)); - -static cl::opt<bool> -UseInitArray("use-init-array", - cl::desc("Use .init_array instead of .ctors."), - cl::init(false)); - -static cl::opt<std::string> StopAfter("stop-after", - cl::desc("Stop compilation after a specific pass"), - cl::value_desc("pass-name"), - cl::init("")); -static cl::opt<std::string> StartAfter("start-after", - cl::desc("Resume compilation after a specific pass"), - cl::value_desc("pass-name"), - cl::init("")); - -static cl::opt<unsigned> -SSPBufferSize("stack-protector-buffer-size", cl::init(8), - cl::desc("Lower bound for a buffer to be considered for " - "stack protection")); +static int compileModule(char**, LLVMContext&); // GetFileNameRoot - Helper function to get the basename of a filename. static inline std::string @@ -383,6 +188,15 @@ int main(int argc, char **argv) { cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n"); + // Compile the module TimeCompilations times to give better compile time + // metrics. + for (unsigned I = TimeCompilations; I; --I) + if (int RetVal = compileModule(argv, Context)) + return RetVal; + return 0; +} + +static int compileModule(char **argv, LLVMContext &Context) { // Load the module to be compiled... SMDiagnostic Err; std::auto_ptr<Module> M; @@ -505,11 +319,14 @@ int main(int argc, char **argv) { TLI->disableAllFunctions(); PM.add(TLI); + // Add intenal analysis passes from the target machine. + Target.addAnalysisPasses(PM); + // Add the target data from the target machine, if it exists, or the module. - if (const TargetData *TD = Target.getTargetData()) - PM.add(new TargetData(*TD)); + if (const DataLayout *TD = Target.getDataLayout()) + PM.add(new DataLayout(*TD)); else - PM.add(new TargetData(mod)); + PM.add(new DataLayout(mod)); // Override default to generate verbose assembly. Target.setAsmVerbosityDefault(true); diff --git a/tools/lli/CMakeLists.txt b/tools/lli/CMakeLists.txt index 68cb921..ed479f5 100644 --- a/tools/lli/CMakeLists.txt +++ b/tools/lli/CMakeLists.txt @@ -1,7 +1,5 @@ -link_directories( ${LLVM_INTEL_JITEVENTS_LIBDIR} ) - -set(LLVM_LINK_COMPONENTS mcjit jit interpreter nativecodegen bitreader asmparser selectiondag) +set(LLVM_LINK_COMPONENTS mcjit jit interpreter nativecodegen bitreader asmparser selectiondag native) if( LLVM_USE_OPROFILE ) set(LLVM_LINK_COMPONENTS diff --git a/tools/lli/LLVMBuild.txt b/tools/lli/LLVMBuild.txt index 4eb82bd..36ceb39 100644 --- a/tools/lli/LLVMBuild.txt +++ b/tools/lli/LLVMBuild.txt @@ -19,4 +19,4 @@ type = Tool name = lli parent = Tools -required_libraries = AsmParser BitReader Interpreter JIT MCJIT NativeCodeGen SelectionDAG +required_libraries = AsmParser BitReader Interpreter JIT MCJIT NativeCodeGen SelectionDAG Native diff --git a/tools/lli/Makefile b/tools/lli/Makefile index 100fc2e..31f3ab8 100644 --- a/tools/lli/Makefile +++ b/tools/lli/Makefile @@ -12,7 +12,7 @@ TOOLNAME := lli include $(LEVEL)/Makefile.config -LINK_COMPONENTS := mcjit jit interpreter nativecodegen bitreader asmparser selectiondag +LINK_COMPONENTS := mcjit jit interpreter nativecodegen bitreader asmparser selectiondag native # If Intel JIT Events support is confiured, link against the LLVM Intel JIT # Events interface library diff --git a/tools/lli/RecordingMemoryManager.cpp b/tools/lli/RecordingMemoryManager.cpp index 9e1cff5..75cb978 100644 --- a/tools/lli/RecordingMemoryManager.cpp +++ b/tools/lli/RecordingMemoryManager.cpp @@ -28,7 +28,8 @@ allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID) { } uint8_t *RecordingMemoryManager:: -allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID) { +allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, bool IsReadOnly) { // The recording memory manager is just a local copy of the remote target. // The alignment requirement is just stored here for later use. Regular // heap storage is sufficient here. @@ -81,7 +82,20 @@ void RecordingMemoryManager::endExceptionTable(const Function *F, uint8_t *Table void RecordingMemoryManager::deallocateExceptionTable(void *ET) { llvm_unreachable("Unexpected!"); } + +static int jit_noop() { + return 0; +} + void *RecordingMemoryManager::getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure) { + // We should not invoke parent's ctors/dtors from generated main()! + // On Mingw and Cygwin, the symbol __main is resolved to + // callee's(eg. tools/lli) one, to invoke wrong duplicated ctors + // (and register wrong callee's dtors with atexit(3)). + // We expect ExecutionEngine::runStaticConstructorsDestructors() + // is called before ExecutionEngine::runFunctionAsMain() is called. + if (Name == "__main") return (void*)(intptr_t)&jit_noop; + return NULL; } diff --git a/tools/lli/RecordingMemoryManager.h b/tools/lli/RecordingMemoryManager.h index 1590235..20fd0c2 100644 --- a/tools/lli/RecordingMemoryManager.h +++ b/tools/lli/RecordingMemoryManager.h @@ -47,10 +47,13 @@ public: unsigned SectionID); uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID); + unsigned SectionID, bool IsReadOnly); void *getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure = true); + + bool applyPermissions(std::string *ErrMsg) { return false; } + // The following obsolete JITMemoryManager calls are stubbed out for // this model. void setMemoryWritable(); diff --git a/tools/lli/RemoteTarget.cpp b/tools/lli/RemoteTarget.cpp index 918f157..212bdfd 100644 --- a/tools/lli/RemoteTarget.cpp +++ b/tools/lli/RemoteTarget.cpp @@ -13,9 +13,9 @@ //===----------------------------------------------------------------------===// #include "RemoteTarget.h" -#include <llvm/ADT/StringRef.h> -#include <llvm/Support/DataTypes.h> -#include <llvm/Support/Memory.h> +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/Memory.h" #include <stdlib.h> #include <string> using namespace llvm; @@ -36,13 +36,13 @@ bool RemoteTarget::allocateSpace(size_t Size, unsigned Alignment, bool RemoteTarget::loadData(uint64_t Address, const void *Data, size_t Size) { memcpy ((void*)Address, Data, Size); - sys::MemoryBlock Mem((void*)Address, Size); - sys::Memory::setExecutable(Mem, &ErrorMsg); return false; } bool RemoteTarget::loadCode(uint64_t Address, const void *Data, size_t Size) { memcpy ((void*)Address, Data, Size); + sys::MemoryBlock Mem((void*)Address, Size); + sys::Memory::setExecutable(Mem, &ErrorMsg); return false; } diff --git a/tools/lli/RemoteTarget.h b/tools/lli/RemoteTarget.h index c584526..b2a6d0e 100644 --- a/tools/lli/RemoteTarget.h +++ b/tools/lli/RemoteTarget.h @@ -15,10 +15,10 @@ #ifndef REMOTEPROCESS_H #define REMOTEPROCESS_H -#include <llvm/ADT/StringRef.h> -#include <llvm/ADT/SmallVector.h> -#include <llvm/Support/DataTypes.h> -#include <llvm/Support/Memory.h> +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/Memory.h" #include <stdlib.h> #include <string> diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp index 4004b6c..332660f 100644 --- a/tools/lli/lli.cpp +++ b/tools/lli/lli.cpp @@ -14,11 +14,9 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "lli" +#include "llvm/IR/LLVMContext.h" #include "RecordingMemoryManager.h" #include "RemoteTarget.h" -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" -#include "llvm/Type.h" #include "llvm/ADT/Triple.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/CodeGen/LinkAllCodegenComponents.h" @@ -28,32 +26,26 @@ #include "llvm/ExecutionEngine/JITEventListener.h" #include "llvm/ExecutionEngine/JITMemoryManager.h" #include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/Format.h" #include "llvm/Support/IRReader.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/Memory.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PluginLoader.h" #include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/Format.h" #include "llvm/Support/Process.h" #include "llvm/Support/Signals.h" #include "llvm/Support/TargetSelect.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/DynamicLibrary.h" -#include "llvm/Support/Memory.h" +#include "llvm/Support/raw_ostream.h" #include <cerrno> -#ifdef __linux__ -// These includes used by LLIMCJITMemoryManager::getPointerToNamedFunction() -// for Glibc trickery. Look comments in this function for more information. -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif -#include <fcntl.h> -#include <unistd.h> -#endif - #ifdef __CYGWIN__ #include <cygwin/version.h> #if defined(CYGWIN_VERSION_DLL_MAJOR) && CYGWIN_VERSION_DLL_MAJOR<1007 @@ -171,6 +163,23 @@ namespace { cl::init(false)); cl::opt<bool> + GenerateSoftFloatCalls("soft-float", + cl::desc("Generate software floating point library calls"), + cl::init(false)); + + cl::opt<llvm::FloatABI::ABIType> + FloatABIForCalls("float-abi", + cl::desc("Choose float ABI type"), + cl::init(FloatABI::Default), + cl::values( + clEnumValN(FloatABI::Default, "default", + "Target default float ABI type"), + clEnumValN(FloatABI::Soft, "soft", + "Soft float ABI (implied by -soft-float)"), + clEnumValN(FloatABI::Hard, "hard", + "Hard float ABI (uses FP registers)"), + clEnumValEnd)); + cl::opt<bool> // In debug builds, make this default to true. #ifdef NDEBUG #define EMIT_DEBUG false @@ -199,192 +208,6 @@ static void do_shutdown() { #endif } -// Memory manager for MCJIT -class LLIMCJITMemoryManager : public JITMemoryManager { -public: - SmallVector<sys::MemoryBlock, 16> AllocatedDataMem; - SmallVector<sys::MemoryBlock, 16> AllocatedCodeMem; - SmallVector<sys::MemoryBlock, 16> FreeCodeMem; - - LLIMCJITMemoryManager() { } - ~LLIMCJITMemoryManager(); - - virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID); - - virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID); - - virtual void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true); - - // Invalidate instruction cache for code sections. Some platforms with - // separate data cache and instruction cache require explicit cache flush, - // otherwise JIT code manipulations (like resolved relocations) will get to - // the data cache but not to the instruction cache. - virtual void invalidateInstructionCache(); - - // The MCJITMemoryManager doesn't use the following functions, so we don't - // need implement them. - virtual void setMemoryWritable() { - llvm_unreachable("Unexpected call!"); - } - virtual void setMemoryExecutable() { - llvm_unreachable("Unexpected call!"); - } - virtual void setPoisonMemory(bool poison) { - llvm_unreachable("Unexpected call!"); - } - virtual void AllocateGOT() { - llvm_unreachable("Unexpected call!"); - } - virtual uint8_t *getGOTBase() const { - llvm_unreachable("Unexpected call!"); - return 0; - } - virtual uint8_t *startFunctionBody(const Function *F, - uintptr_t &ActualSize){ - llvm_unreachable("Unexpected call!"); - return 0; - } - virtual uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize, - unsigned Alignment) { - llvm_unreachable("Unexpected call!"); - return 0; - } - virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart, - uint8_t *FunctionEnd) { - llvm_unreachable("Unexpected call!"); - } - virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) { - llvm_unreachable("Unexpected call!"); - return 0; - } - virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) { - llvm_unreachable("Unexpected call!"); - return 0; - } - virtual void deallocateFunctionBody(void *Body) { - llvm_unreachable("Unexpected call!"); - } - virtual uint8_t* startExceptionTable(const Function* F, - uintptr_t &ActualSize) { - llvm_unreachable("Unexpected call!"); - return 0; - } - virtual void endExceptionTable(const Function *F, uint8_t *TableStart, - uint8_t *TableEnd, uint8_t* FrameRegister) { - llvm_unreachable("Unexpected call!"); - } - virtual void deallocateExceptionTable(void *ET) { - llvm_unreachable("Unexpected call!"); - } -}; - -uint8_t *LLIMCJITMemoryManager::allocateDataSection(uintptr_t Size, - unsigned Alignment, - unsigned SectionID) { - if (!Alignment) - Alignment = 16; - uint8_t *Addr = (uint8_t*)calloc((Size + Alignment - 1)/Alignment, Alignment); - AllocatedDataMem.push_back(sys::MemoryBlock(Addr, Size)); - return Addr; -} - -uint8_t *LLIMCJITMemoryManager::allocateCodeSection(uintptr_t Size, - unsigned Alignment, - unsigned SectionID) { - if (!Alignment) - Alignment = 16; - unsigned NeedAllocate = Alignment * ((Size + Alignment - 1)/Alignment + 1); - uintptr_t Addr = 0; - // Look in the list of free code memory regions and use a block there if one - // is available. - for (int i = 0, e = FreeCodeMem.size(); i != e; ++i) { - sys::MemoryBlock &MB = FreeCodeMem[i]; - if (MB.size() >= NeedAllocate) { - Addr = (uintptr_t)MB.base(); - uintptr_t EndOfBlock = Addr + MB.size(); - // Align the address. - Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1); - // Store cutted free memory block. - FreeCodeMem[i] = sys::MemoryBlock((void*)(Addr + Size), - EndOfBlock - Addr - Size); - return (uint8_t*)Addr; - } - } - - // No pre-allocated free block was large enough. Allocate a new memory region. - sys::MemoryBlock MB = sys::Memory::AllocateRWX(NeedAllocate, 0, 0); - - AllocatedCodeMem.push_back(MB); - Addr = (uintptr_t)MB.base(); - uintptr_t EndOfBlock = Addr + MB.size(); - // Align the address. - Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1); - // The AllocateRWX may allocate much more memory than we need. In this case, - // we store the unused memory as a free memory block. - unsigned FreeSize = EndOfBlock-Addr-Size; - if (FreeSize > 16) - FreeCodeMem.push_back(sys::MemoryBlock((void*)(Addr + Size), FreeSize)); - - // Return aligned address - return (uint8_t*)Addr; -} - -void LLIMCJITMemoryManager::invalidateInstructionCache() { - for (int i = 0, e = AllocatedCodeMem.size(); i != e; ++i) - sys::Memory::InvalidateInstructionCache(AllocatedCodeMem[i].base(), - AllocatedCodeMem[i].size()); -} - -void *LLIMCJITMemoryManager::getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure) { -#if defined(__linux__) - //===--------------------------------------------------------------------===// - // Function stubs that are invoked instead of certain library calls - // - // Force the following functions to be linked in to anything that uses the - // JIT. This is a hack designed to work around the all-too-clever Glibc - // strategy of making these functions work differently when inlined vs. when - // not inlined, and hiding their real definitions in a separate archive file - // that the dynamic linker can't see. For more info, search for - // 'libc_nonshared.a' on Google, or read http://llvm.org/PR274. - if (Name == "stat") return (void*)(intptr_t)&stat; - if (Name == "fstat") return (void*)(intptr_t)&fstat; - if (Name == "lstat") return (void*)(intptr_t)&lstat; - if (Name == "stat64") return (void*)(intptr_t)&stat64; - if (Name == "fstat64") return (void*)(intptr_t)&fstat64; - if (Name == "lstat64") return (void*)(intptr_t)&lstat64; - if (Name == "atexit") return (void*)(intptr_t)&atexit; - if (Name == "mknod") return (void*)(intptr_t)&mknod; -#endif // __linux__ - - const char *NameStr = Name.c_str(); - void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr); - if (Ptr) return Ptr; - - // If it wasn't found and if it starts with an underscore ('_') character, - // try again without the underscore. - if (NameStr[0] == '_') { - Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1); - if (Ptr) return Ptr; - } - - if (AbortOnFailure) - report_fatal_error("Program used external function '" + Name + - "' which could not be resolved!"); - return 0; -} - -LLIMCJITMemoryManager::~LLIMCJITMemoryManager() { - for (unsigned i = 0, e = AllocatedCodeMem.size(); i != e; ++i) - sys::Memory::ReleaseRWX(AllocatedCodeMem[i]); - for (unsigned i = 0, e = AllocatedDataMem.size(); i != e; ++i) - free(AllocatedDataMem[i].base()); -} - - void layoutRemoteTargetMemory(RemoteTarget *T, RecordingMemoryManager *JMM) { // Lay out our sections in order, with all the code sections first, then // all the data sections. @@ -435,9 +258,13 @@ void layoutRemoteTargetMemory(RemoteTarget *T, RecordingMemoryManager *JMM) { EE->mapSectionAddress(const_cast<void*>(Offsets[i].first), Addr); DEBUG(dbgs() << " Mapping local: " << Offsets[i].first - << " to remote: " << format("%#018x", Addr) << "\n"); + << " to remote: " << format("%p", Addr) << "\n"); } + + // Trigger application of relocations + EE->finalizeObject(); + // Now load it all to the target. for (unsigned i = 0, e = Offsets.size(); i != e; ++i) { uint64_t Addr = RemoteAddr + Offsets[i].second; @@ -446,12 +273,12 @@ void layoutRemoteTargetMemory(RemoteTarget *T, RecordingMemoryManager *JMM) { T->loadCode(Addr, Offsets[i].first, Sizes[i]); DEBUG(dbgs() << " loading code: " << Offsets[i].first - << " to remote: " << format("%#018x", Addr) << "\n"); + << " to remote: " << format("%p", Addr) << "\n"); } else { T->loadData(Addr, Offsets[i].first, Sizes[i]); DEBUG(dbgs() << " loading data: " << Offsets[i].first - << " to remote: " << format("%#018x", Addr) << "\n"); + << " to remote: " << format("%p", Addr) << "\n"); } } @@ -471,6 +298,7 @@ int main(int argc, char **argv, char * const *envp) { // usable by the JIT. InitializeNativeTarget(); InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); cl::ParseCommandLineOptions(argc, argv, "llvm interpreter & dynamic compiler\n"); @@ -519,7 +347,7 @@ int main(int argc, char **argv, char * const *envp) { if (RemoteMCJIT) JMM = new RecordingMemoryManager(); else - JMM = new LLIMCJITMemoryManager(); + JMM = new SectionMemoryManager(); builder.setJITMemoryManager(JMM); } else { if (RemoteMCJIT) { @@ -543,15 +371,22 @@ int main(int argc, char **argv, char * const *envp) { } builder.setOptLevel(OLvl); + TargetOptions Options; + Options.UseSoftFloat = GenerateSoftFloatCalls; + if (FloatABIForCalls != FloatABI::Default) + Options.FloatABIType = FloatABIForCalls; + if (GenerateSoftFloatCalls) + FloatABIForCalls = FloatABI::Soft; + // Remote target execution doesn't handle EH or debug registration. if (!RemoteMCJIT) { - TargetOptions Options; Options.JITExceptionHandling = EnableJITExceptionHandling; Options.JITEmitDebugInfo = EmitJitDebugInfo; Options.JITEmitDebugInfoToDisk = EmitJitDebugInfoToDisk; - builder.setTargetOptions(Options); } + builder.setTargetOptions(Options); + EE = builder.create(); if (!EE) { if (!ErrorMsg.empty()) @@ -613,8 +448,13 @@ int main(int argc, char **argv, char * const *envp) { // MCJIT itself. FIXME. // // Run static constructors. - if (!RemoteMCJIT) - EE->runStaticConstructorsDestructors(false); + if (!RemoteMCJIT) { + if (UseMCJIT && !ForceInterpreter) { + // Give MCJIT a chance to apply relocations and set page permissions. + EE->finalizeObject(); + } + EE->runStaticConstructorsDestructors(false); + } if (NoLazyCompilation) { for (Module::iterator I = Mod->begin(), E = Mod->end(); I != E; ++I) { @@ -649,16 +489,19 @@ int main(int argc, char **argv, char * const *envp) { uint64_t Entry = (uint64_t)EE->getPointerToFunction(EntryFn); DEBUG(dbgs() << "Executing '" << EntryFn->getName() << "' at " - << format("%#18x", Entry) << "\n"); + << format("%p", Entry) << "\n"); if (Target.executeCode(Entry, Result)) errs() << "ERROR: " << Target.getErrorMsg() << "\n"; Target.stop(); } else { + // Trigger compilation separately so code regions that need to be + // invalidated will be known. + (void)EE->getPointerToFunction(EntryFn); // Clear instruction cache before code will be executed. if (JMM) - static_cast<LLIMCJITMemoryManager*>(JMM)->invalidateInstructionCache(); + static_cast<SectionMemoryManager*>(JMM)->invalidateInstructionCache(); // Run main. Result = EE->runFunctionAsMain(EntryFn, InputArgv, envp); diff --git a/tools/llvm-ar/CMakeLists.txt b/tools/llvm-ar/CMakeLists.txt index c8b0b72..70eb760 100644 --- a/tools/llvm-ar/CMakeLists.txt +++ b/tools/llvm-ar/CMakeLists.txt @@ -1,5 +1,4 @@ set(LLVM_LINK_COMPONENTS archive) -set(LLVM_REQUIRES_EH 1) add_llvm_tool(llvm-ar llvm-ar.cpp diff --git a/tools/llvm-ar/Makefile b/tools/llvm-ar/Makefile index 6ee6f34..fafb14b 100644 --- a/tools/llvm-ar/Makefile +++ b/tools/llvm-ar/Makefile @@ -10,7 +10,6 @@ LEVEL := ../.. TOOLNAME := llvm-ar LINK_COMPONENTS := archive -REQUIRES_EH := 1 # This tool has no plugins, optimize startup time. TOOL_NO_EXPORTS := 1 diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp index 7c53701..86eb8e2 100644 --- a/tools/llvm-ar/llvm-ar.cpp +++ b/tools/llvm-ar/llvm-ar.cpp @@ -12,19 +12,20 @@ // //===----------------------------------------------------------------------===// -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/Bitcode/Archive.h" +#include "llvm/IR/Module.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Format.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Signals.h" +#include "llvm/Support/raw_ostream.h" #include <algorithm> -#include <memory> +#include <cstdlib> #include <fstream> +#include <memory> using namespace llvm; // Option for compatibility with AIX, not used but must allow it to be present. @@ -126,40 +127,57 @@ std::set<sys::Path> Paths; // The Archive object to which all the editing operations will be sent. Archive* TheArchive = 0; +// The name this program was invoked as. +static const char *program_name; + +// show_help - Show the error message, the help message and exit. +LLVM_ATTRIBUTE_NORETURN static void +show_help(const std::string &msg) { + errs() << program_name << ": " << msg << "\n\n"; + cl::PrintHelpMessage(); + if (TheArchive) + delete TheArchive; + std::exit(1); +} + +// fail - Show the error message and exit. +LLVM_ATTRIBUTE_NORETURN static void +fail(const std::string &msg) { + errs() << program_name << ": " << msg << "\n\n"; + if (TheArchive) + delete TheArchive; + std::exit(1); +} + // getRelPos - Extract the member filename from the command line for // the [relpos] argument associated with a, b, and i modifiers void getRelPos() { - if(RestOfArgs.size() > 0) { - RelPos = RestOfArgs[0]; - RestOfArgs.erase(RestOfArgs.begin()); - } - else - throw "Expected [relpos] for a, b, or i modifier"; + if(RestOfArgs.size() == 0) + show_help("Expected [relpos] for a, b, or i modifier"); + RelPos = RestOfArgs[0]; + RestOfArgs.erase(RestOfArgs.begin()); } // getCount - Extract the [count] argument associated with the N modifier // from the command line and check its value. void getCount() { - if(RestOfArgs.size() > 0) { - Count = atoi(RestOfArgs[0].c_str()); - RestOfArgs.erase(RestOfArgs.begin()); - } - else - throw "Expected [count] value with N modifier"; + if(RestOfArgs.size() == 0) + show_help("Expected [count] value with N modifier"); + + Count = atoi(RestOfArgs[0].c_str()); + RestOfArgs.erase(RestOfArgs.begin()); // Non-positive counts are not allowed if (Count < 1) - throw "Invalid [count] value (not a positive integer)"; + show_help("Invalid [count] value (not a positive integer)"); } // getArchive - Get the archive file name from the command line void getArchive() { - if(RestOfArgs.size() > 0) { - ArchiveName = RestOfArgs[0]; - RestOfArgs.erase(RestOfArgs.begin()); - } - else - throw "An archive name must be specified."; + if(RestOfArgs.size() == 0) + show_help("An archive name must be specified"); + ArchiveName = RestOfArgs[0]; + RestOfArgs.erase(RestOfArgs.begin()); } // getMembers - Copy over remaining items in RestOfArgs to our Members vector @@ -240,25 +258,27 @@ ArchiveOperation parseCommandLine() { // Perform various checks on the operation/modifier specification // to make sure we are dealing with a legal request. if (NumOperations == 0) - throw "You must specify at least one of the operations"; + show_help("You must specify at least one of the operations"); if (NumOperations > 1) - throw "Only one operation may be specified"; + show_help("Only one operation may be specified"); if (NumPositional > 1) - throw "You may only specify one of a, b, and i modifiers"; - if (AddAfter || AddBefore || InsertBefore) + show_help("You may only specify one of a, b, and i modifiers"); + if (AddAfter || AddBefore || InsertBefore) { if (Operation != Move && Operation != ReplaceOrInsert) - throw "The 'a', 'b' and 'i' modifiers can only be specified with " - "the 'm' or 'r' operations"; + show_help("The 'a', 'b' and 'i' modifiers can only be specified with " + "the 'm' or 'r' operations"); + } if (RecurseDirectories && Operation != ReplaceOrInsert) - throw "The 'R' modifiers is only applicabe to the 'r' operation"; + show_help("The 'R' modifiers is only applicabe to the 'r' operation"); if (OriginalDates && Operation != Extract) - throw "The 'o' modifier is only applicable to the 'x' operation"; + show_help("The 'o' modifier is only applicable to the 'x' operation"); if (TruncateNames && Operation!=QuickAppend && Operation!=ReplaceOrInsert) - throw "The 'f' modifier is only applicable to the 'q' and 'r' operations"; + show_help("The 'f' modifier is only applicable to the 'q' and 'r' " + "operations"); if (OnlyUpdate && Operation != ReplaceOrInsert) - throw "The 'u' modifier is only applicable to the 'r' operation"; + show_help("The 'u' modifier is only applicable to the 'r' operation"); if (Count > 1 && Members.size() > 1) - throw "Only one member name may be specified with the 'N' modifier"; + show_help("Only one member name may be specified with the 'N' modifier"); // Return the parsed operation to the caller return Operation; @@ -304,16 +324,16 @@ bool buildPaths(bool checkExistence, std::string* ErrMsg) { for (unsigned i = 0; i < Members.size(); i++) { sys::Path aPath; if (!aPath.set(Members[i])) - throw std::string("File member name invalid: ") + Members[i]; + fail(std::string("File member name invalid: ") + Members[i]); if (checkExistence) { bool Exists; if (sys::fs::exists(aPath.str(), Exists) || !Exists) - throw std::string("File does not exist: ") + Members[i]; + fail(std::string("File does not exist: ") + Members[i]); std::string Err; sys::PathWithStatus PwS(aPath); const sys::FileStatus *si = PwS.getFileStatus(false, &Err); if (!si) - throw Err; + fail(Err); if (si->isDir) { std::set<sys::Path> dirpaths; if (recurseDirectories(aPath, dirpaths, ErrMsg)) @@ -683,6 +703,7 @@ doReplaceOrInsert(std::string* ErrMsg) { // main - main program for llvm-ar .. see comments in the code int main(int argc, char **argv) { + program_name = argv[0]; // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); @@ -698,77 +719,61 @@ int main(int argc, char **argv) { int exitCode = 0; - // Make sure we don't exit with "unhandled exception". - try { - // Do our own parsing of the command line because the CommandLine utility - // can't handle the grouped positional parameters without a dash. - ArchiveOperation Operation = parseCommandLine(); - - // Check the path name of the archive - sys::Path ArchivePath; - if (!ArchivePath.set(ArchiveName)) - throw std::string("Archive name invalid: ") + ArchiveName; - - // Create or open the archive object. - 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"; - TheArchive = Archive::CreateEmpty(ArchivePath, Context); - TheArchive->writeToDisk(); - } else { - std::string Error; - TheArchive = Archive::OpenAndLoad(ArchivePath, Context, &Error); - if (TheArchive == 0) { - errs() << argv[0] << ": error loading '" << ArchivePath.str() << "': " - << Error << "!\n"; - return 1; - } - } + // Do our own parsing of the command line because the CommandLine utility + // can't handle the grouped positional parameters without a dash. + ArchiveOperation Operation = parseCommandLine(); - // Make sure we're not fooling ourselves. - assert(TheArchive && "Unable to instantiate the archive"); - - // Make sure we clean up the archive even on failure. - std::auto_ptr<Archive> AutoArchive(TheArchive); - - // Perform the operation - std::string ErrMsg; - bool haveError = false; - switch (Operation) { - case Print: haveError = doPrint(&ErrMsg); break; - case Delete: haveError = doDelete(&ErrMsg); break; - case Move: haveError = doMove(&ErrMsg); break; - case QuickAppend: haveError = doQuickAppend(&ErrMsg); break; - case ReplaceOrInsert: haveError = doReplaceOrInsert(&ErrMsg); break; - case DisplayTable: haveError = doDisplayTable(&ErrMsg); break; - case Extract: haveError = doExtract(&ErrMsg); break; - case NoOperation: - errs() << argv[0] << ": No operation was selected.\n"; - break; - } - if (haveError) { - errs() << argv[0] << ": " << ErrMsg << "\n"; + // Check the path name of the archive + sys::Path ArchivePath; + if (!ArchivePath.set(ArchiveName)) { + errs() << argv[0] << ": Archive name invalid: " << ArchiveName << "\n"; + return 1; + } + + // Create or open the archive object. + 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"; + TheArchive = Archive::CreateEmpty(ArchivePath, Context); + TheArchive->writeToDisk(); + } else { + std::string Error; + TheArchive = Archive::OpenAndLoad(ArchivePath, Context, &Error); + if (TheArchive == 0) { + errs() << argv[0] << ": error loading '" << ArchivePath.str() << "': " + << Error << "!\n"; return 1; } - } catch (const char*msg) { - // These errors are usage errors, thrown only by the various checks in the - // code above. - errs() << argv[0] << ": " << msg << "\n\n"; - cl::PrintHelpMessage(); - exitCode = 1; - } catch (const std::string& msg) { - // These errors are thrown by LLVM libraries (e.g. lib System) and represent - // a more serious error so we bump the exitCode and don't print the usage. - errs() << argv[0] << ": " << msg << "\n"; - exitCode = 2; - } catch (...) { - // This really shouldn't happen, but just in case .... - errs() << argv[0] << ": An unexpected unknown exception occurred.\n"; - exitCode = 3; } + // Make sure we're not fooling ourselves. + assert(TheArchive && "Unable to instantiate the archive"); + + // Perform the operation + std::string ErrMsg; + bool haveError = false; + switch (Operation) { + case Print: haveError = doPrint(&ErrMsg); break; + case Delete: haveError = doDelete(&ErrMsg); break; + case Move: haveError = doMove(&ErrMsg); break; + case QuickAppend: haveError = doQuickAppend(&ErrMsg); break; + case ReplaceOrInsert: haveError = doReplaceOrInsert(&ErrMsg); break; + case DisplayTable: haveError = doDisplayTable(&ErrMsg); break; + case Extract: haveError = doExtract(&ErrMsg); break; + case NoOperation: + errs() << argv[0] << ": No operation was selected.\n"; + break; + } + if (haveError) { + errs() << argv[0] << ": " << ErrMsg << "\n"; + return 1; + } + + delete TheArchive; + TheArchive = 0; + // Return result code back to operating system. return exitCode; } diff --git a/tools/llvm-as/CMakeLists.txt b/tools/llvm-as/CMakeLists.txt index eef4a13..d5620e7 100644 --- a/tools/llvm-as/CMakeLists.txt +++ b/tools/llvm-as/CMakeLists.txt @@ -1,5 +1,4 @@ set(LLVM_LINK_COMPONENTS asmparser bitwriter) -set(LLVM_REQUIRES_EH 1) add_llvm_tool(llvm-as llvm-as.cpp diff --git a/tools/llvm-as/llvm-as.cpp b/tools/llvm-as/llvm-as.cpp index 1def9a4..273c427 100644 --- a/tools/llvm-as/llvm-as.cpp +++ b/tools/llvm-as/llvm-as.cpp @@ -15,18 +15,18 @@ // //===----------------------------------------------------------------------===// -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" -#include "llvm/Assembly/Parser.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/Analysis/Verifier.h" +#include "llvm/Assembly/Parser.h" #include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/IR/Module.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Signals.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/SystemUtils.h" #include "llvm/Support/ToolOutputFile.h" -#include "llvm/Support/Signals.h" #include <memory> using namespace llvm; diff --git a/tools/llvm-bcanalyzer/CMakeLists.txt b/tools/llvm-bcanalyzer/CMakeLists.txt index 732bc32..0151ea9 100644 --- a/tools/llvm-bcanalyzer/CMakeLists.txt +++ b/tools/llvm-bcanalyzer/CMakeLists.txt @@ -1,5 +1,4 @@ set(LLVM_LINK_COMPONENTS bitreader) -set(LLVM_REQUIRES_EH 1) add_llvm_tool(llvm-bcanalyzer llvm-bcanalyzer.cpp diff --git a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp index 8109ca4..46b687e 100644 --- a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp +++ b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp @@ -37,12 +37,11 @@ #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Signals.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" - -#include <map> #include <algorithm> +#include <map> using namespace llvm; static cl::opt<std::string> @@ -150,7 +149,7 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, case bitc::MODULE_CODE_DATALAYOUT: return "DATALAYOUT"; case bitc::MODULE_CODE_ASM: return "ASM"; case bitc::MODULE_CODE_SECTIONNAME: return "SECTIONNAME"; - case bitc::MODULE_CODE_DEPLIB: return "DEPLIB"; + case bitc::MODULE_CODE_DEPLIB: return "DEPLIB"; // FIXME: Remove in 4.0 case bitc::MODULE_CODE_GLOBALVAR: return "GLOBALVAR"; case bitc::MODULE_CODE_FUNCTION: return "FUNCTION"; case bitc::MODULE_CODE_ALIAS: return "ALIAS"; diff --git a/tools/llvm-config/Makefile b/tools/llvm-config/Makefile index e8c8692..b20b6bf 100644 --- a/tools/llvm-config/Makefile +++ b/tools/llvm-config/Makefile @@ -63,5 +63,5 @@ ifeq ($(LLVM_CROSS_COMPILING),1) install:: $(DESTDIR)$(PROJ_bindir) $(Echo) Installing llvm-config-host $(Verb) $(ProgInstall) $(BuildLLVMToolDir)/llvm-config \ - $(DESTDIR)$(PROJ_bindir)/llvm-config-host + $(DESTDIR)$(PROJ_bindir)/$(program_prefix)llvm-config-host endif diff --git a/tools/llvm-diff/DiffConsumer.cpp b/tools/llvm-diff/DiffConsumer.cpp index 91c1699..9078013 100644 --- a/tools/llvm-diff/DiffConsumer.cpp +++ b/tools/llvm-diff/DiffConsumer.cpp @@ -12,9 +12,8 @@ //===----------------------------------------------------------------------===// #include "DiffConsumer.h" - -#include "llvm/Module.h" -#include "llvm/Instructions.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" #include "llvm/Support/ErrorHandling.h" using namespace llvm; diff --git a/tools/llvm-diff/DiffConsumer.h b/tools/llvm-diff/DiffConsumer.h index 98e369b..6c2209f 100644 --- a/tools/llvm-diff/DiffConsumer.h +++ b/tools/llvm-diff/DiffConsumer.h @@ -15,12 +15,11 @@ #define _LLVM_DIFFCONSUMER_H_ #include "DiffLog.h" - -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/raw_ostream.h" namespace llvm { class Module; diff --git a/tools/llvm-diff/DiffLog.cpp b/tools/llvm-diff/DiffLog.cpp index 9cc0c88..caf779b 100644 --- a/tools/llvm-diff/DiffLog.cpp +++ b/tools/llvm-diff/DiffLog.cpp @@ -13,10 +13,9 @@ #include "DiffLog.h" #include "DiffConsumer.h" - -#include "llvm/Instructions.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/IR/Instructions.h" using namespace llvm; diff --git a/tools/llvm-diff/DifferenceEngine.cpp b/tools/llvm-diff/DifferenceEngine.cpp index 0c1e30c..4b11315 100644 --- a/tools/llvm-diff/DifferenceEngine.cpp +++ b/tools/llvm-diff/DifferenceEngine.cpp @@ -13,22 +13,20 @@ //===----------------------------------------------------------------------===// #include "DifferenceEngine.h" - -#include "llvm/Constants.h" -#include "llvm/Function.h" -#include "llvm/Instructions.h" -#include "llvm/Module.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" -#include "llvm/Support/CallSite.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" #include "llvm/Support/CFG.h" +#include "llvm/Support/CallSite.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/type_traits.h" - #include <utility> using namespace llvm; diff --git a/tools/llvm-diff/DifferenceEngine.h b/tools/llvm-diff/DifferenceEngine.h index 0246d8f..73bf6eb 100644 --- a/tools/llvm-diff/DifferenceEngine.h +++ b/tools/llvm-diff/DifferenceEngine.h @@ -15,11 +15,10 @@ #ifndef _LLVM_DIFFERENCE_ENGINE_H_ #define _LLVM_DIFFERENCE_ENGINE_H_ +#include "DiffConsumer.h" +#include "DiffLog.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "DiffLog.h" -#include "DiffConsumer.h" - #include <utility> namespace llvm { diff --git a/tools/llvm-diff/llvm-diff.cpp b/tools/llvm-diff/llvm-diff.cpp index 45957b3..0b9e92b 100644 --- a/tools/llvm-diff/llvm-diff.cpp +++ b/tools/llvm-diff/llvm-diff.cpp @@ -13,19 +13,17 @@ #include "DiffLog.h" #include "DifferenceEngine.h" - -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" -#include "llvm/Type.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/IRReader.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/SourceMgr.h" - +#include "llvm/Support/raw_ostream.h" #include <string> #include <utility> diff --git a/tools/llvm-dis/CMakeLists.txt b/tools/llvm-dis/CMakeLists.txt index 3125f8a..9f12ecb 100644 --- a/tools/llvm-dis/CMakeLists.txt +++ b/tools/llvm-dis/CMakeLists.txt @@ -1,5 +1,4 @@ set(LLVM_LINK_COMPONENTS bitreader analysis) -set(LLVM_REQUIRES_EH 1) add_llvm_tool(llvm-dis llvm-dis.cpp diff --git a/tools/llvm-dis/llvm-dis.cpp b/tools/llvm-dis/llvm-dis.cpp index 41f023d..2baa91d 100644 --- a/tools/llvm-dis/llvm-dis.cpp +++ b/tools/llvm-dis/llvm-dis.cpp @@ -16,21 +16,21 @@ // //===----------------------------------------------------------------------===// -#include "llvm/LLVMContext.h" -#include "llvm/DebugInfo.h" -#include "llvm/Module.h" -#include "llvm/Type.h" -#include "llvm/IntrinsicInst.h" -#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/Assembly/AssemblyAnnotationWriter.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/DebugInfo.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/DataStream.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/Signals.h" +#include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/system_error.h" using namespace llvm; diff --git a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp index 38c3a1e..34302fa 100644 --- a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp @@ -1,4 +1,4 @@ -//===-- llvm-dwarfdump.cpp - Debug info dumping utility for llvm -----------===// +//===-- llvm-dwarfdump.cpp - Debug info dumping utility for llvm ----------===// // // The LLVM Compiler Infrastructure // @@ -12,10 +12,11 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/Triple.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/Object/ObjectFile.h" +#include "llvm/ADT/Triple.h" #include "llvm/DebugInfo/DIContext.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/RelocVisitor.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Format.h" @@ -28,6 +29,9 @@ #include "llvm/Support/system_error.h" #include <algorithm> #include <cstring> +#include <list> +#include <string> + using namespace llvm; using namespace object; @@ -65,47 +69,8 @@ static void DumpInput(const StringRef &Filename) { } OwningPtr<ObjectFile> Obj(ObjectFile::createObjectFile(Buff.take())); + OwningPtr<DIContext> dictx(DIContext::getDWARFContext(Obj.get())); - StringRef DebugInfoSection; - StringRef DebugAbbrevSection; - StringRef DebugLineSection; - StringRef DebugArangesSection; - StringRef DebugStringSection; - StringRef DebugRangesSection; - - error_code ec; - for (section_iterator i = Obj->begin_sections(), - e = Obj->end_sections(); - i != e; i.increment(ec)) { - StringRef name; - i->getName(name); - StringRef data; - i->getContents(data); - - if (name.startswith("__DWARF,")) - name = name.substr(8); // Skip "__DWARF," prefix. - name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes. - if (name == "debug_info") - DebugInfoSection = data; - else if (name == "debug_abbrev") - DebugAbbrevSection = data; - else if (name == "debug_line") - DebugLineSection = data; - else if (name == "debug_aranges") - DebugArangesSection = data; - else if (name == "debug_str") - DebugStringSection = data; - else if (name == "debug_ranges") - DebugRangesSection = data; - } - - OwningPtr<DIContext> dictx(DIContext::getDWARFContext(/*FIXME*/true, - DebugInfoSection, - DebugAbbrevSection, - DebugArangesSection, - DebugLineSection, - DebugStringSection, - DebugRangesSection)); if (Address == -1ULL) { outs() << Filename << ":\tfile format " << Obj->getFileFormatName() << "\n\n"; @@ -118,8 +83,8 @@ static void DumpInput(const StringRef &Filename) { if (PrintFunctions) SpecFlags |= DILineInfoSpecifier::FunctionName; if (PrintInlining) { - DIInliningInfo InliningInfo = dictx->getInliningInfoForAddress( - Address, SpecFlags); + DIInliningInfo InliningInfo = + dictx->getInliningInfoForAddress(Address, SpecFlags); uint32_t n = InliningInfo.getNumberOfFrames(); if (n == 0) { // Print one empty debug line info in any case. diff --git a/tools/llvm-extract/llvm-extract.cpp b/tools/llvm-extract/llvm-extract.cpp index 2ed11c5..85a9211 100644 --- a/tools/llvm-extract/llvm-extract.cpp +++ b/tools/llvm-extract/llvm-extract.cpp @@ -12,23 +12,23 @@ // //===----------------------------------------------------------------------===// -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" -#include "llvm/PassManager.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/Assembly/PrintModulePass.h" #include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/Transforms/IPO.h" -#include "llvm/Target/TargetData.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Module.h" +#include "llvm/PassManager.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/IRReader.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/ToolOutputFile.h" -#include "llvm/Support/SystemUtils.h" -#include "llvm/Support/Signals.h" #include "llvm/Support/Regex.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SetVector.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/SystemUtils.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Transforms/IPO.h" #include <memory> using namespace llvm; @@ -59,6 +59,19 @@ ExtractRegExpFuncs("rfunc", cl::desc("Specify function(s) to extract using a " "regular expression"), cl::ZeroOrMore, cl::value_desc("rfunction")); +// ExtractAlias - The alias to extract from the module. +static cl::list<std::string> +ExtractAliases("alias", cl::desc("Specify alias to extract"), + cl::ZeroOrMore, cl::value_desc("alias")); + + +// ExtractRegExpAliases - The aliases, matched via regular expression, to +// extract from the module. +static cl::list<std::string> +ExtractRegExpAliases("ralias", cl::desc("Specify alias(es) to extract using a " + "regular expression"), + cl::ZeroOrMore, cl::value_desc("ralias")); + // ExtractGlobals - The globals to extract from the module. static cl::list<std::string> ExtractGlobals("glob", cl::desc("Specify global to extract"), @@ -97,6 +110,40 @@ int main(int argc, char **argv) { // Use SetVector to avoid duplicates. SetVector<GlobalValue *> GVs; + // Figure out which aliases we should extract. + for (size_t i = 0, e = ExtractAliases.size(); i != e; ++i) { + GlobalAlias *GA = M->getNamedAlias(ExtractAliases[i]); + if (!GA) { + errs() << argv[0] << ": program doesn't contain alias named '" + << ExtractAliases[i] << "'!\n"; + return 1; + } + GVs.insert(GA); + } + + // Extract aliases via regular expression matching. + for (size_t i = 0, e = ExtractRegExpAliases.size(); i != e; ++i) { + std::string Error; + Regex RegEx(ExtractRegExpAliases[i]); + if (!RegEx.isValid(Error)) { + errs() << argv[0] << ": '" << ExtractRegExpAliases[i] << "' " + "invalid regex: " << Error; + } + bool match = false; + for (Module::alias_iterator GA = M->alias_begin(), E = M->alias_end(); + GA != E; GA++) { + if (RegEx.match(GA->getName())) { + GVs.insert(&*GA); + match = true; + } + } + if (!match) { + errs() << argv[0] << ": program doesn't contain global named '" + << ExtractRegExpAliases[i] << "'!\n"; + return 1; + } + } + // Figure out which globals we should extract. for (size_t i = 0, e = ExtractGlobals.size(); i != e; ++i) { GlobalValue *GV = M->getNamedGlobal(ExtractGlobals[i]); @@ -206,7 +253,7 @@ int main(int argc, char **argv) { // In addition to deleting all other functions, we also want to spiff it // up a little bit. Do this now. PassManager Passes; - Passes.add(new TargetData(M.get())); // Use correct TargetData + Passes.add(new DataLayout(M.get())); // Use correct DataLayout std::vector<GlobalValue*> Gvs(GVs.begin(), GVs.end()); diff --git a/tools/llvm-jitlistener/CMakeLists.txt b/tools/llvm-jitlistener/CMakeLists.txt new file mode 100644 index 0000000..57a4a0c --- /dev/null +++ b/tools/llvm-jitlistener/CMakeLists.txt @@ -0,0 +1,20 @@ +# This tool is excluded from the CMake build if Intel JIT events are disabled.
+
+link_directories( ${LLVM_INTEL_JITEVENTS_LIBDIR} )
+include_directories( ${LLVM_INTEL_JITEVENTS_INCDIR} )
+
+set(LLVM_LINK_COMPONENTS
+ asmparser
+ bitreader
+ inteljitevents
+ interpreter
+ jit
+ mcjit
+ nativecodegen
+ object
+ selectiondag
+ )
+
+add_llvm_tool(llvm-jitlistener
+ llvm-jitlistener.cpp
+ )
diff --git a/tools/llvm-jitlistener/LLVMBuild.txt b/tools/llvm-jitlistener/LLVMBuild.txt new file mode 100644 index 0000000..c436dd9 --- /dev/null +++ b/tools/llvm-jitlistener/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/llvm-jitlistener/LLVMBuild.txt -------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = llvm-jitlistener +parent = Tools +required_libraries = AsmParser BitReader Interpreter JIT MCJIT NativeCodeGen Object SelectionDAG Native diff --git a/tools/llvm-jitlistener/Makefile b/tools/llvm-jitlistener/Makefile new file mode 100644 index 0000000..0971e6a --- /dev/null +++ b/tools/llvm-jitlistener/Makefile @@ -0,0 +1,27 @@ +##===- tools/llvm-jitlistener/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-jitlistener
+
+include $(LEVEL)/Makefile.config
+
+LINK_COMPONENTS := mcjit jit interpreter nativecodegen bitreader asmparser selectiondag Object
+
+# If Intel JIT Events support is configured, link against the LLVM Intel JIT
+# Events interface library. If not, this tool will do nothing useful, but it
+# will build correctly.
+ifeq ($(USE_INTEL_JITEVENTS), 1)
+ LINK_COMPONENTS += inteljitevents
+endif
+
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS := 1
+
+include $(LLVM_SRC_ROOT)/Makefile.rules
diff --git a/tools/llvm-jitlistener/llvm-jitlistener.cpp b/tools/llvm-jitlistener/llvm-jitlistener.cpp new file mode 100644 index 0000000..2f72e42 --- /dev/null +++ b/tools/llvm-jitlistener/llvm-jitlistener.cpp @@ -0,0 +1,207 @@ +//===-- llvm-jitlistener.cpp - Utility for testing MCJIT event listener ---===// +// +// 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 used by lit tests to verify the MCJIT JITEventListener +// interface. It registers a mock JIT event listener, generates a module from +// an input IR file and dumps the reported event information to stdout. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/LLVMContext.h" +#include "../../lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/Triple.h" +#include "llvm/ExecutionEngine/JITEventListener.h" +#include "llvm/ExecutionEngine/JITMemoryManager.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/ObjectImage.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/IRReader.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetSelect.h" +#include <string> + +using namespace llvm; + +namespace { + +typedef std::vector<std::pair<std::string, unsigned int> > SourceLocations; +typedef std::map<uint64_t, SourceLocations> NativeCodeMap; + +NativeCodeMap ReportedDebugFuncs; + +int NotifyEvent(iJIT_JVM_EVENT EventType, void *EventSpecificData) { + switch (EventType) { + case iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED: { + if (!EventSpecificData) { + errs() << + "Error: The JIT event listener did not provide a event data."; + return -1; + } + iJIT_Method_Load* msg = static_cast<iJIT_Method_Load*>(EventSpecificData); + + ReportedDebugFuncs[msg->method_id]; + + outs() << "Method load [" << msg->method_id << "]: " << msg->method_name + << ", Size = " << msg->method_size << "\n"; + + for(unsigned int i = 0; i < msg->line_number_size; ++i) { + if (!msg->line_number_table) { + errs() << "A function with a non-zero line count had no line table."; + return -1; + } + std::pair<std::string, unsigned int> loc( + std::string(msg->source_file_name), + msg->line_number_table[i].LineNumber); + ReportedDebugFuncs[msg->method_id].push_back(loc); + outs() << " Line info @ " << msg->line_number_table[i].Offset + << ": " << msg->source_file_name + << ", line " << msg->line_number_table[i].LineNumber << "\n"; + } + outs() << "\n"; + } + break; + case iJVM_EVENT_TYPE_METHOD_UNLOAD_START: { + if (!EventSpecificData) { + errs() << + "Error: The JIT event listener did not provide a event data."; + return -1; + } + unsigned int UnloadId + = *reinterpret_cast<unsigned int*>(EventSpecificData); + assert(1 == ReportedDebugFuncs.erase(UnloadId)); + outs() << "Method unload [" << UnloadId << "]\n"; + } + break; + default: + break; + } + return 0; +} + +iJIT_IsProfilingActiveFlags IsProfilingActive(void) { + // for testing, pretend we have an Intel Parallel Amplifier XE 2011 + // instance attached + return iJIT_SAMPLING_ON; +} + +unsigned int GetNewMethodID(void) { + static unsigned int id = 0; + return ++id; +} + +class JitEventListenerTest { +protected: + void InitEE(const std::string &IRFile) { + LLVMContext &Context = getGlobalContext(); + + // If we have a native target, initialize it to ensure it is linked in and + // usable by the JIT. + InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + + // Parse the bitcode... + SMDiagnostic Err; + TheModule = ParseIRFile(IRFile, Err, Context); + if (!TheModule) { + errs() << Err.getMessage(); + return; + } + + // FIXME: This is using the default legacy JITMemoryManager because it + // supports poison memory. At some point, we'll need to update this to + // use an MCJIT-specific memory manager. It might be nice to have the + // poison memory option there too. + JITMemoryManager *MemMgr = JITMemoryManager::CreateDefaultMemManager(); + if (!MemMgr) { + errs() << "Unable to create memory manager."; + return; + } + + // Tell the memory manager to poison freed memory so that accessing freed + // memory is more easily tested. + MemMgr->setPoisonMemory(true); + + // Override the triple to generate ELF on Windows since that's supported + Triple Tuple(TheModule->getTargetTriple()); + if (Tuple.getTriple().empty()) + Tuple.setTriple(LLVM_HOSTTRIPLE); + + if (Tuple.isOSWindows() && Triple::ELF != Tuple.getEnvironment()) { + Tuple.setEnvironment(Triple::ELF); + TheModule->setTargetTriple(Tuple.getTriple()); + } + + // Compile the IR + std::string Error; + TheJIT.reset(EngineBuilder(TheModule) + .setEngineKind(EngineKind::JIT) + .setErrorStr(&Error) + .setJITMemoryManager(MemMgr) + .setUseMCJIT(true) + .create()); + if (Error.empty() == false) + errs() << Error; + } + + void DestroyEE() { + TheJIT.reset(); + } + + LLVMContext Context; // Global ownership + Module *TheModule; // Owned by ExecutionEngine. + JITMemoryManager *JMM; // Owned by ExecutionEngine. + OwningPtr<ExecutionEngine> TheJIT; + +public: + void ProcessInput(const std::string &Filename) { + InitEE(Filename); + + llvm::OwningPtr<llvm::JITEventListener> Listener(JITEventListener::createIntelJITEventListener( + new IntelJITEventsWrapper(NotifyEvent, 0, + IsProfilingActive, 0, 0, + GetNewMethodID))); + + TheJIT->RegisterJITEventListener(Listener.get()); + + TheJIT->finalizeObject(); + + // Destroy the JIT engine instead of unregistering to get unload events. + DestroyEE(); + } +}; + + + +} // end anonymous namespace + +static cl::opt<std::string> +InputFilename(cl::Positional, cl::desc("<input IR file>"), + cl::Required); + +int main(int argc, char **argv) { + // Print a stack trace if we signal out. + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + + cl::ParseCommandLineOptions(argc, argv, "llvm jit event listener test utility\n"); + + JitEventListenerTest Test; + + Test.ProcessInput(InputFilename); + + return 0; +} diff --git a/tools/llvm-link/llvm-link.cpp b/tools/llvm-link/llvm-link.cpp index 378a833..f6c9f11 100644 --- a/tools/llvm-link/llvm-link.cpp +++ b/tools/llvm-link/llvm-link.cpp @@ -13,18 +13,18 @@ //===----------------------------------------------------------------------===// #include "llvm/Linker.h" -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/IRReader.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/Path.h" #include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/ToolOutputFile.h" -#include "llvm/Support/SystemUtils.h" -#include "llvm/Support/IRReader.h" #include "llvm/Support/Signals.h" -#include "llvm/Support/Path.h" +#include "llvm/Support/SystemUtils.h" +#include "llvm/Support/ToolOutputFile.h" #include <memory> using namespace llvm; diff --git a/tools/llvm-mc/Disassembler.cpp b/tools/llvm-mc/Disassembler.cpp index 5f2fdb8..06c7721 100644 --- a/tools/llvm-mc/Disassembler.cpp +++ b/tools/llvm-mc/Disassembler.cpp @@ -13,16 +13,12 @@ //===----------------------------------------------------------------------===// #include "Disassembler.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/MCDisassembler.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/Triple.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryObject.h" #include "llvm/Support/SourceMgr.h" @@ -169,175 +165,3 @@ int Disassembler::disassemble(const Target &T, return ErrorOccurred; } - -static int byteArrayReader(uint8_t *B, uint64_t A, void *Arg) { - ByteArrayTy &ByteArray = *((ByteArrayTy*)Arg); - - if (A >= ByteArray.size()) - return -1; - - *B = ByteArray[A].first; - - return 0; -} - -static int verboseEvaluator(uint64_t *V, unsigned R, void *Arg) { - EDDisassembler &disassembler = *(EDDisassembler *)((void **)Arg)[0]; - raw_ostream &Out = *(raw_ostream *)((void **)Arg)[1]; - - if (const char *regName = disassembler.nameWithRegisterID(R)) - Out << "[" << regName << "/" << R << "]"; - - if (disassembler.registerIsStackPointer(R)) - Out << "(sp)"; - if (disassembler.registerIsProgramCounter(R)) - Out << "(pc)"; - - *V = 0; - return 0; -} - -int Disassembler::disassembleEnhanced(const std::string &TS, - MemoryBuffer &Buffer, - SourceMgr &SM, - raw_ostream &Out) { - ByteArrayTy ByteArray; - StringRef Str = Buffer.getBuffer(); - - if (ByteArrayFromString(ByteArray, Str, SM)) { - return -1; - } - - Triple T(TS); - EDDisassembler::AssemblySyntax AS; - - switch (T.getArch()) { - default: - errs() << "error: no default assembly syntax for " << TS.c_str() << "\n"; - return -1; - case Triple::arm: - case Triple::thumb: - AS = EDDisassembler::kEDAssemblySyntaxARMUAL; - break; - case Triple::x86: - case Triple::x86_64: - AS = EDDisassembler::kEDAssemblySyntaxX86ATT; - break; - } - - OwningPtr<EDDisassembler> - disassembler(EDDisassembler::getDisassembler(TS.c_str(), AS)); - - if (disassembler == 0) { - errs() << "error: couldn't get disassembler for " << TS << '\n'; - return -1; - } - - while (ByteArray.size()) { - OwningPtr<EDInst> - inst(disassembler->createInst(byteArrayReader, 0, &ByteArray)); - - if (inst == 0) { - errs() << "error: Didn't get an instruction\n"; - return -1; - } - - ByteArray.erase (ByteArray.begin(), ByteArray.begin() + inst->byteSize()); - - unsigned numTokens = inst->numTokens(); - if ((int)numTokens < 0) { - errs() << "error: couldn't count the instruction's tokens\n"; - return -1; - } - - for (unsigned tokenIndex = 0; tokenIndex != numTokens; ++tokenIndex) { - EDToken *token; - - if (inst->getToken(token, tokenIndex)) { - errs() << "error: Couldn't get token\n"; - return -1; - } - - const char *buf; - if (token->getString(buf)) { - errs() << "error: Couldn't get string for token\n"; - return -1; - } - - Out << '['; - int operandIndex = token->operandID(); - - if (operandIndex >= 0) - Out << operandIndex << "-"; - - switch (token->type()) { - case EDToken::kTokenWhitespace: Out << "w"; break; - case EDToken::kTokenPunctuation: Out << "p"; break; - case EDToken::kTokenOpcode: Out << "o"; break; - case EDToken::kTokenLiteral: Out << "l"; break; - case EDToken::kTokenRegister: Out << "r"; break; - } - - Out << ":" << buf; - - if (token->type() == EDToken::kTokenLiteral) { - Out << "="; - if (token->literalSign()) - Out << "-"; - uint64_t absoluteValue; - if (token->literalAbsoluteValue(absoluteValue)) { - errs() << "error: Couldn't get the value of a literal token\n"; - return -1; - } - Out << absoluteValue; - } else if (token->type() == EDToken::kTokenRegister) { - Out << "="; - unsigned regID; - if (token->registerID(regID)) { - errs() << "error: Couldn't get the ID of a register token\n"; - return -1; - } - Out << "r" << regID; - } - - Out << "]"; - } - - Out << " "; - - if (inst->isBranch()) - Out << "<br> "; - if (inst->isMove()) - Out << "<mov> "; - - unsigned numOperands = inst->numOperands(); - - if ((int)numOperands < 0) { - errs() << "error: Couldn't count operands\n"; - return -1; - } - - for (unsigned operandIndex = 0; operandIndex != numOperands; - ++operandIndex) { - Out << operandIndex << ":"; - - EDOperand *operand; - if (inst->getOperand(operand, operandIndex)) { - errs() << "error: couldn't get operand\n"; - return -1; - } - - uint64_t evaluatedResult; - void *Arg[] = { disassembler.get(), &Out }; - if (operand->evaluate(evaluatedResult, verboseEvaluator, Arg)) { - errs() << "error: Couldn't evaluate an operand\n"; - return -1; - } - Out << "=" << evaluatedResult << " "; - } - - Out << '\n'; - } - - return 0; -} diff --git a/tools/llvm-mc/Disassembler.h b/tools/llvm-mc/Disassembler.h index 17d622f..5615da8 100644 --- a/tools/llvm-mc/Disassembler.h +++ b/tools/llvm-mc/Disassembler.h @@ -35,11 +35,6 @@ public: MemoryBuffer &Buffer, SourceMgr &SM, raw_ostream &Out); - - static int disassembleEnhanced(const std::string &tripleString, - MemoryBuffer &buffer, - SourceMgr &SM, - raw_ostream &Out); }; } // namespace llvm diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index 3bceb14..e77f27e 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -12,36 +12,36 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCParser/AsmLexer.h" -#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "Disassembler.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" #include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCInstPrinter.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCParser/AsmLexer.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCTargetAsmParser.h" #include "llvm/MC/SubtargetFeature.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileUtilities.h" #include "llvm/Support/FormattedStream.h" +#include "llvm/Support/Host.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/ToolOutputFile.h" -#include "llvm/Support/Host.h" #include "llvm/Support/Signals.h" +#include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" +#include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/system_error.h" -#include "Disassembler.h" using namespace llvm; static cl::opt<std::string> @@ -69,6 +69,9 @@ static cl::opt<bool> RelaxAll("mc-relax-all", cl::desc("Relax all fixups")); static cl::opt<bool> +DisableCFI("disable-cfi", cl::desc("Do not use .cfi_* directives")); + +static cl::opt<bool> NoExecStack("mc-no-exec-stack", cl::desc("File doesn't need an exec stack")); enum OutputFileType { @@ -154,11 +157,20 @@ static cl::opt<bool> GenDwarfForAssembly("g", cl::desc("Generate dwarf debugging info for assembly " "source files")); +static cl::opt<std::string> +DebugCompilationDir("fdebug-compilation-dir", + cl::desc("Specifies the debug info's compilation dir")); + +static cl::opt<std::string> +MainFileName("main-file-name", + cl::desc("Specifies the name we should consider the input file")); + enum ActionType { AC_AsLex, AC_Assemble, AC_Disassemble, - AC_EDisassemble + AC_MDisassemble, + AC_HDisassemble }; static cl::opt<ActionType> @@ -170,8 +182,11 @@ Action(cl::desc("Action to perform:"), "Assemble a .s file (default)"), clEnumValN(AC_Disassemble, "disassemble", "Disassemble strings of hex bytes"), - clEnumValN(AC_EDisassemble, "edis", - "Enhanced disassembly of strings of hex bytes"), + clEnumValN(AC_MDisassemble, "mdis", + "Marked up disassembly of strings of hex bytes"), + clEnumValN(AC_HDisassemble, "hdis", + "Disassemble strings of hex bytes printing " + "immediates as hex"), clEnumValEnd)); static const Target *GetTarget(const char *ProgName) { @@ -248,9 +263,6 @@ static int AsLexInput(SourceMgr &SrcMgr, MCAsmInfo &MAI, tool_output_file *Out) 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; @@ -379,8 +391,12 @@ int main(int argc, char **argv) { Ctx.setAllowTemporaryLabels(false); Ctx.setGenDwarfForAssembly(GenDwarfForAssembly); - if (!DwarfDebugFlags.empty()) + if (!DwarfDebugFlags.empty()) Ctx.setDwarfDebugFlags(StringRef(DwarfDebugFlags)); + if (!DebugCompilationDir.empty()) + Ctx.setCompilationDir(DebugCompilationDir); + if (!MainFileName.empty()) + Ctx.setMainFileName(MainFileName); // Package up features to be passed to target/subtarget std::string FeaturesStr; @@ -402,18 +418,20 @@ int main(int argc, char **argv) { OwningPtr<MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr)); + MCInstPrinter *IP; if (FileType == OFT_AssemblyFile) { - MCInstPrinter *IP = + IP = TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *MCII, *MRI, *STI); MCCodeEmitter *CE = 0; MCAsmBackend *MAB = 0; if (ShowEncoding) { CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); - MAB = TheTarget->createMCAsmBackend(TripleName); + MAB = TheTarget->createMCAsmBackend(TripleName, MCPU); } + bool UseCFI = !DisableCFI; Str.reset(TheTarget->createAsmStreamer(Ctx, FOS, /*asmverbose*/true, /*useLoc*/ true, - /*useCFI*/ true, + UseCFI, /*useDwarfDirectory*/ true, IP, CE, MAB, ShowInst)); @@ -422,13 +440,14 @@ int main(int argc, char **argv) { } else { assert(FileType == OFT_ObjectFile && "Invalid file type!"); MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); - MCAsmBackend *MAB = TheTarget->createMCAsmBackend(TripleName); + MCAsmBackend *MAB = TheTarget->createMCAsmBackend(TripleName, MCPU); Str.reset(TheTarget->createMCObjectStreamer(TripleName, Ctx, *MAB, FOS, CE, RelaxAll, NoExecStack)); } int Res = 1; + bool disassemble = false; switch (Action) { case AC_AsLex: Res = AsLexInput(SrcMgr, *MAI, Out.get()); @@ -436,14 +455,21 @@ int main(int argc, char **argv) { case AC_Assemble: Res = AssembleInput(ProgName, TheTarget, SrcMgr, Ctx, *Str, *MAI, *STI); break; - case AC_Disassemble: - Res = Disassembler::disassemble(*TheTarget, TripleName, *STI, *Str, - *Buffer, SrcMgr, Out->os()); + case AC_MDisassemble: + IP->setUseMarkup(1); + disassemble = true; break; - case AC_EDisassemble: - Res = Disassembler::disassembleEnhanced(TripleName, *Buffer, SrcMgr, Out->os()); + case AC_HDisassemble: + IP->setPrintImmHex(1); + disassemble = true; + break; + case AC_Disassemble: + disassemble = true; break; } + if (disassemble) + Res = Disassembler::disassemble(*TheTarget, TripleName, *STI, *Str, + *Buffer, SrcMgr, Out->os()); // Keep output if no errors. if (Res == 0) Out->keep(); diff --git a/tools/llvm-mcmarkup/CMakeLists.txt b/tools/llvm-mcmarkup/CMakeLists.txt new file mode 100644 index 0000000..0a51e99 --- /dev/null +++ b/tools/llvm-mcmarkup/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS support) + +add_llvm_tool(llvm-mcmarkup + llvm-mcmarkup.cpp + ) diff --git a/tools/llvm-mcmarkup/LLVMBuild.txt b/tools/llvm-mcmarkup/LLVMBuild.txt new file mode 100644 index 0000000..6423493 --- /dev/null +++ b/tools/llvm-mcmarkup/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/llvm-mcmarkup/LLVMBuild.txt ----------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = llvm-mcmarkup +parent = Tools +required_libraries = Support diff --git a/tools/llvm-mcmarkup/Makefile b/tools/llvm-mcmarkup/Makefile new file mode 100644 index 0000000..5633a9c --- /dev/null +++ b/tools/llvm-mcmarkup/Makefile @@ -0,0 +1,17 @@ +##===- tools/llvm-mcmarkup/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-mcmarkup +LINK_COMPONENTS := support + +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS = 1 + +include $(LEVEL)/Makefile.common diff --git a/tools/llvm-mcmarkup/llvm-mcmarkup.cpp b/tools/llvm-mcmarkup/llvm-mcmarkup.cpp new file mode 100644 index 0000000..888761f --- /dev/null +++ b/tools/llvm-mcmarkup/llvm-mcmarkup.cpp @@ -0,0 +1,225 @@ +//===-- llvm-mcmarkup.cpp - Parse the MC assembly markup tags -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Example simple parser implementation for the MC assembly markup language. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/OwningPtr.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MemoryBuffer.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" +using namespace llvm; + +static cl::list<std::string> + InputFilenames(cl::Positional, cl::desc("<input files>"), + cl::ZeroOrMore); +static cl::opt<bool> +DumpTags("dump-tags", cl::desc("List all tags encountered in input")); + +static StringRef ToolName; + +/// Trivial lexer for the markup parser. Input is always handled a character +/// at a time. The lexer just encapsulates EOF and lookahead handling. +class MarkupLexer { + StringRef::const_iterator Start; + StringRef::const_iterator CurPtr; + StringRef::const_iterator End; +public: + MarkupLexer(StringRef Source) + : Start(Source.begin()), CurPtr(Source.begin()), End(Source.end()) {} + // When processing non-markup, input is consumed a character at a time. + bool isEOF() { return CurPtr == End; } + int getNextChar() { + if (CurPtr == End) return EOF; + return *CurPtr++; + } + int peekNextChar() { + if (CurPtr == End) return EOF; + return *CurPtr; + } + StringRef::const_iterator getPosition() const { return CurPtr; } +}; + +/// A markup tag is a name and a (usually empty) list of modifiers. +class MarkupTag { + StringRef Name; + StringRef Modifiers; + SMLoc StartLoc; +public: + MarkupTag(StringRef n, StringRef m, SMLoc Loc) + : Name(n), Modifiers(m), StartLoc(Loc) {} + StringRef getName() const { return Name; } + StringRef getModifiers() const { return Modifiers; } + SMLoc getLoc() const { return StartLoc; } +}; + +/// A simple parser implementation for creating MarkupTags from input text. +class MarkupParser { + MarkupLexer &Lex; + SourceMgr &SM; +public: + MarkupParser(MarkupLexer &lex, SourceMgr &SrcMgr) : Lex(lex), SM(SrcMgr) {} + /// Create a MarkupTag from the current position in the MarkupLexer. + /// The parseTag() method should be called when the lexer has processed + /// the opening '<' character. Input will be consumed up to and including + /// the ':' which terminates the tag open. + MarkupTag parseTag(); + /// Issue a diagnostic and terminate program execution. + void FatalError(SMLoc Loc, StringRef Msg); +}; + +void MarkupParser::FatalError(SMLoc Loc, StringRef Msg) { + SM.PrintMessage(Loc, SourceMgr::DK_Error, Msg); + exit(1); +} + +// Example handler for when a tag is recognized. +static void processStartTag(MarkupTag &Tag) { + // If we're just printing the tags, do that, otherwise do some simple + // colorization. + if (DumpTags) { + outs() << Tag.getName(); + if (Tag.getModifiers().size()) + outs() << " " << Tag.getModifiers(); + outs() << "\n"; + return; + } + + if (!outs().has_colors()) + return; + // Color registers as red and immediates as cyan. Those don't have nested + // tags, so don't bother keeping a stack of colors to reset to. + if (Tag.getName() == "reg") + outs().changeColor(raw_ostream::RED); + else if (Tag.getName() == "imm") + outs().changeColor(raw_ostream::CYAN); +} + +// Example handler for when the end of a tag is recognized. +static void processEndTag(MarkupTag &Tag) { + // If we're printing the tags, there's nothing more to do here. Otherwise, + // set the color back the normal. + if (DumpTags) + return; + if (!outs().has_colors()) + return; + // Just reset to basic white. + outs().changeColor(raw_ostream::WHITE, false); +} + +MarkupTag MarkupParser::parseTag() { + // First off, extract the tag into it's own StringRef so we can look at it + // outside of the context of consuming input. + StringRef::const_iterator Start = Lex.getPosition(); + SMLoc Loc = SMLoc::getFromPointer(Start - 1); + while(Lex.getNextChar() != ':') { + // EOF is an error. + if (Lex.isEOF()) + FatalError(SMLoc::getFromPointer(Start), "unterminated markup tag"); + } + StringRef RawTag(Start, Lex.getPosition() - Start - 1); + std::pair<StringRef, StringRef> SplitTag = RawTag.split(' '); + return MarkupTag(SplitTag.first, SplitTag.second, Loc); +} + +static void parseMCMarkup(StringRef Filename) { + OwningPtr<MemoryBuffer> BufferPtr; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, BufferPtr)) { + errs() << ToolName << ": " << ec.message() << '\n'; + return; + } + MemoryBuffer *Buffer = BufferPtr.take(); + + SourceMgr SrcMgr; + + // Tell SrcMgr about this buffer, which is what the parser will pick up. + SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); + + StringRef InputSource = Buffer->getBuffer(); + MarkupLexer Lex(InputSource); + MarkupParser Parser(Lex, SrcMgr); + + SmallVector<MarkupTag, 4> TagStack; + + for (int CurChar = Lex.getNextChar(); + CurChar != EOF; + CurChar = Lex.getNextChar()) { + switch (CurChar) { + case '<': { + // A "<<" is output as a literal '<' and does not start a markup tag. + if (Lex.peekNextChar() == '<') { + (void)Lex.getNextChar(); + break; + } + // Parse the markup entry. + TagStack.push_back(Parser.parseTag()); + + // Do any special handling for the start of a tag. + processStartTag(TagStack.back()); + continue; + } + case '>': { + SMLoc Loc = SMLoc::getFromPointer(Lex.getPosition() - 1); + // A ">>" is output as a literal '>' and does not end a markup tag. + if (Lex.peekNextChar() == '>') { + (void)Lex.getNextChar(); + break; + } + // Close out the innermost tag. + if (TagStack.empty()) + Parser.FatalError(Loc, "'>' without matching '<'"); + + // Do any special handling for the end of a tag. + processEndTag(TagStack.back()); + + TagStack.pop_back(); + continue; + } + default: + break; + } + // For anything else, just echo the character back out. + if (!DumpTags && CurChar != EOF) + outs() << (char)CurChar; + } + + // If there are any unterminated markup tags, issue diagnostics for them. + while (!TagStack.empty()) { + MarkupTag &Tag = TagStack.back(); + SrcMgr.PrintMessage(Tag.getLoc(), SourceMgr::DK_Error, + "unterminated markup tag"); + TagStack.pop_back(); + } +} + +int main(int argc, char **argv) { + // Print a stack trace if we signal out. + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + cl::ParseCommandLineOptions(argc, argv, "llvm MC markup parser\n"); + + ToolName = argv[0]; + + // If no input files specified, read from stdin. + if (InputFilenames.size() == 0) + InputFilenames.push_back("-"); + + std::for_each(InputFilenames.begin(), InputFilenames.end(), + parseMCMarkup); + return 0; +} diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp index eb52acc..056fd35 100644 --- a/tools/llvm-nm/llvm-nm.cpp +++ b/tools/llvm-nm/llvm-nm.cpp @@ -16,21 +16,21 @@ // //===----------------------------------------------------------------------===// -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" -#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/Bitcode/Archive.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/IR/Module.h" #include "llvm/Object/Archive.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Format.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Program.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Signals.h" -#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" #include <algorithm> #include <cctype> @@ -110,6 +110,13 @@ namespace { cl::opt<bool> SizeSort("size-sort", cl::desc("Sort symbols by size")); + cl::opt<bool> WithoutAliases("without-aliases", cl::Hidden, + cl::desc("Exclude aliases from output")); + + cl::opt<bool> ArchiveMap("print-armap", + cl::desc("Print the archive map")); + cl::alias ArchiveMaps("s", cl::desc("Alias for --print-armap"), + cl::aliasopt(ArchiveMap)); bool PrintAddress = true; bool MultipleFiles = false; @@ -143,6 +150,8 @@ namespace { return true; else if (a.Address == b.Address && a.Name < b.Name) return true; + else if (a.Address == b.Address && a.Name == b.Name && a.Size < b.Size) + return true; else return false; @@ -153,12 +162,21 @@ namespace { return true; else if (a.Size == b.Size && a.Name < b.Name) return true; + else if (a.Size == b.Size && a.Name == b.Name && a.Address < b.Address) + return true; else return false; } static bool CompareSymbolName(const NMSymbol &a, const NMSymbol &b) { - return a.Name < b.Name; + if (a.Name < b.Name) + return true; + else if (a.Name == b.Name && a.Size < b.Size) + return true; + else if (a.Name == b.Name && a.Size == b.Size && a.Address < b.Address) + return true; + else + return false; } StringRef CurrentFilename; @@ -275,8 +293,9 @@ static void DumpSymbolNamesFromModule(Module *M) { 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); + if (!WithoutAliases) + std::for_each (M->alias_begin(), M->alias_end(), + DumpSymbolNameForGlobalValue); SortAndPrintSymbolList(); } @@ -342,6 +361,24 @@ static void DumpSymbolNamesFromFile(std::string &Filename) { return; if (object::Archive *a = dyn_cast<object::Archive>(arch.get())) { + if (ArchiveMap) { + outs() << "Archive map" << "\n"; + for (object::Archive::symbol_iterator i = a->begin_symbols(), + e = a->end_symbols(); i != e; ++i) { + object::Archive::child_iterator c; + StringRef symname; + StringRef filename; + if (error(i->getMember(c))) + return; + if (error(i->getName(symname))) + return; + if (error(c->getName(filename))) + return; + outs() << symname << " in " << filename << "\n"; + } + outs() << "\n"; + } + for (object::Archive::child_iterator i = a->begin_children(), e = a->end_children(); i != e; ++i) { OwningPtr<Binary> child; diff --git a/tools/llvm-objdump/CMakeLists.txt b/tools/llvm-objdump/CMakeLists.txt index f3b2e1f..0c49d0b 100644 --- a/tools/llvm-objdump/CMakeLists.txt +++ b/tools/llvm-objdump/CMakeLists.txt @@ -9,6 +9,8 @@ set(LLVM_LINK_COMPONENTS add_llvm_tool(llvm-objdump llvm-objdump.cpp + COFFDump.cpp + ELFDump.cpp MachODump.cpp MCFunction.cpp ) diff --git a/tools/llvm-objdump/COFFDump.cpp b/tools/llvm-objdump/COFFDump.cpp new file mode 100644 index 0000000..2ada683 --- /dev/null +++ b/tools/llvm-objdump/COFFDump.cpp @@ -0,0 +1,355 @@ +//===-- COFFDump.cpp - COFF-specific dumper ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file implements the COFF-specific dumper for llvm-objdump. +/// It outputs the Win64 EH data structures as plain text. +/// The encoding of the unwind codes is decribed in MSDN: +/// http://msdn.microsoft.com/en-us/library/ck9asaa9.aspx +/// +//===----------------------------------------------------------------------===// + +#include "llvm-objdump.h" +#include "llvm/Object/COFF.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/Win64EH.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/system_error.h" +#include <algorithm> +#include <cstring> + +using namespace llvm; +using namespace object; +using namespace llvm::Win64EH; + +// Returns the name of the unwind code. +static StringRef getUnwindCodeTypeName(uint8_t Code) { + switch(Code) { + default: llvm_unreachable("Invalid unwind code"); + case UOP_PushNonVol: return "UOP_PushNonVol"; + case UOP_AllocLarge: return "UOP_AllocLarge"; + case UOP_AllocSmall: return "UOP_AllocSmall"; + case UOP_SetFPReg: return "UOP_SetFPReg"; + case UOP_SaveNonVol: return "UOP_SaveNonVol"; + case UOP_SaveNonVolBig: return "UOP_SaveNonVolBig"; + case UOP_SaveXMM128: return "UOP_SaveXMM128"; + case UOP_SaveXMM128Big: return "UOP_SaveXMM128Big"; + case UOP_PushMachFrame: return "UOP_PushMachFrame"; + } +} + +// Returns the name of a referenced register. +static StringRef getUnwindRegisterName(uint8_t Reg) { + switch(Reg) { + default: llvm_unreachable("Invalid register"); + case 0: return "RAX"; + case 1: return "RCX"; + case 2: return "RDX"; + case 3: return "RBX"; + case 4: return "RSP"; + case 5: return "RBP"; + case 6: return "RSI"; + case 7: return "RDI"; + case 8: return "R8"; + case 9: return "R9"; + case 10: return "R10"; + case 11: return "R11"; + case 12: return "R12"; + case 13: return "R13"; + case 14: return "R14"; + case 15: return "R15"; + } +} + +// Calculates the number of array slots required for the unwind code. +static unsigned getNumUsedSlots(const UnwindCode &UnwindCode) { + switch (UnwindCode.getUnwindOp()) { + default: llvm_unreachable("Invalid unwind code"); + case UOP_PushNonVol: + case UOP_AllocSmall: + case UOP_SetFPReg: + case UOP_PushMachFrame: + return 1; + case UOP_SaveNonVol: + case UOP_SaveXMM128: + return 2; + case UOP_SaveNonVolBig: + case UOP_SaveXMM128Big: + return 3; + case UOP_AllocLarge: + return (UnwindCode.getOpInfo() == 0) ? 2 : 3; + } +} + +// Prints one unwind code. Because an unwind code can occupy up to 3 slots in +// the unwind codes array, this function requires that the correct number of +// slots is provided. +static void printUnwindCode(ArrayRef<UnwindCode> UCs) { + assert(UCs.size() >= getNumUsedSlots(UCs[0])); + outs() << format(" 0x%02x: ", unsigned(UCs[0].u.CodeOffset)) + << getUnwindCodeTypeName(UCs[0].getUnwindOp()); + switch (UCs[0].getUnwindOp()) { + case UOP_PushNonVol: + outs() << " " << getUnwindRegisterName(UCs[0].getOpInfo()); + break; + case UOP_AllocLarge: + if (UCs[0].getOpInfo() == 0) { + outs() << " " << UCs[1].FrameOffset; + } else { + outs() << " " << UCs[1].FrameOffset + + (static_cast<uint32_t>(UCs[2].FrameOffset) << 16); + } + break; + case UOP_AllocSmall: + outs() << " " << ((UCs[0].getOpInfo() + 1) * 8); + break; + case UOP_SetFPReg: + outs() << " "; + break; + case UOP_SaveNonVol: + outs() << " " << getUnwindRegisterName(UCs[0].getOpInfo()) + << format(" [0x%04x]", 8 * UCs[1].FrameOffset); + break; + case UOP_SaveNonVolBig: + outs() << " " << getUnwindRegisterName(UCs[0].getOpInfo()) + << format(" [0x%08x]", UCs[1].FrameOffset + + (static_cast<uint32_t>(UCs[2].FrameOffset) << 16)); + break; + case UOP_SaveXMM128: + outs() << " XMM" << static_cast<uint32_t>(UCs[0].getOpInfo()) + << format(" [0x%04x]", 16 * UCs[1].FrameOffset); + break; + case UOP_SaveXMM128Big: + outs() << " XMM" << UCs[0].getOpInfo() + << format(" [0x%08x]", UCs[1].FrameOffset + + (static_cast<uint32_t>(UCs[2].FrameOffset) << 16)); + break; + case UOP_PushMachFrame: + outs() << " " << (UCs[0].getOpInfo() ? "w/o" : "w") + << " error code"; + break; + } + outs() << "\n"; +} + +static void printAllUnwindCodes(ArrayRef<UnwindCode> UCs) { + for (const UnwindCode *I = UCs.begin(), *E = UCs.end(); I < E; ) { + unsigned UsedSlots = getNumUsedSlots(*I); + if (UsedSlots > UCs.size()) { + outs() << "Unwind data corrupted: Encountered unwind op " + << getUnwindCodeTypeName((*I).getUnwindOp()) + << " which requires " << UsedSlots + << " slots, but only " << UCs.size() + << " remaining in buffer"; + return ; + } + printUnwindCode(ArrayRef<UnwindCode>(I, E)); + I += UsedSlots; + } +} + +// Given a symbol sym this functions returns the address and section of it. +static error_code resolveSectionAndAddress(const COFFObjectFile *Obj, + const SymbolRef &Sym, + const coff_section *&ResolvedSection, + uint64_t &ResolvedAddr) { + if (error_code ec = Sym.getAddress(ResolvedAddr)) return ec; + section_iterator iter(Obj->begin_sections()); + if (error_code ec = Sym.getSection(iter)) return ec; + ResolvedSection = Obj->getCOFFSection(iter); + return object_error::success; +} + +// Given a vector of relocations for a section and an offset into this section +// the function returns the symbol used for the relocation at the offset. +static error_code resolveSymbol(const std::vector<RelocationRef> &Rels, + uint64_t Offset, SymbolRef &Sym) { + for (std::vector<RelocationRef>::const_iterator I = Rels.begin(), + E = Rels.end(); + I != E; ++I) { + uint64_t Ofs; + if (error_code ec = I->getOffset(Ofs)) return ec; + if (Ofs == Offset) { + if (error_code ec = I->getSymbol(Sym)) return ec; + break; + } + } + return object_error::success; +} + +// Given a vector of relocations for a section and an offset into this section +// the function resolves the symbol used for the relocation at the offset and +// returns the section content and the address inside the content pointed to +// by the symbol. +static error_code getSectionContents(const COFFObjectFile *Obj, + const std::vector<RelocationRef> &Rels, + uint64_t Offset, + ArrayRef<uint8_t> &Contents, + uint64_t &Addr) { + SymbolRef Sym; + if (error_code ec = resolveSymbol(Rels, Offset, Sym)) return ec; + const coff_section *Section; + if (error_code ec = resolveSectionAndAddress(Obj, Sym, Section, Addr)) + return ec; + if (error_code ec = Obj->getSectionContents(Section, Contents)) return ec; + return object_error::success; +} + +// Given a vector of relocations for a section and an offset into this section +// the function returns the name of the symbol used for the relocation at the +// offset. +static error_code resolveSymbolName(const std::vector<RelocationRef> &Rels, + uint64_t Offset, StringRef &Name) { + SymbolRef Sym; + if (error_code ec = resolveSymbol(Rels, Offset, Sym)) return ec; + if (error_code ec = Sym.getName(Name)) return ec; + return object_error::success; +} + +static void printCOFFSymbolAddress(llvm::raw_ostream &Out, + const std::vector<RelocationRef> &Rels, + uint64_t Offset, uint32_t Disp) { + StringRef Sym; + if (error_code ec = resolveSymbolName(Rels, Offset, Sym)) { + error(ec); + return ; + } + Out << Sym; + if (Disp > 0) + Out << format(" + 0x%04x", Disp); +} + +void llvm::printCOFFUnwindInfo(const COFFObjectFile *Obj) { + const coff_file_header *Header; + if (error(Obj->getHeader(Header))) return; + + if (Header->Machine != COFF::IMAGE_FILE_MACHINE_AMD64) { + errs() << "Unsupported image machine type " + "(currently only AMD64 is supported).\n"; + return; + } + + const coff_section *Pdata = 0; + + error_code ec; + for (section_iterator SI = Obj->begin_sections(), + SE = Obj->end_sections(); + SI != SE; SI.increment(ec)) { + if (error(ec)) return; + + StringRef Name; + if (error(SI->getName(Name))) continue; + + if (Name != ".pdata") continue; + + Pdata = Obj->getCOFFSection(SI); + std::vector<RelocationRef> Rels; + for (relocation_iterator RI = SI->begin_relocations(), + RE = SI->end_relocations(); + RI != RE; RI.increment(ec)) { + if (error(ec)) break; + Rels.push_back(*RI); + } + + // Sort relocations by address. + std::sort(Rels.begin(), Rels.end(), RelocAddressLess); + + ArrayRef<uint8_t> Contents; + if (error(Obj->getSectionContents(Pdata, Contents))) continue; + if (Contents.empty()) continue; + + ArrayRef<RuntimeFunction> RFs( + reinterpret_cast<const RuntimeFunction *>(Contents.data()), + Contents.size() / sizeof(RuntimeFunction)); + for (const RuntimeFunction *I = RFs.begin(), *E = RFs.end(); I < E; ++I) { + const uint64_t SectionOffset = std::distance(RFs.begin(), I) + * sizeof(RuntimeFunction); + + outs() << "Function Table:\n"; + + outs() << " Start Address: "; + printCOFFSymbolAddress(outs(), Rels, SectionOffset + + /*offsetof(RuntimeFunction, StartAddress)*/ 0, + I->StartAddress); + outs() << "\n"; + + outs() << " End Address: "; + printCOFFSymbolAddress(outs(), Rels, SectionOffset + + /*offsetof(RuntimeFunction, EndAddress)*/ 4, + I->EndAddress); + outs() << "\n"; + + outs() << " Unwind Info Address: "; + printCOFFSymbolAddress(outs(), Rels, SectionOffset + + /*offsetof(RuntimeFunction, UnwindInfoOffset)*/ 8, + I->UnwindInfoOffset); + outs() << "\n"; + + ArrayRef<uint8_t> XContents; + uint64_t UnwindInfoOffset = 0; + if (error(getSectionContents(Obj, Rels, SectionOffset + + /*offsetof(RuntimeFunction, UnwindInfoOffset)*/ 8, + XContents, UnwindInfoOffset))) continue; + if (XContents.empty()) continue; + + UnwindInfoOffset += I->UnwindInfoOffset; + if (UnwindInfoOffset > XContents.size()) continue; + + const Win64EH::UnwindInfo *UI = + reinterpret_cast<const Win64EH::UnwindInfo *> + (XContents.data() + UnwindInfoOffset); + + // The casts to int are required in order to output the value as number. + // Without the casts the value would be interpreted as char data (which + // results in garbage output). + outs() << " Version: " << static_cast<int>(UI->getVersion()) << "\n"; + outs() << " Flags: " << static_cast<int>(UI->getFlags()); + if (UI->getFlags()) { + if (UI->getFlags() & UNW_ExceptionHandler) + outs() << " UNW_ExceptionHandler"; + if (UI->getFlags() & UNW_TerminateHandler) + outs() << " UNW_TerminateHandler"; + if (UI->getFlags() & UNW_ChainInfo) + outs() << " UNW_ChainInfo"; + } + outs() << "\n"; + outs() << " Size of prolog: " + << static_cast<int>(UI->PrologSize) << "\n"; + outs() << " Number of Codes: " + << static_cast<int>(UI->NumCodes) << "\n"; + // Maybe this should move to output of UOP_SetFPReg? + if (UI->getFrameRegister()) { + outs() << " Frame register: " + << getUnwindRegisterName(UI->getFrameRegister()) + << "\n"; + outs() << " Frame offset: " + << 16 * UI->getFrameOffset() + << "\n"; + } else { + outs() << " No frame pointer used\n"; + } + if (UI->getFlags() & (UNW_ExceptionHandler | UNW_TerminateHandler)) { + // FIXME: Output exception handler data + } else if (UI->getFlags() & UNW_ChainInfo) { + // FIXME: Output chained unwind info + } + + if (UI->NumCodes) + outs() << " Unwind Codes:\n"; + + printAllUnwindCodes(ArrayRef<UnwindCode>(&UI->UnwindCodes[0], + UI->NumCodes)); + + outs() << "\n\n"; + outs().flush(); + } + } +} diff --git a/tools/llvm-objdump/ELFDump.cpp b/tools/llvm-objdump/ELFDump.cpp new file mode 100644 index 0000000..a635fef --- /dev/null +++ b/tools/llvm-objdump/ELFDump.cpp @@ -0,0 +1,89 @@ +//===-- ELFDump.cpp - ELF-specific dumper -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file implements the ELF-specific dumper for llvm-objdump. +/// +//===----------------------------------------------------------------------===// + +#include "llvm-objdump.h" + +#include "llvm/Object/ELF.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; +using namespace llvm::object; + +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +void printProgramHeaders( + const ELFObjectFile<target_endianness, max_alignment, is64Bits> *o) { + typedef ELFObjectFile<target_endianness, max_alignment, is64Bits> ELFO; + outs() << "Program Header:\n"; + for (typename ELFO::Elf_Phdr_Iter pi = o->begin_program_headers(), + pe = o->end_program_headers(); + pi != pe; ++pi) { + switch (pi->p_type) { + case ELF::PT_LOAD: + outs() << " LOAD "; + break; + case ELF::PT_GNU_STACK: + outs() << " STACK "; + break; + case ELF::PT_GNU_EH_FRAME: + outs() << "EH_FRAME "; + break; + default: + outs() << " UNKNOWN "; + } + + const char *Fmt = is64Bits ? "0x%016" PRIx64 " " : "0x%08" PRIx64 " "; + + outs() << "off " + << format(Fmt, (uint64_t)pi->p_offset) + << "vaddr " + << format(Fmt, (uint64_t)pi->p_vaddr) + << "paddr " + << format(Fmt, (uint64_t)pi->p_paddr) + << format("align 2**%u\n", CountTrailingZeros_64(pi->p_align)) + << " filesz " + << format(Fmt, (uint64_t)pi->p_filesz) + << "memsz " + << format(Fmt, (uint64_t)pi->p_memsz) + << "flags " + << ((pi->p_flags & ELF::PF_R) ? "r" : "-") + << ((pi->p_flags & ELF::PF_W) ? "w" : "-") + << ((pi->p_flags & ELF::PF_X) ? "x" : "-") + << "\n"; + } + outs() << "\n"; +} + +void llvm::printELFFileHeader(const object::ObjectFile *Obj) { + // Little-endian 32-bit + if (const ELFObjectFile<support::little, 4, false> *ELFObj = + dyn_cast<ELFObjectFile<support::little, 4, false> >(Obj)) + printProgramHeaders(ELFObj); + + // Big-endian 32-bit + if (const ELFObjectFile<support::big, 4, false> *ELFObj = + dyn_cast<ELFObjectFile<support::big, 4, false> >(Obj)) + printProgramHeaders(ELFObj); + + // Little-endian 64-bit + if (const ELFObjectFile<support::little, 8, true> *ELFObj = + dyn_cast<ELFObjectFile<support::little, 8, true> >(Obj)) + printProgramHeaders(ELFObj); + + // Big-endian 64-bit + if (const ELFObjectFile<support::big, 8, true> *ELFObj = + dyn_cast<ELFObjectFile<support::big, 8, true> >(Obj)) + printProgramHeaders(ELFObj); +} diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index 1feea42..c324ff1 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -13,11 +13,9 @@ #include "llvm-objdump.h" #include "MCFunction.h" -#include "llvm/Support/MachO.h" -#include "llvm/Object/MachO.h" #include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/Triple.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Triple.h" #include "llvm/DebugInfo/DIContext.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCDisassembler.h" @@ -28,10 +26,12 @@ #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Object/MachO.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Format.h" #include "llvm/Support/GraphWriter.h" +#include "llvm/Support/MachO.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" @@ -309,16 +309,10 @@ void llvm::DisassembleInputMachO(StringRef Filename) { raw_ostream &DebugOut = nulls(); #endif - StringRef DebugAbbrevSection, DebugInfoSection, DebugArangesSection, - DebugLineSection, DebugStrSection; OwningPtr<DIContext> diContext; - OwningPtr<MachOObjectFile> DSYMObj; - MachOObject *DbgInfoObj = MachOObj; + ObjectFile *DbgObj = MachOOF.get(); // Try to find debug info and set up the DIContext for it. if (UseDbg) { - ArrayRef<SectionRef> DebugSections = Sections; - std::vector<SectionRef> DSYMSections; - // A separate DSym file path was specified, parse it as a macho file, // get the sections and supply it to the section name parsing machinery. if (!DSYMFile.empty()) { @@ -327,42 +321,11 @@ void llvm::DisassembleInputMachO(StringRef Filename) { errs() << "llvm-objdump: " << Filename << ": " << ec.message() << '\n'; return; } - DSYMObj.reset(static_cast<MachOObjectFile*>( - ObjectFile::createMachOObjectFile(Buf.take()))); - const macho::Header &Header = DSYMObj->getObject()->getHeader(); - - std::vector<SymbolRef> Symbols; - SmallVector<uint64_t, 8> FoundFns; - getSectionsAndSymbols(Header, DSYMObj.get(), 0, DSYMSections, Symbols, - FoundFns); - DebugSections = DSYMSections; - DbgInfoObj = DSYMObj.get()->getObject(); - } - - // Find the named debug info sections. - for (unsigned SectIdx = 0; SectIdx != DebugSections.size(); SectIdx++) { - StringRef SectName; - if (!DebugSections[SectIdx].getName(SectName)) { - if (SectName.equals("__DWARF,__debug_abbrev")) - DebugSections[SectIdx].getContents(DebugAbbrevSection); - else if (SectName.equals("__DWARF,__debug_info")) - DebugSections[SectIdx].getContents(DebugInfoSection); - else if (SectName.equals("__DWARF,__debug_aranges")) - DebugSections[SectIdx].getContents(DebugArangesSection); - else if (SectName.equals("__DWARF,__debug_line")) - DebugSections[SectIdx].getContents(DebugLineSection); - else if (SectName.equals("__DWARF,__debug_str")) - DebugSections[SectIdx].getContents(DebugStrSection); - } + DbgObj = ObjectFile::createMachOObjectFile(Buf.take()); } - // Setup the DIContext. - diContext.reset(DIContext::getDWARFContext(DbgInfoObj->isLittleEndian(), - DebugInfoSection, - DebugAbbrevSection, - DebugArangesSection, - DebugLineSection, - DebugStrSection)); + // Setup the DIContext + diContext.reset(DIContext::getDWARFContext(DbgObj)); } FunctionMapTy FunctionMap; @@ -371,9 +334,15 @@ void llvm::DisassembleInputMachO(StringRef Filename) { for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) { StringRef SectName; if (Sections[SectIdx].getName(SectName) || - SectName.compare("__TEXT,__text")) + SectName != "__text") continue; // Skip non-text sections + StringRef SegmentName; + DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl(); + if (MachOOF->getSectionFinalSegmentName(DR, SegmentName) || + SegmentName != "__TEXT") + continue; + // Insert the functions from the function starts segment into our map. uint64_t VMAddr; Sections[SectIdx].getAddress(VMAddr); diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index 13ea4e3..9958dad 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -15,13 +15,10 @@ #include "llvm-objdump.h" #include "MCFunction.h" -#include "llvm/Object/Archive.h" -#include "llvm/Object/COFF.h" -#include "llvm/Object/ObjectFile.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Triple.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCDisassembler.h" #include "llvm/MC/MCInst.h" @@ -29,6 +26,11 @@ #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Object/Archive.h" +#include "llvm/Object/COFF.h" +#include "llvm/Object/ELF.h" +#include "llvm/Object/MachO.h" +#include "llvm/Object/ObjectFile.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -72,9 +74,9 @@ static cl::opt<bool> SymbolTable("t", cl::desc("Display the symbol table")); static cl::opt<bool> -MachO("macho", cl::desc("Use MachO specific object file parser")); +MachOOpt("macho", cl::desc("Use MachO specific object file parser")); static cl::alias -MachOm("m", cl::desc("Alias for --macho"), cl::aliasopt(MachO)); +MachOm("m", cl::desc("Alias for --macho"), cl::aliasopt(MachOOpt)); cl::opt<std::string> llvm::TripleName("triple", cl::desc("Target triple to disassemble for, " @@ -100,9 +102,28 @@ MAttrs("mattr", cl::desc("Target specific attributes"), cl::value_desc("a1,+a2,-a3,...")); +static cl::opt<bool> +NoShowRawInsn("no-show-raw-insn", cl::desc("When disassembling instructions, " + "do not print the instruction bytes.")); + +static cl::opt<bool> +UnwindInfo("unwind-info", cl::desc("Display unwind information")); + +static cl::alias +UnwindInfoShort("u", cl::desc("Alias for --unwind-info"), + cl::aliasopt(UnwindInfo)); + +static cl::opt<bool> +PrivateHeaders("private-headers", + cl::desc("Display format specific file headers")); + +static cl::alias +PrivateHeadersShort("p", cl::desc("Alias for --private-headers"), + cl::aliasopt(PrivateHeaders)); + static StringRef ToolName; -static bool error(error_code ec) { +bool llvm::error(error_code ec) { if (!ec) return false; outs() << ToolName << ": error reading file: " << ec.message() << ".\n"; @@ -161,7 +182,7 @@ void llvm::DumpBytes(StringRef bytes) { outs() << output; } -static bool RelocAddressLess(RelocationRef a, RelocationRef b) { +bool llvm::RelocAddressLess(RelocationRef a, RelocationRef b) { uint64_t a_addr, b_addr; if (error(a.getAddress(a_addr))) return false; if (error(b.getAddress(b_addr))) return false; @@ -230,9 +251,18 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { // Sort relocations by address. std::sort(Rels.begin(), Rels.end(), RelocAddressLess); + StringRef SegmentName = ""; + if (const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(Obj)) { + DataRefImpl DR = i->getRawDataRefImpl(); + if (error(MachO->getSectionFinalSegmentName(DR, SegmentName))) + break; + } StringRef name; if (error(i->getName(name))) break; - outs() << "Disassembly of section " << name << ':'; + outs() << "Disassembly of section "; + if (!SegmentName.empty()) + outs() << SegmentName << ","; + outs() << name << ':'; // If the section has no symbols just insert a dummy one and disassemble // the whole section. @@ -321,8 +351,11 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { if (DisAsm->getInstruction(Inst, Size, memoryObject, Index, DebugOut, nulls())) { - outs() << format("%8" PRIx64 ":\t", SectionAddr + Index); - DumpBytes(StringRef(Bytes.data() + Index, Size)); + outs() << format("%8" PRIx64 ":", SectionAddr + Index); + if (!NoShowRawInsn) { + outs() << "\t"; + DumpBytes(StringRef(Bytes.data() + Index, Size)); + } IP->printInst(&Inst, outs(), ""); outs() << "\n"; } else { @@ -553,6 +586,13 @@ static void PrintSymbolTable(const ObjectFile *o) { else if (Section == o->end_sections()) outs() << "*UND*"; else { + if (const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(o)) { + StringRef SegmentName; + DataRefImpl DR = Section->getRawDataRefImpl(); + if (error(MachO->getSectionFinalSegmentName(DR, SegmentName))) + SegmentName = ""; + outs() << SegmentName << ","; + } StringRef SectionName; if (error(Section->getName(SectionName))) SectionName = ""; @@ -566,6 +606,19 @@ static void PrintSymbolTable(const ObjectFile *o) { } } +static void PrintUnwindInfo(const ObjectFile *o) { + outs() << "Unwind info:\n\n"; + + if (const COFFObjectFile *coff = dyn_cast<COFFObjectFile>(o)) { + printCOFFUnwindInfo(coff); + } else { + // TODO: Extract DWARF dump tool to objdump. + errs() << "This operation is only currently supported " + "for COFF object files.\n"; + return; + } +} + static void DumpObject(const ObjectFile *o) { outs() << '\n'; outs() << o->getFileName() @@ -581,6 +634,10 @@ static void DumpObject(const ObjectFile *o) { PrintSectionContents(o); if (SymbolTable) PrintSymbolTable(o); + if (UnwindInfo) + PrintUnwindInfo(o); + if (PrivateHeaders && o->isELF()) + printELFFileHeader(o); } /// @brief Dump each object file in \a a; @@ -611,7 +668,7 @@ static void DumpInput(StringRef file) { return; } - if (MachO && Disassemble) { + if (MachOOpt && Disassemble) { DisassembleInputMachO(file); return; } @@ -659,7 +716,9 @@ int main(int argc, char **argv) { && !Relocations && !SectionHeaders && !SectionContents - && !SymbolTable) { + && !SymbolTable + && !UnwindInfo + && !PrivateHeaders) { cl::PrintHelpMessage(); return 2; } diff --git a/tools/llvm-objdump/llvm-objdump.h b/tools/llvm-objdump/llvm-objdump.h index aa71b77..ca7bced 100644 --- a/tools/llvm-objdump/llvm-objdump.h +++ b/tools/llvm-objdump/llvm-objdump.h @@ -17,12 +17,23 @@ namespace llvm { +namespace object { + class COFFObjectFile; + class ObjectFile; + class RelocationRef; +} +class error_code; + extern cl::opt<std::string> TripleName; extern cl::opt<std::string> ArchName; // Various helper functions. +bool error(error_code ec); +bool RelocAddressLess(object::RelocationRef a, object::RelocationRef b); void DumpBytes(StringRef bytes); void DisassembleInputMachO(StringRef Filename); +void printCOFFUnwindInfo(const object::COFFObjectFile* o); +void printELFFileHeader(const object::ObjectFile *o); class StringRefMemoryObject : public MemoryObject { virtual void anchor(); diff --git a/tools/llvm-prof/llvm-prof.cpp b/tools/llvm-prof/llvm-prof.cpp index 81e9503..b2c3f06 100644 --- a/tools/llvm-prof/llvm-prof.cpp +++ b/tools/llvm-prof/llvm-prof.cpp @@ -13,23 +13,23 @@ // //===----------------------------------------------------------------------===// -#include "llvm/InstrTypes.h" -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" -#include "llvm/PassManager.h" -#include "llvm/Assembly/AssemblyAnnotationWriter.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/Analysis/Passes.h" #include "llvm/Analysis/ProfileInfo.h" #include "llvm/Analysis/ProfileInfoLoader.h" -#include "llvm/Analysis/Passes.h" +#include "llvm/Assembly/AssemblyAnnotationWriter.h" #include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Module.h" +#include "llvm/PassManager.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/Format.h" #include "llvm/Support/Signals.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" #include <algorithm> #include <iomanip> diff --git a/tools/llvm-ranlib/CMakeLists.txt b/tools/llvm-ranlib/CMakeLists.txt index 3116d2e..2d7defe 100644 --- a/tools/llvm-ranlib/CMakeLists.txt +++ b/tools/llvm-ranlib/CMakeLists.txt @@ -1,5 +1,4 @@ set(LLVM_LINK_COMPONENTS archive) -set(LLVM_REQUIRES_EH 1) add_llvm_tool(llvm-ranlib llvm-ranlib.cpp diff --git a/tools/llvm-ranlib/Makefile b/tools/llvm-ranlib/Makefile index 36195f4..cca9501 100644 --- a/tools/llvm-ranlib/Makefile +++ b/tools/llvm-ranlib/Makefile @@ -10,7 +10,6 @@ LEVEL := ../.. TOOLNAME := llvm-ranlib LINK_COMPONENTS := archive -REQUIRES_EH := 1 # This tool has no plugins, optimize startup time. TOOL_NO_EXPORTS := 1 diff --git a/tools/llvm-ranlib/llvm-ranlib.cpp b/tools/llvm-ranlib/llvm-ranlib.cpp index 4006765..fe9d3e2 100644 --- a/tools/llvm-ranlib/llvm-ranlib.cpp +++ b/tools/llvm-ranlib/llvm-ranlib.cpp @@ -11,16 +11,16 @@ // //===----------------------------------------------------------------------===// -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/Bitcode/Archive.h" +#include "llvm/IR/Module.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Format.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Signals.h" +#include "llvm/Support/raw_ostream.h" #include <memory> using namespace llvm; @@ -61,41 +61,38 @@ int main(int argc, char **argv) { int exitCode = 0; - // Make sure we don't exit with "unhandled exception". - try { - - // Check the path name of the archive - sys::Path ArchivePath; - if (!ArchivePath.set(ArchiveName)) - throw std::string("Archive name invalid: ") + ArchiveName; + // Check the path name of the archive + sys::Path ArchivePath; + if (!ArchivePath.set(ArchiveName)) { + errs() << argv[0] << ": " << "Archive name invalid: " << ArchiveName << + "\n"; + return 1; + } - // Make sure it exists, we don't create empty archives - bool Exists; - if (llvm::sys::fs::exists(ArchivePath.str(), Exists) || !Exists) - throw std::string("Archive file does not exist"); + // Make sure it exists, we don't create empty archives + bool Exists; + if (llvm::sys::fs::exists(ArchivePath.str(), Exists) || !Exists) { + errs() << argv[0] << ": " << "Archive file does not exist" << + ArchivePath.str() << "\n"; + return 1; + } - std::string err_msg; - std::auto_ptr<Archive> - AutoArchive(Archive::OpenAndLoad(ArchivePath, Context, &err_msg)); - Archive* TheArchive = AutoArchive.get(); - if (!TheArchive) - throw err_msg; + std::string err_msg; + std::auto_ptr<Archive> + AutoArchive(Archive::OpenAndLoad(ArchivePath, Context, &err_msg)); + Archive* TheArchive = AutoArchive.get(); + if (!TheArchive) { + errs() << argv[0] << ": " << err_msg << "\n"; + return 1; + } - if (TheArchive->writeToDisk(true, false, &err_msg )) - throw err_msg; + if (TheArchive->writeToDisk(true, false, &err_msg )) { + errs() << argv[0] << ": " << err_msg << "\n"; + return 1; + } - if (Verbose) - printSymbolTable(TheArchive); + if (Verbose) + printSymbolTable(TheArchive); - } catch (const char* msg) { - errs() << argv[0] << ": " << msg << "\n\n"; - exitCode = 1; - } catch (const std::string& msg) { - errs() << argv[0] << ": " << msg << "\n"; - exitCode = 2; - } catch (...) { - errs() << argv[0] << ": An unexpected unknown exception occurred.\n"; - exitCode = 3; - } return exitCode; } diff --git a/tools/llvm-readobj/llvm-readobj.cpp b/tools/llvm-readobj/llvm-readobj.cpp index 3be1289..d22ecd1 100644 --- a/tools/llvm-readobj/llvm-readobj.cpp +++ b/tools/llvm-readobj/llvm-readobj.cpp @@ -16,16 +16,16 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Object/ObjectFile.h" -#include "llvm/Object/ELF.h" -#include "llvm/Analysis/Verifier.h" #include "llvm/ADT/Triple.h" -#include "llvm/Support/Format.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Object/ELF.h" +#include "llvm/Object/ObjectFile.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/Signals.h" +#include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Signals.h" using namespace llvm; using namespace llvm::object; @@ -33,7 +33,7 @@ using namespace llvm::object; static cl::opt<std::string> InputFilename(cl::Positional, cl::desc("<input object>"), cl::init("")); -void DumpSymbolHeader() { +static void dumpSymbolHeader() { outs() << format(" %-32s", (const char*)"Name") << format(" %-4s", (const char*)"Type") << format(" %-16s", (const char*)"Address") @@ -43,7 +43,16 @@ void DumpSymbolHeader() { << "\n"; } -const char *GetTypeStr(SymbolRef::Type Type) { +static void dumpSectionHeader() { + outs() << format(" %-24s", (const char*)"Name") + << format(" %-16s", (const char*)"Address") + << format(" %-16s", (const char*)"Size") + << format(" %-8s", (const char*)"Align") + << format(" %-26s", (const char*)"Flags") + << "\n"; +} + +static const char *getTypeStr(SymbolRef::Type Type) { switch (Type) { case SymbolRef::ST_Unknown: return "?"; case SymbolRef::ST_Data: return "DATA"; @@ -55,7 +64,7 @@ const char *GetTypeStr(SymbolRef::Type Type) { return "INV"; } -std::string GetFlagStr(uint32_t Flags) { +static std::string getSymbolFlagStr(uint32_t Flags) { std::string result; if (Flags & SymbolRef::SF_Undefined) result += "undef,"; @@ -79,102 +88,126 @@ std::string GetFlagStr(uint32_t Flags) { return result; } -void DumpSymbol(const SymbolRef &Sym, const ObjectFile *obj, bool IsDynamic) { - StringRef Name; - SymbolRef::Type Type; - uint32_t Flags; - uint64_t Address; - uint64_t Size; - uint64_t FileOffset; - Sym.getName(Name); - Sym.getAddress(Address); - Sym.getSize(Size); - Sym.getFileOffset(FileOffset); - Sym.getType(Type); - Sym.getFlags(Flags); - std::string FullName = Name; - - // If this is a dynamic symbol from an ELF object, append - // the symbol's version to the name. - if (IsDynamic && obj->isELF()) { - StringRef Version; - bool IsDefault; - GetELFSymbolVersion(obj, Sym, Version, IsDefault); - if (!Version.empty()) { - FullName += (IsDefault ? "@@" : "@"); - FullName += Version; - } - } - - // format() can't handle StringRefs - outs() << format(" %-32s", FullName.c_str()) - << format(" %-4s", GetTypeStr(Type)) - << format(" %16" PRIx64, Address) - << format(" %16" PRIx64, Size) - << format(" %16" PRIx64, FileOffset) - << " " << GetFlagStr(Flags) - << "\n"; +static void checkError(error_code ec, const char *msg) { + if (ec) + report_fatal_error(std::string(msg) + ": " + ec.message()); } +static std::string getSectionFlagStr(const SectionRef &Section) { + const struct { + error_code (SectionRef::*MemF)(bool &) const; + const char *FlagStr, *ErrorStr; + } Work[] = + {{ &SectionRef::isText, "text,", "Section.isText() failed" }, + { &SectionRef::isData, "data,", "Section.isData() failed" }, + { &SectionRef::isBSS, "bss,", "Section.isBSS() failed" }, + { &SectionRef::isRequiredForExecution, "required,", + "Section.isRequiredForExecution() failed" }, + { &SectionRef::isVirtual, "virtual,", "Section.isVirtual() failed" }, + { &SectionRef::isZeroInit, "zeroinit,", "Section.isZeroInit() failed" }, + { &SectionRef::isReadOnlyData, "rodata,", + "Section.isReadOnlyData() failed" }}; -// Iterate through the normal symbols in the ObjectFile -void DumpSymbols(const ObjectFile *obj) { - error_code ec; - uint32_t count = 0; - outs() << "Symbols:\n"; - symbol_iterator it = obj->begin_symbols(); - symbol_iterator ie = obj->end_symbols(); - while (it != ie) { - DumpSymbol(*it, obj, false); - it.increment(ec); - if (ec) - report_fatal_error("Symbol iteration failed"); - ++count; + std::string result; + for (uint32_t I = 0; I < sizeof(Work)/sizeof(*Work); ++I) { + bool B; + checkError((Section.*Work[I].MemF)(B), Work[I].ErrorStr); + if (B) + result += Work[I].FlagStr; } - outs() << " Total: " << count << "\n\n"; + + // Remove trailing comma + if (result.size() > 0) { + result.erase(result.size() - 1); + } + return result; } -// Iterate through the dynamic symbols in the ObjectFile. -void DumpDynamicSymbols(const ObjectFile *obj) { - error_code ec; - uint32_t count = 0; - outs() << "Dynamic Symbols:\n"; - symbol_iterator it = obj->begin_dynamic_symbols(); - symbol_iterator ie = obj->end_dynamic_symbols(); - while (it != ie) { - DumpSymbol(*it, obj, true); - it.increment(ec); - if (ec) - report_fatal_error("Symbol iteration failed"); - ++count; +static void +dumpSymbol(const SymbolRef &Sym, const ObjectFile *obj, bool IsDynamic) { + StringRef Name; + SymbolRef::Type Type; + uint32_t Flags; + uint64_t Address; + uint64_t Size; + uint64_t FileOffset; + checkError(Sym.getName(Name), "SymbolRef.getName() failed"); + checkError(Sym.getAddress(Address), "SymbolRef.getAddress() failed"); + checkError(Sym.getSize(Size), "SymbolRef.getSize() failed"); + checkError(Sym.getFileOffset(FileOffset), + "SymbolRef.getFileOffset() failed"); + checkError(Sym.getType(Type), "SymbolRef.getType() failed"); + checkError(Sym.getFlags(Flags), "SymbolRef.getFlags() failed"); + std::string FullName = Name; + + // If this is a dynamic symbol from an ELF object, append + // the symbol's version to the name. + if (IsDynamic && obj->isELF()) { + StringRef Version; + bool IsDefault; + GetELFSymbolVersion(obj, Sym, Version, IsDefault); + if (!Version.empty()) { + FullName += (IsDefault ? "@@" : "@"); + FullName += Version; + } } - outs() << " Total: " << count << "\n\n"; + + // format() can't handle StringRefs + outs() << format(" %-32s", FullName.c_str()) + << format(" %-4s", getTypeStr(Type)) + << format(" %16" PRIx64, Address) + << format(" %16" PRIx64, Size) + << format(" %16" PRIx64, FileOffset) + << " " << getSymbolFlagStr(Flags) + << "\n"; } -void DumpLibrary(const LibraryRef &lib) { +static void dumpStaticSymbol(const SymbolRef &Sym, const ObjectFile *obj) { + return dumpSymbol(Sym, obj, false); +} + +static void dumpDynamicSymbol(const SymbolRef &Sym, const ObjectFile *obj) { + return dumpSymbol(Sym, obj, true); +} + +static void dumpSection(const SectionRef &Section, const ObjectFile *obj) { + StringRef Name; + checkError(Section.getName(Name), "SectionRef::getName() failed"); + uint64_t Addr, Size, Align; + checkError(Section.getAddress(Addr), "SectionRef::getAddress() failed"); + checkError(Section.getSize(Size), "SectionRef::getSize() failed"); + checkError(Section.getAlignment(Align), "SectionRef::getAlignment() failed"); + outs() << format(" %-24s", std::string(Name).c_str()) + << format(" %16" PRIx64, Addr) + << format(" %16" PRIx64, Size) + << format(" %8" PRIx64, Align) + << " " << getSectionFlagStr(Section) + << "\n"; +} + +static void dumpLibrary(const LibraryRef &lib, const ObjectFile *obj) { StringRef path; lib.getPath(path); outs() << " " << path << "\n"; } -// Iterate through needed libraries -void DumpLibrariesNeeded(const ObjectFile *obj) { +template<typename Iterator, typename Func> +static void dump(const ObjectFile *obj, Func f, Iterator begin, Iterator end, + const char *errStr) { error_code ec; uint32_t count = 0; - library_iterator it = obj->begin_libraries_needed(); - library_iterator ie = obj->end_libraries_needed(); - outs() << "Libraries needed:\n"; + Iterator it = begin, ie = end; while (it != ie) { - DumpLibrary(*it); + f(*it, obj); it.increment(ec); if (ec) - report_fatal_error("Needed libraries iteration failed"); + report_fatal_error(errStr); ++count; } outs() << " Total: " << count << "\n\n"; } -void DumpHeaders(const ObjectFile *obj) { +static void dumpHeaders(const ObjectFile *obj) { outs() << "File Format : " << obj->getFileFormatName() << "\n"; outs() << "Arch : " << Triple::getArchTypeName((llvm::Triple::ArchType)obj->getArch()) @@ -209,10 +242,27 @@ int main(int argc, char** argv) { errs() << InputFilename << ": Object type not recognized\n"; } - DumpHeaders(obj); - DumpSymbols(obj); - DumpDynamicSymbols(obj); - DumpLibrariesNeeded(obj); + dumpHeaders(obj); + + outs() << "Symbols:\n"; + dumpSymbolHeader(); + dump(obj, dumpStaticSymbol, obj->begin_symbols(), obj->end_symbols(), + "Symbol iteration failed"); + + outs() << "Dynamic Symbols:\n"; + dumpSymbolHeader(); + dump(obj, dumpDynamicSymbol, obj->begin_dynamic_symbols(), + obj->end_dynamic_symbols(), "Symbol iteration failed"); + + outs() << "Sections:\n"; + dumpSectionHeader(); + dump(obj, &dumpSection, obj->begin_sections(), obj->end_sections(), + "Section iteration failed"); + + outs() << "Libraries needed:\n"; + dump(obj, &dumpLibrary, obj->begin_libraries_needed(), + obj->end_libraries_needed(), "Needed libraries iteration failed"); + return 0; } diff --git a/tools/llvm-rtdyld/llvm-rtdyld.cpp b/tools/llvm-rtdyld/llvm-rtdyld.cpp index 95de8d8..ec63c9b 100644 --- a/tools/llvm-rtdyld/llvm-rtdyld.cpp +++ b/tools/llvm-rtdyld/llvm-rtdyld.cpp @@ -11,8 +11,10 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/StringMap.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ExecutionEngine/ObjectBuffer.h" +#include "llvm/ExecutionEngine/ObjectImage.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/Object/MachOObject.h" #include "llvm/Support/CommandLine.h" @@ -56,13 +58,15 @@ public: uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID); uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID); + unsigned SectionID, bool IsReadOnly); virtual void *getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure = true) { return 0; } + bool applyPermissions(std::string *ErrMsg) { return false; } + // Invalidate instruction cache for sections with execute permissions. // Some platforms with separate data cache and instruction cache require // explicit cache flush, otherwise JIT code manipulations (like resolved @@ -80,7 +84,8 @@ uint8_t *TrivialMemoryManager::allocateCodeSection(uintptr_t Size, uint8_t *TrivialMemoryManager::allocateDataSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID) { + unsigned SectionID, + bool IsReadOnly) { sys::MemoryBlock MB = sys::Memory::AllocateRWX(Size, 0, 0); DataMemory.push_back(MB); return (uint8_t*)MB.base(); @@ -120,12 +125,14 @@ static int executeInput() { for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) { // Load the input memory buffer. OwningPtr<MemoryBuffer> InputBuffer; + OwningPtr<ObjectImage> LoadedObject; if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFileList[i], InputBuffer)) return Error("unable to read input: '" + ec.message() + "'"); - // Load the object file into it. - if (Dyld.loadObject(InputBuffer.take())) { + // Load the object file + LoadedObject.reset(Dyld.loadObject(new ObjectBuffer(InputBuffer.take()))); + if (!LoadedObject) { return Error(Dyld.getErrorString()); } } diff --git a/tools/llvm-size/llvm-size.cpp b/tools/llvm-size/llvm-size.cpp index 462da40..3de6605 100644 --- a/tools/llvm-size/llvm-size.cpp +++ b/tools/llvm-size/llvm-size.cpp @@ -23,8 +23,8 @@ #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Signals.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" #include <algorithm> #include <string> diff --git a/tools/llvm-stress/llvm-stress.cpp b/tools/llvm-stress/llvm-stress.cpp index 31252dd..bb15c6b 100644 --- a/tools/llvm-stress/llvm-stress.cpp +++ b/tools/llvm-stress/llvm-stress.cpp @@ -11,25 +11,25 @@ // different components in LLVM. // //===----------------------------------------------------------------------===// -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" -#include "llvm/PassManager.h" -#include "llvm/Constants.h" -#include "llvm/Instruction.h" -#include "llvm/CallGraphSCCPass.h" -#include "llvm/Assembly/PrintModulePass.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/Analysis/CallGraphSCCPass.h" #include "llvm/Analysis/Verifier.h" -#include "llvm/Support/PassNameParser.h" +#include "llvm/Assembly/PrintModulePass.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Module.h" +#include "llvm/PassManager.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/PassNameParser.h" #include "llvm/Support/PluginLoader.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/ToolOutputFile.h" +#include <algorithm> #include <memory> -#include <sstream> #include <set> +#include <sstream> #include <vector> -#include <algorithm> using namespace llvm; static cl::opt<unsigned> SeedCL("seed", @@ -126,6 +126,10 @@ public: /// C'tor Modifier(BasicBlock *Block, PieceTable *PT, Random *R): BB(Block),PT(PT),Ran(R),Context(BB->getContext()) {} + + /// virtual D'tor to silence warnings. + virtual ~Modifier() {} + /// Add a new instruction. virtual void Act() = 0; /// Add N new instructions, diff --git a/tools/llvm-symbolizer/CMakeLists.txt b/tools/llvm-symbolizer/CMakeLists.txt new file mode 100644 index 0000000..5e27463 --- /dev/null +++ b/tools/llvm-symbolizer/CMakeLists.txt @@ -0,0 +1,13 @@ +# FIXME: As we plan to execute llvm-symbolizer binary from compiler-rt +# libraries, it has to be compiled for all supported targets (x86_64, i386 etc). +# This means that we need LLVM libraries to be compiled for these +# targets as well. Currently, there is no support for such a build strategy. + +set(LLVM_LINK_COMPONENTS + DebugInfo + Object + ) + +add_llvm_tool(llvm-symbolizer + llvm-symbolizer.cpp + ) diff --git a/tools/llvm-symbolizer/Makefile b/tools/llvm-symbolizer/Makefile new file mode 100644 index 0000000..5ac83a5 --- /dev/null +++ b/tools/llvm-symbolizer/Makefile @@ -0,0 +1,17 @@ +##===- tools/llvm-symbolizer/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-symbolizer +LINK_COMPONENTS := DebugInfo Object + +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS := 1 + +include $(LEVEL)/Makefile.common diff --git a/tools/llvm-symbolizer/llvm-symbolizer.cpp b/tools/llvm-symbolizer/llvm-symbolizer.cpp new file mode 100644 index 0000000..6a5eb4a --- /dev/null +++ b/tools/llvm-symbolizer/llvm-symbolizer.cpp @@ -0,0 +1,322 @@ +//===-- llvm-symbolizer.cpp - Simple addr2line-like symbolizer ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This utility works much like "addr2line". It is able of transforming +// tuples (module name, module offset) to code locations (function name, +// file, line number, column number). It is targeted for compiler-rt tools +// (especially AddressSanitizer and ThreadSanitizer) that can use it +// to symbolize stack traces in their error reports. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/Object/MachO.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/raw_ostream.h" +#include <cstdio> +#include <cstring> +#include <map> +#include <string> + +using namespace llvm; +using namespace object; + +static cl::opt<bool> +UseSymbolTable("use-symbol-table", cl::init(true), + cl::desc("Prefer names in symbol table to names " + "in debug info")); + +static cl::opt<bool> +PrintFunctions("functions", cl::init(true), + cl::desc("Print function names as well as line " + "information for a given address")); + +static cl::opt<bool> +PrintInlining("inlining", cl::init(true), + cl::desc("Print all inlined frames for a given address")); + +static cl::opt<bool> +Demangle("demangle", cl::init(true), + cl::desc("Demangle function names")); + +static StringRef ToolInvocationPath; + +static bool error(error_code ec) { + if (!ec) return false; + errs() << ToolInvocationPath << ": error reading file: " + << ec.message() << ".\n"; + return true; +} + +static uint32_t getDILineInfoSpecifierFlags() { + uint32_t Flags = llvm::DILineInfoSpecifier::FileLineInfo | + llvm::DILineInfoSpecifier::AbsoluteFilePath; + if (PrintFunctions) + Flags |= llvm::DILineInfoSpecifier::FunctionName; + return Flags; +} + +static void patchFunctionNameInDILineInfo(const std::string &NewFunctionName, + DILineInfo &LineInfo) { + std::string FileName = LineInfo.getFileName(); + LineInfo = DILineInfo(StringRef(FileName), StringRef(NewFunctionName), + LineInfo.getLine(), LineInfo.getColumn()); +} + +namespace { +class ModuleInfo { + OwningPtr<ObjectFile> Module; + OwningPtr<DIContext> DebugInfoContext; + public: + ModuleInfo(ObjectFile *Obj, DIContext *DICtx) + : Module(Obj), DebugInfoContext(DICtx) {} + + DILineInfo symbolizeCode(uint64_t ModuleOffset) const { + DILineInfo LineInfo; + if (DebugInfoContext) { + LineInfo = DebugInfoContext->getLineInfoForAddress( + ModuleOffset, getDILineInfoSpecifierFlags()); + } + // Override function name from symbol table if necessary. + if (PrintFunctions && UseSymbolTable) { + std::string Function; + if (getFunctionNameFromSymbolTable(ModuleOffset, Function)) { + patchFunctionNameInDILineInfo(Function, LineInfo); + } + } + return LineInfo; + } + + DIInliningInfo symbolizeInlinedCode(uint64_t ModuleOffset) const { + DIInliningInfo InlinedContext; + if (DebugInfoContext) { + InlinedContext = DebugInfoContext->getInliningInfoForAddress( + ModuleOffset, getDILineInfoSpecifierFlags()); + } + // Make sure there is at least one frame in context. + if (InlinedContext.getNumberOfFrames() == 0) { + InlinedContext.addFrame(DILineInfo()); + } + // Override the function name in lower frame with name from symbol table. + if (PrintFunctions && UseSymbolTable) { + DIInliningInfo PatchedInlinedContext; + for (uint32_t i = 0, n = InlinedContext.getNumberOfFrames(); + i != n; i++) { + DILineInfo LineInfo = InlinedContext.getFrame(i); + if (i == n - 1) { + std::string Function; + if (getFunctionNameFromSymbolTable(ModuleOffset, Function)) { + patchFunctionNameInDILineInfo(Function, LineInfo); + } + } + PatchedInlinedContext.addFrame(LineInfo); + } + InlinedContext = PatchedInlinedContext; + } + return InlinedContext; + } + + private: + bool getFunctionNameFromSymbolTable(uint64_t Address, + std::string &FunctionName) const { + assert(Module); + error_code ec; + for (symbol_iterator si = Module->begin_symbols(), + se = Module->end_symbols(); + si != se; si.increment(ec)) { + if (error(ec)) return false; + uint64_t SymbolAddress; + uint64_t SymbolSize; + SymbolRef::Type SymbolType; + if (error(si->getAddress(SymbolAddress)) || + SymbolAddress == UnknownAddressOrSize) continue; + if (error(si->getSize(SymbolSize)) || + SymbolSize == UnknownAddressOrSize) continue; + if (error(si->getType(SymbolType))) continue; + // FIXME: If a function has alias, there are two entries in symbol table + // with same address size. Make sure we choose the correct one. + if (SymbolAddress <= Address && Address < SymbolAddress + SymbolSize && + SymbolType == SymbolRef::ST_Function) { + StringRef Name; + if (error(si->getName(Name))) continue; + FunctionName = Name.str(); + return true; + } + } + return false; + } +}; + +typedef std::map<std::string, ModuleInfo*> ModuleMapTy; +typedef ModuleMapTy::iterator ModuleMapIter; +} // namespace + +static ModuleMapTy Modules; + +// Returns true if the object endianness is known. +static bool getObjectEndianness(const ObjectFile *Obj, + bool &IsLittleEndian) { + // FIXME: Implement this when libLLVMObject allows to do it easily. + IsLittleEndian = true; + return true; +} + +static ObjectFile *getObjectFile(const std::string &Path) { + OwningPtr<MemoryBuffer> Buff; + MemoryBuffer::getFile(Path, Buff); + return ObjectFile::createObjectFile(Buff.take()); +} + +static std::string getDarwinDWARFResourceForModule(const std::string &Path) { + StringRef Basename = sys::path::filename(Path); + const std::string &DSymDirectory = Path + ".dSYM"; + SmallString<16> ResourceName = StringRef(DSymDirectory); + sys::path::append(ResourceName, "Contents", "Resources", "DWARF"); + sys::path::append(ResourceName, Basename); + return ResourceName.str(); +} + +static ModuleInfo *getOrCreateModuleInfo(const std::string &ModuleName) { + ModuleMapIter I = Modules.find(ModuleName); + if (I != Modules.end()) + return I->second; + + ObjectFile *Obj = getObjectFile(ModuleName); + ObjectFile *DbgObj = Obj; + if (Obj == 0) { + // Module name doesn't point to a valid object file. + Modules.insert(make_pair(ModuleName, (ModuleInfo*)0)); + return 0; + } + + DIContext *Context = 0; + bool IsLittleEndian; + if (getObjectEndianness(Obj, IsLittleEndian)) { + // On Darwin we may find DWARF in separate object file in + // resource directory. + if (isa<MachOObjectFile>(Obj)) { + const std::string &ResourceName = getDarwinDWARFResourceForModule( + ModuleName); + ObjectFile *ResourceObj = getObjectFile(ResourceName); + if (ResourceObj != 0) + DbgObj = ResourceObj; + } + Context = DIContext::getDWARFContext(DbgObj); + assert(Context); + } + + ModuleInfo *Info = new ModuleInfo(Obj, Context); + Modules.insert(make_pair(ModuleName, Info)); + return Info; +} + +#if !defined(_MSC_VER) +// Assume that __cxa_demangle is provided by libcxxabi (except for Windows). +extern "C" char *__cxa_demangle(const char *mangled_name, char *output_buffer, + size_t *length, int *status); +#endif + +static void printDILineInfo(DILineInfo LineInfo) { + // By default, DILineInfo contains "<invalid>" for function/filename it + // cannot fetch. We replace it to "??" to make our output closer to addr2line. + static const std::string kDILineInfoBadString = "<invalid>"; + static const std::string kSymbolizerBadString = "??"; + if (PrintFunctions) { + std::string FunctionName = LineInfo.getFunctionName(); + if (FunctionName == kDILineInfoBadString) + FunctionName = kSymbolizerBadString; +#if !defined(_MSC_VER) + if (Demangle) { + int status = 0; + char *DemangledName = __cxa_demangle( + FunctionName.c_str(), 0, 0, &status); + if (status == 0) { + FunctionName = DemangledName; + free(DemangledName); + } + } +#endif + outs() << FunctionName << "\n"; + } + std::string Filename = LineInfo.getFileName(); + if (Filename == kDILineInfoBadString) + Filename = kSymbolizerBadString; + outs() << Filename << + ":" << LineInfo.getLine() << + ":" << LineInfo.getColumn() << + "\n"; +} + +static void symbolize(std::string ModuleName, std::string ModuleOffsetStr) { + ModuleInfo *Info = getOrCreateModuleInfo(ModuleName); + uint64_t Offset = 0; + if (Info == 0 || + StringRef(ModuleOffsetStr).getAsInteger(0, Offset)) { + printDILineInfo(DILineInfo()); + } else if (PrintInlining) { + DIInliningInfo InlinedContext = Info->symbolizeInlinedCode(Offset); + uint32_t FramesNum = InlinedContext.getNumberOfFrames(); + assert(FramesNum > 0); + for (uint32_t i = 0; i < FramesNum; i++) { + DILineInfo LineInfo = InlinedContext.getFrame(i); + printDILineInfo(LineInfo); + } + } else { + DILineInfo LineInfo = Info->symbolizeCode(Offset); + printDILineInfo(LineInfo); + } + + outs() << "\n"; // Print extra empty line to mark the end of output. + outs().flush(); +} + +static bool parseModuleNameAndOffset(std::string &ModuleName, + std::string &ModuleOffsetStr) { + static const int kMaxInputStringLength = 1024; + static const char kDelimiters[] = " \n"; + char InputString[kMaxInputStringLength]; + if (!fgets(InputString, sizeof(InputString), stdin)) + return false; + ModuleName = ""; + ModuleOffsetStr = ""; + // FIXME: Handle case when filename is given in quotes. + if (char *FilePath = strtok(InputString, kDelimiters)) { + ModuleName = FilePath; + if (char *OffsetStr = strtok((char*)0, kDelimiters)) + ModuleOffsetStr = OffsetStr; + } + return true; +} + +int main(int argc, char **argv) { + // Print stack trace if we signal out. + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + + cl::ParseCommandLineOptions(argc, argv, "llvm symbolizer for compiler-rt\n"); + ToolInvocationPath = argv[0]; + + std::string ModuleName; + std::string ModuleOffsetStr; + while (parseModuleNameAndOffset(ModuleName, ModuleOffsetStr)) { + symbolize(ModuleName, ModuleOffsetStr); + } + return 0; +} diff --git a/tools/lto/CMakeLists.txt b/tools/lto/CMakeLists.txt index 9112976..5820b14 100644 --- a/tools/lto/CMakeLists.txt +++ b/tools/lto/CMakeLists.txt @@ -6,10 +6,13 @@ add_definitions( -DLLVM_VERSION_INFO=\"${PACKAGE_VERSION}\" ) set(SOURCES LTOCodeGenerator.cpp + LTODisassembler.cpp lto.cpp LTOModule.cpp ) +set(LLVM_COMMON_DEPENDS intrinsics_gen) + if( NOT WIN32 AND LLVM_ENABLE_PIC ) set(bsl ${BUILD_SHARED_LIBS}) set(BUILD_SHARED_LIBS ON) diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp index f8b07b2..e87b378 100644 --- a/tools/lto/LTOCodeGenerator.cpp +++ b/tools/lto/LTOCodeGenerator.cpp @@ -14,36 +14,36 @@ #include "LTOCodeGenerator.h" #include "LTOModule.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Linker.h" -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" -#include "llvm/PassManager.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Analysis/Passes.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/Config/config.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Linker.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/SubtargetFeature.h" -#include "llvm/Target/Mangler.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/Transforms/IPO.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include "llvm/PassManager.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/Host.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Signals.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" +#include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/system_error.h" -#include "llvm/ADT/StringExtras.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" using namespace llvm; static cl::opt<bool> @@ -218,12 +218,13 @@ bool LTOCodeGenerator::determineTarget(std::string& errMsg) { if (_target != NULL) return false; - std::string Triple = _linker.getModule()->getTargetTriple(); - if (Triple.empty()) - Triple = sys::getDefaultTargetTriple(); + std::string TripleStr = _linker.getModule()->getTargetTriple(); + if (TripleStr.empty()) + TripleStr = sys::getDefaultTargetTriple(); + llvm::Triple Triple(TripleStr); // create target machine from info for merged modules - const Target *march = TargetRegistry::lookupTarget(Triple, errMsg); + const Target *march = TargetRegistry::lookupTarget(TripleStr, errMsg); if (march == NULL) return true; @@ -244,11 +245,18 @@ bool LTOCodeGenerator::determineTarget(std::string& errMsg) { // construct LTOModule, hand over ownership of module and target SubtargetFeatures Features; - Features.getDefaultSubtargetFeatures(llvm::Triple(Triple)); + Features.getDefaultSubtargetFeatures(Triple); std::string FeatureStr = Features.getString(); + // Set a default CPU for Darwin triples. + if (_mCpu.empty() && Triple.isOSDarwin()) { + if (Triple.getArch() == llvm::Triple::x86_64) + _mCpu = "core2"; + else if (Triple.getArch() == llvm::Triple::x86) + _mCpu = "yonah"; + } TargetOptions Options; LTOModule::getTargetOptions(Options); - _target = march->createTargetMachine(Triple, _mCpu, FeatureStr, Options, + _target = march->createTargetMachine(TripleStr, _mCpu, FeatureStr, Options, RelocModel, CodeModel::Default, CodeGenOpt::Aggressive); return false; @@ -293,7 +301,7 @@ void LTOCodeGenerator::applyScopeRestrictions() { // mark which symbols can not be internalized MCContext Context(*_target->getMCAsmInfo(), *_target->getRegisterInfo(),NULL); - Mangler mangler(Context, *_target->getTargetData()); + Mangler mangler(Context, *_target->getDataLayout()); std::vector<const char*> mustPreserveList; SmallPtrSet<GlobalValue*, 8> asmUsed; @@ -361,13 +369,15 @@ bool LTOCodeGenerator::generateObjectFile(raw_ostream &out, // Start off with a verification pass. passes.add(createVerifierPass()); - // Add an appropriate TargetData instance for this module... - passes.add(new TargetData(*_target->getTargetData())); + // Add an appropriate DataLayout instance for this module... + passes.add(new DataLayout(*_target->getDataLayout())); + _target->addAnalysisPasses(passes); // Enabling internalize here would use its AllButMain variant. It // keeps only main if it exists and does nothing for libraries. Instead // we create the pass ourselves with the symbol list provided by the linker. - PassManagerBuilder().populateLTOPassManager(passes, /*Internalize=*/false, + PassManagerBuilder().populateLTOPassManager(passes, + /*Internalize=*/false, !DisableInline, DisableGVNLoadPRE); @@ -376,7 +386,7 @@ bool LTOCodeGenerator::generateObjectFile(raw_ostream &out, FunctionPassManager *codeGenPasses = new FunctionPassManager(mergedModule); - codeGenPasses->add(new TargetData(*_target->getTargetData())); + codeGenPasses->add(new DataLayout(*_target->getDataLayout())); formatted_raw_ostream Out(out); diff --git a/tools/lto/LTOCodeGenerator.h b/tools/lto/LTOCodeGenerator.h index 3081b7d..601dbfa 100644 --- a/tools/lto/LTOCodeGenerator.h +++ b/tools/lto/LTOCodeGenerator.h @@ -14,10 +14,10 @@ #ifndef LTO_CODE_GENERATOR_H #define LTO_CODE_GENERATOR_H -#include "llvm/Linker.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm-c/lto.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Linker.h" #include <string> namespace llvm { diff --git a/tools/lto/LTODisassembler.cpp b/tools/lto/LTODisassembler.cpp new file mode 100644 index 0000000..186aceb --- /dev/null +++ b/tools/lto/LTODisassembler.cpp @@ -0,0 +1,26 @@ +//===-- LTODisassembler.cpp - LTO Disassembler interface ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This function provides utility methods used by clients of libLTO that want +// to use the disassembler. +// +//===----------------------------------------------------------------------===// + +#include "llvm-c/lto.h" +#include "llvm/Support/TargetSelect.h" + +using namespace llvm; + +void lto_initialize_disassembler() { + // Initialize targets and assembly printers/parsers. + llvm::InitializeAllTargetInfos(); + llvm::InitializeAllTargetMCs(); + llvm::InitializeAllAsmParsers(); + llvm::InitializeAllDisassemblers(); +} diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp index b98bfab..23a8fb4 100644 --- a/tools/lto/LTOModule.cpp +++ b/tools/lto/LTOModule.cpp @@ -13,19 +13,20 @@ //===----------------------------------------------------------------------===// #include "LTOModule.h" -#include "llvm/Constants.h" -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/Triple.h" #include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCTargetAsmParser.h" #include "llvm/MC/SubtargetFeature.h" -#include "llvm/MC/MCParser/MCAsmParser.h" -#include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Host.h" #include "llvm/Support/MemoryBuffer.h" @@ -34,8 +35,7 @@ #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/system_error.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/Triple.h" +#include "llvm/Target/TargetRegisterInfo.h" using namespace llvm; static cl::opt<bool> @@ -158,7 +158,7 @@ SSPBufferSize("stack-protector-buffer-size", cl::init(8), LTOModule::LTOModule(llvm::Module *m, llvm::TargetMachine *t) : _module(m), _target(t), _context(*_target->getMCAsmInfo(), *_target->getRegisterInfo(), NULL), - _mangler(_context, *_target->getTargetData()) {} + _mangler(_context, *_target->getDataLayout()) {} /// isBitcodeFile - Returns 'true' if the file (or memory contents) is LLVM /// bitcode. @@ -278,23 +278,31 @@ LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer, return NULL; } - std::string Triple = m->getTargetTriple(); - if (Triple.empty()) - Triple = sys::getDefaultTargetTriple(); + std::string TripleStr = m->getTargetTriple(); + if (TripleStr.empty()) + TripleStr = sys::getDefaultTargetTriple(); + llvm::Triple Triple(TripleStr); // find machine architecture for this module - const Target *march = TargetRegistry::lookupTarget(Triple, errMsg); + const Target *march = TargetRegistry::lookupTarget(TripleStr, errMsg); if (!march) return NULL; // construct LTOModule, hand over ownership of module and target SubtargetFeatures Features; - Features.getDefaultSubtargetFeatures(llvm::Triple(Triple)); + Features.getDefaultSubtargetFeatures(Triple); std::string FeatureStr = Features.getString(); + // Set a default CPU for Darwin triples. std::string CPU; + if (Triple.isOSDarwin()) { + if (Triple.getArch() == llvm::Triple::x86_64) + CPU = "core2"; + else if (Triple.getArch() == llvm::Triple::x86) + CPU = "yonah"; + } TargetOptions Options; getTargetOptions(Options); - TargetMachine *target = march->createTargetMachine(Triple, CPU, FeatureStr, + TargetMachine *target = march->createTargetMachine(TripleStr, CPU, FeatureStr, Options); LTOModule *Ret = new LTOModule(m.take(), target); if (Ret->parseSymbols(errMsg)) { @@ -312,8 +320,9 @@ MemoryBuffer *LTOModule::makeBuffer(const void *mem, size_t length) { } /// objcClassNameFromExpression - Get string that the data pointer points to. -bool LTOModule::objcClassNameFromExpression(Constant *c, std::string &name) { - if (ConstantExpr *ce = dyn_cast<ConstantExpr>(c)) { +bool +LTOModule::objcClassNameFromExpression(const Constant *c, std::string &name) { + if (const ConstantExpr *ce = dyn_cast<ConstantExpr>(c)) { Constant *op = ce->getOperand(0); if (GlobalVariable *gvn = dyn_cast<GlobalVariable>(op)) { Constant *cn = gvn->getInitializer(); @@ -329,8 +338,8 @@ bool LTOModule::objcClassNameFromExpression(Constant *c, std::string &name) { } /// addObjCClass - Parse i386/ppc ObjC class data structure. -void LTOModule::addObjCClass(GlobalVariable *clgv) { - ConstantStruct *c = dyn_cast<ConstantStruct>(clgv->getInitializer()); +void LTOModule::addObjCClass(const GlobalVariable *clgv) { + const ConstantStruct *c = dyn_cast<ConstantStruct>(clgv->getInitializer()); if (!c) return; // second slot in __OBJC,__class is pointer to superclass name @@ -366,8 +375,8 @@ void LTOModule::addObjCClass(GlobalVariable *clgv) { } /// addObjCCategory - Parse i386/ppc ObjC category data structure. -void LTOModule::addObjCCategory(GlobalVariable *clgv) { - ConstantStruct *c = dyn_cast<ConstantStruct>(clgv->getInitializer()); +void LTOModule::addObjCCategory(const GlobalVariable *clgv) { + const ConstantStruct *c = dyn_cast<ConstantStruct>(clgv->getInitializer()); if (!c) return; // second slot in __OBJC,__category is pointer to target class name @@ -391,7 +400,7 @@ void LTOModule::addObjCCategory(GlobalVariable *clgv) { } /// addObjCClassRef - Parse i386/ppc ObjC class list data structure. -void LTOModule::addObjCClassRef(GlobalVariable *clgv) { +void LTOModule::addObjCClassRef(const GlobalVariable *clgv) { std::string targetclassName; if (!objcClassNameFromExpression(clgv->getInitializer(), targetclassName)) return; @@ -411,7 +420,7 @@ void LTOModule::addObjCClassRef(GlobalVariable *clgv) { } /// addDefinedDataSymbol - Add a data symbol as defined to the list. -void LTOModule::addDefinedDataSymbol(GlobalValue *v) { +void LTOModule::addDefinedDataSymbol(const GlobalValue *v) { // Add to list of defined symbols. addDefinedSymbol(v, false); @@ -440,34 +449,34 @@ void LTOModule::addDefinedDataSymbol(GlobalValue *v) { // special case if this data blob is an ObjC class definition if (v->getSection().compare(0, 15, "__OBJC,__class,") == 0) { - if (GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) { + if (const GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) { addObjCClass(gv); } } // special case if this data blob is an ObjC category definition else if (v->getSection().compare(0, 18, "__OBJC,__category,") == 0) { - if (GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) { + if (const GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) { addObjCCategory(gv); } } // special case if this data blob is the list of referenced classes else if (v->getSection().compare(0, 18, "__OBJC,__cls_refs,") == 0) { - if (GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) { + if (const GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) { addObjCClassRef(gv); } } } /// addDefinedFunctionSymbol - Add a function symbol as defined to the list. -void LTOModule::addDefinedFunctionSymbol(Function *f) { +void LTOModule::addDefinedFunctionSymbol(const Function *f) { // add to list of defined symbols addDefinedSymbol(f, true); } /// addDefinedSymbol - Add a defined symbol to the list. -void LTOModule::addDefinedSymbol(GlobalValue *def, bool isFunction) { +void LTOModule::addDefinedSymbol(const GlobalValue *def, bool isFunction) { // ignore all llvm.* symbols if (def->getName().startswith("llvm.")) return; @@ -484,7 +493,7 @@ void LTOModule::addDefinedSymbol(GlobalValue *def, bool isFunction) { if (isFunction) { attr |= LTO_SYMBOL_PERMISSIONS_CODE; } else { - GlobalVariable *gv = dyn_cast<GlobalVariable>(def); + const GlobalVariable *gv = dyn_cast<GlobalVariable>(def); if (gv && gv->isConstant()) attr |= LTO_SYMBOL_PERMISSIONS_RODATA; else @@ -599,7 +608,8 @@ void LTOModule::addAsmGlobalSymbolUndef(const char *name) { /// addPotentialUndefinedSymbol - Add a symbol which isn't defined just yet to a /// list to be resolved later. -void LTOModule::addPotentialUndefinedSymbol(GlobalValue *decl, bool isFunc) { +void +LTOModule::addPotentialUndefinedSymbol(const GlobalValue *decl, bool isFunc) { // ignore all llvm.* symbols if (decl->getName().startswith("llvm.")) return; @@ -735,6 +745,9 @@ namespace { Symbol->setSection(*getCurrentSection()); markDefined(*Symbol); } + virtual void EmitDebugLabel(MCSymbol *Symbol) { + EmitLabel(Symbol); + } virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { // FIXME: should we handle aliases? markDefined(*Symbol); @@ -752,6 +765,10 @@ namespace { markDefined(*Symbol); } + virtual void EmitBundleAlignMode(unsigned AlignPow2) {} + virtual void EmitBundleLock(bool AlignToEnd) {} + virtual void EmitBundleUnlock() {} + // Noop calls. virtual void ChangeSection(const MCSection *Section) {} virtual void InitSections() {} diff --git a/tools/lto/LTOModule.h b/tools/lto/LTOModule.h index 8e52206..83f3a7d 100644 --- a/tools/lto/LTOModule.h +++ b/tools/lto/LTOModule.h @@ -14,15 +14,15 @@ #ifndef LTO_MODULE_H #define LTO_MODULE_H -#include "llvm/Module.h" +#include "llvm-c/lto.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/IR/Module.h" #include "llvm/MC/MCContext.h" #include "llvm/Target/Mangler.h" #include "llvm/Target/TargetMachine.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/StringMap.h" -#include "llvm-c/lto.h" -#include <vector> #include <string> +#include <vector> // Forward references to llvm classes. namespace llvm { @@ -44,7 +44,7 @@ private: const char *name; uint32_t attributes; bool isFunction; - llvm::GlobalValue *symbol; + const llvm::GlobalValue *symbol; }; llvm::OwningPtr<llvm::Module> _module; @@ -138,16 +138,16 @@ private: /// addPotentialUndefinedSymbol - Add a symbol which isn't defined just yet /// to a list to be resolved later. - void addPotentialUndefinedSymbol(llvm::GlobalValue *dcl, bool isFunc); + void addPotentialUndefinedSymbol(const llvm::GlobalValue *dcl, bool isFunc); /// addDefinedSymbol - Add a defined symbol to the list. - void addDefinedSymbol(llvm::GlobalValue *def, bool isFunction); + void addDefinedSymbol(const llvm::GlobalValue *def, bool isFunction); /// addDefinedFunctionSymbol - Add a function symbol as defined to the list. - void addDefinedFunctionSymbol(llvm::Function *f); + void addDefinedFunctionSymbol(const llvm::Function *f); /// addDefinedDataSymbol - Add a data symbol as defined to the list. - void addDefinedDataSymbol(llvm::GlobalValue *v); + void addDefinedDataSymbol(const llvm::GlobalValue *v); /// addAsmGlobalSymbols - Add global symbols from module-level ASM to the /// defined or undefined lists. @@ -162,17 +162,17 @@ private: void addAsmGlobalSymbolUndef(const char *); /// addObjCClass - Parse i386/ppc ObjC class data structure. - void addObjCClass(llvm::GlobalVariable *clgv); + void addObjCClass(const llvm::GlobalVariable *clgv); /// addObjCCategory - Parse i386/ppc ObjC category data structure. - void addObjCCategory(llvm::GlobalVariable *clgv); + void addObjCCategory(const llvm::GlobalVariable *clgv); /// addObjCClassRef - Parse i386/ppc ObjC class list data structure. - void addObjCClassRef(llvm::GlobalVariable *clgv); + void addObjCClassRef(const llvm::GlobalVariable *clgv); /// objcClassNameFromExpression - Get string that the data pointer points /// to. - bool objcClassNameFromExpression(llvm::Constant* c, std::string &name); + bool objcClassNameFromExpression(const llvm::Constant* c, std::string &name); /// isTargetMatch - Returns 'true' if the memory buffer is for the specified /// target triple. diff --git a/tools/lto/Makefile b/tools/lto/Makefile index 153fa03..3610fed 100644 --- a/tools/lto/Makefile +++ b/tools/lto/Makefile @@ -49,4 +49,11 @@ ifeq ($(HOST_OS),Darwin) -Wl,-install_name \ -Wl,"@executable_path/../lib/lib$(LIBRARYNAME)$(SHLIBEXT)" endif + + # If we're doing an Apple-style build, add the LTO object path. + ifeq ($(RC_BUILDIT),YES) + TempFile := $(shell mkdir -p ${OBJROOT}/dSYMs ; mktemp ${OBJROOT}/dSYMs/llvm-lto.XXXXXX) + LLVMLibsOptions := $(LLVMLibsOptions) \ + -Wl,-object_path_lto -Wl,$(TempFile) + endif endif diff --git a/tools/lto/lto.cpp b/tools/lto/lto.cpp index a7e633d..11ad532 100644 --- a/tools/lto/lto.cpp +++ b/tools/lto/lto.cpp @@ -13,10 +13,9 @@ //===----------------------------------------------------------------------===// #include "llvm-c/lto.h" -#include "llvm-c/Core.h" - -#include "LTOModule.h" #include "LTOCodeGenerator.h" +#include "LTOModule.h" +#include "llvm-c/Core.h" // Holds most recent error string. diff --git a/tools/lto/lto.exports b/tools/lto/lto.exports index b900bfb..46d0d74 100644 --- a/tools/lto/lto.exports +++ b/tools/lto/lto.exports @@ -1,5 +1,6 @@ lto_get_error_message lto_get_version +lto_initialize_disassembler lto_module_create lto_module_create_from_fd lto_module_create_from_fd_at_offset @@ -28,5 +29,7 @@ lto_codegen_set_assembler_path lto_codegen_set_cpu lto_codegen_compile_to_file LLVMCreateDisasm +LLVMCreateDisasmCPU LLVMDisasmDispose LLVMDisasmInstruction +LLVMSetDisasmOptions diff --git a/tools/opt/AnalysisWrappers.cpp b/tools/opt/AnalysisWrappers.cpp index a2b57bb..55f544f 100644 --- a/tools/opt/AnalysisWrappers.cpp +++ b/tools/opt/AnalysisWrappers.cpp @@ -17,10 +17,10 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Module.h" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/IR/Module.h" #include "llvm/Pass.h" #include "llvm/Support/CallSite.h" -#include "llvm/Analysis/CallGraph.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; diff --git a/tools/opt/CMakeLists.txt b/tools/opt/CMakeLists.txt index 7daf22a..32de6d4 100644 --- a/tools/opt/CMakeLists.txt +++ b/tools/opt/CMakeLists.txt @@ -1,4 +1,4 @@ -set(LLVM_LINK_COMPONENTS bitreader asmparser bitwriter instrumentation scalaropts ipo vectorize) +set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} bitreader asmparser bitwriter instrumentation scalaropts ipo vectorize) add_llvm_tool(opt AnalysisWrappers.cpp diff --git a/tools/opt/GraphPrinters.cpp b/tools/opt/GraphPrinters.cpp index 30361f5..c7481e5 100644 --- a/tools/opt/GraphPrinters.cpp +++ b/tools/opt/GraphPrinters.cpp @@ -14,11 +14,11 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/GraphWriter.h" -#include "llvm/Pass.h" -#include "llvm/Value.h" #include "llvm/Analysis/CallGraph.h" #include "llvm/Analysis/Dominators.h" +#include "llvm/IR/Value.h" +#include "llvm/Pass.h" +#include "llvm/Support/GraphWriter.h" #include "llvm/Support/ToolOutputFile.h" using namespace llvm; diff --git a/tools/opt/LLVMBuild.txt b/tools/opt/LLVMBuild.txt index 4de99f5..b174431 100644 --- a/tools/opt/LLVMBuild.txt +++ b/tools/opt/LLVMBuild.txt @@ -19,4 +19,4 @@ type = Tool name = opt parent = Tools -required_libraries = AsmParser BitReader BitWriter IPO Instrumentation Scalar +required_libraries = AsmParser BitReader BitWriter IPO Instrumentation Scalar all-targets diff --git a/tools/opt/Makefile b/tools/opt/Makefile index 16d116d..ee7e1cf 100644 --- a/tools/opt/Makefile +++ b/tools/opt/Makefile @@ -9,6 +9,6 @@ LEVEL := ../.. TOOLNAME := opt -LINK_COMPONENTS := bitreader bitwriter asmparser instrumentation scalaropts ipo vectorize +LINK_COMPONENTS := bitreader bitwriter asmparser instrumentation scalaropts ipo vectorize all-targets include $(LEVEL)/Makefile.common diff --git a/tools/opt/PrintSCC.cpp b/tools/opt/PrintSCC.cpp index 11efdcd..a502fa7 100644 --- a/tools/opt/PrintSCC.cpp +++ b/tools/opt/PrintSCC.cpp @@ -25,12 +25,12 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Pass.h" -#include "llvm/Module.h" +#include "llvm/ADT/SCCIterator.h" #include "llvm/Analysis/CallGraph.h" +#include "llvm/IR/Module.h" +#include "llvm/Pass.h" #include "llvm/Support/CFG.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/ADT/SCCIterator.h" using namespace llvm; namespace { diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp index 7ecd25c..ac8323b 100644 --- a/tools/opt/opt.cpp +++ b/tools/opt/opt.cpp @@ -12,36 +12,40 @@ // //===----------------------------------------------------------------------===// -#include "llvm/LLVMContext.h" -#include "llvm/DebugInfo.h" -#include "llvm/Module.h" -#include "llvm/PassManager.h" -#include "llvm/CallGraphSCCPass.h" -#include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/Assembly/PrintModulePass.h" -#include "llvm/Analysis/Verifier.h" -#include "llvm/Analysis/LoopPass.h" -#include "llvm/Analysis/RegionPass.h" -#include "llvm/Analysis/CallGraph.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetLibraryInfo.h" -#include "llvm/Target/TargetMachine.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/ADT/StringSet.h" #include "llvm/ADT/Triple.h" -#include "llvm/Support/PassNameParser.h" -#include "llvm/Support/Signals.h" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/Analysis/CallGraphSCCPass.h" +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/RegionPass.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Assembly/PrintModulePass.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/CodeGen/CommandFlags.h" +#include "llvm/DebugInfo.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Module.h" +#include "llvm/LinkAllPasses.h" +#include "llvm/LinkAllVMCore.h" +#include "llvm/MC/SubtargetFeature.h" +#include "llvm/PassManager.h" #include "llvm/Support/Debug.h" #include "llvm/Support/IRReader.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/PassNameParser.h" #include "llvm/Support/PluginLoader.h" #include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Signals.h" #include "llvm/Support/SystemUtils.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" #include "llvm/Support/ToolOutputFile.h" -#include "llvm/LinkAllPasses.h" -#include "llvm/LinkAllVMCore.h" +#include "llvm/Target/TargetLibraryInfo.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" -#include <memory> #include <algorithm> +#include <memory> using namespace llvm; // The OptimizationList is automatically populated with registered Passes by the @@ -478,6 +482,70 @@ static void AddStandardLinkPasses(PassManagerBase &PM) { /*RunInliner=*/ !DisableInline); } +//===----------------------------------------------------------------------===// +// CodeGen-related helper functions. +// +static TargetOptions GetTargetOptions() { + TargetOptions Options; + Options.LessPreciseFPMADOption = EnableFPMAD; + Options.NoFramePointerElim = DisableFPElim; + Options.NoFramePointerElimNonLeaf = DisableFPElimNonLeaf; + Options.AllowFPOpFusion = FuseFPOps; + Options.UnsafeFPMath = EnableUnsafeFPMath; + Options.NoInfsFPMath = EnableNoInfsFPMath; + Options.NoNaNsFPMath = EnableNoNaNsFPMath; + Options.HonorSignDependentRoundingFPMathOption = + EnableHonorSignDependentRoundingFPMath; + Options.UseSoftFloat = GenerateSoftFloatCalls; + if (FloatABIForCalls != FloatABI::Default) + Options.FloatABIType = FloatABIForCalls; + Options.NoZerosInBSS = DontPlaceZerosInBSS; + Options.GuaranteedTailCallOpt = EnableGuaranteedTailCallOpt; + Options.DisableTailCalls = DisableTailCalls; + Options.StackAlignmentOverride = OverrideStackAlignment; + Options.RealignStack = EnableRealignStack; + Options.TrapFuncName = TrapFuncName; + Options.PositionIndependentExecutable = EnablePIE; + Options.EnableSegmentedStacks = SegmentedStacks; + Options.UseInitArray = UseInitArray; + Options.SSPBufferSize = SSPBufferSize; + return Options; +} + +CodeGenOpt::Level GetCodeGenOptLevel() { + if (OptLevelO1) + return CodeGenOpt::Less; + if (OptLevelO2) + return CodeGenOpt::Default; + if (OptLevelO3) + return CodeGenOpt::Aggressive; + return CodeGenOpt::None; +} + +// Returns the TargetMachine instance or zero if no triple is provided. +static TargetMachine* GetTargetMachine(Triple TheTriple) { + std::string Error; + const Target *TheTarget = TargetRegistry::lookupTarget(MArch, TheTriple, + Error); + // Some modules don't specify a triple, and this is okay. + if (!TheTarget) { + return 0; + } + + // Package up features to be passed to target/subtarget + std::string FeaturesStr; + if (MAttrs.size()) { + SubtargetFeatures Features; + for (unsigned i = 0; i != MAttrs.size(); ++i) + Features.AddFeature(MAttrs[i]); + FeaturesStr = Features.getString(); + } + + return TheTarget->createTargetMachine(TheTriple.getTriple(), + MCPU, FeaturesStr, GetTargetOptions(), + RelocModel, CMModel, + GetCodeGenOptLevel()); +} //===----------------------------------------------------------------------===// // main for opt @@ -492,6 +560,9 @@ int main(int argc, char **argv) { llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. LLVMContext &Context = getGlobalContext(); + InitializeAllTargets(); + InitializeAllTargetMCs(); + // Initialize passes PassRegistry &Registry = *PassRegistry::getPassRegistry(); initializeCore(Registry); @@ -568,22 +639,32 @@ int main(int argc, char **argv) { TLI->disableAllFunctions(); Passes.add(TLI); - // Add an appropriate TargetData instance for this module. - TargetData *TD = 0; + // Add an appropriate DataLayout instance for this module. + DataLayout *TD = 0; const std::string &ModuleDataLayout = M.get()->getDataLayout(); if (!ModuleDataLayout.empty()) - TD = new TargetData(ModuleDataLayout); + TD = new DataLayout(ModuleDataLayout); else if (!DefaultDataLayout.empty()) - TD = new TargetData(DefaultDataLayout); + TD = new DataLayout(DefaultDataLayout); if (TD) Passes.add(TD); + Triple ModuleTriple(M->getTargetTriple()); + TargetMachine *Machine = 0; + if (ModuleTriple.getArch()) + Machine = GetTargetMachine(Triple(ModuleTriple)); + std::auto_ptr<TargetMachine> TM(Machine); + + // Add internal analysis passes from the target machine. + if (TM.get()) + TM->addAnalysisPasses(Passes); + OwningPtr<FunctionPassManager> FPasses; if (OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz || OptLevelO3) { FPasses.reset(new FunctionPassManager(M.get())); if (TD) - FPasses->add(new TargetData(*TD)); + FPasses->add(new DataLayout(*TD)); } if (PrintBreakpoints) { |
