diff options
| author | Stephen Hines <srhines@google.com> | 2013-01-21 13:15:17 -0800 |
|---|---|---|
| committer | Stephen Hines <srhines@google.com> | 2013-01-21 13:15:17 -0800 |
| commit | 059800f9e3fee2852672f846d91a2da14da7783a (patch) | |
| tree | a6ef16b7263252ae1b8069295ea9cbbae0d9467d /tools/lli/lli.cpp | |
| parent | cbefa15de4821975bb99fc6d74b3bdb42b2df45c (diff) | |
| parent | b6714227eda5d499f7667fc865f931126a8dc488 (diff) | |
| download | external_llvm-059800f9e3fee2852672f846d91a2da14da7783a.zip external_llvm-059800f9e3fee2852672f846d91a2da14da7783a.tar.gz external_llvm-059800f9e3fee2852672f846d91a2da14da7783a.tar.bz2 | |
Merge remote-tracking branch 'upstream/master' into merge-llvm
Conflicts:
lib/CodeGen/AsmPrinter/AsmPrinter.cpp
lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
lib/MC/MCAssembler.cpp
lib/Support/Atomic.cpp
lib/Support/Memory.cpp
lib/Target/ARM/ARMJITInfo.cpp
Change-Id: Ib339baf88df5b04870c8df1bedcfe1f877ccab8d
Diffstat (limited to 'tools/lli/lli.cpp')
| -rw-r--r-- | tools/lli/lli.cpp | 271 |
1 files changed, 57 insertions, 214 deletions
diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp index 4004b6c..332660f 100644 --- a/tools/lli/lli.cpp +++ b/tools/lli/lli.cpp @@ -14,11 +14,9 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "lli" +#include "llvm/IR/LLVMContext.h" #include "RecordingMemoryManager.h" #include "RemoteTarget.h" -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" -#include "llvm/Type.h" #include "llvm/ADT/Triple.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/CodeGen/LinkAllCodegenComponents.h" @@ -28,32 +26,26 @@ #include "llvm/ExecutionEngine/JITEventListener.h" #include "llvm/ExecutionEngine/JITMemoryManager.h" #include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/Format.h" #include "llvm/Support/IRReader.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/Memory.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PluginLoader.h" #include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/Format.h" #include "llvm/Support/Process.h" #include "llvm/Support/Signals.h" #include "llvm/Support/TargetSelect.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/DynamicLibrary.h" -#include "llvm/Support/Memory.h" +#include "llvm/Support/raw_ostream.h" #include <cerrno> -#ifdef __linux__ -// These includes used by LLIMCJITMemoryManager::getPointerToNamedFunction() -// for Glibc trickery. Look comments in this function for more information. -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif -#include <fcntl.h> -#include <unistd.h> -#endif - #ifdef __CYGWIN__ #include <cygwin/version.h> #if defined(CYGWIN_VERSION_DLL_MAJOR) && CYGWIN_VERSION_DLL_MAJOR<1007 @@ -171,6 +163,23 @@ namespace { cl::init(false)); cl::opt<bool> + GenerateSoftFloatCalls("soft-float", + cl::desc("Generate software floating point library calls"), + cl::init(false)); + + cl::opt<llvm::FloatABI::ABIType> + FloatABIForCalls("float-abi", + cl::desc("Choose float ABI type"), + cl::init(FloatABI::Default), + cl::values( + clEnumValN(FloatABI::Default, "default", + "Target default float ABI type"), + clEnumValN(FloatABI::Soft, "soft", + "Soft float ABI (implied by -soft-float)"), + clEnumValN(FloatABI::Hard, "hard", + "Hard float ABI (uses FP registers)"), + clEnumValEnd)); + cl::opt<bool> // In debug builds, make this default to true. #ifdef NDEBUG #define EMIT_DEBUG false @@ -199,192 +208,6 @@ static void do_shutdown() { #endif } -// Memory manager for MCJIT -class LLIMCJITMemoryManager : public JITMemoryManager { -public: - SmallVector<sys::MemoryBlock, 16> AllocatedDataMem; - SmallVector<sys::MemoryBlock, 16> AllocatedCodeMem; - SmallVector<sys::MemoryBlock, 16> FreeCodeMem; - - LLIMCJITMemoryManager() { } - ~LLIMCJITMemoryManager(); - - virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID); - - virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID); - - virtual void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true); - - // Invalidate instruction cache for code sections. Some platforms with - // separate data cache and instruction cache require explicit cache flush, - // otherwise JIT code manipulations (like resolved relocations) will get to - // the data cache but not to the instruction cache. - virtual void invalidateInstructionCache(); - - // The MCJITMemoryManager doesn't use the following functions, so we don't - // need implement them. - virtual void setMemoryWritable() { - llvm_unreachable("Unexpected call!"); - } - virtual void setMemoryExecutable() { - llvm_unreachable("Unexpected call!"); - } - virtual void setPoisonMemory(bool poison) { - llvm_unreachable("Unexpected call!"); - } - virtual void AllocateGOT() { - llvm_unreachable("Unexpected call!"); - } - virtual uint8_t *getGOTBase() const { - llvm_unreachable("Unexpected call!"); - return 0; - } - virtual uint8_t *startFunctionBody(const Function *F, - uintptr_t &ActualSize){ - llvm_unreachable("Unexpected call!"); - return 0; - } - virtual uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize, - unsigned Alignment) { - llvm_unreachable("Unexpected call!"); - return 0; - } - virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart, - uint8_t *FunctionEnd) { - llvm_unreachable("Unexpected call!"); - } - virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) { - llvm_unreachable("Unexpected call!"); - return 0; - } - virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) { - llvm_unreachable("Unexpected call!"); - return 0; - } - virtual void deallocateFunctionBody(void *Body) { - llvm_unreachable("Unexpected call!"); - } - virtual uint8_t* startExceptionTable(const Function* F, - uintptr_t &ActualSize) { - llvm_unreachable("Unexpected call!"); - return 0; - } - virtual void endExceptionTable(const Function *F, uint8_t *TableStart, - uint8_t *TableEnd, uint8_t* FrameRegister) { - llvm_unreachable("Unexpected call!"); - } - virtual void deallocateExceptionTable(void *ET) { - llvm_unreachable("Unexpected call!"); - } -}; - -uint8_t *LLIMCJITMemoryManager::allocateDataSection(uintptr_t Size, - unsigned Alignment, - unsigned SectionID) { - if (!Alignment) - Alignment = 16; - uint8_t *Addr = (uint8_t*)calloc((Size + Alignment - 1)/Alignment, Alignment); - AllocatedDataMem.push_back(sys::MemoryBlock(Addr, Size)); - return Addr; -} - -uint8_t *LLIMCJITMemoryManager::allocateCodeSection(uintptr_t Size, - unsigned Alignment, - unsigned SectionID) { - if (!Alignment) - Alignment = 16; - unsigned NeedAllocate = Alignment * ((Size + Alignment - 1)/Alignment + 1); - uintptr_t Addr = 0; - // Look in the list of free code memory regions and use a block there if one - // is available. - for (int i = 0, e = FreeCodeMem.size(); i != e; ++i) { - sys::MemoryBlock &MB = FreeCodeMem[i]; - if (MB.size() >= NeedAllocate) { - Addr = (uintptr_t)MB.base(); - uintptr_t EndOfBlock = Addr + MB.size(); - // Align the address. - Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1); - // Store cutted free memory block. - FreeCodeMem[i] = sys::MemoryBlock((void*)(Addr + Size), - EndOfBlock - Addr - Size); - return (uint8_t*)Addr; - } - } - - // No pre-allocated free block was large enough. Allocate a new memory region. - sys::MemoryBlock MB = sys::Memory::AllocateRWX(NeedAllocate, 0, 0); - - AllocatedCodeMem.push_back(MB); - Addr = (uintptr_t)MB.base(); - uintptr_t EndOfBlock = Addr + MB.size(); - // Align the address. - Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1); - // The AllocateRWX may allocate much more memory than we need. In this case, - // we store the unused memory as a free memory block. - unsigned FreeSize = EndOfBlock-Addr-Size; - if (FreeSize > 16) - FreeCodeMem.push_back(sys::MemoryBlock((void*)(Addr + Size), FreeSize)); - - // Return aligned address - return (uint8_t*)Addr; -} - -void LLIMCJITMemoryManager::invalidateInstructionCache() { - for (int i = 0, e = AllocatedCodeMem.size(); i != e; ++i) - sys::Memory::InvalidateInstructionCache(AllocatedCodeMem[i].base(), - AllocatedCodeMem[i].size()); -} - -void *LLIMCJITMemoryManager::getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure) { -#if defined(__linux__) - //===--------------------------------------------------------------------===// - // Function stubs that are invoked instead of certain library calls - // - // Force the following functions to be linked in to anything that uses the - // JIT. This is a hack designed to work around the all-too-clever Glibc - // strategy of making these functions work differently when inlined vs. when - // not inlined, and hiding their real definitions in a separate archive file - // that the dynamic linker can't see. For more info, search for - // 'libc_nonshared.a' on Google, or read http://llvm.org/PR274. - if (Name == "stat") return (void*)(intptr_t)&stat; - if (Name == "fstat") return (void*)(intptr_t)&fstat; - if (Name == "lstat") return (void*)(intptr_t)&lstat; - if (Name == "stat64") return (void*)(intptr_t)&stat64; - if (Name == "fstat64") return (void*)(intptr_t)&fstat64; - if (Name == "lstat64") return (void*)(intptr_t)&lstat64; - if (Name == "atexit") return (void*)(intptr_t)&atexit; - if (Name == "mknod") return (void*)(intptr_t)&mknod; -#endif // __linux__ - - const char *NameStr = Name.c_str(); - void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr); - if (Ptr) return Ptr; - - // If it wasn't found and if it starts with an underscore ('_') character, - // try again without the underscore. - if (NameStr[0] == '_') { - Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1); - if (Ptr) return Ptr; - } - - if (AbortOnFailure) - report_fatal_error("Program used external function '" + Name + - "' which could not be resolved!"); - return 0; -} - -LLIMCJITMemoryManager::~LLIMCJITMemoryManager() { - for (unsigned i = 0, e = AllocatedCodeMem.size(); i != e; ++i) - sys::Memory::ReleaseRWX(AllocatedCodeMem[i]); - for (unsigned i = 0, e = AllocatedDataMem.size(); i != e; ++i) - free(AllocatedDataMem[i].base()); -} - - void layoutRemoteTargetMemory(RemoteTarget *T, RecordingMemoryManager *JMM) { // Lay out our sections in order, with all the code sections first, then // all the data sections. @@ -435,9 +258,13 @@ void layoutRemoteTargetMemory(RemoteTarget *T, RecordingMemoryManager *JMM) { EE->mapSectionAddress(const_cast<void*>(Offsets[i].first), Addr); DEBUG(dbgs() << " Mapping local: " << Offsets[i].first - << " to remote: " << format("%#018x", Addr) << "\n"); + << " to remote: " << format("%p", Addr) << "\n"); } + + // Trigger application of relocations + EE->finalizeObject(); + // Now load it all to the target. for (unsigned i = 0, e = Offsets.size(); i != e; ++i) { uint64_t Addr = RemoteAddr + Offsets[i].second; @@ -446,12 +273,12 @@ void layoutRemoteTargetMemory(RemoteTarget *T, RecordingMemoryManager *JMM) { T->loadCode(Addr, Offsets[i].first, Sizes[i]); DEBUG(dbgs() << " loading code: " << Offsets[i].first - << " to remote: " << format("%#018x", Addr) << "\n"); + << " to remote: " << format("%p", Addr) << "\n"); } else { T->loadData(Addr, Offsets[i].first, Sizes[i]); DEBUG(dbgs() << " loading data: " << Offsets[i].first - << " to remote: " << format("%#018x", Addr) << "\n"); + << " to remote: " << format("%p", Addr) << "\n"); } } @@ -471,6 +298,7 @@ int main(int argc, char **argv, char * const *envp) { // usable by the JIT. InitializeNativeTarget(); InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); cl::ParseCommandLineOptions(argc, argv, "llvm interpreter & dynamic compiler\n"); @@ -519,7 +347,7 @@ int main(int argc, char **argv, char * const *envp) { if (RemoteMCJIT) JMM = new RecordingMemoryManager(); else - JMM = new LLIMCJITMemoryManager(); + JMM = new SectionMemoryManager(); builder.setJITMemoryManager(JMM); } else { if (RemoteMCJIT) { @@ -543,15 +371,22 @@ int main(int argc, char **argv, char * const *envp) { } builder.setOptLevel(OLvl); + TargetOptions Options; + Options.UseSoftFloat = GenerateSoftFloatCalls; + if (FloatABIForCalls != FloatABI::Default) + Options.FloatABIType = FloatABIForCalls; + if (GenerateSoftFloatCalls) + FloatABIForCalls = FloatABI::Soft; + // Remote target execution doesn't handle EH or debug registration. if (!RemoteMCJIT) { - TargetOptions Options; Options.JITExceptionHandling = EnableJITExceptionHandling; Options.JITEmitDebugInfo = EmitJitDebugInfo; Options.JITEmitDebugInfoToDisk = EmitJitDebugInfoToDisk; - builder.setTargetOptions(Options); } + builder.setTargetOptions(Options); + EE = builder.create(); if (!EE) { if (!ErrorMsg.empty()) @@ -613,8 +448,13 @@ int main(int argc, char **argv, char * const *envp) { // MCJIT itself. FIXME. // // Run static constructors. - if (!RemoteMCJIT) - EE->runStaticConstructorsDestructors(false); + if (!RemoteMCJIT) { + if (UseMCJIT && !ForceInterpreter) { + // Give MCJIT a chance to apply relocations and set page permissions. + EE->finalizeObject(); + } + EE->runStaticConstructorsDestructors(false); + } if (NoLazyCompilation) { for (Module::iterator I = Mod->begin(), E = Mod->end(); I != E; ++I) { @@ -649,16 +489,19 @@ int main(int argc, char **argv, char * const *envp) { uint64_t Entry = (uint64_t)EE->getPointerToFunction(EntryFn); DEBUG(dbgs() << "Executing '" << EntryFn->getName() << "' at " - << format("%#18x", Entry) << "\n"); + << format("%p", Entry) << "\n"); if (Target.executeCode(Entry, Result)) errs() << "ERROR: " << Target.getErrorMsg() << "\n"; Target.stop(); } else { + // Trigger compilation separately so code regions that need to be + // invalidated will be known. + (void)EE->getPointerToFunction(EntryFn); // Clear instruction cache before code will be executed. if (JMM) - static_cast<LLIMCJITMemoryManager*>(JMM)->invalidateInstructionCache(); + static_cast<SectionMemoryManager*>(JMM)->invalidateInstructionCache(); // Run main. Result = EE->runFunctionAsMain(EntryFn, InputArgv, envp); |
