xref: /llvm-project/llvm/unittests/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerTest.cpp (revision 4eaff6c58ae2f130ac8d63cf2c87bbb483114876)
1dad60f80SLang Hames //===-------------- EPCGenericJITLinkMemoryManagerTest.cpp ----------------===//
2dad60f80SLang Hames //
3dad60f80SLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4dad60f80SLang Hames // See https://llvm.org/LICENSE.txt for license information.
5dad60f80SLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6dad60f80SLang Hames //
7dad60f80SLang Hames //===----------------------------------------------------------------------===//
8dad60f80SLang Hames 
9dad60f80SLang Hames #include "OrcTestCommon.h"
10dad60f80SLang Hames 
11dad60f80SLang Hames #include "llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h"
1278b083dbSLang Hames 
1378b083dbSLang Hames #include "llvm/ADT/DenseMap.h"
142c8e7849SLang Hames #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
15dad60f80SLang Hames #include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
1678b083dbSLang Hames #include "llvm/Support/FormatVariadic.h"
17dad60f80SLang Hames #include "llvm/Support/Memory.h"
18dad60f80SLang Hames #include "llvm/Testing/Support/Error.h"
19dad60f80SLang Hames 
2002b46203SDavid Spickett #include <limits>
2178b083dbSLang Hames #include <vector>
2202b46203SDavid Spickett 
23dad60f80SLang Hames using namespace llvm;
24dad60f80SLang Hames using namespace llvm::orc;
25dad60f80SLang Hames using namespace llvm::orc::shared;
26dad60f80SLang Hames 
27dad60f80SLang Hames namespace {
28dad60f80SLang Hames 
2978b083dbSLang Hames class SimpleAllocator {
3078b083dbSLang Hames public:
31ef391df2SLang Hames   Expected<ExecutorAddr> reserve(uint64_t Size) {
32dad60f80SLang Hames     std::error_code EC;
33dad60f80SLang Hames     auto MB = sys::Memory::allocateMappedMemory(
34dad60f80SLang Hames         Size, 0, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC);
35dad60f80SLang Hames     if (EC)
36dad60f80SLang Hames       return errorCodeToError(EC);
3778b083dbSLang Hames     Blocks[MB.base()] = sys::OwningMemoryBlock(std::move(MB));
38ef391df2SLang Hames     return ExecutorAddr::fromPtr(MB.base());
39dad60f80SLang Hames   }
40dad60f80SLang Hames 
4178b083dbSLang Hames   Error finalize(tpctypes::FinalizeRequest FR) {
4278b083dbSLang Hames     for (auto &Seg : FR.Segments) {
43dad60f80SLang Hames       char *Mem = Seg.Addr.toPtr<char *>();
44dad60f80SLang Hames       memcpy(Mem, Seg.Content.data(), Seg.Content.size());
4578b083dbSLang Hames       memset(Mem + Seg.Content.size(), 0, Seg.Size - Seg.Content.size());
4602b46203SDavid Spickett       assert(Seg.Size <= std::numeric_limits<size_t>::max());
47dad60f80SLang Hames       if (auto EC = sys::Memory::protectMappedMemory(
4802b46203SDavid Spickett               {Mem, static_cast<size_t>(Seg.Size)},
490b7e16afSLang Hames               toSysMemoryProtectionFlags(Seg.RAG.Prot)))
50dad60f80SLang Hames         return errorCodeToError(EC);
510b7e16afSLang Hames       if ((Seg.RAG.Prot & MemProt::Exec) != MemProt::Exec)
52dad60f80SLang Hames         sys::Memory::InvalidateInstructionCache(Mem, Seg.Size);
53dad60f80SLang Hames     }
54dad60f80SLang Hames     return Error::success();
5578b083dbSLang Hames   }
5678b083dbSLang Hames 
57ef391df2SLang Hames   Error deallocate(std::vector<ExecutorAddr> &Bases) {
5878b083dbSLang Hames     Error Err = Error::success();
5978b083dbSLang Hames     for (auto &Base : Bases) {
6078b083dbSLang Hames       auto I = Blocks.find(Base.toPtr<void *>());
6178b083dbSLang Hames       if (I == Blocks.end()) {
6278b083dbSLang Hames         Err = joinErrors(
6378b083dbSLang Hames             std::move(Err),
6478b083dbSLang Hames             make_error<StringError>("No allocation for " +
6578b083dbSLang Hames                                         formatv("{0:x}", Base.getValue()),
6678b083dbSLang Hames                                     inconvertibleErrorCode()));
6778b083dbSLang Hames         continue;
6878b083dbSLang Hames       }
6978b083dbSLang Hames       auto MB = std::move(I->second);
7078b083dbSLang Hames       Blocks.erase(I);
71bbc2fc54SLang Hames       if (auto EC = MB.release())
7278b083dbSLang Hames         Err = joinErrors(std::move(Err), errorCodeToError(EC));
7378b083dbSLang Hames     }
7478b083dbSLang Hames     return Err;
7578b083dbSLang Hames   }
7678b083dbSLang Hames 
7778b083dbSLang Hames private:
7878b083dbSLang Hames   DenseMap<void *, sys::OwningMemoryBlock> Blocks;
7978b083dbSLang Hames };
8078b083dbSLang Hames 
81213666f8SLang Hames llvm::orc::shared::CWrapperFunctionResult testReserve(const char *ArgData,
82213666f8SLang Hames                                                       size_t ArgSize) {
8378b083dbSLang Hames   return WrapperFunction<rt::SPSSimpleExecutorMemoryManagerReserveSignature>::
8478b083dbSLang Hames       handle(ArgData, ArgSize,
8578b083dbSLang Hames              makeMethodWrapperHandler(&SimpleAllocator::reserve))
8678b083dbSLang Hames           .release();
8778b083dbSLang Hames }
8878b083dbSLang Hames 
89213666f8SLang Hames llvm::orc::shared::CWrapperFunctionResult testFinalize(const char *ArgData,
90213666f8SLang Hames                                                        size_t ArgSize) {
9178b083dbSLang Hames   return WrapperFunction<rt::SPSSimpleExecutorMemoryManagerFinalizeSignature>::
9278b083dbSLang Hames       handle(ArgData, ArgSize,
9378b083dbSLang Hames              makeMethodWrapperHandler(&SimpleAllocator::finalize))
94dad60f80SLang Hames           .release();
95dad60f80SLang Hames }
96dad60f80SLang Hames 
97213666f8SLang Hames llvm::orc::shared::CWrapperFunctionResult testDeallocate(const char *ArgData,
98213666f8SLang Hames                                                          size_t ArgSize) {
9978b083dbSLang Hames   return WrapperFunction<
10078b083dbSLang Hames              rt::SPSSimpleExecutorMemoryManagerDeallocateSignature>::
10178b083dbSLang Hames       handle(ArgData, ArgSize,
10278b083dbSLang Hames              makeMethodWrapperHandler(&SimpleAllocator::deallocate))
103dad60f80SLang Hames           .release();
104dad60f80SLang Hames }
105dad60f80SLang Hames 
106dad60f80SLang Hames TEST(EPCGenericJITLinkMemoryManagerTest, AllocFinalizeFree) {
107dad60f80SLang Hames   auto SelfEPC = cantFail(SelfExecutorProcessControl::Create());
10878b083dbSLang Hames   SimpleAllocator SA;
109dad60f80SLang Hames 
11078b083dbSLang Hames   EPCGenericJITLinkMemoryManager::SymbolAddrs SAs;
111ef391df2SLang Hames   SAs.Allocator = ExecutorAddr::fromPtr(&SA);
112ef391df2SLang Hames   SAs.Reserve = ExecutorAddr::fromPtr(&testReserve);
113ef391df2SLang Hames   SAs.Finalize = ExecutorAddr::fromPtr(&testFinalize);
114ef391df2SLang Hames   SAs.Deallocate = ExecutorAddr::fromPtr(&testDeallocate);
115dad60f80SLang Hames 
11678b083dbSLang Hames   auto MemMgr = std::make_unique<EPCGenericJITLinkMemoryManager>(*SelfEPC, SAs);
117dad60f80SLang Hames   StringRef Hello = "hello";
118962a2479SLang Hames   auto SSA = jitlink::SimpleSegmentAlloc::Create(
119*4eaff6c5SLang Hames       *MemMgr, std::make_shared<orc::SymbolStringPool>(),
120*4eaff6c5SLang Hames       Triple("x86_64-apple-darwin"), nullptr,
1212ccf7ed2SJared Wyles       {{MemProt::Read, {Hello.size(), Align(1)}}});
122962a2479SLang Hames   EXPECT_THAT_EXPECTED(SSA, Succeeded());
123d3d9f7caSLang Hames   auto SegInfo = SSA->getSegInfo(MemProt::Read);
124962a2479SLang Hames   memcpy(SegInfo.WorkingMem.data(), Hello.data(), Hello.size());
125dad60f80SLang Hames 
126962a2479SLang Hames   auto FA = SSA->finalize();
127962a2479SLang Hames   EXPECT_THAT_EXPECTED(FA, Succeeded());
128dad60f80SLang Hames 
129962a2479SLang Hames   ExecutorAddr TargetAddr(SegInfo.Addr);
130dad60f80SLang Hames 
131dad60f80SLang Hames   const char *TargetMem = TargetAddr.toPtr<const char *>();
132962a2479SLang Hames   EXPECT_NE(TargetMem, SegInfo.WorkingMem.data());
133dad60f80SLang Hames   StringRef TargetHello(TargetMem, Hello.size());
134dad60f80SLang Hames   EXPECT_EQ(Hello, TargetHello);
135dad60f80SLang Hames 
136962a2479SLang Hames   auto Err2 = MemMgr->deallocate(std::move(*FA));
137dad60f80SLang Hames   EXPECT_THAT_ERROR(std::move(Err2), Succeeded());
138adf55ac6SLang Hames 
139adf55ac6SLang Hames   cantFail(SelfEPC->disconnect());
140dad60f80SLang Hames }
141dad60f80SLang Hames 
142dad60f80SLang Hames } // namespace
143