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"
12dad60f80SLang Hames #include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
13dad60f80SLang Hames #include "llvm/Support/Memory.h"
14dad60f80SLang Hames #include "llvm/Testing/Support/Error.h"
15dad60f80SLang Hames 
16*02b46203SDavid Spickett #include <limits>
17*02b46203SDavid Spickett 
18dad60f80SLang Hames using namespace llvm;
19dad60f80SLang Hames using namespace llvm::orc;
20dad60f80SLang Hames using namespace llvm::orc::shared;
21dad60f80SLang Hames 
22dad60f80SLang Hames namespace {
23dad60f80SLang Hames 
24dad60f80SLang Hames llvm::orc::shared::detail::CWrapperFunctionResult
25dad60f80SLang Hames testReserve(const char *ArgData, size_t ArgSize) {
26dad60f80SLang Hames   return WrapperFunction<SPSOrcTargetProcessAllocate>::handle(
27dad60f80SLang Hames              ArgData, ArgSize,
28dad60f80SLang Hames              [](uint64_t Size) -> Expected<ExecutorAddress> {
29dad60f80SLang Hames                std::error_code EC;
30dad60f80SLang Hames                auto MB = sys::Memory::allocateMappedMemory(
31dad60f80SLang Hames                    Size, 0, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC);
32dad60f80SLang Hames                if (EC)
33dad60f80SLang Hames                  return errorCodeToError(EC);
34dad60f80SLang Hames                return ExecutorAddress::fromPtr(MB.base());
35dad60f80SLang Hames              })
36dad60f80SLang Hames       .release();
37dad60f80SLang Hames }
38dad60f80SLang Hames 
39dad60f80SLang Hames llvm::orc::shared::detail::CWrapperFunctionResult
40dad60f80SLang Hames testFinalize(const char *ArgData, size_t ArgSize) {
41dad60f80SLang Hames   return WrapperFunction<SPSOrcTargetProcessFinalize>::handle(
42dad60f80SLang Hames              ArgData, ArgSize,
43dad60f80SLang Hames              [](const tpctypes::FinalizeRequest &FR) -> Error {
44dad60f80SLang Hames                for (auto &Seg : FR) {
45dad60f80SLang Hames                  char *Mem = Seg.Addr.toPtr<char *>();
46dad60f80SLang Hames                  memcpy(Mem, Seg.Content.data(), Seg.Content.size());
47dad60f80SLang Hames                  memset(Mem + Seg.Content.size(), 0,
48dad60f80SLang Hames                         Seg.Size - Seg.Content.size());
49*02b46203SDavid Spickett                  assert(Seg.Size <= std::numeric_limits<size_t>::max());
50dad60f80SLang Hames                  if (auto EC = sys::Memory::protectMappedMemory(
51*02b46203SDavid Spickett                          {Mem, static_cast<size_t>(Seg.Size)},
52dad60f80SLang Hames                          tpctypes::fromWireProtectionFlags(Seg.Prot)))
53dad60f80SLang Hames                    return errorCodeToError(EC);
54dad60f80SLang Hames                  if (Seg.Prot & tpctypes::WPF_Exec)
55dad60f80SLang Hames                    sys::Memory::InvalidateInstructionCache(Mem, Seg.Size);
56dad60f80SLang Hames                }
57dad60f80SLang Hames                return Error::success();
58dad60f80SLang Hames              })
59dad60f80SLang Hames       .release();
60dad60f80SLang Hames }
61dad60f80SLang Hames 
62dad60f80SLang Hames llvm::orc::shared::detail::CWrapperFunctionResult
63dad60f80SLang Hames testDeallocate(const char *ArgData, size_t ArgSize) {
64dad60f80SLang Hames   return WrapperFunction<SPSOrcTargetProcessDeallocate>::handle(
65dad60f80SLang Hames              ArgData, ArgSize,
66dad60f80SLang Hames              [](ExecutorAddress Base, uint64_t Size) -> Error {
67dad60f80SLang Hames                sys::MemoryBlock MB(Base.toPtr<void *>(), Size);
68dad60f80SLang Hames                if (auto EC = sys::Memory::releaseMappedMemory(MB))
69dad60f80SLang Hames                  return errorCodeToError(EC);
70dad60f80SLang Hames                return Error::success();
71dad60f80SLang Hames              })
72dad60f80SLang Hames       .release();
73dad60f80SLang Hames }
74dad60f80SLang Hames 
75dad60f80SLang Hames TEST(EPCGenericJITLinkMemoryManagerTest, AllocFinalizeFree) {
76dad60f80SLang Hames   auto SelfEPC = cantFail(SelfExecutorProcessControl::Create());
77dad60f80SLang Hames 
78dad60f80SLang Hames   EPCGenericJITLinkMemoryManager::FuncAddrs FAs;
79dad60f80SLang Hames   FAs.Reserve = ExecutorAddress::fromPtr(&testReserve);
80dad60f80SLang Hames   FAs.Finalize = ExecutorAddress::fromPtr(&testFinalize);
81dad60f80SLang Hames   FAs.Deallocate = ExecutorAddress::fromPtr(&testDeallocate);
82dad60f80SLang Hames 
83dad60f80SLang Hames   auto MemMgr = std::make_unique<EPCGenericJITLinkMemoryManager>(*SelfEPC, FAs);
84dad60f80SLang Hames 
85dad60f80SLang Hames   jitlink::JITLinkMemoryManager::SegmentsRequestMap SRM;
86dad60f80SLang Hames   StringRef Hello = "hello";
87dad60f80SLang Hames   SRM[sys::Memory::MF_READ] = {8, Hello.size(), 8};
88dad60f80SLang Hames   auto Alloc = MemMgr->allocate(nullptr, SRM);
89dad60f80SLang Hames   EXPECT_THAT_EXPECTED(Alloc, Succeeded());
90dad60f80SLang Hames 
91dad60f80SLang Hames   MutableArrayRef<char> WorkingMem =
92dad60f80SLang Hames       (*Alloc)->getWorkingMemory(sys::Memory::MF_READ);
93dad60f80SLang Hames   memcpy(WorkingMem.data(), Hello.data(), Hello.size());
94dad60f80SLang Hames 
95dad60f80SLang Hames   auto Err = (*Alloc)->finalize();
96dad60f80SLang Hames   EXPECT_THAT_ERROR(std::move(Err), Succeeded());
97dad60f80SLang Hames 
98dad60f80SLang Hames   ExecutorAddress TargetAddr((*Alloc)->getTargetMemory(sys::Memory::MF_READ));
99dad60f80SLang Hames 
100dad60f80SLang Hames   const char *TargetMem = TargetAddr.toPtr<const char *>();
101dad60f80SLang Hames   EXPECT_NE(TargetMem, WorkingMem.data());
102dad60f80SLang Hames   StringRef TargetHello(TargetMem, Hello.size());
103dad60f80SLang Hames   EXPECT_EQ(Hello, TargetHello);
104dad60f80SLang Hames 
105dad60f80SLang Hames   auto Err2 = (*Alloc)->deallocate();
106dad60f80SLang Hames   EXPECT_THAT_ERROR(std::move(Err2), Succeeded());
107dad60f80SLang Hames }
108dad60f80SLang Hames 
109dad60f80SLang Hames } // namespace
110