LLVM  14.0.0git
EPCGenericJITLinkMemoryManager.cpp
Go to the documentation of this file.
1 //===---- EPCGenericJITLinkMemoryManager.cpp -- Mem management via EPC ----===//
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 
10 
14 
15 #include <limits>
16 
17 using namespace llvm::jitlink;
18 
19 namespace llvm {
20 namespace orc {
21 
24 public:
25 
26  // FIXME: The C++98 initializer is an attempt to work around compile failures
27  // due to http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1397.
28  // We should be able to switch this back to member initialization once that
29  // issue is fixed.
30  struct SegInfo {
31  SegInfo() : WorkingMem(nullptr), ContentSize(0), ZeroFillSize(0) {}
32 
33  char *WorkingMem;
37  };
38 
40 
42  ExecutorAddr AllocAddr, SegInfoMap Segs)
43  : Parent(Parent), G(G), AllocAddr(AllocAddr), Segs(std::move(Segs)) {}
44 
45  void finalize(OnFinalizedFunction OnFinalize) override {
47  for (auto &KV : Segs) {
48  assert(KV.second.ContentSize <= std::numeric_limits<size_t>::max());
51  toSysMemoryProtectionFlags(KV.first.getMemProt())),
52  KV.second.Addr,
53  alignTo(KV.second.ContentSize + KV.second.ZeroFillSize,
54  Parent.EPC.getPageSize()),
55  {KV.second.WorkingMem, static_cast<size_t>(KV.second.ContentSize)}});
56  }
57 
58  // Transfer allocation actions.
59  // FIXME: Merge JITLink and ORC SupportFunctionCall and Action list types,
60  // turn this into a std::swap.
61  FR.Actions.reserve(G.allocActions().size());
62  for (auto &ActPair : G.allocActions())
63  FR.Actions.push_back({{ExecutorAddr(ActPair.Finalize.FnAddr),
64  {ExecutorAddr(ActPair.Finalize.CtxAddr),
65  ExecutorAddrDiff(ActPair.Finalize.CtxSize)}},
66  {ExecutorAddr(ActPair.Dealloc.FnAddr),
67  {ExecutorAddr(ActPair.Dealloc.CtxAddr),
68  ExecutorAddrDiff(ActPair.Dealloc.CtxSize)}}});
69  G.allocActions().clear();
70 
71  Parent.EPC.callSPSWrapperAsync<
73  Parent.SAs.Finalize,
74  [OnFinalize = std::move(OnFinalize), AllocAddr = this->AllocAddr](
75  Error SerializationErr, Error FinalizeErr) mutable {
76  // FIXME: Release abandoned alloc.
77  if (SerializationErr) {
78  cantFail(std::move(FinalizeErr));
79  OnFinalize(std::move(SerializationErr));
80  } else if (FinalizeErr)
81  OnFinalize(std::move(FinalizeErr));
82  else
83  OnFinalize(FinalizedAlloc(AllocAddr.getValue()));
84  },
85  Parent.SAs.Allocator, std::move(FR));
86  }
87 
88  void abandon(OnAbandonedFunction OnAbandoned) override {
89  // FIXME: Return memory to pool instead.
90  Parent.EPC.callSPSWrapperAsync<
92  Parent.SAs.Deallocate,
93  [OnAbandoned = std::move(OnAbandoned)](Error SerializationErr,
94  Error DeallocateErr) mutable {
95  if (SerializationErr) {
96  cantFail(std::move(DeallocateErr));
97  OnAbandoned(std::move(SerializationErr));
98  } else
99  OnAbandoned(std::move(DeallocateErr));
100  },
101  Parent.SAs.Allocator, ArrayRef<ExecutorAddr>(AllocAddr));
102  }
103 
104 private:
106  LinkGraph &G;
107  ExecutorAddr AllocAddr;
108  SegInfoMap Segs;
109 };
110 
111 void EPCGenericJITLinkMemoryManager::allocate(const JITLinkDylib *JD,
112  LinkGraph &G,
113  OnAllocatedFunction OnAllocated) {
114  BasicLayout BL(G);
115 
116  auto Pages = BL.getContiguousPageBasedLayoutSizes(EPC.getPageSize());
117  if (!Pages)
118  return OnAllocated(Pages.takeError());
119 
121  SAs.Reserve,
122  [this, BL = std::move(BL), OnAllocated = std::move(OnAllocated)](
123  Error SerializationErr, Expected<ExecutorAddr> AllocAddr) mutable {
124  if (SerializationErr) {
125  cantFail(AllocAddr.takeError());
126  return OnAllocated(std::move(SerializationErr));
127  }
128  if (!AllocAddr)
129  return OnAllocated(AllocAddr.takeError());
130 
131  completeAllocation(*AllocAddr, std::move(BL), std::move(OnAllocated));
132  },
133  SAs.Allocator, Pages->total());
134 }
135 
136 void EPCGenericJITLinkMemoryManager::deallocate(
137  std::vector<FinalizedAlloc> Allocs, OnDeallocatedFunction OnDeallocated) {
138  EPC.callSPSWrapperAsync<
140  SAs.Deallocate,
141  [OnDeallocated = std::move(OnDeallocated)](Error SerErr,
142  Error DeallocErr) mutable {
143  if (SerErr) {
144  cantFail(std::move(DeallocErr));
145  OnDeallocated(std::move(SerErr));
146  } else
147  OnDeallocated(std::move(DeallocErr));
148  },
149  SAs.Allocator, Allocs);
150  for (auto &A : Allocs)
151  A.release();
152 }
153 
154 void EPCGenericJITLinkMemoryManager::completeAllocation(
155  ExecutorAddr AllocAddr, BasicLayout BL, OnAllocatedFunction OnAllocated) {
156 
157  InFlightAlloc::SegInfoMap SegInfos;
158 
159  ExecutorAddr NextSegAddr = AllocAddr;
160  for (auto &KV : BL.segments()) {
161  const auto &AG = KV.first;
162  auto &Seg = KV.second;
163 
164  Seg.Addr = NextSegAddr.getValue();
165  KV.second.WorkingMem = BL.getGraph().allocateBuffer(Seg.ContentSize).data();
166  NextSegAddr += ExecutorAddrDiff(
167  alignTo(Seg.ContentSize + Seg.ZeroFillSize, EPC.getPageSize()));
168 
169  auto &SegInfo = SegInfos[AG];
170  SegInfo.ContentSize = Seg.ContentSize;
171  SegInfo.ZeroFillSize = Seg.ZeroFillSize;
172  SegInfo.Addr = ExecutorAddr(Seg.Addr);
173  SegInfo.WorkingMem = Seg.WorkingMem;
174  }
175 
176  if (auto Err = BL.apply())
177  return OnAllocated(std::move(Err));
178 
179  OnAllocated(std::make_unique<InFlightAlloc>(*this, BL.getGraph(), AllocAddr,
180  std::move(SegInfos)));
181 }
182 
183 } // end namespace orc
184 } // end namespace llvm
llvm::orc::ExecutorAddr
Represents an address in the executor process.
Definition: ExecutorAddress.h:37
llvm::orc::tpctypes::toWireProtectionFlags
WireProtectionFlags toWireProtectionFlags(sys::Memory::ProtectionFlags PF)
Convert from sys::Memory::ProtectionFlags.
Definition: TargetProcessControlTypes.h:41
llvm::alignTo
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:148
llvm::orc::EPCGenericJITLinkMemoryManager::InFlightAlloc::SegInfo::WorkingMem
char * WorkingMem
Definition: EPCGenericJITLinkMemoryManager.cpp:33
llvm::orc::ExecutorAddrDiff
Represents the difference between two addresses in the executor process.
Definition: ExecutorAddress.h:25
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
llvm::unique_function
unique_function is a type-erasing functor similar to std::function.
Definition: FunctionExtras.h:56
llvm::orc::ExecutorAddr::getValue
uint64_t getValue() const
Definition: ExecutorAddress.h:60
llvm::orc::EPCGenericJITLinkMemoryManager::InFlightAlloc::SegInfo
Definition: EPCGenericJITLinkMemoryManager.cpp:30
llvm::orc::rt::SPSSimpleExecutorMemoryManagerFinalizeSignature
shared::SPSError(shared::SPSExecutorAddr, shared::SPSFinalizeRequest) SPSSimpleExecutorMemoryManagerFinalizeSignature
Definition: OrcRTBridge.h:57
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
llvm::orc::tpctypes::SegFinalizeRequest
Definition: TargetProcessControlTypes.h:116
EPCGenericJITLinkMemoryManager.h
llvm::ARCISD::BL
@ BL
Definition: ARCISelLowering.h:34
llvm::orc::tpctypes::FinalizeRequest
Definition: TargetProcessControlTypes.h:123
llvm::orc::EPCGenericJITLinkMemoryManager
Definition: EPCGenericJITLinkMemoryManager.h:27
llvm::orc::rt::SPSSimpleExecutorMemoryManagerReserveSignature
shared::SPSExpected< shared::SPSExecutorAddr >(shared::SPSExecutorAddr, uint64_t) SPSSimpleExecutorMemoryManagerReserveSignature
Definition: OrcRTBridge.h:55
G
const DataFlowGraph & G
Definition: RDFGraph.cpp:202
uint64_t
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::orc::EPCGenericJITLinkMemoryManager::InFlightAlloc::SegInfo::ContentSize
uint64_t ContentSize
Definition: EPCGenericJITLinkMemoryManager.cpp:35
LookupAndRecordAddrs.h
llvm::orc::tpctypes::FinalizeRequest::Actions
std::vector< AllocationActionsPair > Actions
Definition: TargetProcessControlTypes.h:125
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::move
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1639
llvm::orc::tpctypes::FinalizeRequest::Segments
std::vector< SegFinalizeRequest > Segments
Definition: TargetProcessControlTypes.h:124
llvm::orc::EPCGenericJITLinkMemoryManager::InFlightAlloc::abandon
void abandon(OnAbandonedFunction OnAbandoned) override
Called prior to finalization if the allocation should be abandoned.
Definition: EPCGenericJITLinkMemoryManager.cpp:88
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: APInt.h:32
llvm::cantFail
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition: Error.h:747
llvm::orc::EPCGenericJITLinkMemoryManager::InFlightAlloc::SegInfo::ZeroFillSize
uint64_t ZeroFillSize
Definition: EPCGenericJITLinkMemoryManager.cpp:36
std
Definition: BitVector.h:838
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
llvm::orc::EPCGenericJITLinkMemoryManager::InFlightAlloc::finalize
void finalize(OnFinalizedFunction OnFinalize) override
Called to transfer working memory to the target and apply finalization.
Definition: EPCGenericJITLinkMemoryManager.cpp:45
llvm::orc::EPCGenericJITLinkMemoryManager::InFlightAlloc
Definition: EPCGenericJITLinkMemoryManager.cpp:22
llvm::max
Align max(MaybeAlign Lhs, Align Rhs)
Definition: Alignment.h:340
llvm::orc::EPCGenericJITLinkMemoryManager::InFlightAlloc::SegInfo::SegInfo
SegInfo()
Definition: EPCGenericJITLinkMemoryManager.cpp:31
llvm::orc::EPCGenericJITLinkMemoryManager::InFlightAlloc::InFlightAlloc
InFlightAlloc(EPCGenericJITLinkMemoryManager &Parent, LinkGraph &G, ExecutorAddr AllocAddr, SegInfoMap Segs)
Definition: EPCGenericJITLinkMemoryManager.cpp:41
OrcRTBridge.h
llvm::orc::rt::SPSSimpleExecutorMemoryManagerDeallocateSignature
shared::SPSError(shared::SPSExecutorAddr, shared::SPSSequence< shared::SPSExecutorAddr >) SPSSimpleExecutorMemoryManagerDeallocateSignature
Definition: OrcRTBridge.h:59
llvm::orc::EPCGenericJITLinkMemoryManager::InFlightAlloc::SegInfo::Addr
ExecutorAddr Addr
Definition: EPCGenericJITLinkMemoryManager.cpp:34