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