diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index 0920c5d0b0d..6b62f33261e 100644 --- a/include/llvm-c/Core.h +++ b/include/llvm-c/Core.h @@ -411,7 +411,6 @@ void LLVMShutdown(); /*===-- Error handling ----------------------------------------------------===*/ -char *LLVMCreateMessage(const char *Message); void LLVMDisposeMessage(char *Message); diff --git a/include/llvm-c/ExecutionEngine.h b/include/llvm-c/ExecutionEngine.h index 50fdb6bd735..8fae77def44 100644 --- a/include/llvm-c/ExecutionEngine.h +++ b/include/llvm-c/ExecutionEngine.h @@ -40,14 +40,12 @@ void LLVMLinkInInterpreter(void); typedef struct LLVMOpaqueGenericValue *LLVMGenericValueRef; typedef struct LLVMOpaqueExecutionEngine *LLVMExecutionEngineRef; -typedef struct LLVMOpaqueMCJITMemoryManager *LLVMMCJITMemoryManagerRef; struct LLVMMCJITCompilerOptions { unsigned OptLevel; LLVMCodeModel CodeModel; LLVMBool NoFramePointerElim; LLVMBool EnableFastISel; - LLVMMCJITMemoryManagerRef MCJMM; }; /*===-- Operations on generic values --------------------------------------===*/ @@ -169,32 +167,6 @@ void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global); -/*===-- Operations on memory managers -------------------------------------===*/ - -/** - * Create a simple custom MCJIT memory manager. This memory manager can - * intercept allocations in a module-oblivious way. This will return NULL - * if any of the passed functions are NULL. - * - * @param Opaque An opaque client object to pass back to the callbacks. - * @param AllocateCodeSection Allocate a block of memory for executable code. - * @param AllocateDataSection Allocate a block of memory for data. - * @param FinalizeMemory Set page permissions and flush cache. Return 0 on - * success, 1 on error. - */ -LLVMMCJITMemoryManagerRef LLVMCreateSimpleMCJITMemoryManager( - void *Opaque, - uint8_t *(*AllocateCodeSection)(void *Opaque, - uintptr_t Size, unsigned Alignment, - unsigned SectionID), - uint8_t *(*AllocateDataSection)(void *Opaque, - uintptr_t Size, unsigned Alignment, - unsigned SectionID, LLVMBool IsReadOnly), - LLVMBool (*FinalizeMemory)(void *Opaque, char **ErrMsg), - void (*Destroy)(void *Opaque)); - -void LLVMDisposeMCJITMemoryManager(LLVMMCJITMemoryManagerRef MM); - /** * @} */ diff --git a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h deleted file mode 100644 index 99e2594f3cc..00000000000 --- a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h +++ /dev/null @@ -1,80 +0,0 @@ -//===-- RTDyldMemoryManager.cpp - Memory manager for MC-JIT -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Interface of the runtime dynamic memory manager base class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_RT_DYLD_MEMORY_MANAGER_H -#define LLVM_EXECUTIONENGINE_RT_DYLD_MEMORY_MANAGER_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/CBindingWrapping.h" -#include "llvm/Support/Memory.h" -#include "llvm-c/ExecutionEngine.h" - -namespace llvm { - -// RuntimeDyld clients often want to handle the memory management of -// what gets placed where. For JIT clients, this is the subset of -// JITMemoryManager required for dynamic loading of binaries. -// -// FIXME: As the RuntimeDyld fills out, additional routines will be needed -// for the varying types of objects to be allocated. -class RTDyldMemoryManager { - RTDyldMemoryManager(const RTDyldMemoryManager&) LLVM_DELETED_FUNCTION; - void operator=(const RTDyldMemoryManager&) LLVM_DELETED_FUNCTION; -public: - RTDyldMemoryManager() {} - virtual ~RTDyldMemoryManager(); - - /// Allocate a memory block of (at least) the given size suitable for - /// executable code. The SectionID is a unique identifier assigned by the JIT - /// engine, and optionally recorded by the memory manager to access a loaded - /// section. - virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID) = 0; - - /// Allocate a memory block of (at least) the given size suitable for data. - /// The SectionID is a unique identifier assigned by the JIT engine, and - /// optionally recorded by the memory manager to access a loaded section. - virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID, bool IsReadOnly) = 0; - - /// Register the EH frames with the runtime so that c++ exceptions work. - virtual void registerEHFrames(StringRef SectionData); - - /// This method returns the address of the specified function. As such it is - /// only useful for resolving library symbols, not code generated symbols. - /// - /// If \p AbortOnFailure is false and no function with the given name is - /// found, this function returns a null pointer. Otherwise, it prints a - /// message to stderr and aborts. - virtual void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true); - - /// This method is called when object loading is complete and section page - /// permissions can be applied. It is up to the memory manager implementation - /// to decide whether or not to act on this method. The memory manager will - /// typically allocate all sections as read-write and then apply specific - /// permissions when this method is called. Code sections cannot be executed - /// until this function has been called. In addition, any cache coherency - /// operations needed to reliably use the memory are also performed. - /// - /// Returns true if an error occurred, false otherwise. - virtual bool finalizeMemory(std::string *ErrMsg = 0) = 0; -}; - -// Create wrappers for C Binding types (see CBindingWrapping.h). -DEFINE_SIMPLE_CONVERSION_FUNCTIONS( - RTDyldMemoryManager, LLVMMCJITMemoryManagerRef) - -} // namespace llvm - -#endif // LLVM_EXECUTIONENGINE_RT_DYLD_MEMORY_MANAGER_H diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index 1a573171a45..7dba040961a 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -16,7 +16,6 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/ObjectBuffer.h" -#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/Support/Memory.h" namespace llvm { @@ -24,6 +23,58 @@ namespace llvm { class RuntimeDyldImpl; class ObjectImage; +// RuntimeDyld clients often want to handle the memory management of +// what gets placed where. For JIT clients, this is the subset of +// JITMemoryManager required for dynamic loading of binaries. +// +// FIXME: As the RuntimeDyld fills out, additional routines will be needed +// for the varying types of objects to be allocated. +class RTDyldMemoryManager { + RTDyldMemoryManager(const RTDyldMemoryManager&) LLVM_DELETED_FUNCTION; + void operator=(const RTDyldMemoryManager&) LLVM_DELETED_FUNCTION; +public: + RTDyldMemoryManager() {} + virtual ~RTDyldMemoryManager(); + + /// Allocate a memory block of (at least) the given size suitable for + /// executable code. The SectionID is a unique identifier assigned by the JIT + /// engine, and optionally recorded by the memory manager to access a loaded + /// section. + virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID) = 0; + + /// Allocate a memory block of (at least) the given size suitable for data. + /// The SectionID is a unique identifier assigned by the JIT engine, and + /// optionally recorded by the memory manager to access a loaded section. + virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, bool IsReadOnly) = 0; + + /// This method returns the address of the specified function. As such it is + /// only useful for resolving library symbols, not code generated symbols. + /// + /// If AbortOnFailure is false and no function with the given name is + /// found, this function returns a null pointer. Otherwise, it prints a + /// message to stderr and aborts. + virtual void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true) = 0; + + /// This method is called when object loading is complete and section page + /// permissions can be applied. It is up to the memory manager implementation + /// to decide whether or not to act on this method. The memory manager will + /// typically allocate all sections as read-write and then apply specific + /// permissions when this method is called. Code sections cannot be executed + /// until this function has been called. In addition, any cache coherency + /// operations needed to reliably use the memory are also performed. + /// + /// Returns true if an error occurred, false otherwise. + virtual bool finalizeMemory(std::string *ErrMsg = 0) = 0; + + /// Register the EH frames with the runtime so that c++ exceptions work. The + /// default implementation does nothing. Look at SectionMemoryManager for one + /// that uses __register_frame. + virtual void registerEHFrames(StringRef SectionData); +}; + class RuntimeDyld { RuntimeDyld(const RuntimeDyld &) LLVM_DELETED_FUNCTION; void operator=(const RuntimeDyld &) LLVM_DELETED_FUNCTION; diff --git a/include/llvm/ExecutionEngine/SectionMemoryManager.h b/include/llvm/ExecutionEngine/SectionMemoryManager.h index 6ee2a2aae59..fc8dacfcc09 100644 --- a/include/llvm/ExecutionEngine/SectionMemoryManager.h +++ b/include/llvm/ExecutionEngine/SectionMemoryManager.h @@ -73,6 +73,17 @@ public: /// \returns true if an error occurred, false otherwise. virtual bool finalizeMemory(std::string *ErrMsg = 0); + void registerEHFrames(StringRef SectionData); + + /// This method returns the address of the specified function. As such it is + /// only useful for resolving library symbols, not code generated symbols. + /// + /// If \p AbortOnFailure is false and no function with the given name is + /// found, this function returns a null pointer. Otherwise, it prints a + /// message to stderr and aborts. + virtual void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true); + /// \brief Invalidate instruction cache for code sections. /// /// Some platforms with separate data cache and instruction cache require diff --git a/lib/ExecutionEngine/CMakeLists.txt b/lib/ExecutionEngine/CMakeLists.txt index 3102c7bd582..cb11bfe93c7 100644 --- a/lib/ExecutionEngine/CMakeLists.txt +++ b/lib/ExecutionEngine/CMakeLists.txt @@ -3,7 +3,6 @@ add_llvm_library(LLVMExecutionEngine ExecutionEngine.cpp ExecutionEngineBindings.cpp - RTDyldMemoryManager.cpp TargetSelect.cpp ) diff --git a/lib/ExecutionEngine/ExecutionEngineBindings.cpp b/lib/ExecutionEngine/ExecutionEngineBindings.cpp index 88e73bf253e..f9b08a01ea7 100644 --- a/lib/ExecutionEngine/ExecutionEngineBindings.cpp +++ b/lib/ExecutionEngine/ExecutionEngineBindings.cpp @@ -15,7 +15,6 @@ #include "llvm-c/ExecutionEngine.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/GenericValue.h" -#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Module.h" #include "llvm/Support/ErrorHandling.h" @@ -158,8 +157,10 @@ LLVMBool LLVMCreateJITCompilerForModule(LLVMExecutionEngineRef *OutJIT, void LLVMInitializeMCJITCompilerOptions(LLVMMCJITCompilerOptions *PassedOptions, size_t SizeOfPassedOptions) { LLVMMCJITCompilerOptions options; - memset(&options, 0, sizeof(options)); // Most fields are zero by default. + options.OptLevel = 0; options.CodeModel = LLVMCodeModelJITDefault; + options.NoFramePointerElim = false; + options.EnableFastISel = false; memcpy(PassedOptions, &options, std::min(sizeof(options), SizeOfPassedOptions)); @@ -198,8 +199,6 @@ LLVMBool LLVMCreateMCJITCompilerForModule( .setOptLevel((CodeGenOpt::Level)options.OptLevel) .setCodeModel(unwrap(options.CodeModel)) .setTargetOptions(targetOptions); - if (options.MCJMM) - builder.setMCJITMemoryManager(unwrap(options.MCJMM)); if (ExecutionEngine *JIT = builder.create()) { *OutJIT = wrap(JIT); return 0; @@ -333,110 +332,3 @@ void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global) { return unwrap(EE)->getPointerToGlobal(unwrap(Global)); } - -/*===-- Operations on memory managers -------------------------------------===*/ - -namespace { - -struct SimpleBindingMMFunctions { - uint8_t *(*AllocateCodeSection)(void *Opaque, - uintptr_t Size, unsigned Alignment, - unsigned SectionID); - uint8_t *(*AllocateDataSection)(void *Opaque, - uintptr_t Size, unsigned Alignment, - unsigned SectionID, LLVMBool IsReadOnly); - LLVMBool (*FinalizeMemory)(void *Opaque, char **ErrMsg); - void (*Destroy)(void *Opaque); -}; - -class SimpleBindingMemoryManager : public RTDyldMemoryManager { -public: - SimpleBindingMemoryManager(const SimpleBindingMMFunctions& Functions, - void *Opaque); - virtual ~SimpleBindingMemoryManager(); - - virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID); - - virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID, - bool isReadOnly); - - virtual bool finalizeMemory(std::string *ErrMsg); - -private: - SimpleBindingMMFunctions Functions; - void *Opaque; -}; - -SimpleBindingMemoryManager::SimpleBindingMemoryManager( - const SimpleBindingMMFunctions& Functions, - void *Opaque) - : Functions(Functions), Opaque(Opaque) { - assert(Functions.AllocateCodeSection && - "No AllocateCodeSection function provided!"); - assert(Functions.AllocateDataSection && - "No AllocateDataSection function provided!"); - assert(Functions.FinalizeMemory && - "No FinalizeMemory function provided!"); - assert(Functions.Destroy && - "No Destroy function provided!"); -} - -SimpleBindingMemoryManager::~SimpleBindingMemoryManager() { - Functions.Destroy(Opaque); -} - -uint8_t *SimpleBindingMemoryManager::allocateCodeSection( - uintptr_t Size, unsigned Alignment, unsigned SectionID) { - return Functions.AllocateCodeSection(Opaque, Size, Alignment, SectionID); -} - -uint8_t *SimpleBindingMemoryManager::allocateDataSection( - uintptr_t Size, unsigned Alignment, unsigned SectionID, bool isReadOnly) { - return Functions.AllocateDataSection(Opaque, Size, Alignment, SectionID, - isReadOnly); -} - -bool SimpleBindingMemoryManager::finalizeMemory(std::string *ErrMsg) { - char *errMsgCString = 0; - bool result = Functions.FinalizeMemory(Opaque, &errMsgCString); - assert((result || !errMsgCString) && - "Did not expect an error message if FinalizeMemory succeeded"); - if (errMsgCString) { - if (ErrMsg) - *ErrMsg = errMsgCString; - free(errMsgCString); - } - return result; -} - -} // anonymous namespace - -LLVMMCJITMemoryManagerRef LLVMCreateSimpleMCJITMemoryManager( - void *Opaque, - uint8_t *(*AllocateCodeSection)(void *Opaque, - uintptr_t Size, unsigned Alignment, - unsigned SectionID), - uint8_t *(*AllocateDataSection)(void *Opaque, - uintptr_t Size, unsigned Alignment, - unsigned SectionID, LLVMBool IsReadOnly), - LLVMBool (*FinalizeMemory)(void *Opaque, char **ErrMsg), - void (*Destroy)(void *Opaque)) { - - if (!AllocateCodeSection || !AllocateDataSection || !FinalizeMemory || - !Destroy) - return NULL; - - SimpleBindingMMFunctions functions; - functions.AllocateCodeSection = AllocateCodeSection; - functions.AllocateDataSection = AllocateDataSection; - functions.FinalizeMemory = FinalizeMemory; - functions.Destroy = Destroy; - return wrap(new SimpleBindingMemoryManager(functions, Opaque)); -} - -void LLVMDisposeMCJITMemoryManager(LLVMMCJITMemoryManagerRef MM) { - delete unwrap(MM); -} - diff --git a/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp b/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp index 397426afd48..1bb0103f08e 100644 --- a/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp +++ b/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp @@ -14,6 +14,7 @@ #include "llvm/Config/config.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/MathExtras.h" #ifdef __linux__ @@ -145,6 +146,38 @@ bool SectionMemoryManager::finalizeMemory(std::string *ErrMsg) return false; } +// Determine whether we can register EH tables. +#if (defined(__GNUC__) && !defined(__ARM_EABI__) && \ + !defined(__USING_SJLJ_EXCEPTIONS__)) +#define HAVE_EHTABLE_SUPPORT 1 +#else +#define HAVE_EHTABLE_SUPPORT 0 +#endif + +#if HAVE_EHTABLE_SUPPORT +extern "C" void __register_frame(void*); + +static const char *processFDE(const char *Entry) { + const char *P = Entry; + uint32_t Length = *((uint32_t*)P); + P += 4; + uint32_t Offset = *((uint32_t*)P); + if (Offset != 0) + __register_frame((void*)Entry); + return P + Length; +} +#endif + +void SectionMemoryManager::registerEHFrames(StringRef SectionData) { +#if HAVE_EHTABLE_SUPPORT + const char *P = SectionData.data(); + const char *End = SectionData.data() + SectionData.size(); + do { + P = processFDE(P); + } while(P != End); +#endif +} + error_code SectionMemoryManager::applyMemoryGroupPermissions(MemoryGroup &MemGroup, unsigned Permissions) { @@ -166,6 +199,57 @@ void SectionMemoryManager::invalidateInstructionCache() { CodeMem.AllocatedMem[i].size()); } +static int jit_noop() { + return 0; +} + +void *SectionMemoryManager::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__ + + // 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; + + // 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; +} + SectionMemoryManager::~SectionMemoryManager() { for (unsigned i = 0, e = CodeMem.AllocatedMem.size(); i != e; ++i) sys::Memory::releaseMappedMemory(CodeMem.AllocatedMem[i]); diff --git a/lib/ExecutionEngine/RTDyldMemoryManager.cpp b/lib/ExecutionEngine/RTDyldMemoryManager.cpp deleted file mode 100644 index 9d80281ccbf..00000000000 --- a/lib/ExecutionEngine/RTDyldMemoryManager.cpp +++ /dev/null @@ -1,105 +0,0 @@ -//===-- RTDyldMemoryManager.cpp - Memory manager for MC-JIT -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Implementation of the runtime dynamic memory manager base class. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" -#include "llvm/Support/DynamicLibrary.h" -#include "llvm/Support/ErrorHandling.h" - -namespace llvm { - -RTDyldMemoryManager::~RTDyldMemoryManager() {} - -// Determine whether we can register EH tables. -#if (defined(__GNUC__) && !defined(__ARM_EABI__) && \ - !defined(__USING_SJLJ_EXCEPTIONS__)) -#define HAVE_EHTABLE_SUPPORT 1 -#else -#define HAVE_EHTABLE_SUPPORT 0 -#endif - -#if HAVE_EHTABLE_SUPPORT -extern "C" void __register_frame(void*); - -static const char *processFDE(const char *Entry) { - const char *P = Entry; - uint32_t Length = *((uint32_t*)P); - P += 4; - uint32_t Offset = *((uint32_t*)P); - if (Offset != 0) - __register_frame((void*)Entry); - return P + Length; -} -#endif - -void RTDyldMemoryManager::registerEHFrames(StringRef SectionData) { -#if HAVE_EHTABLE_SUPPORT - const char *P = SectionData.data(); - const char *End = SectionData.data() + SectionData.size(); - do { - P = processFDE(P); - } while(P != End); -#endif -} - -static int jit_noop() { - return 0; -} - -void *RTDyldMemoryManager::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__ - - // 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; - - // 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; -} - -} // namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index 844f1c2931c..a08b508a8df 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -24,6 +24,8 @@ using namespace llvm; using namespace llvm::object; // Empty out-of-line virtual destructor as the key function. +RTDyldMemoryManager::~RTDyldMemoryManager() {} +void RTDyldMemoryManager::registerEHFrames(StringRef SectionData) {} RuntimeDyldImpl::~RuntimeDyldImpl() {} namespace llvm { diff --git a/lib/IR/Core.cpp b/lib/IR/Core.cpp index 66610bd7f5b..889d5742906 100644 --- a/lib/IR/Core.cpp +++ b/lib/IR/Core.cpp @@ -58,10 +58,6 @@ void LLVMShutdown() { /*===-- Error handling ----------------------------------------------------===*/ -char *LLVMCreateMessage(const char *Message) { - return strdup(Message); -} - void LLVMDisposeMessage(char *Message) { free(Message); } diff --git a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp index c434a7c0b25..e49af05a235 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp @@ -17,46 +17,12 @@ #include "llvm-c/ExecutionEngine.h" #include "llvm-c/Target.h" #include "llvm-c/Transforms/Scalar.h" -#include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/Support/Host.h" #include "MCJITTestAPICommon.h" #include "gtest/gtest.h" using namespace llvm; -static bool didCallAllocateCodeSection; - -static uint8_t *roundTripAllocateCodeSection(void *object, uintptr_t size, - unsigned alignment, - unsigned sectionID) { - didCallAllocateCodeSection = true; - return static_cast(object)->allocateCodeSection( - size, alignment, sectionID); -} - -static uint8_t *roundTripAllocateDataSection(void *object, uintptr_t size, - unsigned alignment, - unsigned sectionID, - LLVMBool isReadOnly) { - return static_cast(object)->allocateDataSection( - size, alignment, sectionID, isReadOnly); -} - -static LLVMBool roundTripFinalizeMemory(void *object, char **errMsg) { - std::string errMsgString; - bool result = - static_cast(object)->finalizeMemory(&errMsgString); - if (result) { - *errMsg = LLVMCreateMessage(errMsgString.c_str()); - return 1; - } - return 0; -} - -static void roundTripDestroy(void *object) { - delete static_cast(object); -} - class MCJITCAPITest : public testing::Test, public MCJITTestAPICommon { protected: MCJITCAPITest() { @@ -80,113 +46,60 @@ protected: // that they will fail the MCJIT C API tests. UnsupportedOSs.push_back(Triple::Cygwin); } - - virtual void SetUp() { - didCallAllocateCodeSection = false; - Module = 0; - Function = 0; - Engine = 0; - Error = 0; - } - - virtual void TearDown() { - if (Engine) - LLVMDisposeExecutionEngine(Engine); - else if (Module) - LLVMDisposeModule(Module); - } - - void buildSimpleFunction() { - Module = LLVMModuleCreateWithName("simple_module"); - - LLVMSetTarget(Module, HostTriple.c_str()); - - Function = LLVMAddFunction( - Module, "simple_function", LLVMFunctionType(LLVMInt32Type(), 0, 0, 0)); - LLVMSetFunctionCallConv(Function, LLVMCCallConv); - - LLVMBasicBlockRef entry = LLVMAppendBasicBlock(Function, "entry"); - LLVMBuilderRef builder = LLVMCreateBuilder(); - LLVMPositionBuilderAtEnd(builder, entry); - LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0)); - - LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error); - LLVMDisposeMessage(Error); - - LLVMDisposeBuilder(builder); - } - - void buildMCJITOptions() { - LLVMInitializeMCJITCompilerOptions(&Options, sizeof(Options)); - Options.OptLevel = 2; - - // Just ensure that this field still exists. - Options.NoFramePointerElim = false; - } - - void useRoundTripSectionMemoryManager() { - Options.MCJMM = LLVMCreateSimpleMCJITMemoryManager( - new SectionMemoryManager(), - roundTripAllocateCodeSection, - roundTripAllocateDataSection, - roundTripFinalizeMemory, - roundTripDestroy); - } - - void buildMCJITEngine() { - ASSERT_EQ( - 0, LLVMCreateMCJITCompilerForModule(&Engine, Module, &Options, - sizeof(Options), &Error)); - } - - void buildAndRunPasses() { - LLVMPassManagerRef pass = LLVMCreatePassManager(); - LLVMAddTargetData(LLVMGetExecutionEngineTargetData(Engine), pass); - LLVMAddConstantPropagationPass(pass); - LLVMAddInstructionCombiningPass(pass); - LLVMRunPassManager(pass, Module); - LLVMDisposePassManager(pass); - } - - LLVMModuleRef Module; - LLVMValueRef Function; - LLVMMCJITCompilerOptions Options; - LLVMExecutionEngineRef Engine; - char *Error; }; TEST_F(MCJITCAPITest, simple_function) { SKIP_UNSUPPORTED_PLATFORM; - buildSimpleFunction(); - buildMCJITOptions(); - buildMCJITEngine(); - buildAndRunPasses(); + char *error = 0; + + // Creates a function that returns 42, compiles it, and runs it. + + LLVMModuleRef module = LLVMModuleCreateWithName("simple_module"); + + LLVMSetTarget(module, HostTriple.c_str()); + + LLVMValueRef function = LLVMAddFunction( + module, "simple_function", LLVMFunctionType(LLVMInt32Type(), 0, 0, 0)); + LLVMSetFunctionCallConv(function, LLVMCCallConv); + + LLVMBasicBlockRef entry = LLVMAppendBasicBlock(function, "entry"); + LLVMBuilderRef builder = LLVMCreateBuilder(); + LLVMPositionBuilderAtEnd(builder, entry); + LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0)); + + LLVMVerifyModule(module, LLVMAbortProcessAction, &error); + LLVMDisposeMessage(error); + + LLVMDisposeBuilder(builder); + + LLVMMCJITCompilerOptions options; + LLVMInitializeMCJITCompilerOptions(&options, sizeof(options)); + options.OptLevel = 2; + + // Just ensure that this field still exists. + options.NoFramePointerElim = false; + + LLVMExecutionEngineRef engine; + ASSERT_EQ( + 0, LLVMCreateMCJITCompilerForModule(&engine, module, &options, + sizeof(options), &error)); + + LLVMPassManagerRef pass = LLVMCreatePassManager(); + LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), pass); + LLVMAddConstantPropagationPass(pass); + LLVMAddInstructionCombiningPass(pass); + LLVMRunPassManager(pass, module); + LLVMDisposePassManager(pass); union { void *raw; int (*usable)(); } functionPointer; - functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function); + functionPointer.raw = LLVMGetPointerToGlobal(engine, function); EXPECT_EQ(42, functionPointer.usable()); + + LLVMDisposeExecutionEngine(engine); } -TEST_F(MCJITCAPITest, custom_memory_manager) { - SKIP_UNSUPPORTED_PLATFORM; - - buildSimpleFunction(); - buildMCJITOptions(); - useRoundTripSectionMemoryManager(); - buildMCJITEngine(); - buildAndRunPasses(); - - union { - void *raw; - int (*usable)(); - } functionPointer; - functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function); - - EXPECT_EQ(42, functionPointer.usable()); - EXPECT_TRUE(didCallAllocateCodeSection); -}