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