1*2c8e7849SLang Hames //===------------------------ OrcRTBootstrap.cpp --------------------------===// 2*2c8e7849SLang Hames // 3*2c8e7849SLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*2c8e7849SLang Hames // See https://llvm.org/LICENSE.txt for license information. 5*2c8e7849SLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*2c8e7849SLang Hames // 7*2c8e7849SLang Hames //===----------------------------------------------------------------------===// 8*2c8e7849SLang Hames 9*2c8e7849SLang Hames #include "OrcRTBootstrap.h" 10*2c8e7849SLang Hames 11*2c8e7849SLang Hames #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h" 12*2c8e7849SLang Hames #include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h" 13*2c8e7849SLang Hames #include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h" 14*2c8e7849SLang Hames 15*2c8e7849SLang Hames #define DEBUG_TYPE "orc" 16*2c8e7849SLang Hames 17*2c8e7849SLang Hames using namespace llvm::orc::shared; 18*2c8e7849SLang Hames 19*2c8e7849SLang Hames namespace llvm { 20*2c8e7849SLang Hames namespace orc { 21*2c8e7849SLang Hames namespace rt_bootstrap { 22*2c8e7849SLang Hames 23*2c8e7849SLang Hames static llvm::orc::shared::detail::CWrapperFunctionResult 24*2c8e7849SLang Hames reserveWrapper(const char *ArgData, size_t ArgSize) { 25*2c8e7849SLang Hames return WrapperFunction<rt::SPSMemoryReserveSignature>::handle( 26*2c8e7849SLang Hames ArgData, ArgSize, 27*2c8e7849SLang Hames [](uint64_t Size) -> Expected<ExecutorAddress> { 28*2c8e7849SLang Hames std::error_code EC; 29*2c8e7849SLang Hames auto MB = sys::Memory::allocateMappedMemory( 30*2c8e7849SLang Hames Size, 0, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC); 31*2c8e7849SLang Hames if (EC) 32*2c8e7849SLang Hames return errorCodeToError(EC); 33*2c8e7849SLang Hames return ExecutorAddress::fromPtr(MB.base()); 34*2c8e7849SLang Hames }) 35*2c8e7849SLang Hames .release(); 36*2c8e7849SLang Hames } 37*2c8e7849SLang Hames 38*2c8e7849SLang Hames static llvm::orc::shared::detail::CWrapperFunctionResult 39*2c8e7849SLang Hames finalizeWrapper(const char *ArgData, size_t ArgSize) { 40*2c8e7849SLang Hames return WrapperFunction<rt::SPSMemoryFinalizeSignature>::handle( 41*2c8e7849SLang Hames ArgData, ArgSize, 42*2c8e7849SLang Hames [](const tpctypes::FinalizeRequest &FR) -> Error { 43*2c8e7849SLang Hames for (auto &Seg : FR) { 44*2c8e7849SLang Hames char *Mem = Seg.Addr.toPtr<char *>(); 45*2c8e7849SLang Hames memcpy(Mem, Seg.Content.data(), Seg.Content.size()); 46*2c8e7849SLang Hames memset(Mem + Seg.Content.size(), 0, 47*2c8e7849SLang Hames Seg.Size - Seg.Content.size()); 48*2c8e7849SLang Hames assert(Seg.Size <= std::numeric_limits<size_t>::max()); 49*2c8e7849SLang Hames if (auto EC = sys::Memory::protectMappedMemory( 50*2c8e7849SLang Hames {Mem, static_cast<size_t>(Seg.Size)}, 51*2c8e7849SLang Hames tpctypes::fromWireProtectionFlags(Seg.Prot))) 52*2c8e7849SLang Hames return errorCodeToError(EC); 53*2c8e7849SLang Hames if (Seg.Prot & tpctypes::WPF_Exec) 54*2c8e7849SLang Hames sys::Memory::InvalidateInstructionCache(Mem, Seg.Size); 55*2c8e7849SLang Hames } 56*2c8e7849SLang Hames return Error::success(); 57*2c8e7849SLang Hames }) 58*2c8e7849SLang Hames .release(); 59*2c8e7849SLang Hames } 60*2c8e7849SLang Hames 61*2c8e7849SLang Hames static llvm::orc::shared::detail::CWrapperFunctionResult 62*2c8e7849SLang Hames deallocateWrapper(const char *ArgData, size_t ArgSize) { 63*2c8e7849SLang Hames return WrapperFunction<rt::SPSMemoryDeallocateSignature>::handle( 64*2c8e7849SLang Hames ArgData, ArgSize, 65*2c8e7849SLang Hames [](ExecutorAddress Base, uint64_t Size) -> Error { 66*2c8e7849SLang Hames sys::MemoryBlock MB(Base.toPtr<void *>(), Size); 67*2c8e7849SLang Hames if (auto EC = sys::Memory::releaseMappedMemory(MB)) 68*2c8e7849SLang Hames return errorCodeToError(EC); 69*2c8e7849SLang Hames return Error::success(); 70*2c8e7849SLang Hames }) 71*2c8e7849SLang Hames .release(); 72*2c8e7849SLang Hames } 73*2c8e7849SLang Hames 74*2c8e7849SLang Hames template <typename WriteT, typename SPSWriteT> 75*2c8e7849SLang Hames static llvm::orc::shared::detail::CWrapperFunctionResult 76*2c8e7849SLang Hames writeUIntsWrapper(const char *ArgData, size_t ArgSize) { 77*2c8e7849SLang Hames return WrapperFunction<void(SPSSequence<SPSWriteT>)>::handle( 78*2c8e7849SLang Hames ArgData, ArgSize, 79*2c8e7849SLang Hames [](std::vector<WriteT> Ws) { 80*2c8e7849SLang Hames for (auto &W : Ws) 81*2c8e7849SLang Hames *jitTargetAddressToPointer<decltype(W.Value) *>(W.Address) = 82*2c8e7849SLang Hames W.Value; 83*2c8e7849SLang Hames }) 84*2c8e7849SLang Hames .release(); 85*2c8e7849SLang Hames } 86*2c8e7849SLang Hames 87*2c8e7849SLang Hames static llvm::orc::shared::detail::CWrapperFunctionResult 88*2c8e7849SLang Hames writeBuffersWrapper(const char *ArgData, size_t ArgSize) { 89*2c8e7849SLang Hames return WrapperFunction<void(SPSSequence<SPSMemoryAccessBufferWrite>)>::handle( 90*2c8e7849SLang Hames ArgData, ArgSize, 91*2c8e7849SLang Hames [](std::vector<tpctypes::BufferWrite> Ws) { 92*2c8e7849SLang Hames for (auto &W : Ws) 93*2c8e7849SLang Hames memcpy(jitTargetAddressToPointer<char *>(W.Address), 94*2c8e7849SLang Hames W.Buffer.data(), W.Buffer.size()); 95*2c8e7849SLang Hames }) 96*2c8e7849SLang Hames .release(); 97*2c8e7849SLang Hames } 98*2c8e7849SLang Hames 99*2c8e7849SLang Hames static llvm::orc::shared::detail::CWrapperFunctionResult 100*2c8e7849SLang Hames runAsMainWrapper(const char *ArgData, size_t ArgSize) { 101*2c8e7849SLang Hames return WrapperFunction<rt::SPSRunAsMainSignature>::handle( 102*2c8e7849SLang Hames ArgData, ArgSize, 103*2c8e7849SLang Hames [](ExecutorAddress MainAddr, 104*2c8e7849SLang Hames std::vector<std::string> Args) -> int64_t { 105*2c8e7849SLang Hames return runAsMain(MainAddr.toPtr<int (*)(int, char *[])>(), Args); 106*2c8e7849SLang Hames }) 107*2c8e7849SLang Hames .release(); 108*2c8e7849SLang Hames } 109*2c8e7849SLang Hames 110*2c8e7849SLang Hames void addTo(StringMap<ExecutorAddress> &M) { 111*2c8e7849SLang Hames M[rt::MemoryReserveWrapperName] = ExecutorAddress::fromPtr(&reserveWrapper); 112*2c8e7849SLang Hames M[rt::MemoryFinalizeWrapperName] = ExecutorAddress::fromPtr(&finalizeWrapper); 113*2c8e7849SLang Hames M[rt::MemoryDeallocateWrapperName] = 114*2c8e7849SLang Hames ExecutorAddress::fromPtr(&deallocateWrapper); 115*2c8e7849SLang Hames M[rt::MemoryWriteUInt8sWrapperName] = ExecutorAddress::fromPtr( 116*2c8e7849SLang Hames &writeUIntsWrapper<tpctypes::UInt8Write, 117*2c8e7849SLang Hames shared::SPSMemoryAccessUInt8Write>); 118*2c8e7849SLang Hames M[rt::MemoryWriteUInt16sWrapperName] = ExecutorAddress::fromPtr( 119*2c8e7849SLang Hames &writeUIntsWrapper<tpctypes::UInt16Write, 120*2c8e7849SLang Hames shared::SPSMemoryAccessUInt16Write>); 121*2c8e7849SLang Hames M[rt::MemoryWriteUInt32sWrapperName] = ExecutorAddress::fromPtr( 122*2c8e7849SLang Hames &writeUIntsWrapper<tpctypes::UInt32Write, 123*2c8e7849SLang Hames shared::SPSMemoryAccessUInt32Write>); 124*2c8e7849SLang Hames M[rt::MemoryWriteUInt64sWrapperName] = ExecutorAddress::fromPtr( 125*2c8e7849SLang Hames &writeUIntsWrapper<tpctypes::UInt64Write, 126*2c8e7849SLang Hames shared::SPSMemoryAccessUInt64Write>); 127*2c8e7849SLang Hames M[rt::MemoryWriteBuffersWrapperName] = 128*2c8e7849SLang Hames ExecutorAddress::fromPtr(&writeBuffersWrapper); 129*2c8e7849SLang Hames M[rt::RunAsMainWrapperName] = ExecutorAddress::fromPtr(&runAsMainWrapper); 130*2c8e7849SLang Hames } 131*2c8e7849SLang Hames 132*2c8e7849SLang Hames } // end namespace rt_bootstrap 133*2c8e7849SLang Hames } // end namespace orc 134*2c8e7849SLang Hames } // end namespace llvm 135