#ifndef LLVM_EXECUTIONENGINE_JITLINK_JITLINK_H
#define LLVM_EXECUTIONENGINE_JITLINK_JITLINK_H
+#include "JITLinkMemoryManager.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Optional.h"
std::string ErrMsg;
};
-/// Manages allocations of JIT memory.
-///
-/// Instances of this class may be accessed concurrently from multiple threads
-/// and their implemetations should include any necessary synchronization.
-class JITLinkMemoryManager {
-public:
- using ProtectionFlags = sys::Memory::ProtectionFlags;
-
- class SegmentRequest {
- public:
- SegmentRequest() = default;
- SegmentRequest(size_t ContentSize, unsigned ContentAlign,
- uint64_t ZeroFillSize, unsigned ZeroFillAlign)
- : ContentSize(ContentSize), ZeroFillSize(ZeroFillSize),
- ContentAlign(ContentAlign), ZeroFillAlign(ZeroFillAlign) {}
- size_t getContentSize() const { return ContentSize; }
- unsigned getContentAlignment() const { return ContentAlign; }
- uint64_t getZeroFillSize() const { return ZeroFillSize; }
- unsigned getZeroFillAlignment() const { return ZeroFillAlign; }
-
- private:
- size_t ContentSize = 0;
- uint64_t ZeroFillSize = 0;
- unsigned ContentAlign = 0;
- unsigned ZeroFillAlign = 0;
- };
-
- using SegmentsRequestMap = DenseMap<unsigned, SegmentRequest>;
-
- /// Represents an allocation created by the memory manager.
- ///
- /// An allocation object is responsible for allocating and owning jit-linker
- /// working and target memory, and for transfering from working to target
- /// memory.
- ///
- class Allocation {
- public:
-
- using FinalizeContinuation = std::function<void(Error)>;
-
- virtual ~Allocation();
-
- /// Should return the address of linker working memory for the segment with
- /// the given protection flags.
- virtual MutableArrayRef<char> getWorkingMemory(ProtectionFlags Seg) = 0;
-
- /// Should return the final address in the target process where the segment
- /// will reside.
- virtual JITTargetAddress getTargetMemory(ProtectionFlags Seg) = 0;
-
- /// Should transfer from working memory to target memory, and release
- /// working memory.
- virtual void finalizeAsync(FinalizeContinuation OnFinalize) = 0;
-
- /// Should deallocate target memory.
- virtual Error deallocate() = 0;
- };
-
- virtual ~JITLinkMemoryManager();
-
- /// Create an Allocation object.
- virtual Expected<std::unique_ptr<Allocation>>
- allocate(const SegmentsRequestMap &Request) = 0;
-};
-
// Forward declare the Atom class.
class Atom;
AtomGraphPassList PostFixupPasses;
};
-/// A JITLinkMemoryManager that allocates in-process memory.
-class InProcessMemoryManager : public JITLinkMemoryManager {
-public:
- Expected<std::unique_ptr<Allocation>>
- allocate(const SegmentsRequestMap &Request) override;
-};
-
/// A map of symbol names to resolved addresses.
using AsyncLookupResult = DenseMap<StringRef, JITEvaluatedSymbol>;
--- /dev/null
+//===-- JITLinkMemoryManager.h - JITLink mem manager interface --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Contains the JITLinkMemoryManager interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_JITLINK_JITLINKMEMORYMANAGER_H
+#define LLVM_EXECUTIONENGINE_JITLINK_JITLINKMEMORYMANAGER_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Memory.h"
+#include <cstdint>
+
+namespace llvm {
+namespace jitlink {
+
+/// Manages allocations of JIT memory.
+///
+/// Instances of this class may be accessed concurrently from multiple threads
+/// and their implemetations should include any necessary synchronization.
+class JITLinkMemoryManager {
+public:
+ using ProtectionFlags = sys::Memory::ProtectionFlags;
+
+ class SegmentRequest {
+ public:
+ SegmentRequest() = default;
+ SegmentRequest(size_t ContentSize, unsigned ContentAlign,
+ uint64_t ZeroFillSize, unsigned ZeroFillAlign)
+ : ContentSize(ContentSize), ZeroFillSize(ZeroFillSize),
+ ContentAlign(ContentAlign), ZeroFillAlign(ZeroFillAlign) {}
+ size_t getContentSize() const { return ContentSize; }
+ unsigned getContentAlignment() const { return ContentAlign; }
+ uint64_t getZeroFillSize() const { return ZeroFillSize; }
+ unsigned getZeroFillAlignment() const { return ZeroFillAlign; }
+
+ private:
+ size_t ContentSize = 0;
+ uint64_t ZeroFillSize = 0;
+ unsigned ContentAlign = 0;
+ unsigned ZeroFillAlign = 0;
+ };
+
+ using SegmentsRequestMap = DenseMap<unsigned, SegmentRequest>;
+
+ /// Represents an allocation created by the memory manager.
+ ///
+ /// An allocation object is responsible for allocating and owning jit-linker
+ /// working and target memory, and for transfering from working to target
+ /// memory.
+ ///
+ class Allocation {
+ public:
+ using FinalizeContinuation = std::function<void(Error)>;
+
+ virtual ~Allocation();
+
+ /// Should return the address of linker working memory for the segment with
+ /// the given protection flags.
+ virtual MutableArrayRef<char> getWorkingMemory(ProtectionFlags Seg) = 0;
+
+ /// Should return the final address in the target process where the segment
+ /// will reside.
+ virtual JITTargetAddress getTargetMemory(ProtectionFlags Seg) = 0;
+
+ /// Should transfer from working memory to target memory, and release
+ /// working memory.
+ virtual void finalizeAsync(FinalizeContinuation OnFinalize) = 0;
+
+ /// Should deallocate target memory.
+ virtual Error deallocate() = 0;
+ };
+
+ virtual ~JITLinkMemoryManager();
+
+ /// Create an Allocation object.
+ virtual Expected<std::unique_ptr<Allocation>>
+ allocate(const SegmentsRequestMap &Request) = 0;
+};
+
+/// A JITLinkMemoryManager that allocates in-process memory.
+class InProcessMemoryManager : public JITLinkMemoryManager {
+public:
+ Expected<std::unique_ptr<Allocation>>
+ allocate(const SegmentsRequestMap &Request) override;
+};
+
+} // end namespace jitlink
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_JITLINK_JITLINK_H
add_llvm_library(LLVMJITLink
JITLink.cpp
JITLinkGeneric.cpp
+ JITLinkMemoryManager.cpp
EHFrameSupport.cpp
MachO.cpp
MachO_x86_64.cpp
#include "llvm/Support/Format.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Process.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
return std::error_code(GenericJITLinkError, *JITLinkerErrorCategory);
}
-JITLinkMemoryManager::~JITLinkMemoryManager() = default;
-
-JITLinkMemoryManager::Allocation::~Allocation() = default;
-
const StringRef getGenericEdgeKindName(Edge::Kind K) {
switch (K) {
case Edge::Invalid:
<< "\n";
}
-Expected<std::unique_ptr<JITLinkMemoryManager::Allocation>>
-InProcessMemoryManager::allocate(const SegmentsRequestMap &Request) {
-
- using AllocationMap = DenseMap<unsigned, sys::MemoryBlock>;
-
- // Local class for allocation.
- class IPMMAlloc : public Allocation {
- public:
- IPMMAlloc(AllocationMap SegBlocks) : SegBlocks(std::move(SegBlocks)) {}
- MutableArrayRef<char> getWorkingMemory(ProtectionFlags Seg) override {
- assert(SegBlocks.count(Seg) && "No allocation for segment");
- return {static_cast<char *>(SegBlocks[Seg].base()),
- SegBlocks[Seg].allocatedSize()};
- }
- JITTargetAddress getTargetMemory(ProtectionFlags Seg) override {
- assert(SegBlocks.count(Seg) && "No allocation for segment");
- return reinterpret_cast<JITTargetAddress>(SegBlocks[Seg].base());
- }
- void finalizeAsync(FinalizeContinuation OnFinalize) override {
- OnFinalize(applyProtections());
- }
- Error deallocate() override {
- for (auto &KV : SegBlocks)
- if (auto EC = sys::Memory::releaseMappedMemory(KV.second))
- return errorCodeToError(EC);
- return Error::success();
- }
-
- private:
- Error applyProtections() {
- for (auto &KV : SegBlocks) {
- auto &Prot = KV.first;
- auto &Block = KV.second;
- if (auto EC = sys::Memory::protectMappedMemory(Block, Prot))
- return errorCodeToError(EC);
- if (Prot & sys::Memory::MF_EXEC)
- sys::Memory::InvalidateInstructionCache(Block.base(),
- Block.allocatedSize());
- }
- return Error::success();
- }
-
- AllocationMap SegBlocks;
- };
-
- AllocationMap Blocks;
- const sys::Memory::ProtectionFlags ReadWrite =
- static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
- sys::Memory::MF_WRITE);
-
- for (auto &KV : Request) {
- auto &Seg = KV.second;
-
- if (Seg.getContentAlignment() > sys::Process::getPageSizeEstimate())
- return make_error<StringError>("Cannot request higher than page "
- "alignment",
- inconvertibleErrorCode());
-
- if (sys::Process::getPageSizeEstimate() % Seg.getContentAlignment() != 0)
- return make_error<StringError>("Page size is not a multiple of "
- "alignment",
- inconvertibleErrorCode());
-
- uint64_t ZeroFillStart =
- alignTo(Seg.getContentSize(), Seg.getZeroFillAlignment());
- uint64_t SegmentSize = ZeroFillStart + Seg.getZeroFillSize();
-
- std::error_code EC;
- auto SegMem =
- sys::Memory::allocateMappedMemory(SegmentSize, nullptr, ReadWrite, EC);
-
- if (EC)
- return errorCodeToError(EC);
-
- // Zero out the zero-fill memory.
- memset(static_cast<char *>(SegMem.base()) + ZeroFillStart, 0,
- Seg.getZeroFillSize());
-
- // Record the block for this segment.
- Blocks[KV.first] = std::move(SegMem);
- }
- return std::unique_ptr<InProcessMemoryManager::Allocation>(
- new IPMMAlloc(std::move(Blocks)));
-}
-
JITLinkContext::~JITLinkContext() {}
bool JITLinkContext::shouldAddDefaultTargetPasses(const Triple &TT) const {
--- /dev/null
+//===--- JITLinkMemoryManager.cpp - JITLinkMemoryManager implementation ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
+#include "llvm/Support/Process.h"
+
+namespace llvm {
+namespace jitlink {
+
+JITLinkMemoryManager::~JITLinkMemoryManager() = default;
+JITLinkMemoryManager::Allocation::~Allocation() = default;
+
+Expected<std::unique_ptr<JITLinkMemoryManager::Allocation>>
+InProcessMemoryManager::allocate(const SegmentsRequestMap &Request) {
+
+ using AllocationMap = DenseMap<unsigned, sys::MemoryBlock>;
+
+ // Local class for allocation.
+ class IPMMAlloc : public Allocation {
+ public:
+ IPMMAlloc(AllocationMap SegBlocks) : SegBlocks(std::move(SegBlocks)) {}
+ MutableArrayRef<char> getWorkingMemory(ProtectionFlags Seg) override {
+ assert(SegBlocks.count(Seg) && "No allocation for segment");
+ return {static_cast<char *>(SegBlocks[Seg].base()),
+ SegBlocks[Seg].allocatedSize()};
+ }
+ JITTargetAddress getTargetMemory(ProtectionFlags Seg) override {
+ assert(SegBlocks.count(Seg) && "No allocation for segment");
+ return reinterpret_cast<JITTargetAddress>(SegBlocks[Seg].base());
+ }
+ void finalizeAsync(FinalizeContinuation OnFinalize) override {
+ OnFinalize(applyProtections());
+ }
+ Error deallocate() override {
+ for (auto &KV : SegBlocks)
+ if (auto EC = sys::Memory::releaseMappedMemory(KV.second))
+ return errorCodeToError(EC);
+ return Error::success();
+ }
+
+ private:
+ Error applyProtections() {
+ for (auto &KV : SegBlocks) {
+ auto &Prot = KV.first;
+ auto &Block = KV.second;
+ if (auto EC = sys::Memory::protectMappedMemory(Block, Prot))
+ return errorCodeToError(EC);
+ if (Prot & sys::Memory::MF_EXEC)
+ sys::Memory::InvalidateInstructionCache(Block.base(),
+ Block.allocatedSize());
+ }
+ return Error::success();
+ }
+
+ AllocationMap SegBlocks;
+ };
+
+ AllocationMap Blocks;
+ const sys::Memory::ProtectionFlags ReadWrite =
+ static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
+ sys::Memory::MF_WRITE);
+
+ for (auto &KV : Request) {
+ auto &Seg = KV.second;
+
+ if (Seg.getContentAlignment() > sys::Process::getPageSizeEstimate())
+ return make_error<StringError>("Cannot request higher than page "
+ "alignment",
+ inconvertibleErrorCode());
+
+ if (sys::Process::getPageSizeEstimate() % Seg.getContentAlignment() != 0)
+ return make_error<StringError>("Page size is not a multiple of "
+ "alignment",
+ inconvertibleErrorCode());
+
+ uint64_t ZeroFillStart =
+ alignTo(Seg.getContentSize(), Seg.getZeroFillAlignment());
+ uint64_t SegmentSize = ZeroFillStart + Seg.getZeroFillSize();
+
+ std::error_code EC;
+ auto SegMem =
+ sys::Memory::allocateMappedMemory(SegmentSize, nullptr, ReadWrite, EC);
+
+ if (EC)
+ return errorCodeToError(EC);
+
+ // Zero out the zero-fill memory.
+ memset(static_cast<char *>(SegMem.base()) + ZeroFillStart, 0,
+ Seg.getZeroFillSize());
+
+ // Record the block for this segment.
+ Blocks[KV.first] = std::move(SegMem);
+ }
+ return std::unique_ptr<InProcessMemoryManager::Allocation>(
+ new IPMMAlloc(std::move(Blocks)));
+}
+
+} // end namespace jitlink
+} // end namespace llvm