xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1349cc55cSDimitry Andric //===---- EPCGenericJITLinkMemoryManager.cpp -- Mem management via EPC ----===//
2349cc55cSDimitry Andric //
3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6349cc55cSDimitry Andric //
7349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
8349cc55cSDimitry Andric 
9349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h"
10349cc55cSDimitry Andric 
11349cc55cSDimitry Andric #include "llvm/ExecutionEngine/JITLink/JITLink.h"
12349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
13349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
14349cc55cSDimitry Andric 
15349cc55cSDimitry Andric #include <limits>
16349cc55cSDimitry Andric 
17349cc55cSDimitry Andric using namespace llvm::jitlink;
18349cc55cSDimitry Andric 
19349cc55cSDimitry Andric namespace llvm {
20349cc55cSDimitry Andric namespace orc {
21349cc55cSDimitry Andric 
22349cc55cSDimitry Andric class EPCGenericJITLinkMemoryManager::InFlightAlloc
23349cc55cSDimitry Andric     : public jitlink::JITLinkMemoryManager::InFlightAlloc {
24349cc55cSDimitry Andric public:
25349cc55cSDimitry Andric 
26349cc55cSDimitry Andric   // FIXME: The C++98 initializer is an attempt to work around compile failures
27349cc55cSDimitry Andric   // due to http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1397.
28349cc55cSDimitry Andric   // We should be able to switch this back to member initialization once that
29349cc55cSDimitry Andric   // issue is fixed.
30349cc55cSDimitry Andric   struct SegInfo {
SegInfollvm::orc::EPCGenericJITLinkMemoryManager::InFlightAlloc::SegInfo31349cc55cSDimitry Andric     SegInfo() : WorkingMem(nullptr), ContentSize(0), ZeroFillSize(0) {}
32349cc55cSDimitry Andric 
33349cc55cSDimitry Andric     char *WorkingMem;
34349cc55cSDimitry Andric     ExecutorAddr Addr;
35349cc55cSDimitry Andric     uint64_t ContentSize;
36349cc55cSDimitry Andric     uint64_t ZeroFillSize;
37349cc55cSDimitry Andric   };
38349cc55cSDimitry Andric 
39349cc55cSDimitry Andric   using SegInfoMap = AllocGroupSmallMap<SegInfo>;
40349cc55cSDimitry Andric 
InFlightAlloc(EPCGenericJITLinkMemoryManager & Parent,LinkGraph & G,ExecutorAddr AllocAddr,SegInfoMap Segs)41349cc55cSDimitry Andric   InFlightAlloc(EPCGenericJITLinkMemoryManager &Parent, LinkGraph &G,
42349cc55cSDimitry Andric                 ExecutorAddr AllocAddr, SegInfoMap Segs)
43349cc55cSDimitry Andric       : Parent(Parent), G(G), AllocAddr(AllocAddr), Segs(std::move(Segs)) {}
44349cc55cSDimitry Andric 
finalize(OnFinalizedFunction OnFinalize)45349cc55cSDimitry Andric   void finalize(OnFinalizedFunction OnFinalize) override {
46349cc55cSDimitry Andric     tpctypes::FinalizeRequest FR;
47349cc55cSDimitry Andric     for (auto &KV : Segs) {
48349cc55cSDimitry Andric       assert(KV.second.ContentSize <= std::numeric_limits<size_t>::max());
49349cc55cSDimitry Andric       FR.Segments.push_back(tpctypes::SegFinalizeRequest{
50bdd1243dSDimitry Andric           KV.first,
51349cc55cSDimitry Andric           KV.second.Addr,
52349cc55cSDimitry Andric           alignTo(KV.second.ContentSize + KV.second.ZeroFillSize,
53349cc55cSDimitry Andric                   Parent.EPC.getPageSize()),
54349cc55cSDimitry Andric           {KV.second.WorkingMem, static_cast<size_t>(KV.second.ContentSize)}});
55349cc55cSDimitry Andric     }
56349cc55cSDimitry Andric 
57349cc55cSDimitry Andric     // Transfer allocation actions.
5804eeddc0SDimitry Andric     std::swap(FR.Actions, G.allocActions());
59349cc55cSDimitry Andric 
60349cc55cSDimitry Andric     Parent.EPC.callSPSWrapperAsync<
61349cc55cSDimitry Andric         rt::SPSSimpleExecutorMemoryManagerFinalizeSignature>(
62349cc55cSDimitry Andric         Parent.SAs.Finalize,
63349cc55cSDimitry Andric         [OnFinalize = std::move(OnFinalize), AllocAddr = this->AllocAddr](
64349cc55cSDimitry Andric             Error SerializationErr, Error FinalizeErr) mutable {
65349cc55cSDimitry Andric           // FIXME: Release abandoned alloc.
66349cc55cSDimitry Andric           if (SerializationErr) {
67349cc55cSDimitry Andric             cantFail(std::move(FinalizeErr));
68349cc55cSDimitry Andric             OnFinalize(std::move(SerializationErr));
69349cc55cSDimitry Andric           } else if (FinalizeErr)
70349cc55cSDimitry Andric             OnFinalize(std::move(FinalizeErr));
71349cc55cSDimitry Andric           else
7204eeddc0SDimitry Andric             OnFinalize(FinalizedAlloc(AllocAddr));
73349cc55cSDimitry Andric         },
74349cc55cSDimitry Andric         Parent.SAs.Allocator, std::move(FR));
75349cc55cSDimitry Andric   }
76349cc55cSDimitry Andric 
abandon(OnAbandonedFunction OnAbandoned)77349cc55cSDimitry Andric   void abandon(OnAbandonedFunction OnAbandoned) override {
78349cc55cSDimitry Andric     // FIXME: Return memory to pool instead.
79349cc55cSDimitry Andric     Parent.EPC.callSPSWrapperAsync<
80349cc55cSDimitry Andric         rt::SPSSimpleExecutorMemoryManagerDeallocateSignature>(
81349cc55cSDimitry Andric         Parent.SAs.Deallocate,
82349cc55cSDimitry Andric         [OnAbandoned = std::move(OnAbandoned)](Error SerializationErr,
83349cc55cSDimitry Andric                                                Error DeallocateErr) mutable {
84349cc55cSDimitry Andric           if (SerializationErr) {
85349cc55cSDimitry Andric             cantFail(std::move(DeallocateErr));
86349cc55cSDimitry Andric             OnAbandoned(std::move(SerializationErr));
87349cc55cSDimitry Andric           } else
88349cc55cSDimitry Andric             OnAbandoned(std::move(DeallocateErr));
89349cc55cSDimitry Andric         },
90349cc55cSDimitry Andric         Parent.SAs.Allocator, ArrayRef<ExecutorAddr>(AllocAddr));
91349cc55cSDimitry Andric   }
92349cc55cSDimitry Andric 
93349cc55cSDimitry Andric private:
94349cc55cSDimitry Andric   EPCGenericJITLinkMemoryManager &Parent;
95349cc55cSDimitry Andric   LinkGraph &G;
96349cc55cSDimitry Andric   ExecutorAddr AllocAddr;
97349cc55cSDimitry Andric   SegInfoMap Segs;
98349cc55cSDimitry Andric };
99349cc55cSDimitry Andric 
allocate(const JITLinkDylib * JD,LinkGraph & G,OnAllocatedFunction OnAllocated)100349cc55cSDimitry Andric void EPCGenericJITLinkMemoryManager::allocate(const JITLinkDylib *JD,
101349cc55cSDimitry Andric                                               LinkGraph &G,
102349cc55cSDimitry Andric                                               OnAllocatedFunction OnAllocated) {
103349cc55cSDimitry Andric   BasicLayout BL(G);
104349cc55cSDimitry Andric 
105349cc55cSDimitry Andric   auto Pages = BL.getContiguousPageBasedLayoutSizes(EPC.getPageSize());
106349cc55cSDimitry Andric   if (!Pages)
107349cc55cSDimitry Andric     return OnAllocated(Pages.takeError());
108349cc55cSDimitry Andric 
109349cc55cSDimitry Andric   EPC.callSPSWrapperAsync<rt::SPSSimpleExecutorMemoryManagerReserveSignature>(
110349cc55cSDimitry Andric       SAs.Reserve,
111349cc55cSDimitry Andric       [this, BL = std::move(BL), OnAllocated = std::move(OnAllocated)](
112349cc55cSDimitry Andric           Error SerializationErr, Expected<ExecutorAddr> AllocAddr) mutable {
113349cc55cSDimitry Andric         if (SerializationErr) {
114349cc55cSDimitry Andric           cantFail(AllocAddr.takeError());
115349cc55cSDimitry Andric           return OnAllocated(std::move(SerializationErr));
116349cc55cSDimitry Andric         }
117349cc55cSDimitry Andric         if (!AllocAddr)
118349cc55cSDimitry Andric           return OnAllocated(AllocAddr.takeError());
119349cc55cSDimitry Andric 
120349cc55cSDimitry Andric         completeAllocation(*AllocAddr, std::move(BL), std::move(OnAllocated));
121349cc55cSDimitry Andric       },
122349cc55cSDimitry Andric       SAs.Allocator, Pages->total());
123349cc55cSDimitry Andric }
124349cc55cSDimitry Andric 
deallocate(std::vector<FinalizedAlloc> Allocs,OnDeallocatedFunction OnDeallocated)125349cc55cSDimitry Andric void EPCGenericJITLinkMemoryManager::deallocate(
126349cc55cSDimitry Andric     std::vector<FinalizedAlloc> Allocs, OnDeallocatedFunction OnDeallocated) {
127349cc55cSDimitry Andric   EPC.callSPSWrapperAsync<
128349cc55cSDimitry Andric       rt::SPSSimpleExecutorMemoryManagerDeallocateSignature>(
129349cc55cSDimitry Andric       SAs.Deallocate,
130349cc55cSDimitry Andric       [OnDeallocated = std::move(OnDeallocated)](Error SerErr,
131349cc55cSDimitry Andric                                                  Error DeallocErr) mutable {
132349cc55cSDimitry Andric         if (SerErr) {
133349cc55cSDimitry Andric           cantFail(std::move(DeallocErr));
134349cc55cSDimitry Andric           OnDeallocated(std::move(SerErr));
135349cc55cSDimitry Andric         } else
136349cc55cSDimitry Andric           OnDeallocated(std::move(DeallocErr));
137349cc55cSDimitry Andric       },
138349cc55cSDimitry Andric       SAs.Allocator, Allocs);
139349cc55cSDimitry Andric   for (auto &A : Allocs)
140349cc55cSDimitry Andric     A.release();
141349cc55cSDimitry Andric }
142349cc55cSDimitry Andric 
completeAllocation(ExecutorAddr AllocAddr,BasicLayout BL,OnAllocatedFunction OnAllocated)143349cc55cSDimitry Andric void EPCGenericJITLinkMemoryManager::completeAllocation(
144349cc55cSDimitry Andric     ExecutorAddr AllocAddr, BasicLayout BL, OnAllocatedFunction OnAllocated) {
145349cc55cSDimitry Andric 
146349cc55cSDimitry Andric   InFlightAlloc::SegInfoMap SegInfos;
147349cc55cSDimitry Andric 
148349cc55cSDimitry Andric   ExecutorAddr NextSegAddr = AllocAddr;
149349cc55cSDimitry Andric   for (auto &KV : BL.segments()) {
150349cc55cSDimitry Andric     const auto &AG = KV.first;
151349cc55cSDimitry Andric     auto &Seg = KV.second;
152349cc55cSDimitry Andric 
15304eeddc0SDimitry Andric     Seg.Addr = NextSegAddr;
154349cc55cSDimitry Andric     KV.second.WorkingMem = BL.getGraph().allocateBuffer(Seg.ContentSize).data();
155349cc55cSDimitry Andric     NextSegAddr += ExecutorAddrDiff(
156349cc55cSDimitry Andric         alignTo(Seg.ContentSize + Seg.ZeroFillSize, EPC.getPageSize()));
157349cc55cSDimitry Andric 
158349cc55cSDimitry Andric     auto &SegInfo = SegInfos[AG];
159349cc55cSDimitry Andric     SegInfo.ContentSize = Seg.ContentSize;
160349cc55cSDimitry Andric     SegInfo.ZeroFillSize = Seg.ZeroFillSize;
161*06c3fb27SDimitry Andric     SegInfo.Addr = Seg.Addr;
162349cc55cSDimitry Andric     SegInfo.WorkingMem = Seg.WorkingMem;
163349cc55cSDimitry Andric   }
164349cc55cSDimitry Andric 
165349cc55cSDimitry Andric   if (auto Err = BL.apply())
166349cc55cSDimitry Andric     return OnAllocated(std::move(Err));
167349cc55cSDimitry Andric 
168349cc55cSDimitry Andric   OnAllocated(std::make_unique<InFlightAlloc>(*this, BL.getGraph(), AllocAddr,
169349cc55cSDimitry Andric                                               std::move(SegInfos)));
170349cc55cSDimitry Andric }
171349cc55cSDimitry Andric 
172349cc55cSDimitry Andric } // end namespace orc
173349cc55cSDimitry Andric } // end namespace llvm
174