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