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 
26 namespace llvm {
27 namespace 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.
33 class JITLinkMemoryManager {
34 public:
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.
112 class InProcessMemoryManager : public JITLinkMemoryManager {
113 public:
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