1//===------------------------ OrcRTBootstrap.cpp --------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/ExecutionEngine/Orc/TargetProcess/OrcRTBootstrap.h"
10
11#include "llvm/ExecutionEngine/Orc/Shared/Mangler.h"
12#include "llvm/TargetParser/Host.h"
13#include "llvm/TargetParser/Triple.h"
14
15#include "llvm/ExecutionEngine/Orc/Shared/SPSCI/CallSPSCI.h"
16#include "llvm/ExecutionEngine/Orc/Shared/SPSCI/MemoryAccessSPSCI.h"
17#include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
18#include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h"
19
20#define DEBUG_TYPE "orc"
21
22using namespace llvm::orc::shared;
23
24namespace llvm {
25namespace orc {
26namespace rt_bootstrap {
27
28template <typename WriteT, typename SPSWriteT>
29static llvm::orc::shared::CWrapperFunctionBuffer
30writeUIntsWrapper(const char *ArgData, size_t ArgSize) {
31 return WrapperFunction<void(SPSSequence<SPSWriteT>)>::handle(
32 ArgData, ArgSize,
33 [](std::vector<WriteT> Ws) {
34 for (auto &W : Ws)
35 *W.Addr.template toPtr<decltype(W.Value) *>() = W.Value;
36 })
37 .release();
38}
39
40static llvm::orc::shared::CWrapperFunctionBuffer
41writePointersWrapper(const char *ArgData, size_t ArgSize) {
42 return WrapperFunction<void(SPSSequence<SPSMemoryAccessPointerWrite>)>::
43 handle(ArgData, ArgSize,
44 Handler: [](std::vector<tpctypes::PointerWrite> Ws) {
45 for (auto &W : Ws)
46 *W.Addr.template toPtr<void **>() =
47 W.Value.template toPtr<void *>();
48 })
49 .release();
50}
51
52static llvm::orc::shared::CWrapperFunctionBuffer
53writeBuffersWrapper(const char *ArgData, size_t ArgSize) {
54 return WrapperFunction<void(SPSSequence<SPSMemoryAccessBufferWrite>)>::handle(
55 ArgData, ArgSize,
56 Handler: [](std::vector<tpctypes::BufferWrite> Ws) {
57 for (auto &W : Ws)
58 memcpy(dest: W.Addr.template toPtr<char *>(), src: W.Buffer.data(),
59 n: W.Buffer.size());
60 })
61 .release();
62}
63
64template <typename ReadT>
65static llvm::orc::shared::CWrapperFunctionBuffer
66readUIntsWrapper(const char *ArgData, size_t ArgSize) {
67 using SPSSig = SPSSequence<ReadT>(SPSSequence<SPSExecutorAddr>);
68 return WrapperFunction<SPSSig>::handle(ArgData, ArgSize,
69 [](std::vector<ExecutorAddr> Rs) {
70 std::vector<ReadT> Result;
71 Result.reserve(Rs.size());
72 for (auto &R : Rs)
73 Result.push_back(
74 *R.toPtr<ReadT *>());
75 return Result;
76 })
77 .release();
78}
79
80static llvm::orc::shared::CWrapperFunctionBuffer
81readPointersWrapper(const char *ArgData, size_t ArgSize) {
82 using SPSSig = SPSSequence<SPSExecutorAddr>(SPSSequence<SPSExecutorAddr>);
83 return WrapperFunction<SPSSig>::handle(
84 ArgData, ArgSize,
85 Handler: [](std::vector<ExecutorAddr> Rs) {
86 std::vector<ExecutorAddr> Result;
87 Result.reserve(n: Rs.size());
88 for (auto &R : Rs)
89 Result.push_back(x: ExecutorAddr::fromPtr(Ptr: *R.toPtr<void **>()));
90 return Result;
91 })
92 .release();
93}
94
95static llvm::orc::shared::CWrapperFunctionBuffer
96readBuffersWrapper(const char *ArgData, size_t ArgSize) {
97 using SPSSig =
98 SPSSequence<SPSSequence<uint8_t>>(SPSSequence<SPSExecutorAddrRange>);
99 return WrapperFunction<SPSSig>::handle(
100 ArgData, ArgSize,
101 Handler: [](std::vector<ExecutorAddrRange> Rs) {
102 std::vector<std::vector<uint8_t>> Result;
103 Result.reserve(n: Rs.size());
104 for (auto &R : Rs) {
105 Result.push_back(x: {});
106 Result.back().resize(new_size: R.size());
107 memcpy(dest: reinterpret_cast<char *>(Result.back().data()),
108 src: R.Start.toPtr<char *>(), n: R.size());
109 }
110 return Result;
111 })
112 .release();
113}
114
115static llvm::orc::shared::CWrapperFunctionBuffer
116readStringsWrapper(const char *ArgData, size_t ArgSize) {
117 using SPSSig = SPSSequence<SPSString>(SPSSequence<SPSExecutorAddr>);
118 return WrapperFunction<SPSSig>::handle(ArgData, ArgSize,
119 Handler: [](std::vector<ExecutorAddr> Rs) {
120 std::vector<std::string> Result;
121 Result.reserve(n: Rs.size());
122 for (auto &R : Rs)
123 Result.push_back(
124 x: R.toPtr<char *>());
125 return Result;
126 })
127 .release();
128}
129
130static llvm::orc::shared::CWrapperFunctionBuffer
131runAsMainWrapper(const char *ArgData, size_t ArgSize) {
132 return WrapperFunction<rt::sps_ci::CallMain::SPSSig>::handle(
133 ArgData, ArgSize,
134 Handler: [](ExecutorAddr MainAddr,
135 std::vector<std::string> Args) -> int64_t {
136 return runAsMain(Main: MainAddr.toPtr<int (*)(int, char *[])>(), Args);
137 })
138 .release();
139}
140
141static llvm::orc::shared::CWrapperFunctionBuffer
142runAsInt32VoidFunctionWrapper(const char *ArgData, size_t ArgSize) {
143 return WrapperFunction<rt::sps_ci::CallInt32Void::SPSSig>::handle(
144 ArgData, ArgSize,
145 Handler: [](ExecutorAddr MainAddr) -> int32_t {
146 return runAsVoidFunction(Func: MainAddr.toPtr<int32_t (*)(void)>());
147 })
148 .release();
149}
150
151static llvm::orc::shared::CWrapperFunctionBuffer
152runAsInt32Int32FunctionWrapper(const char *ArgData, size_t ArgSize) {
153 return WrapperFunction<rt::sps_ci::CallInt32Int32::SPSSig>::handle(
154 ArgData, ArgSize,
155 Handler: [](ExecutorAddr MainAddr, int32_t Arg) -> int32_t {
156 return runAsIntFunction(Func: MainAddr.toPtr<int32_t (*)(int32_t)>(),
157 Arg);
158 })
159 .release();
160}
161
162void addRunAsFunctionWrappersTo(StringMap<ExecutorAddr> &M) {
163 Mangler Mangle{Triple(sys::getProcessTriple())};
164 M[Mangle.mangledCopy(Name: rt::sps_ci::CallInt32Void::Name)] =
165 ExecutorAddr::fromPtr(Ptr: &runAsInt32VoidFunctionWrapper);
166 M[Mangle.mangledCopy(Name: rt::sps_ci::CallInt32Int32::Name)] =
167 ExecutorAddr::fromPtr(Ptr: &runAsInt32Int32FunctionWrapper);
168}
169
170void addTo(StringMap<ExecutorAddr> &M) {
171 Mangler Mangle{Triple(sys::getProcessTriple())};
172 M[Mangle.mangledCopy(Name: rt::sps_ci::MemWriteUInt8s::Name)] =
173 ExecutorAddr::fromPtr(
174 Ptr: &writeUIntsWrapper<tpctypes::UInt8Write,
175 shared::SPSMemoryAccessUInt8Write>);
176 M[Mangle.mangledCopy(Name: rt::sps_ci::MemWriteUInt16s::Name)] =
177 ExecutorAddr::fromPtr(
178 Ptr: &writeUIntsWrapper<tpctypes::UInt16Write,
179 shared::SPSMemoryAccessUInt16Write>);
180 M[Mangle.mangledCopy(Name: rt::sps_ci::MemWriteUInt32s::Name)] =
181 ExecutorAddr::fromPtr(
182 Ptr: &writeUIntsWrapper<tpctypes::UInt32Write,
183 shared::SPSMemoryAccessUInt32Write>);
184 M[Mangle.mangledCopy(Name: rt::sps_ci::MemWriteUInt64s::Name)] =
185 ExecutorAddr::fromPtr(
186 Ptr: &writeUIntsWrapper<tpctypes::UInt64Write,
187 shared::SPSMemoryAccessUInt64Write>);
188 M[Mangle.mangledCopy(Name: rt::sps_ci::MemWritePointers::Name)] =
189 ExecutorAddr::fromPtr(Ptr: &writePointersWrapper);
190 M[Mangle.mangledCopy(Name: rt::sps_ci::MemWriteBuffers::Name)] =
191 ExecutorAddr::fromPtr(Ptr: &writeBuffersWrapper);
192 M[Mangle.mangledCopy(Name: rt::sps_ci::MemReadUInt8s::Name)] =
193 ExecutorAddr::fromPtr(Ptr: &readUIntsWrapper<uint8_t>);
194 M[Mangle.mangledCopy(Name: rt::sps_ci::MemReadUInt16s::Name)] =
195 ExecutorAddr::fromPtr(Ptr: &readUIntsWrapper<uint16_t>);
196 M[Mangle.mangledCopy(Name: rt::sps_ci::MemReadUInt32s::Name)] =
197 ExecutorAddr::fromPtr(Ptr: &readUIntsWrapper<uint32_t>);
198 M[Mangle.mangledCopy(Name: rt::sps_ci::MemReadUInt64s::Name)] =
199 ExecutorAddr::fromPtr(Ptr: &readUIntsWrapper<uint64_t>);
200 M[Mangle.mangledCopy(Name: rt::sps_ci::MemReadPointers::Name)] =
201 ExecutorAddr::fromPtr(Ptr: &readPointersWrapper);
202 M[Mangle.mangledCopy(Name: rt::sps_ci::MemReadBuffers::Name)] =
203 ExecutorAddr::fromPtr(Ptr: &readBuffersWrapper);
204 M[Mangle.mangledCopy(Name: rt::sps_ci::MemReadStrings::Name)] =
205 ExecutorAddr::fromPtr(Ptr: &readStringsWrapper);
206 M[Mangle.mangledCopy(Name: rt::sps_ci::CallMain::Name)] =
207 ExecutorAddr::fromPtr(Ptr: &runAsMainWrapper);
208 addRunAsFunctionWrappersTo(M);
209}
210
211} // end namespace rt_bootstrap
212} // end namespace orc
213} // end namespace llvm
214