1//===-- JITLinkMemoryManager.h - JITLink mem manager interface --*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Contains the JITLinkMemoryManager interface.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_EXECUTIONENGINE_JITLINK_JITLINKMEMORYMANAGER_H
14#define LLVM_EXECUTIONENGINE_JITLINK_JITLINKMEMORYMANAGER_H
15
16#include "llvm/ADT/DenseMap.h"
17#include "llvm/ExecutionEngine/JITLink/JITLinkDylib.h"
18#include "llvm/ExecutionEngine/JITSymbol.h"
19#include "llvm/Support/Error.h"
20#include "llvm/Support/MSVCErrorWorkarounds.h"
21#include "llvm/Support/Memory.h"
22
23#include <cstdint>
24#include <future>
25
26namespace llvm {
27namespace jitlink {
28
29/// Manages allocations of JIT memory.
30///
31/// Instances of this class may be accessed concurrently from multiple threads
32/// and their implemetations should include any necessary synchronization.
33class JITLinkMemoryManager {
34public:
35 using ProtectionFlags = sys::Memory::ProtectionFlags;
36
37 class SegmentRequest {
38 public:
39 SegmentRequest() = default;
40 SegmentRequest(uint64_t Alignment, size_t ContentSize,
41 uint64_t ZeroFillSize)
42 : Alignment(Alignment), ContentSize(ContentSize),
43 ZeroFillSize(ZeroFillSize) {
44 assert(isPowerOf2_32(Alignment) && "Alignment must be power of 2");
45 }
46 uint64_t getAlignment() const { return Alignment; }
47 size_t getContentSize() const { return ContentSize; }
48 uint64_t getZeroFillSize() const { return ZeroFillSize; }
49 private:
50 uint64_t Alignment = 0;
51 size_t ContentSize = 0;
52 uint64_t ZeroFillSize = 0;
53 };
54
55 using SegmentsRequestMap = DenseMap<unsigned, SegmentRequest>;
56
57 /// Represents an allocation created by the memory manager.
58 ///
59 /// An allocation object is responsible for allocating and owning jit-linker
60 /// working and target memory, and for transfering from working to target
61 /// memory.
62 ///
63 class Allocation {
64 public:
65 using FinalizeContinuation = std::function<void(Error)>;
66
67 virtual ~Allocation();
68
69 /// Should return the address of linker working memory for the segment with
70 /// the given protection flags.
71 virtual MutableArrayRef<char> getWorkingMemory(ProtectionFlags Seg) = 0;
72
73 /// Should return the final address in the target process where the segment
74 /// will reside.
75 virtual JITTargetAddress getTargetMemory(ProtectionFlags Seg) = 0;
76
77 /// Should transfer from working memory to target memory, and release
78 /// working memory.
79 virtual void finalizeAsync(FinalizeContinuation OnFinalize) = 0;
80
81 /// Calls finalizeAsync and waits for completion.
82 Error finalize() {
83 std::promise<MSVCPError> FinalizeResultP;
84 auto FinalizeResultF = FinalizeResultP.get_future();
85 finalizeAsync(
86 [&](Error Err) { FinalizeResultP.set_value(std::move(Err)); });
87 return FinalizeResultF.get();
88 }
89
90 /// Should deallocate target memory.
91 virtual Error deallocate() = 0;
92 };
93
94 virtual ~JITLinkMemoryManager();
95
96 /// Create an Allocation object.
97 ///
98 /// The JD argument represents the target JITLinkDylib, and can be used by
99 /// JITLinkMemoryManager implementers to manage per-dylib allocation pools
100 /// (e.g. one pre-reserved address space slab per dylib to ensure that all
101 /// allocations for the dylib are within a certain range). The JD argument
102 /// may be null (representing an allocation not associated with any
103 /// JITDylib.
104 ///
105 /// The request argument describes the segment sizes and permisssions being
106 /// requested.
107 virtual Expected<std::unique_ptr<Allocation>>
108 allocate(const JITLinkDylib *JD, const SegmentsRequestMap &Request) = 0;
109};
110
111/// A JITLinkMemoryManager that allocates in-process memory.
112class InProcessMemoryManager : public JITLinkMemoryManager {
113public:
114 Expected<std::unique_ptr<Allocation>>
115 allocate(const JITLinkDylib *JD, const SegmentsRequestMap &Request) override;
116};
117
118} // end namespace jitlink
119} // end namespace llvm
120
121#endif // LLVM_EXECUTIONENGINE_JITLINK_JITLINKMEMORYMANAGER_H
122