llvm-6502/include/llvm/ExecutionEngine/SectionMemoryManager.h
Lang Hames da62155c11 [MCJIT][Orc] Refactor RTDyldMemoryManager, weave RuntimeDyld::SymbolInfo through
MCJIT.

This patch decouples the two responsibilities of the RTDyldMemoryManager class,
memory management and symbol resolution, into two new classes:
RuntimeDyld::MemoryManager and RuntimeDyld::SymbolResolver.

The symbol resolution interface is modified slightly, from:

  uint64_t getSymbolAddress(const std::string &Name);

to:

  RuntimeDyld::SymbolInfo findSymbol(const std::string &Name);

The latter passes symbol flags along with symbol addresses, allowing RuntimeDyld
and others to reason about non-strong/non-exported symbols.


The memory management interface removes the following method:

  void notifyObjectLoaded(ExecutionEngine *EE,
                          const object::ObjectFile &) {}

as it is not related to memory management. (Note: Backwards compatibility *is*
maintained for this method in MCJIT and OrcMCJITReplacement, see below).


The RTDyldMemoryManager class remains in-tree for backwards compatibility.
It inherits directly from RuntimeDyld::SymbolResolver, and indirectly from
RuntimeDyld::MemoryManager via the new MCJITMemoryManager class, which
just subclasses RuntimeDyld::MemoryManager and reintroduces the
notifyObjectLoaded method for backwards compatibility).

The EngineBuilder class retains the existing method:

  EngineBuilder&
  setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager> mcjmm);

and includes two new methods:

  EngineBuilder&
  setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM);

  EngineBuilder&
  setSymbolResolver(std::unique_ptr<RuntimeDyld::SymbolResolver> SR);

Clients should use EITHER:

A single call to setMCJITMemoryManager with an RTDyldMemoryManager.

OR (exclusive)

One call each to each of setMemoryManager and setSymbolResolver.

This patch should be fully compatible with existing uses of RTDyldMemoryManager.
If it is not it should be considered a bug, and the patch either fixed or
reverted.

If clients find the new API to be an improvement the goal will be to deprecate
and eventually remove the RTDyldMemoryManager class in favor of the new classes.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@233509 91177308-0d34-0410-b5e6-96231b3b80d8
2015-03-30 03:37:06 +00:00

107 lines
4.4 KiB
C++

//===- SectionMemoryManager.h - Memory manager for MCJIT/RtDyld -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declaration of a section-based memory manager used by
// the MCJIT execution engine and RuntimeDyld.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H
#define LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Memory.h"
namespace llvm {
/// This is a simple memory manager which implements the methods called by
/// the RuntimeDyld class to allocate memory for section-based loading of
/// objects, usually those generated by the MCJIT execution engine.
///
/// This memory manager allocates all section memory as read-write. The
/// RuntimeDyld will copy JITed section memory into these allocated blocks
/// and perform any necessary linking and relocations.
///
/// 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::finalizeMemory
/// directly. Clients of MCJIT should call MCJIT::finalizeObject.
class SectionMemoryManager : public RTDyldMemoryManager {
SectionMemoryManager(const SectionMemoryManager&) = delete;
void operator=(const SectionMemoryManager&) = delete;
public:
SectionMemoryManager() { }
virtual ~SectionMemoryManager();
/// \brief Allocates a memory block of (at least) the given size suitable for
/// executable code.
///
/// The value of \p Alignment must be a power of two. If \p Alignment is zero
/// a default alignment of 16 will be used.
uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID,
StringRef SectionName) override;
/// \brief Allocates a memory block of (at least) the given size suitable for
/// executable code.
///
/// The value of \p Alignment must be a power of two. If \p Alignment is zero
/// a default alignment of 16 will be used.
uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID, StringRef SectionName,
bool isReadOnly) override;
/// \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. In addition, any cache coherency
/// operations needed to reliably use the memory are also performed.
///
/// \returns true if an error occurred, false otherwise.
bool finalizeMemory(std::string *ErrMsg = nullptr) override;
/// \brief 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.
///
/// This method is called from finalizeMemory.
virtual void invalidateInstructionCache();
private:
struct MemoryGroup {
SmallVector<sys::MemoryBlock, 16> AllocatedMem;
SmallVector<sys::MemoryBlock, 16> FreeMem;
sys::MemoryBlock Near;
};
uint8_t *allocateSection(MemoryGroup &MemGroup, uintptr_t Size,
unsigned Alignment);
std::error_code applyMemoryGroupPermissions(MemoryGroup &MemGroup,
unsigned Permissions);
MemoryGroup CodeMem;
MemoryGroup RWDataMem;
MemoryGroup RODataMem;
};
}
#endif // LLVM_EXECUTION_ENGINE_SECTION_MEMORY_MANAGER_H