diff options
Diffstat (limited to 'tools')
46 files changed, 1335 insertions, 469 deletions
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 1bfc2fe..69182856 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -36,6 +36,7 @@ add_subdirectory(bugpoint) add_subdirectory(bugpoint-passes) add_subdirectory(llvm-bcanalyzer) add_subdirectory(llvm-stress) +add_subdirectory(llvm-mcmarkup) if( NOT WIN32 ) add_subdirectory(lto) diff --git a/tools/LLVMBuild.txt b/tools/LLVMBuild.txt index df4aa9f..64164792 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-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..a29e49f 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -34,7 +34,7 @@ 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 # Let users override the set of tools to build from the command line. ifdef ONLY_TOOLS diff --git a/tools/bugpoint/ExtractFunction.cpp b/tools/bugpoint/ExtractFunction.cpp index 888d2c8..b40b4f1 100644 --- a/tools/bugpoint/ExtractFunction.cpp +++ b/tools/bugpoint/ExtractFunction.cpp @@ -14,6 +14,7 @@ #include "BugDriver.h" #include "llvm/Constants.h" +#include "llvm/DataLayout.h" #include "llvm/DerivedTypes.h" #include "llvm/LLVMContext.h" #include "llvm/Module.h" @@ -25,7 +26,6 @@ #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Transforms/Utils/CodeExtractor.h" -#include "llvm/Target/TargetData.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileUtilities.h" diff --git a/tools/bugpoint/OptimizerDriver.cpp b/tools/bugpoint/OptimizerDriver.cpp index fb090ee..c56911a 100644 --- a/tools/bugpoint/OptimizerDriver.cpp +++ b/tools/bugpoint/OptimizerDriver.cpp @@ -16,11 +16,11 @@ //===----------------------------------------------------------------------===// #include "BugDriver.h" +#include "llvm/DataLayout.h" #include "llvm/Module.h" #include "llvm/PassManager.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/Target/TargetData.h" #include "llvm/Support/FileUtilities.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/SystemUtils.h" diff --git a/tools/gold/Makefile b/tools/gold/Makefile index 02f66d7..496e31c 100644 --- a/tools/gold/Makefile +++ b/tools/gold/Makefile @@ -24,6 +24,8 @@ include $(LEVEL)/Makefile.config # Because off_t is used in the public API, the largefile parts are required for # ABI compatibility. CXXFLAGS += -I$(BINUTILS_INCDIR) -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -CXXFLAGS += -L$(SharedLibDir)/$(SharedPrefix) -lLTO +LDFLAGS += -L$(SharedLibDir)/$(SharedPrefix) include $(LEVEL)/Makefile.common + +LIBS += -lLTO diff --git a/tools/gold/gold-plugin.cpp b/tools/gold/gold-plugin.cpp index 9c17da6..b0a0dd2 100644 --- a/tools/gold/gold-plugin.cpp +++ b/tools/gold/gold-plugin.cpp @@ -378,9 +378,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 +386,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 +396,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 8951050..4d4a74c 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -14,12 +14,14 @@ //===----------------------------------------------------------------------===// #include "llvm/LLVMContext.h" +#include "llvm/DataLayout.h" #include "llvm/Module.h" #include "llvm/PassManager.h" #include "llvm/Pass.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/MC/SubtargetFeature.h" @@ -34,7 +36,6 @@ #include "llvm/Support/Signals.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" -#include "llvm/Target/TargetData.h" #include "llvm/Target/TargetLibraryInfo.h" #include "llvm/Target/TargetMachine.h" #include <memory> @@ -62,211 +63,13 @@ 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)); - -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("")); + cl::desc("Disable simplify-libcalls"), + cl::init(false)); // GetFileNameRoot - Helper function to get the basename of a filename. static inline std::string @@ -459,6 +262,7 @@ int main(int argc, char **argv) { Options.PositionIndependentExecutable = EnablePIE; Options.EnableSegmentedStacks = SegmentedStacks; Options.UseInitArray = UseInitArray; + Options.SSPBufferSize = SSPBufferSize; std::auto_ptr<TargetMachine> target(TheTarget->createTargetMachine(TheTriple.getTriple(), @@ -499,11 +303,16 @@ int main(int argc, char **argv) { TLI->disableAllFunctions(); PM.add(TLI); + if (target.get()) { + PM.add(new TargetTransformInfo(target->getScalarTargetTransformInfo(), + target->getVectorTargetTransformInfo())); + } + // 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 a5d2e61..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 @@ -19,4 +17,6 @@ endif( LLVM_USE_INTEL_JITEVENTS ) add_llvm_tool(lli lli.cpp + RecordingMemoryManager.cpp + RemoteTarget.cpp ) 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 new file mode 100644 index 0000000..9e1cff5 --- /dev/null +++ b/tools/lli/RecordingMemoryManager.cpp @@ -0,0 +1,87 @@ +//===- RecordingMemoryManager.cpp - Recording memory manager --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This memory manager allocates local storage and keeps a record of each +// allocation. Iterators are provided for all data and code allocations. +// +//===----------------------------------------------------------------------===// + +#include "RecordingMemoryManager.h" +using namespace llvm; + +uint8_t *RecordingMemoryManager:: +allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID) { + // 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. + void *Addr = malloc(Size); + assert(Addr && "malloc() failure!"); + sys::MemoryBlock Block(Addr, Size); + AllocatedCodeMem.push_back(Allocation(Block, Alignment)); + return (uint8_t*)Addr; +} + +uint8_t *RecordingMemoryManager:: +allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID) { + // 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. + void *Addr = malloc(Size); + assert(Addr && "malloc() failure!"); + sys::MemoryBlock Block(Addr, Size); + AllocatedDataMem.push_back(Allocation(Block, Alignment)); + return (uint8_t*)Addr; +} +void RecordingMemoryManager::setMemoryWritable() { llvm_unreachable("Unexpected!"); } +void RecordingMemoryManager::setMemoryExecutable() { llvm_unreachable("Unexpected!"); } +void RecordingMemoryManager::setPoisonMemory(bool poison) { llvm_unreachable("Unexpected!"); } +void RecordingMemoryManager::AllocateGOT() { llvm_unreachable("Unexpected!"); } +uint8_t *RecordingMemoryManager::getGOTBase() const { + llvm_unreachable("Unexpected!"); + return 0; +} +uint8_t *RecordingMemoryManager::startFunctionBody(const Function *F, uintptr_t &ActualSize){ + llvm_unreachable("Unexpected!"); + return 0; +} +uint8_t *RecordingMemoryManager::allocateStub(const GlobalValue* F, unsigned StubSize, + unsigned Alignment) { + llvm_unreachable("Unexpected!"); + return 0; +} +void RecordingMemoryManager::endFunctionBody(const Function *F, uint8_t *FunctionStart, + uint8_t *FunctionEnd) { + llvm_unreachable("Unexpected!"); +} +uint8_t *RecordingMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment) { + llvm_unreachable("Unexpected!"); + return 0; +} +uint8_t *RecordingMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment) { + llvm_unreachable("Unexpected!"); + return 0; +} +void RecordingMemoryManager::deallocateFunctionBody(void *Body) { + llvm_unreachable("Unexpected!"); +} +uint8_t* RecordingMemoryManager::startExceptionTable(const Function* F, uintptr_t &ActualSize) { + llvm_unreachable("Unexpected!"); + return 0; +} +void RecordingMemoryManager::endExceptionTable(const Function *F, uint8_t *TableStart, + uint8_t *TableEnd, uint8_t* FrameRegister) { + llvm_unreachable("Unexpected!"); +} +void RecordingMemoryManager::deallocateExceptionTable(void *ET) { + llvm_unreachable("Unexpected!"); +} +void *RecordingMemoryManager::getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure) { + return NULL; +} diff --git a/tools/lli/RecordingMemoryManager.h b/tools/lli/RecordingMemoryManager.h new file mode 100644 index 0000000..1590235 --- /dev/null +++ b/tools/lli/RecordingMemoryManager.h @@ -0,0 +1,78 @@ +//===- RecordingMemoryManager.h - LLI MCJIT recording memory manager ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This memory manager allocates local storage and keeps a record of each +// allocation. Iterators are provided for all data and code allocations. +// +//===----------------------------------------------------------------------===// + +#ifndef RECORDINGMEMORYMANAGER_H +#define RECORDINGMEMORYMANAGER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ExecutionEngine/JITMemoryManager.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Memory.h" +#include <utility> + +namespace llvm { + +class RecordingMemoryManager : public JITMemoryManager { +public: + typedef std::pair<sys::MemoryBlock, unsigned> Allocation; + +private: + SmallVector<Allocation, 16> AllocatedDataMem; + SmallVector<Allocation, 16> AllocatedCodeMem; + +public: + RecordingMemoryManager() {} + virtual ~RecordingMemoryManager() {} + + typedef SmallVectorImpl<Allocation>::const_iterator const_data_iterator; + typedef SmallVectorImpl<Allocation>::const_iterator const_code_iterator; + + const_data_iterator data_begin() const { return AllocatedDataMem.begin(); } + const_data_iterator data_end() const { return AllocatedDataMem.end(); } + const_code_iterator code_begin() const { return AllocatedCodeMem.begin(); } + const_code_iterator code_end() const { return AllocatedCodeMem.end(); } + + uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID); + + uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID); + + void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true); + // The following obsolete JITMemoryManager calls are stubbed out for + // this model. + void setMemoryWritable(); + void setMemoryExecutable(); + void setPoisonMemory(bool poison); + void AllocateGOT(); + uint8_t *getGOTBase() const; + uint8_t *startFunctionBody(const Function *F, uintptr_t &ActualSize); + uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize, + unsigned Alignment); + void endFunctionBody(const Function *F, uint8_t *FunctionStart, + uint8_t *FunctionEnd); + uint8_t *allocateSpace(intptr_t Size, unsigned Alignment); + uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment); + void deallocateFunctionBody(void *Body); + uint8_t* startExceptionTable(const Function* F, uintptr_t &ActualSize); + void endExceptionTable(const Function *F, uint8_t *TableStart, + uint8_t *TableEnd, uint8_t* FrameRegister); + void deallocateExceptionTable(void *ET); + +}; + +} // end namespace llvm + +#endif diff --git a/tools/lli/RemoteTarget.cpp b/tools/lli/RemoteTarget.cpp new file mode 100644 index 0000000..212bdfd --- /dev/null +++ b/tools/lli/RemoteTarget.cpp @@ -0,0 +1,61 @@ +//===- RemoteTarget.cpp - LLVM Remote process JIT execution --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implementation of the RemoteTarget class which executes JITed code in a +// separate address range from where it was built. +// +//===----------------------------------------------------------------------===// + +#include "RemoteTarget.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/Memory.h" +#include <stdlib.h> +#include <string> +using namespace llvm; + +bool RemoteTarget::allocateSpace(size_t Size, unsigned Alignment, + uint64_t &Address) { + sys::MemoryBlock *Prev = Allocations.size() ? &Allocations.back() : NULL; + sys::MemoryBlock Mem = sys::Memory::AllocateRWX(Size, Prev, &ErrorMsg); + if (Mem.base() == NULL) + return true; + if ((uintptr_t)Mem.base() % Alignment) { + ErrorMsg = "unable to allocate sufficiently aligned memory"; + return true; + } + Address = reinterpret_cast<uint64_t>(Mem.base()); + return false; +} + +bool RemoteTarget::loadData(uint64_t Address, const void *Data, size_t Size) { + memcpy ((void*)Address, Data, Size); + 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; +} + +bool RemoteTarget::executeCode(uint64_t Address, int &RetVal) { + int (*fn)(void) = (int(*)(void))Address; + RetVal = fn(); + return false; +} + +void RemoteTarget::create() { +} + +void RemoteTarget::stop() { + for (unsigned i = 0, e = Allocations.size(); i != e; ++i) + sys::Memory::ReleaseRWX(Allocations[i]); +} diff --git a/tools/lli/RemoteTarget.h b/tools/lli/RemoteTarget.h new file mode 100644 index 0000000..d05d3c6 --- /dev/null +++ b/tools/lli/RemoteTarget.h @@ -0,0 +1,101 @@ +//===- RemoteTarget.h - LLVM Remote process JIT execution ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Definition of the RemoteTarget class which executes JITed code in a +// separate address range from where it was built. +// +//===----------------------------------------------------------------------===// + +#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 <stdlib.h> +#include <string> + +namespace llvm { + +class RemoteTarget { + std::string ErrorMsg; + bool IsRunning; + + SmallVector<sys::MemoryBlock, 16> Allocations; + +public: + StringRef getErrorMsg() const { return ErrorMsg; } + + /// Allocate space in the remote target address space. + /// + /// @param Size Amount of space, in bytes, to allocate. + /// @param Alignment Required minimum alignment for allocated space. + /// @param[out] Address Remote address of the allocated memory. + /// + /// @returns False on success. On failure, ErrorMsg is updated with + /// descriptive text of the encountered error. + bool allocateSpace(size_t Size, unsigned Alignment, uint64_t &Address); + + /// Load data into the target address space. + /// + /// @param Address Destination address in the target process. + /// @param Data Source address in the host process. + /// @param Size Number of bytes to copy. + /// + /// @returns False on success. On failure, ErrorMsg is updated with + /// descriptive text of the encountered error. + bool loadData(uint64_t Address, const void *Data, size_t Size); + + /// Load code into the target address space and prepare it for execution. + /// + /// @param Address Destination address in the target process. + /// @param Data Source address in the host process. + /// @param Size Number of bytes to copy. + /// + /// @returns False on success. On failure, ErrorMsg is updated with + /// descriptive text of the encountered error. + bool loadCode(uint64_t Address, const void *Data, size_t Size); + + /// Execute code in the target process. The called function is required + /// to be of signature int "(*)(void)". + /// + /// @param Address Address of the loaded function in the target + /// process. + /// @param[out] RetVal The integer return value of the called function. + /// + /// @returns False on success. On failure, ErrorMsg is updated with + /// descriptive text of the encountered error. + bool executeCode(uint64_t Address, int &RetVal); + + /// Minimum alignment for memory permissions. Used to seperate code and + /// data regions to make sure data doesn't get marked as code or vice + /// versa. + /// + /// @returns Page alignment return value. Default of 4k. + unsigned getPageAlignment() { return 4096; } + + /// Start the remote process. + void create(); + + /// Terminate the remote process. + void stop(); + + RemoteTarget() : ErrorMsg(""), IsRunning(false) {} + ~RemoteTarget() { if (IsRunning) stop(); } + +private: + // Main processing function for the remote target process. Command messages + // are received on file descriptor CmdFD and responses come back on OutFD. + static void doRemoteTargeting(int CmdFD, int OutFD); +}; + +} // end namespace llvm + +#endif diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp index b6c9299..d41a595 100644 --- a/tools/lli/lli.cpp +++ b/tools/lli/lli.cpp @@ -13,6 +13,9 @@ // //===----------------------------------------------------------------------===// +#define DEBUG_TYPE "lli" +#include "RecordingMemoryManager.h" +#include "RemoteTarget.h" #include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/Type.h" @@ -32,11 +35,14 @@ #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/MathExtras.h" #include <cerrno> #ifdef __linux__ @@ -73,6 +79,13 @@ namespace { "use-mcjit", cl::desc("Enable use of the MC-based JIT (if available)"), cl::init(false)); + // The MCJIT supports building for a target address space separate from + // the JIT compilation process. Use a forked process and a copying + // memory manager with IPC to execute using this functionality. + cl::opt<bool> RemoteMCJIT("remote-mcjit", + cl::desc("Execute MCJIT'ed code in a separate process."), + cl::init(false)); + // Determine optimization level. cl::opt<char> OptLevel("O", @@ -159,6 +172,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 @@ -212,7 +242,7 @@ public: // the data cache but not to the instruction cache. virtual void invalidateInstructionCache(); - // The MCJITMemoryManager doesn't use the following functions, so we don't + // The RTDyldMemoryManager doesn't use the following functions, so we don't // need implement them. virtual void setMemoryWritable() { llvm_unreachable("Unexpected call!"); @@ -274,9 +304,16 @@ uint8_t *LLIMCJITMemoryManager::allocateDataSection(uintptr_t Size, 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; + // Ensure that enough memory is requested to allow aligning. + size_t NumElementsAligned = 1 + (Size + Alignment - 1)/Alignment; + uint8_t *Addr = (uint8_t*)calloc(NumElementsAligned, Alignment); + + // Honour the alignment requirement. + uint8_t *AlignedAddr = (uint8_t*)RoundUpToAlignment((uint64_t)Addr, Alignment); + + // Store the original address from calloc so we can free it later. + AllocatedDataMem.push_back(sys::MemoryBlock(Addr, NumElementsAligned*Alignment)); + return AlignedAddr; } uint8_t *LLIMCJITMemoryManager::allocateCodeSection(uintptr_t Size, @@ -326,6 +363,10 @@ void LLIMCJITMemoryManager::invalidateInstructionCache() { AllocatedCodeMem[i].size()); } +static int jit_noop() { + return 0; +} + void *LLIMCJITMemoryManager::getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure) { #if defined(__linux__) @@ -348,6 +389,14 @@ void *LLIMCJITMemoryManager::getPointerToNamedFunction(const std::string &Name, if (Name == "mknod") return (void*)(intptr_t)&mknod; #endif // __linux__ + // 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; + const char *NameStr = Name.c_str(); void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr); if (Ptr) return Ptr; @@ -372,6 +421,83 @@ LLIMCJITMemoryManager::~LLIMCJITMemoryManager() { 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. + uint64_t CurOffset = 0; + unsigned MaxAlign = T->getPageAlignment(); + SmallVector<std::pair<const void*, uint64_t>, 16> Offsets; + SmallVector<unsigned, 16> Sizes; + for (RecordingMemoryManager::const_code_iterator I = JMM->code_begin(), + E = JMM->code_end(); + I != E; ++I) { + DEBUG(dbgs() << "code region: size " << I->first.size() + << ", alignment " << I->second << "\n"); + // Align the current offset up to whatever is needed for the next + // section. + unsigned Align = I->second; + CurOffset = (CurOffset + Align - 1) / Align * Align; + // Save off the address of the new section and allocate its space. + Offsets.push_back(std::pair<const void*,uint64_t>(I->first.base(), CurOffset)); + Sizes.push_back(I->first.size()); + CurOffset += I->first.size(); + } + // Adjust to keep code and data aligned on seperate pages. + CurOffset = (CurOffset + MaxAlign - 1) / MaxAlign * MaxAlign; + unsigned FirstDataIndex = Offsets.size(); + for (RecordingMemoryManager::const_data_iterator I = JMM->data_begin(), + E = JMM->data_end(); + I != E; ++I) { + DEBUG(dbgs() << "data region: size " << I->first.size() + << ", alignment " << I->second << "\n"); + // Align the current offset up to whatever is needed for the next + // section. + unsigned Align = I->second; + CurOffset = (CurOffset + Align - 1) / Align * Align; + // Save off the address of the new section and allocate its space. + Offsets.push_back(std::pair<const void*,uint64_t>(I->first.base(), CurOffset)); + Sizes.push_back(I->first.size()); + CurOffset += I->first.size(); + } + + // Allocate space in the remote target. + uint64_t RemoteAddr; + if (T->allocateSpace(CurOffset, MaxAlign, RemoteAddr)) + report_fatal_error(T->getErrorMsg()); + // Map the section addresses so relocations will get updated in the local + // copies of the sections. + for (unsigned i = 0, e = Offsets.size(); i != e; ++i) { + uint64_t Addr = RemoteAddr + Offsets[i].second; + EE->mapSectionAddress(const_cast<void*>(Offsets[i].first), Addr); + + DEBUG(dbgs() << " Mapping local: " << Offsets[i].first + << " 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; + + if (i < FirstDataIndex) { + T->loadCode(Addr, Offsets[i].first, Sizes[i]); + + DEBUG(dbgs() << " loading code: " << Offsets[i].first + << " 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("%p", Addr) << "\n"); + } + + } +} + //===----------------------------------------------------------------------===// // main Driver function // @@ -386,6 +512,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"); @@ -428,12 +555,19 @@ int main(int argc, char **argv, char * const *envp) { Mod->setTargetTriple(Triple::normalize(TargetTriple)); // Enable MCJIT if desired. - LLIMCJITMemoryManager *JMM = 0; + JITMemoryManager *JMM = 0; if (UseMCJIT && !ForceInterpreter) { builder.setUseMCJIT(true); - JMM = new LLIMCJITMemoryManager(); + if (RemoteMCJIT) + JMM = new RecordingMemoryManager(); + else + JMM = new LLIMCJITMemoryManager(); builder.setJITMemoryManager(JMM); } else { + if (RemoteMCJIT) { + errs() << "error: Remote process execution requires -use-mcjit\n"; + exit(1); + } builder.setJITMemoryManager(ForceInterpreter ? 0 : JITMemoryManager::CreateDefaultMemManager()); } @@ -452,9 +586,19 @@ int main(int argc, char **argv, char * const *envp) { builder.setOptLevel(OLvl); TargetOptions Options; - Options.JITExceptionHandling = EnableJITExceptionHandling; - Options.JITEmitDebugInfo = EmitJitDebugInfo; - Options.JITEmitDebugInfoToDisk = EmitJitDebugInfoToDisk; + 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) { + Options.JITExceptionHandling = EnableJITExceptionHandling; + Options.JITEmitDebugInfo = EmitJitDebugInfo; + Options.JITEmitDebugInfoToDisk = EmitJitDebugInfoToDisk; + } + builder.setTargetOptions(Options); EE = builder.create(); @@ -466,10 +610,6 @@ int main(int argc, char **argv, char * const *envp) { exit(1); } - // Clear instruction cache before code will be executed. - if (JMM) - JMM->invalidateInstructionCache(); - // The following functions have no effect if their respective profiling // support wasn't enabled in the build configuration. EE->RegisterJITEventListener( @@ -477,6 +617,10 @@ int main(int argc, char **argv, char * const *envp) { EE->RegisterJITEventListener( JITEventListener::createIntelJITEventListener()); + if (!NoLazyCompilation && RemoteMCJIT) { + errs() << "warning: remote mcjit does not support lazy compilation\n"; + NoLazyCompilation = true; + } EE->DisableLazyCompilation(NoLazyCompilation); // If the user specifically requested an argv[0] to pass into the program, @@ -513,8 +657,13 @@ int main(int argc, char **argv, char * const *envp) { // Reset errno to zero on entry to main. errno = 0; + // Remote target MCJIT doesn't (yet) support static constructors. No reason + // it couldn't. This is a limitation of the LLI implemantation, not the + // MCJIT itself. FIXME. + // // Run static constructors. - EE->runStaticConstructorsDestructors(false); + if (!RemoteMCJIT) + EE->runStaticConstructorsDestructors(false); if (NoLazyCompilation) { for (Module::iterator I = Mod->begin(), E = Mod->end(); I != E; ++I) { @@ -524,24 +673,69 @@ int main(int argc, char **argv, char * const *envp) { } } - // Run main. - int Result = EE->runFunctionAsMain(EntryFn, InputArgv, envp); - - // Run static destructors. - EE->runStaticConstructorsDestructors(true); - - // If the program didn't call exit explicitly, we should call it now. - // This ensures that any atexit handlers get called correctly. - if (Function *ExitF = dyn_cast<Function>(Exit)) { - std::vector<GenericValue> Args; - GenericValue ResultGV; - ResultGV.IntVal = APInt(32, Result); - Args.push_back(ResultGV); - EE->runFunction(ExitF, Args); - errs() << "ERROR: exit(" << Result << ") returned!\n"; - abort(); + int Result; + if (RemoteMCJIT) { + RecordingMemoryManager *MM = static_cast<RecordingMemoryManager*>(JMM); + // Everything is prepared now, so lay out our program for the target + // address space, assign the section addresses to resolve any relocations, + // and send it to the target. + RemoteTarget Target; + Target.create(); + + // Ask for a pointer to the entry function. This triggers the actual + // compilation. + (void)EE->getPointerToFunction(EntryFn); + + // Enough has been compiled to execute the entry function now, so + // layout the target memory. + layoutRemoteTargetMemory(&Target, MM); + + // Since we're executing in a (at least simulated) remote address space, + // we can't use the ExecutionEngine::runFunctionAsMain(). We have to + // grab the function address directly here and tell the remote target + // to execute the function. + // FIXME: argv and envp handling. + uint64_t Entry = (uint64_t)EE->getPointerToFunction(EntryFn); + + DEBUG(dbgs() << "Executing '" << EntryFn->getName() << "' at " + << format("%p", Entry) << "\n"); + + if (Target.executeCode(Entry, Result)) + errs() << "ERROR: " << Target.getErrorMsg() << "\n"; + + Target.stop(); } else { - errs() << "ERROR: exit defined with wrong prototype!\n"; - abort(); + // 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(); + + // Run main. + Result = EE->runFunctionAsMain(EntryFn, InputArgv, envp); + } + + // Like static constructors, the remote target MCJIT support doesn't handle + // this yet. It could. FIXME. + if (!RemoteMCJIT) { + // Run static destructors. + EE->runStaticConstructorsDestructors(true); + + // If the program didn't call exit explicitly, we should call it now. + // This ensures that any atexit handlers get called correctly. + if (Function *ExitF = dyn_cast<Function>(Exit)) { + std::vector<GenericValue> Args; + GenericValue ResultGV; + ResultGV.IntVal = APInt(32, Result); + Args.push_back(ResultGV); + EE->runFunction(ExitF, Args); + errs() << "ERROR: exit(" << Result << ") returned!\n"; + abort(); + } else { + errs() << "ERROR: exit defined with wrong prototype!\n"; + abort(); + } } + return Result; } 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..a8a5013a 100644 --- a/tools/llvm-ar/llvm-ar.cpp +++ b/tools/llvm-ar/llvm-ar.cpp @@ -23,6 +23,7 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Signals.h" #include <algorithm> +#include <cstdlib> #include <memory> #include <fstream> using namespace llvm; @@ -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-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 d630087..8109ca4 100644 --- a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp +++ b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp @@ -40,7 +40,7 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Signals.h" #include "llvm/Support/system_error.h" -#include <cstdio> + #include <map> #include <algorithm> using namespace llvm; @@ -463,11 +463,11 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned IndentLevel) { } static void PrintSize(double Bits) { - fprintf(stderr, "%.2f/%.2fB/%luW", Bits, Bits/8,(unsigned long)(Bits/32)); + outs() << format("%.2f/%.2fB/%luW", Bits, Bits/8,(unsigned long)(Bits/32)); } static void PrintSize(uint64_t Bits) { - fprintf(stderr, "%lub/%.2fB/%luW", (unsigned long)Bits, - (double)Bits/8, (unsigned long)(Bits/32)); + outs() << format("%lub/%.2fB/%luW", (unsigned long)Bits, + (double)Bits/8, (unsigned long)(Bits/32)); } @@ -483,7 +483,7 @@ static int AnalyzeBitcode() { if (MemBuf->getBufferSize() & 3) return Error("Bitcode stream should be a multiple of 4 bytes in length"); - const unsigned char *BufPtr = (unsigned char *)MemBuf->getBufferStart(); + const unsigned char *BufPtr = (const unsigned char *)MemBuf->getBufferStart(); const unsigned char *EndBufPtr = BufPtr+MemBuf->getBufferSize(); // If we have a wrapper header, parse it and ignore the non-bc file contents. @@ -556,7 +556,7 @@ static int AnalyzeBitcode() { PrintSize(Stats.NumBits); outs() << "\n"; double pct = (Stats.NumBits * 100.0) / BufferSizeBits; - errs() << " Percent of file: " << format("%2.4f%%", pct) << "\n"; + outs() << " Percent of file: " << format("%2.4f%%", pct) << "\n"; if (Stats.NumInstances > 1) { outs() << " Average Size: "; PrintSize(Stats.NumBits/(double)Stats.NumInstances); @@ -588,24 +588,26 @@ static int AnalyzeBitcode() { std::reverse(FreqPairs.begin(), FreqPairs.end()); outs() << "\tRecord Histogram:\n"; - fprintf(stderr, "\t\t Count # Bits %% Abv Record Kind\n"); + outs() << "\t\t Count # Bits %% Abv Record Kind\n"; for (unsigned i = 0, e = FreqPairs.size(); i != e; ++i) { const PerRecordStats &RecStats = Stats.CodeFreq[FreqPairs[i].second]; - fprintf(stderr, "\t\t%7d %9lu ", RecStats.NumInstances, - (unsigned long)RecStats.TotalBits); + outs() << format("\t\t%7d %9lu", + RecStats.NumInstances, + (unsigned long)RecStats.TotalBits); if (RecStats.NumAbbrev) - fprintf(stderr, "%7.2f ", - (double)RecStats.NumAbbrev/RecStats.NumInstances*100); + outs() << + format("%7.2f ", + (double)RecStats.NumAbbrev/RecStats.NumInstances*100); else - fprintf(stderr, " "); + outs() << " "; if (const char *CodeName = GetCodeName(FreqPairs[i].second, I->first, StreamFile)) - fprintf(stderr, "%s\n", CodeName); + outs() << CodeName << "\n"; else - fprintf(stderr, "UnknownCode%d\n", FreqPairs[i].second); + outs() << "UnknownCode" << FreqPairs[i].second << "\n"; } outs() << "\n"; 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-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-dwarfdump/llvm-dwarfdump.cpp b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp index ec0b4ae..e73300a 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 // @@ -15,6 +15,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Object/RelocVisitor.h" #include "llvm/DebugInfo/DIContext.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.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; @@ -44,6 +48,18 @@ PrintFunctions("functions", cl::init(false), cl::desc("Print function names as well as line information " "for a given address")); +static cl::opt<bool> +PrintInlining("inlining", cl::init(false), + cl::desc("Print all inlined frames for a given address")); + +static void PrintDILineInfo(DILineInfo dli) { + if (PrintFunctions) + outs() << (dli.getFunctionName() ? dli.getFunctionName() : "<unknown>") + << "\n"; + outs() << (dli.getFileName() ? dli.getFileName() : "<unknown>") << ':' + << dli.getLine() << ':' << dli.getColumn() << '\n'; +} + static void DumpInput(const StringRef &Filename) { OwningPtr<MemoryBuffer> Buff; @@ -55,10 +71,12 @@ static void DumpInput(const StringRef &Filename) { OwningPtr<ObjectFile> Obj(ObjectFile::createObjectFile(Buff.take())); StringRef DebugInfoSection; + RelocAddrMap RelocMap; StringRef DebugAbbrevSection; StringRef DebugLineSection; StringRef DebugArangesSection; StringRef DebugStringSection; + StringRef DebugRangesSection; error_code ec; for (section_iterator i = Obj->begin_sections(), @@ -82,6 +100,59 @@ static void DumpInput(const StringRef &Filename) { DebugArangesSection = data; else if (name == "debug_str") DebugStringSection = data; + else if (name == "debug_ranges") + DebugRangesSection = data; + // Any more debug info sections go here. + else + continue; + + // TODO: For now only handle relocations for the debug_info section. + if (name != "debug_info") + continue; + + if (i->begin_relocations() != i->end_relocations()) { + uint64_t SectionSize; + i->getSize(SectionSize); + for (relocation_iterator reloc_i = i->begin_relocations(), + reloc_e = i->end_relocations(); + reloc_i != reloc_e; reloc_i.increment(ec)) { + uint64_t Address; + reloc_i->getAddress(Address); + uint64_t Type; + reloc_i->getType(Type); + + RelocVisitor V(Obj->getFileFormatName()); + // The section address is always 0 for debug sections. + RelocToApply R(V.visit(Type, *reloc_i)); + if (V.error()) { + SmallString<32> Name; + error_code ec(reloc_i->getTypeName(Name)); + if (ec) { + errs() << "Aaaaaa! Nameless relocation! Aaaaaa!\n"; + } + errs() << "error: failed to compute relocation: " + << Name << "\n"; + continue; + } + + if (Address + R.Width > SectionSize) { + errs() << "error: " << R.Width << "-byte relocation starting " + << Address << " bytes into section " << name << " which is " + << SectionSize << " bytes long.\n"; + continue; + } + if (R.Width > 8) { + errs() << "error: can't handle a relocation of more than 8 bytes at " + "a time.\n"; + continue; + } + DEBUG(dbgs() << "Writing " << format("%p", R.Value) + << " at " << format("%p", Address) + << " with width " << format("%d", R.Width) + << "\n"); + RelocMap[Address] = std::make_pair(R.Width, R.Value); + } + } } OwningPtr<DIContext> dictx(DIContext::getDWARFContext(/*FIXME*/true, @@ -89,7 +160,9 @@ static void DumpInput(const StringRef &Filename) { DebugAbbrevSection, DebugArangesSection, DebugLineSection, - DebugStringSection)); + DebugStringSection, + DebugRangesSection, + RelocMap)); if (Address == -1ULL) { outs() << Filename << ":\tfile format " << Obj->getFileFormatName() << "\n\n"; @@ -97,16 +170,27 @@ static void DumpInput(const StringRef &Filename) { dictx->dump(outs()); } else { // Print line info for the specified address. - int spec_flags = DILineInfoSpecifier::FileLineInfo | - DILineInfoSpecifier::AbsoluteFilePath; - if (PrintFunctions) - spec_flags |= DILineInfoSpecifier::FunctionName; - DILineInfo dli = dictx->getLineInfoForAddress(Address, spec_flags); + int SpecFlags = DILineInfoSpecifier::FileLineInfo | + DILineInfoSpecifier::AbsoluteFilePath; if (PrintFunctions) - outs() << (dli.getFunctionName() ? dli.getFunctionName() : "<unknown>") - << "\n"; - outs() << (dli.getFileName() ? dli.getFileName() : "<unknown>") << ':' - << dli.getLine() << ':' << dli.getColumn() << '\n'; + SpecFlags |= DILineInfoSpecifier::FunctionName; + if (PrintInlining) { + DIInliningInfo InliningInfo = + dictx->getInliningInfoForAddress(Address, SpecFlags); + uint32_t n = InliningInfo.getNumberOfFrames(); + if (n == 0) { + // Print one empty debug line info in any case. + PrintDILineInfo(DILineInfo()); + } else { + for (uint32_t i = 0; i < n; i++) { + DILineInfo dli = InliningInfo.getFrame(i); + PrintDILineInfo(dli); + } + } + } else { + DILineInfo dli = dictx->getLineInfoForAddress(Address, SpecFlags); + PrintDILineInfo(dli); + } } } diff --git a/tools/llvm-extract/llvm-extract.cpp b/tools/llvm-extract/llvm-extract.cpp index 2ed11c5..ac82d98 100644 --- a/tools/llvm-extract/llvm-extract.cpp +++ b/tools/llvm-extract/llvm-extract.cpp @@ -18,7 +18,7 @@ #include "llvm/Assembly/PrintModulePass.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/Transforms/IPO.h" -#include "llvm/Target/TargetData.h" +#include "llvm/DataLayout.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/IRReader.h" #include "llvm/Support/ManagedStatic.h" @@ -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-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index 3bceb14..f7c3748 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -158,7 +158,8 @@ enum ActionType { AC_AsLex, AC_Assemble, AC_Disassemble, - AC_EDisassemble + AC_EDisassemble, + AC_MDisassemble }; static cl::opt<ActionType> @@ -172,6 +173,8 @@ Action(cl::desc("Action to perform:"), "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"), clEnumValEnd)); static const Target *GetTarget(const char *ProgName) { @@ -402,14 +405,15 @@ 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); } Str.reset(TheTarget->createAsmStreamer(Ctx, FOS, /*asmverbose*/true, /*useLoc*/ true, @@ -422,7 +426,7 @@ 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)); @@ -436,6 +440,9 @@ int main(int argc, char **argv) { case AC_Assemble: Res = AssembleInput(ProgName, TheTarget, SrcMgr, Ctx, *Str, *MAI, *STI); break; + case AC_MDisassemble: + IP->setUseMarkup(1); + // Fall through to do disassembly. case AC_Disassemble: Res = Disassembler::disassemble(*TheTarget, TripleName, *STI, *Str, *Buffer, SrcMgr, Out->os()); 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 9afbd4d..0543e83 100644 --- a/tools/llvm-nm/llvm-nm.cpp +++ b/tools/llvm-nm/llvm-nm.cpp @@ -110,6 +110,9 @@ 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")); + bool PrintAddress = true; bool MultipleFiles = false; @@ -256,7 +259,6 @@ static void DumpSymbolNameForGlobalValue(GlobalValue &GV) { if (GV.hasPrivateLinkage() || GV.hasLinkerPrivateLinkage() || GV.hasLinkerPrivateWeakLinkage() || - GV.hasLinkerPrivateWeakDefAutoLinkage() || GV.hasAvailableExternallyLinkage()) return; char TypeChar = TypeCharForSymbol(GV); @@ -276,8 +278,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(); } diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index b431c76..13ea4e3 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -94,6 +94,12 @@ static cl::alias SectionHeadersShorter("h", cl::desc("Alias for --section-headers"), cl::aliasopt(SectionHeaders)); +static cl::list<std::string> +MAttrs("mattr", + cl::CommaSeparated, + cl::desc("Target specific attributes"), + cl::value_desc("a1,+a2,-a3,...")); + static StringRef ToolName; static bool error(error_code ec) { @@ -169,6 +175,15 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { if (!TheTarget) return; + // 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(); + } + error_code ec; for (section_iterator i = Obj->begin_sections(), e = Obj->end_sections(); @@ -233,7 +248,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { } OwningPtr<const MCSubtargetInfo> STI( - TheTarget->createMCSubtargetInfo(TripleName, "", "")); + TheTarget->createMCSubtargetInfo(TripleName, "", FeaturesStr)); if (!STI) { errs() << "error: no subtarget info for target " << TripleName << "\n"; 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..d2f5f0f 100644 --- a/tools/llvm-ranlib/llvm-ranlib.cpp +++ b/tools/llvm-ranlib/llvm-ranlib.cpp @@ -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-rtdyld/llvm-rtdyld.cpp b/tools/llvm-rtdyld/llvm-rtdyld.cpp index 95de8d8..7b5bd03 100644 --- a/tools/llvm-rtdyld/llvm-rtdyld.cpp +++ b/tools/llvm-rtdyld/llvm-rtdyld.cpp @@ -14,6 +14,8 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" +#include "llvm/ExecutionEngine/ObjectImage.h" +#include "llvm/ExecutionEngine/ObjectBuffer.h" #include "llvm/Object/MachOObject.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ManagedStatic.h" @@ -120,12 +122,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-stress/llvm-stress.cpp b/tools/llvm-stress/llvm-stress.cpp index 31252dd..8473d94 100644 --- a/tools/llvm-stress/llvm-stress.cpp +++ b/tools/llvm-stress/llvm-stress.cpp @@ -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/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp index b80bc34..b1c4f43 100644 --- a/tools/lto/LTOCodeGenerator.cpp +++ b/tools/lto/LTOCodeGenerator.cpp @@ -15,6 +15,7 @@ #include "LTOCodeGenerator.h" #include "LTOModule.h" #include "llvm/Constants.h" +#include "llvm/DataLayout.h" #include "llvm/DerivedTypes.h" #include "llvm/Linker.h" #include "llvm/LLVMContext.h" @@ -29,7 +30,6 @@ #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" @@ -163,13 +163,16 @@ bool LTOCodeGenerator::compile_to_file(const char** name, std::string& errMsg) { // generate object file bool genResult = false; tool_output_file objFile(uniqueObjPath.c_str(), errMsg); - if (!errMsg.empty()) + if (!errMsg.empty()) { + uniqueObjPath.eraseFromDisk(); return true; + } genResult = this->generateObjectFile(objFile.os(), errMsg); objFile.os().close(); if (objFile.os().has_error()) { objFile.os().clear_error(); + uniqueObjPath.eraseFromDisk(); return true; } @@ -196,6 +199,7 @@ const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) { OwningPtr<MemoryBuffer> BuffPtr; if (error_code ec = MemoryBuffer::getFile(name, BuffPtr, -1, false)) { errMsg = ec.message(); + sys::Path(_nativeObjectPath).eraseFromDisk(); return NULL; } _nativeObjectFile = BuffPtr.take(); @@ -214,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; @@ -240,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; @@ -289,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; @@ -357,8 +369,10 @@ 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())); + passes.add(new TargetTransformInfo(_target->getScalarTargetTransformInfo(), + _target->getVectorTargetTransformInfo())); // Enabling internalize here would use its AllButMain variant. It // keeps only main if it exists and does nothing for libraries. Instead @@ -372,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/LTOModule.cpp b/tools/lto/LTOModule.cpp index c5b3d10..ffdcbe6 100644 --- a/tools/lto/LTOModule.cpp +++ b/tools/lto/LTOModule.cpp @@ -150,15 +150,20 @@ UseInitArray("use-init-array", cl::desc("Use .init_array instead of .ctors."), cl::init(false)); +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")); + 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. bool LTOModule::isBitcodeFile(const void *mem, size_t length) { - return llvm::sys::IdentifyFileType((char*)mem, length) + return llvm::sys::IdentifyFileType((const char*)mem, length) == llvm::sys::Bitcode_FileType; } @@ -252,6 +257,7 @@ void LTOModule::getTargetOptions(TargetOptions &Options) { Options.PositionIndependentExecutable = EnablePIE; Options.EnableSegmentedStacks = SegmentedStacks; Options.UseInitArray = UseInitArray; + Options.SSPBufferSize = SSPBufferSize; } LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer, @@ -272,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)) { @@ -301,7 +315,7 @@ LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer, /// makeBuffer - Create a MemoryBuffer from a memory range. MemoryBuffer *LTOModule::makeBuffer(const void *mem, size_t length) { - const char *startPtr = (char*)mem; + const char *startPtr = (const char*)mem; return MemoryBuffer::getMemBuffer(StringRef(startPtr, length), "", false); } @@ -487,8 +501,7 @@ void LTOModule::addDefinedSymbol(GlobalValue *def, bool isFunction) { // set definition part if (def->hasWeakLinkage() || def->hasLinkOnceLinkage() || - def->hasLinkerPrivateWeakLinkage() || - def->hasLinkerPrivateWeakDefAutoLinkage()) + def->hasLinkerPrivateWeakLinkage()) attr |= LTO_SYMBOL_DEFINITION_WEAK; else if (def->hasCommonLinkage()) attr |= LTO_SYMBOL_DEFINITION_TENTATIVE; @@ -504,7 +517,7 @@ void LTOModule::addDefinedSymbol(GlobalValue *def, bool isFunction) { def->hasLinkOnceLinkage() || def->hasCommonLinkage() || def->hasLinkerPrivateWeakLinkage()) attr |= LTO_SYMBOL_SCOPE_DEFAULT; - else if (def->hasLinkerPrivateWeakDefAutoLinkage()) + else if (def->hasLinkOnceODRAutoHideLinkage()) attr |= LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN; else attr |= LTO_SYMBOL_SCOPE_INTERNAL; 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.exports b/tools/lto/lto.exports index b900bfb..4940bb1 100644 --- a/tools/lto/lto.exports +++ b/tools/lto/lto.exports @@ -30,3 +30,4 @@ lto_codegen_compile_to_file LLVMCreateDisasm LLVMDisasmDispose LLVMDisasmInstruction +LLVMSetDisasmOptions 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/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/opt.cpp b/tools/opt/opt.cpp index 4ada7d1..bac0d46 100644 --- a/tools/opt/opt.cpp +++ b/tools/opt/opt.cpp @@ -13,17 +13,18 @@ //===----------------------------------------------------------------------===// #include "llvm/LLVMContext.h" +#include "llvm/DataLayout.h" #include "llvm/DebugInfo.h" #include "llvm/Module.h" #include "llvm/PassManager.h" #include "llvm/CallGraphSCCPass.h" +#include "llvm/CodeGen/CommandFlags.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/ADT/StringSet.h" @@ -36,7 +37,10 @@ #include "llvm/Support/PluginLoader.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/SystemUtils.h" +#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/MC/SubtargetFeature.h" #include "llvm/LinkAllPasses.h" #include "llvm/LinkAllVMCore.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" @@ -478,6 +482,75 @@ 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(std::string TripleStr) { + if (TripleStr.empty()) + return 0; + + // Get the target specific parser. + std::string Error; + Triple TheTriple(Triple::normalize(TargetTriple)); + + const Target *TheTarget = TargetRegistry::lookupTarget(MArch, TheTriple, + Error); + 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 +565,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); @@ -513,10 +589,6 @@ int main(int argc, char **argv) { return 1; } - // Allocate a full target machine description only if necessary. - // FIXME: The choice of target should be controllable on the command line. - std::auto_ptr<TargetMachine> target; - SMDiagnostic Err; // Load the input module... @@ -572,22 +644,28 @@ 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); + std::auto_ptr<TargetMachine> TM(GetTargetMachine(TargetTriple)); + if (TM.get()) { + Passes.add(new TargetTransformInfo(TM->getScalarTargetTransformInfo(), + TM->getVectorTargetTransformInfo())); + } + 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) { |