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