1 //===--- JITLinkTestUtils.h - Utilities for JITLink unit tests --*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // Utilities for JITLink unit tests.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_UNITTESTS_EXECUTIONENGINE_JITLINK_JITLINKTESTUTILS_H
14 #define LLVM_UNITTESTS_EXECUTIONENGINE_JITLINK_JITLINKTESTUTILS_H
16 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
18 class MockJITLinkMemoryManager
: public llvm::jitlink::JITLinkMemoryManager
{
25 class SimpleAlloc
: public Alloc
{
27 SimpleAlloc(const llvm::jitlink::JITLinkDylib
*JD
,
28 llvm::jitlink::LinkGraph
&G
) {
29 for (auto *B
: G
.blocks())
30 (void)B
->getMutableContent(G
);
34 class MockInFlightAlloc
: public InFlightAlloc
{
36 MockInFlightAlloc(MockJITLinkMemoryManager
&MJMM
, std::unique_ptr
<Alloc
> A
)
37 : MJMM(MJMM
), A(std::move(A
)) {}
39 void abandon(OnAbandonedFunction OnAbandoned
) override
{
40 OnAbandoned(MJMM
.Abandon(std::move(A
)));
43 void finalize(OnFinalizedFunction OnFinalized
) override
{
44 OnFinalized(MJMM
.Finalize(std::move(A
)));
48 MockJITLinkMemoryManager
&MJMM
;
49 std::unique_ptr
<Alloc
> A
;
52 MockJITLinkMemoryManager() {
53 Allocate
= [this](const llvm::jitlink::JITLinkDylib
*JD
,
54 llvm::jitlink::LinkGraph
&G
) {
55 return defaultAllocate(JD
, G
);
58 Deallocate
= [this](std::vector
<FinalizedAlloc
> Allocs
) {
59 return defaultDeallocate(std::move(Allocs
));
62 Abandon
= [this](std::unique_ptr
<Alloc
> A
) {
63 return defaultAbandon(std::move(A
));
66 Finalize
= [this](std::unique_ptr
<Alloc
> A
) {
67 return defaultFinalize(std::move(A
));
71 void allocate(const llvm::jitlink::JITLinkDylib
*JD
,
72 llvm::jitlink::LinkGraph
&G
,
73 OnAllocatedFunction OnAllocated
) override
{
74 auto A
= Allocate(JD
, G
);
76 OnAllocated(A
.takeError());
78 OnAllocated(std::make_unique
<MockInFlightAlloc
>(*this, std::move(*A
)));
81 void deallocate(std::vector
<FinalizedAlloc
> Allocs
,
82 OnDeallocatedFunction OnDeallocated
) override
{
83 OnDeallocated(Deallocate(std::move(Allocs
)));
86 using JITLinkMemoryManager::allocate
;
87 using JITLinkMemoryManager::deallocate
;
89 llvm::Expected
<std::unique_ptr
<Alloc
>>
90 defaultAllocate(const llvm::jitlink::JITLinkDylib
*JD
,
91 llvm::jitlink::LinkGraph
&G
) {
92 return std::make_unique
<SimpleAlloc
>(JD
, G
);
95 llvm::Error
defaultDeallocate(std::vector
<FinalizedAlloc
> Allocs
) {
96 for (auto &A
: Allocs
)
97 delete A
.release().toPtr
<Alloc
*>();
98 return llvm::Error::success();
101 llvm::Error
defaultAbandon(std::unique_ptr
<Alloc
> A
) {
102 return llvm::Error::success();
105 llvm::Expected
<FinalizedAlloc
> defaultFinalize(std::unique_ptr
<Alloc
> A
) {
106 return FinalizedAlloc(llvm::orc::ExecutorAddr::fromPtr(A
.release()));
109 llvm::unique_function
<llvm::Expected
<std::unique_ptr
<Alloc
>>(
110 const llvm::jitlink::JITLinkDylib
*, llvm::jitlink::LinkGraph
&)>
112 llvm::unique_function
<llvm::Error(std::vector
<FinalizedAlloc
>)> Deallocate
;
113 llvm::unique_function
<llvm::Error(std::unique_ptr
<Alloc
>)> Abandon
;
114 llvm::unique_function
<llvm::Expected
<FinalizedAlloc
>(std::unique_ptr
<Alloc
>)>
118 void lookupResolveEverythingToNull(
119 const llvm::jitlink::JITLinkContext::LookupMap
&Symbols
,
120 std::unique_ptr
<llvm::jitlink::JITLinkAsyncLookupContinuation
> LC
);
123 const llvm::jitlink::JITLinkContext::LookupMap
&Symbols
,
124 std::unique_ptr
<llvm::jitlink::JITLinkAsyncLookupContinuation
> LC
);
126 class MockJITLinkContext
: public llvm::jitlink::JITLinkContext
{
128 using HandleFailedFn
= llvm::unique_function
<void(llvm::Error
)>;
130 MockJITLinkContext(std::unique_ptr
<MockJITLinkMemoryManager
> MJMM
,
131 HandleFailedFn HandleFailed
)
132 : JITLinkContext(&JD
), MJMM(std::move(MJMM
)),
133 HandleFailed(std::move(HandleFailed
)) {}
135 ~MockJITLinkContext() {
136 if (auto Err
= MJMM
->deallocate(std::move(FinalizedAllocs
)))
137 notifyFailed(std::move(Err
));
140 llvm::jitlink::JITLinkMemoryManager
&getMemoryManager() override
{
144 void notifyFailed(llvm::Error Err
) override
{ HandleFailed(std::move(Err
)); }
146 void lookup(const LookupMap
&Symbols
,
147 std::unique_ptr
<llvm::jitlink::JITLinkAsyncLookupContinuation
> LC
)
149 Lookup(Symbols
, std::move(LC
));
152 llvm::Error
notifyResolved(llvm::jitlink::LinkGraph
&G
) override
{
153 return NotifyResolved
? NotifyResolved(G
) : llvm::Error::success();
156 void notifyFinalized(
157 llvm::jitlink::JITLinkMemoryManager::FinalizedAlloc Alloc
) override
{
159 NotifyFinalized(std::move(Alloc
));
161 FinalizedAllocs
.push_back(std::move(Alloc
));
164 bool shouldAddDefaultTargetPasses(const llvm::Triple
&TT
) const override
{
168 llvm::jitlink::LinkGraphPassFunction
169 getMarkLivePass(const llvm::Triple
&TT
) const override
{
170 return MarkLivePass
? llvm::jitlink::LinkGraphPassFunction(
171 [this](llvm::jitlink::LinkGraph
&G
) {
172 return MarkLivePass(G
);
174 : llvm::jitlink::LinkGraphPassFunction(
175 [](llvm::jitlink::LinkGraph
&G
) {
176 return markAllSymbolsLive(G
);
181 modifyPassConfig(llvm::jitlink::LinkGraph
&G
,
182 llvm::jitlink::PassConfiguration
&Config
) override
{
183 if (ModifyPassConfig
)
184 return ModifyPassConfig(G
, Config
);
185 return llvm::Error::success();
188 llvm::jitlink::JITLinkDylib JD
{"JD"};
189 std::unique_ptr
<MockJITLinkMemoryManager
> MJMM
;
190 HandleFailedFn HandleFailed
;
191 llvm::unique_function
<void(
193 std::unique_ptr
<llvm::jitlink::JITLinkAsyncLookupContinuation
>)>
195 llvm::unique_function
<llvm::Error(llvm::jitlink::LinkGraph
&)> NotifyResolved
;
196 llvm::unique_function
<void(
197 llvm::jitlink::JITLinkMemoryManager::FinalizedAlloc
)>
199 mutable llvm::unique_function
<llvm::Error(llvm::jitlink::LinkGraph
&)>
201 llvm::unique_function
<llvm::Error(llvm::jitlink::LinkGraph
&,
202 llvm::jitlink::PassConfiguration
&)>
205 std::vector
<llvm::jitlink::JITLinkMemoryManager::FinalizedAlloc
>
209 std::unique_ptr
<MockJITLinkContext
> makeMockContext(
210 llvm::unique_function
<void(llvm::Error
)> HandleFailed
,
211 llvm::unique_function
<void(MockJITLinkMemoryManager
&)> SetupMemMgr
,
212 llvm::unique_function
<void(MockJITLinkContext
&)> SetupContext
);
214 void defaultMemMgrSetup(MockJITLinkMemoryManager
&);
215 void defaultCtxSetup(MockJITLinkContext
&);
217 class JoinErrorsInto
{
219 JoinErrorsInto(llvm::Error
&Err
) : Err(Err
) {}
220 void operator()(llvm::Error E2
) {
221 Err
= llvm::joinErrors(std::move(Err
), std::move(E2
));
228 extern llvm::ArrayRef
<char> BlockContent
;
230 #endif // LLVM_UNITTESTS_EXECUTIONENGINE_JITLINK_JITLINKTESTUTILS_H