diff options
Diffstat (limited to 'include/llvm/ExecutionEngine')
-rw-r--r-- | include/llvm/ExecutionEngine/ExecutionEngine.h | 153 | ||||
-rw-r--r-- | include/llvm/ExecutionEngine/JITMemoryManager.h | 16 | ||||
-rw-r--r-- | include/llvm/ExecutionEngine/ObjectBuffer.h | 3 | ||||
-rw-r--r-- | include/llvm/ExecutionEngine/ObjectCache.h | 25 | ||||
-rw-r--r-- | include/llvm/ExecutionEngine/ObjectImage.h | 1 | ||||
-rw-r--r-- | include/llvm/ExecutionEngine/RTDyldMemoryManager.h | 112 | ||||
-rw-r--r-- | include/llvm/ExecutionEngine/RuntimeDyld.h | 62 | ||||
-rw-r--r-- | include/llvm/ExecutionEngine/SectionMemoryManager.h | 90 |
8 files changed, 237 insertions, 225 deletions
diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index bbaebc6f906b3..233084dd50fad 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -16,7 +16,6 @@ #define LLVM_EXECUTIONENGINE_EXECUTIONENGINE_H #include "llvm-c/ExecutionEngine.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/ValueMap.h" @@ -34,6 +33,7 @@ namespace llvm { struct GenericValue; class Constant; +class DataLayout; class ExecutionEngine; class Function; class GlobalVariable; @@ -44,7 +44,7 @@ class MachineCodeInfo; class Module; class MutexGuard; class ObjectCache; -class DataLayout; +class RTDyldMemoryManager; class Triple; class Type; @@ -142,7 +142,7 @@ protected: static ExecutionEngine *(*MCJITCtor)( Module *M, std::string *ErrorStr, - JITMemoryManager *JMM, + RTDyldMemoryManager *MCJMM, bool GVsWithCode, TargetMachine *TM); static ExecutionEngine *(*InterpCtor)(Module *M, std::string *ErrorStr); @@ -152,17 +152,8 @@ protected: /// abort. void *(*LazyFunctionCreator)(const std::string &); - /// ExceptionTableRegister - If Exception Handling is set, the JIT will - /// register dwarf tables with this function. - typedef void (*EERegisterFn)(void*); - EERegisterFn ExceptionTableRegister; - EERegisterFn ExceptionTableDeregister; - /// This maps functions to their exception tables frames. - DenseMap<const Function*, void*> AllExceptionTables; - - public: - /// lock - This lock protects the ExecutionEngine, JIT, JITResolver and + /// lock - This lock protects the ExecutionEngine, MCJIT, JIT, JITResolver and /// JITEmitter classes. It must be held while changing the internal state of /// any of those classes. sys::Mutex lock; @@ -224,7 +215,7 @@ public: /// FindFunctionNamed - Search all of the active modules to find the one that /// defines FnName. This is very slow operation and shouldn't be used for /// general code. - Function *FindFunctionNamed(const char *FnName); + virtual Function *FindFunctionNamed(const char *FnName); /// runFunction - Execute the specified function with the specified arguments, /// and return the result. @@ -239,6 +230,11 @@ public: /// found, this function silently returns a null pointer. Otherwise, /// it prints a message to stderr and aborts. /// + /// This function is deprecated for the MCJIT execution engine. + /// + /// FIXME: the JIT and MCJIT interfaces should be disentangled or united + /// again, if possible. + /// virtual void *getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure = true) = 0; @@ -251,18 +247,38 @@ public: "EE!"); } - // finalizeObject - This method should be called after sections within an - // object have been relocated using mapSectionAddress. When this method is - // called the MCJIT execution engine will reapply relocations for a loaded - // object. This method has no effect for the legacy JIT engine or the - // interpeter. + /// generateCodeForModule - Run code generationen for the specified module and + /// load it into memory. + /// + /// When this function has completed, all code and data for the specified + /// module, and any module on which this module depends, will be generated + /// and loaded into memory, but relocations will not yet have been applied + /// and all memory will be readable and writable but not executable. + /// + /// This function is primarily useful when generating code for an external + /// target, allowing the client an opportunity to remap section addresses + /// before relocations are applied. Clients that intend to execute code + /// locally can use the getFunctionAddress call, which will generate code + /// and apply final preparations all in one step. + /// + /// This method has no effect for the legacy JIT engine or the interpeter. + virtual void generateCodeForModule(Module *M) {} + + /// finalizeObject - ensure the module is fully processed and is usable. + /// + /// It is the user-level function for completing the process of making the + /// object usable for execution. It should be called after sections within an + /// object have been relocated using mapSectionAddress. When this method is + /// called the MCJIT execution engine will reapply relocations for a loaded + /// object. This method has no effect for the legacy JIT engine or the + /// interpeter. virtual void finalizeObject() {} /// runStaticConstructorsDestructors - This method is used to execute all of /// the static constructors or destructors for a program. /// /// \param isDtors - Run the destructors instead of constructors. - void runStaticConstructorsDestructors(bool isDtors); + virtual void runStaticConstructorsDestructors(bool isDtors); /// runStaticConstructorsDestructors - This method is used to execute all of /// the static constructors or destructors for a particular module. @@ -303,10 +319,16 @@ public: /// getPointerToGlobalIfAvailable - This returns the address of the specified /// global value if it is has already been codegen'd, otherwise it returns /// null. + /// + /// This function is deprecated for the MCJIT execution engine. It doesn't + /// seem to be needed in that case, but an equivalent can be added if it is. void *getPointerToGlobalIfAvailable(const GlobalValue *GV); /// getPointerToGlobal - This returns the address of the specified global /// value. This may involve code generation if it's a function. + /// + /// This function is deprecated for the MCJIT execution engine. Use + /// getGlobalValueAddress instead. void *getPointerToGlobal(const GlobalValue *GV); /// getPointerToFunction - The different EE's represent function bodies in @@ -314,22 +336,48 @@ public: /// pointer should look like. When F is destroyed, the ExecutionEngine will /// remove its global mapping and free any machine code. Be sure no threads /// are running inside F when that happens. + /// + /// This function is deprecated for the MCJIT execution engine. Use + /// getFunctionAddress instead. virtual void *getPointerToFunction(Function *F) = 0; /// getPointerToBasicBlock - The different EE's represent basic blocks in /// different ways. Return the representation for a blockaddress of the /// specified block. + /// + /// This function will not be implemented for the MCJIT execution engine. virtual void *getPointerToBasicBlock(BasicBlock *BB) = 0; /// getPointerToFunctionOrStub - If the specified function has been /// code-gen'd, return a pointer to the function. If not, compile it, or use /// a stub to implement lazy compilation if available. See /// getPointerToFunction for the requirements on destroying F. + /// + /// This function is deprecated for the MCJIT execution engine. Use + /// getFunctionAddress instead. virtual void *getPointerToFunctionOrStub(Function *F) { // Default implementation, just codegen the function. return getPointerToFunction(F); } + /// getGlobalValueAddress - Return the address of the specified global + /// value. This may involve code generation. + /// + /// This function should not be called with the JIT or interpreter engines. + virtual uint64_t getGlobalValueAddress(const std::string &Name) { + // Default implementation for JIT and interpreter. MCJIT will override this. + // JIT and interpreter clients should use getPointerToGlobal instead. + return 0; + } + + /// getFunctionAddress - Return the address of the specified function. + /// This may involve code generation. + virtual uint64_t getFunctionAddress(const std::string &Name) { + // Default implementation for JIT and interpreter. MCJIT will override this. + // JIT and interpreter clients should use getPointerToFunction instead. + return 0; + } + // The JIT overrides a version that actually does this. virtual void runJITOnFunction(Function *, MachineCodeInfo * = 0) { } @@ -362,6 +410,9 @@ public: /// getOrEmitGlobalVariable - Return the address of the specified global /// variable, possibly emitting it to memory if needed. This is used by the /// Emitter. + /// + /// This function is deprecated for the MCJIT execution engine. Use + /// getGlobalValueAddress instead. virtual void *getOrEmitGlobalVariable(const GlobalVariable *GV) { return getPointerToGlobal((const GlobalValue *)GV); } @@ -431,41 +482,6 @@ public: LazyFunctionCreator = P; } - /// InstallExceptionTableRegister - The JIT will use the given function - /// to register the exception tables it generates. - void InstallExceptionTableRegister(EERegisterFn F) { - ExceptionTableRegister = F; - } - void InstallExceptionTableDeregister(EERegisterFn F) { - ExceptionTableDeregister = F; - } - - /// RegisterTable - Registers the given pointer as an exception table. It - /// uses the ExceptionTableRegister function. - void RegisterTable(const Function *fn, void* res) { - if (ExceptionTableRegister) { - ExceptionTableRegister(res); - AllExceptionTables[fn] = res; - } - } - - /// DeregisterTable - Deregisters the exception frame previously registered - /// for the given function. - void DeregisterTable(const Function *Fn) { - if (ExceptionTableDeregister) { - DenseMap<const Function*, void*>::iterator frame = - AllExceptionTables.find(Fn); - if(frame != AllExceptionTables.end()) { - ExceptionTableDeregister(frame->second); - AllExceptionTables.erase(frame); - } - } - } - - /// DeregisterAllTables - Deregisters all previously registered pointers to an - /// exception tables. It uses the ExceptionTableoDeregister function. - void DeregisterAllTables(); - protected: explicit ExecutionEngine(Module *M); @@ -496,6 +512,7 @@ private: EngineKind::Kind WhichEngine; std::string *ErrorStr; CodeGenOpt::Level OptLevel; + RTDyldMemoryManager *MCJMM; JITMemoryManager *JMM; bool AllocateGVsWithCode; TargetOptions Options; @@ -511,6 +528,7 @@ private: WhichEngine = EngineKind::Either; ErrorStr = NULL; OptLevel = CodeGenOpt::Default; + MCJMM = NULL; JMM = NULL; Options = TargetOptions(); AllocateGVsWithCode = false; @@ -532,12 +550,29 @@ public: WhichEngine = w; return *this; } + + /// setMCJITMemoryManager - Sets the MCJIT memory manager to use. This allows + /// clients to customize their memory allocation policies for the MCJIT. This + /// is only appropriate for the MCJIT; setting this and configuring the builder + /// to create anything other than MCJIT will cause a runtime error. If create() + /// is called and is successful, the created engine takes ownership of the + /// memory manager. This option defaults to NULL. Using this option nullifies + /// the setJITMemoryManager() option. + EngineBuilder &setMCJITMemoryManager(RTDyldMemoryManager *mcjmm) { + MCJMM = mcjmm; + JMM = NULL; + return *this; + } - /// setJITMemoryManager - Sets the memory manager to use. This allows - /// clients to customize their memory allocation policies. If create() is - /// called and is successful, the created engine takes ownership of the - /// memory manager. This option defaults to NULL. + /// setJITMemoryManager - Sets the JIT memory manager to use. This allows + /// clients to customize their memory allocation policies. This is only + /// appropriate for either JIT or MCJIT; setting this and configuring the + /// builder to create an interpreter will cause a runtime error. If create() + /// is called and is successful, the created engine takes ownership of the + /// memory manager. This option defaults to NULL. This option overrides + /// setMCJITMemoryManager() as well. EngineBuilder &setJITMemoryManager(JITMemoryManager *jmm) { + MCJMM = NULL; JMM = jmm; return *this; } diff --git a/include/llvm/ExecutionEngine/JITMemoryManager.h b/include/llvm/ExecutionEngine/JITMemoryManager.h index 714a98055a42a..b22d899c9fec3 100644 --- a/include/llvm/ExecutionEngine/JITMemoryManager.h +++ b/include/llvm/ExecutionEngine/JITMemoryManager.h @@ -115,22 +115,6 @@ public: /// emitting a function. virtual void deallocateFunctionBody(void *Body) = 0; - /// startExceptionTable - When we finished JITing the function, if exception - /// handling is set, we emit the exception table. - virtual uint8_t* startExceptionTable(const Function* F, - uintptr_t &ActualSize) = 0; - - /// endExceptionTable - This method is called when the JIT is done emitting - /// the exception table. - virtual void endExceptionTable(const Function *F, uint8_t *TableStart, - uint8_t *TableEnd, uint8_t* FrameRegister) = 0; - - /// deallocateExceptionTable - Free the specified exception table's memory. - /// The argument must be the return value from a call to startExceptionTable() - /// that hasn't been deallocated yet. This is never called when the JIT is - /// currently emitting an exception table. - virtual void deallocateExceptionTable(void *ET) = 0; - /// CheckInvariants - For testing only. Return true if all internal /// invariants are preserved, or return false and set ErrorStr to a helpful /// error message. diff --git a/include/llvm/ExecutionEngine/ObjectBuffer.h b/include/llvm/ExecutionEngine/ObjectBuffer.h index 96a48b28b8477..af2a9263ff120 100644 --- a/include/llvm/ExecutionEngine/ObjectBuffer.h +++ b/include/llvm/ExecutionEngine/ObjectBuffer.h @@ -30,6 +30,7 @@ namespace llvm { /// ObjectFile) as needed, but the MemoryBuffer instance returned does not own the /// actual memory it points to. class ObjectBuffer { + virtual void anchor(); public: ObjectBuffer() {} ObjectBuffer(MemoryBuffer* Buf) : Buffer(Buf) {} @@ -44,6 +45,7 @@ public: const char *getBufferStart() const { return Buffer->getBufferStart(); } size_t getBufferSize() const { return Buffer->getBufferSize(); } + StringRef getBuffer() const { return Buffer->getBuffer(); } protected: // The memory contained in an ObjectBuffer @@ -55,6 +57,7 @@ protected: /// while providing a common ObjectBuffer interface for access to the /// memory once the object has been generated. class ObjectBufferStream : public ObjectBuffer { + virtual void anchor(); public: ObjectBufferStream() : OS(SV) {} virtual ~ObjectBufferStream() {} diff --git a/include/llvm/ExecutionEngine/ObjectCache.h b/include/llvm/ExecutionEngine/ObjectCache.h index 0bee86161bb7a..d1849dfc3bf65 100644 --- a/include/llvm/ExecutionEngine/ObjectCache.h +++ b/include/llvm/ExecutionEngine/ObjectCache.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIB_EXECUTIONENGINE_OBJECTCACHE_H -#define LLVM_LIB_EXECUTIONENGINE_OBJECTCACHE_H +#ifndef LLVM_EXECUTIONENGINE_OBJECTCACHE_H +#define LLVM_EXECUTIONENGINE_OBJECTCACHE_H #include "llvm/Support/MemoryBuffer.h" @@ -20,6 +20,7 @@ class Module; /// ExecutionEngine for the purpose of avoiding compilation for Modules that /// have already been compiled and an object file is available. class ObjectCache { + virtual void anchor(); public: ObjectCache() { } @@ -30,23 +31,9 @@ public: /// getObjectCopy - Returns a pointer to a newly allocated MemoryBuffer that /// contains the object which corresponds with Module M, or 0 if an object is - /// not available. The caller owns the MemoryBuffer returned by this function. - MemoryBuffer* getObjectCopy(const Module* M) { - const MemoryBuffer* Obj = getObject(M); - if (Obj) - return MemoryBuffer::getMemBufferCopy(Obj->getBuffer()); - else - return 0; - } - -protected: - /// getObject - Returns a pointer to a MemoryBuffer that contains an object - /// that corresponds with Module M, or 0 if an object is not available. - /// The pointer returned by this function is not suitable for loading because - /// the memory is read-only and owned by the ObjectCache. To retrieve an - /// owning pointer to a MemoryBuffer (which is suitable for calling - /// RuntimeDyld::loadObject() with) use getObjectCopy() instead. - virtual const MemoryBuffer* getObject(const Module* M) = 0; + /// not available. The caller owns both the MemoryBuffer returned by this + /// and the memory it references. + virtual MemoryBuffer* getObject(const Module* M) = 0; }; } diff --git a/include/llvm/ExecutionEngine/ObjectImage.h b/include/llvm/ExecutionEngine/ObjectImage.h index 9fddca7e33c85..076f4b1146c10 100644 --- a/include/llvm/ExecutionEngine/ObjectImage.h +++ b/include/llvm/ExecutionEngine/ObjectImage.h @@ -25,6 +25,7 @@ namespace llvm { class ObjectImage { ObjectImage() LLVM_DELETED_FUNCTION; ObjectImage(const ObjectImage &other) LLVM_DELETED_FUNCTION; + virtual void anchor(); protected: OwningPtr<ObjectBuffer> Buffer; diff --git a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h new file mode 100644 index 0000000000000..3ad2e5022da38 --- /dev/null +++ b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h @@ -0,0 +1,112 @@ +//===-- 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 { + +class ExecutionEngine; +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, + StringRef SectionName) = 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, + StringRef SectionName, bool IsReadOnly) = 0; + + /// Register the EH frames with the runtime so that c++ exceptions work. + /// + /// \p Addr parameter provides the local address of the EH frame section + /// data, while \p LoadAddr provides the address of the data in the target + /// address space. If the section has not been remapped (which will usually + /// be the case for local execution) these two values will be the same. + virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size); + + virtual void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size); + + /// This method returns the address of the specified function or variable. + /// It is used to resolve symbols during module linking. + virtual uint64_t getSymbolAddress(const std::string &Name); + + /// 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. + /// + /// This function is deprecated for memory managers to be used with + /// MCJIT or RuntimeDyld. Use getSymbolAddress instead. + virtual void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true); + + /// This method is called after an object has been loaded into memory but + /// before relocations are applied to the loaded sections. The object load + /// may have been initiated by MCJIT to resolve an external symbol for another + /// object that is being finalized. In that case, the object about which + /// the memory manager is being notified will be finalized immediately after + /// the memory manager returns from this call. + /// + /// Memory managers which are preparing code for execution in an external + /// address space can use this call to remap the section addresses for the + /// newly loaded object. + virtual void notifyObjectLoaded(ExecutionEngine *EE, + const ObjectImage *) {} + + /// 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 c6c126c6e242e..b8324387bbe6d 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -16,6 +16,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/ObjectBuffer.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/Support/Memory.h" namespace llvm { @@ -23,56 +24,6 @@ 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. - /// - /// Returns true if an error occurred, false otherwise. - virtual bool applyPermissions(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; @@ -113,9 +64,16 @@ public: /// This is the address which will be used for relocation resolution. void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress); - StringRef getErrorString(); + /// Register any EH frame sections that have been loaded but not previously + /// registered with the memory manager. Note, RuntimeDyld is responsible + /// for identifying the EH frame and calling the memory manager with the + /// EH frame section data. However, the memory manager itself will handle + /// the actual target-specific EH frame registration. + void registerEHFrames(); + + void deregisterEHFrames(); - StringRef getEHFrameSection(); + StringRef getErrorString(); }; } // end namespace llvm diff --git a/include/llvm/ExecutionEngine/SectionMemoryManager.h b/include/llvm/ExecutionEngine/SectionMemoryManager.h index 84a4e08cbb5c0..fd6e41f91ffb4 100644 --- a/include/llvm/ExecutionEngine/SectionMemoryManager.h +++ b/include/llvm/ExecutionEngine/SectionMemoryManager.h @@ -16,7 +16,7 @@ #define LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H #include "llvm/ADT/SmallVector.h" -#include "llvm/ExecutionEngine/JITMemoryManager.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Memory.h" @@ -33,9 +33,9 @@ namespace llvm { /// Any client using this memory manager MUST ensure that section-specific /// page permissions have been applied before attempting to execute functions /// in the JITed object. Permissions can be applied either by calling -/// MCJIT::finalizeObject or by calling SectionMemoryManager::applyPermissions +/// MCJIT::finalizeObject or by calling SectionMemoryManager::finalizeMemory /// directly. Clients of MCJIT should call MCJIT::finalizeObject. -class SectionMemoryManager : public JITMemoryManager { +class SectionMemoryManager : public RTDyldMemoryManager { SectionMemoryManager(const SectionMemoryManager&) LLVM_DELETED_FUNCTION; void operator=(const SectionMemoryManager&) LLVM_DELETED_FUNCTION; @@ -49,7 +49,8 @@ public: /// The value of \p Alignment must be a power of two. If \p Alignment is zero /// a default alignment of 16 will be used. virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID); + unsigned SectionID, + StringRef SectionName); /// \brief Allocates a memory block of (at least) the given size suitable for /// executable code. @@ -58,30 +59,21 @@ public: /// a default alignment of 16 will be used. virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, + StringRef SectionName, bool isReadOnly); - /// \brief Applies section-specific memory permissions. + /// \brief Update section-specific memory permissions and other attributes. /// /// 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. + /// 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 applyPermissions(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); + virtual bool finalizeMemory(std::string *ErrMsg = 0); /// \brief Invalidate instruction cache for code sections. /// @@ -89,7 +81,7 @@ public: /// explicit cache flush, otherwise JIT code manipulations (like resolved /// relocations) will get to the data cache but not to the instruction cache. /// - /// This method is called from applyPermissions. + /// This method is called from finalizeMemory. virtual void invalidateInstructionCache(); private: @@ -108,66 +100,6 @@ private: MemoryGroup CodeMem; MemoryGroup RWDataMem; MemoryGroup RODataMem; - -public: - /// - /// Functions below are not used by MCJIT or RuntimeDyld, but must be - /// implemented because they are declared as pure virtuals in the base class. - /// - - 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!"); - } }; } |