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