1 //===-------------- EPCGenericJITLinkMemoryManagerTest.cpp ----------------===//
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 #include "OrcTestCommon.h"
11 #include "llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h"
13 #include "llvm/ADT/DenseMap.h"
14 #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
15 #include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
16 #include "llvm/Support/FormatVariadic.h"
17 #include "llvm/Support/Memory.h"
18 #include "llvm/Testing/Support/Error.h"
24 using namespace llvm::orc
;
25 using namespace llvm::orc::shared
;
29 class SimpleAllocator
{
31 Expected
<ExecutorAddr
> reserve(uint64_t Size
) {
33 auto MB
= sys::Memory::allocateMappedMemory(
34 Size
, 0, sys::Memory::MF_READ
| sys::Memory::MF_WRITE
, EC
);
36 return errorCodeToError(EC
);
37 Blocks
[MB
.base()] = sys::OwningMemoryBlock(std::move(MB
));
38 return ExecutorAddr::fromPtr(MB
.base());
41 Error
finalize(tpctypes::FinalizeRequest FR
) {
42 for (auto &Seg
: FR
.Segments
) {
43 char *Mem
= Seg
.Addr
.toPtr
<char *>();
44 memcpy(Mem
, Seg
.Content
.data(), Seg
.Content
.size());
45 memset(Mem
+ Seg
.Content
.size(), 0, Seg
.Size
- Seg
.Content
.size());
46 assert(Seg
.Size
<= std::numeric_limits
<size_t>::max());
47 if (auto EC
= sys::Memory::protectMappedMemory(
48 {Mem
, static_cast<size_t>(Seg
.Size
)},
49 toSysMemoryProtectionFlags(Seg
.RAG
.Prot
)))
50 return errorCodeToError(EC
);
51 if ((Seg
.RAG
.Prot
& MemProt::Exec
) != MemProt::Exec
)
52 sys::Memory::InvalidateInstructionCache(Mem
, Seg
.Size
);
54 return Error::success();
57 Error
deallocate(std::vector
<ExecutorAddr
> &Bases
) {
58 Error Err
= Error::success();
59 for (auto &Base
: Bases
) {
60 auto I
= Blocks
.find(Base
.toPtr
<void *>());
61 if (I
== Blocks
.end()) {
64 make_error
<StringError
>("No allocation for " +
65 formatv("{0:x}", Base
.getValue()),
66 inconvertibleErrorCode()));
69 auto MB
= std::move(I
->second
);
71 if (auto EC
= MB
.release())
72 Err
= joinErrors(std::move(Err
), errorCodeToError(EC
));
78 DenseMap
<void *, sys::OwningMemoryBlock
> Blocks
;
81 llvm::orc::shared::CWrapperFunctionResult
testReserve(const char *ArgData
,
83 return WrapperFunction
<rt::SPSSimpleExecutorMemoryManagerReserveSignature
>::
84 handle(ArgData
, ArgSize
,
85 makeMethodWrapperHandler(&SimpleAllocator::reserve
))
89 llvm::orc::shared::CWrapperFunctionResult
testFinalize(const char *ArgData
,
91 return WrapperFunction
<rt::SPSSimpleExecutorMemoryManagerFinalizeSignature
>::
92 handle(ArgData
, ArgSize
,
93 makeMethodWrapperHandler(&SimpleAllocator::finalize
))
97 llvm::orc::shared::CWrapperFunctionResult
testDeallocate(const char *ArgData
,
99 return WrapperFunction
<
100 rt::SPSSimpleExecutorMemoryManagerDeallocateSignature
>::
101 handle(ArgData
, ArgSize
,
102 makeMethodWrapperHandler(&SimpleAllocator::deallocate
))
106 TEST(EPCGenericJITLinkMemoryManagerTest
, AllocFinalizeFree
) {
107 auto SelfEPC
= cantFail(SelfExecutorProcessControl::Create());
110 EPCGenericJITLinkMemoryManager::SymbolAddrs SAs
;
111 SAs
.Allocator
= ExecutorAddr::fromPtr(&SA
);
112 SAs
.Reserve
= ExecutorAddr::fromPtr(&testReserve
);
113 SAs
.Finalize
= ExecutorAddr::fromPtr(&testFinalize
);
114 SAs
.Deallocate
= ExecutorAddr::fromPtr(&testDeallocate
);
116 auto MemMgr
= std::make_unique
<EPCGenericJITLinkMemoryManager
>(*SelfEPC
, SAs
);
118 StringRef Hello
= "hello";
119 auto SSA
= jitlink::SimpleSegmentAlloc::Create(
120 *MemMgr
, nullptr, {{MemProt::Read
, {Hello
.size(), Align(1)}}});
121 EXPECT_THAT_EXPECTED(SSA
, Succeeded());
122 auto SegInfo
= SSA
->getSegInfo(MemProt::Read
);
123 memcpy(SegInfo
.WorkingMem
.data(), Hello
.data(), Hello
.size());
125 auto FA
= SSA
->finalize();
126 EXPECT_THAT_EXPECTED(FA
, Succeeded());
128 ExecutorAddr
TargetAddr(SegInfo
.Addr
);
130 const char *TargetMem
= TargetAddr
.toPtr
<const char *>();
131 EXPECT_NE(TargetMem
, SegInfo
.WorkingMem
.data());
132 StringRef
TargetHello(TargetMem
, Hello
.size());
133 EXPECT_EQ(Hello
, TargetHello
);
135 auto Err2
= MemMgr
->deallocate(std::move(*FA
));
136 EXPECT_THAT_ERROR(std::move(Err2
), Succeeded());
138 cantFail(SelfEPC
->disconnect());