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 "OrcRTBootstrap.h"
10
11#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
12#include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
13#include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
14#include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h"
15
16#define DEBUG_TYPE "orc"
17
18using namespace llvm::orc::shared;
19
20namespace llvm {
21namespace orc {
22namespace rt_bootstrap {
23
24template <typename WriteT, typename SPSWriteT>
25static llvm::orc::shared::CWrapperFunctionResult
26writeUIntsWrapper(const char *ArgData, size_t ArgSize) {
27 return WrapperFunction<void(SPSSequence<SPSWriteT>)>::handle(
28 ArgData, ArgSize,
29 [](std::vector<WriteT> Ws) {
30 for (auto &W : Ws)
31 *W.Addr.template toPtr<decltype(W.Value) *>() = W.Value;
32 })
33 .release();
34}
35
36static llvm::orc::shared::CWrapperFunctionResult
37writePointersWrapper(const char *ArgData, size_t ArgSize) {
38 return WrapperFunction<void(SPSSequence<SPSMemoryAccessPointerWrite>)>::
39 handle(ArgData, ArgSize,
40 Handler: [](std::vector<tpctypes::PointerWrite> Ws) {
41 for (auto &W : Ws)
42 *W.Addr.template toPtr<void **>() =
43 W.Value.template toPtr<void *>();
44 })
45 .release();
46}
47
48static llvm::orc::shared::CWrapperFunctionResult
49writeBuffersWrapper(const char *ArgData, size_t ArgSize) {
50 return WrapperFunction<void(SPSSequence<SPSMemoryAccessBufferWrite>)>::handle(
51 ArgData, ArgSize,
52 Handler: [](std::vector<tpctypes::BufferWrite> Ws) {
53 for (auto &W : Ws)
54 memcpy(dest: W.Addr.template toPtr<char *>(), src: W.Buffer.data(),
55 n: W.Buffer.size());
56 })
57 .release();
58}
59
60template <typename ReadT>
61static llvm::orc::shared::CWrapperFunctionResult
62readUIntsWrapper(const char *ArgData, size_t ArgSize) {
63 using SPSSig = SPSSequence<ReadT>(SPSSequence<SPSExecutorAddr>);
64 return WrapperFunction<SPSSig>::handle(ArgData, ArgSize,
65 [](std::vector<ExecutorAddr> Rs) {
66 std::vector<ReadT> Result;
67 Result.reserve(Rs.size());
68 for (auto &R : Rs)
69 Result.push_back(
70 *R.toPtr<ReadT *>());
71 return Result;
72 })
73 .release();
74}
75
76static llvm::orc::shared::CWrapperFunctionResult
77readPointersWrapper(const char *ArgData, size_t ArgSize) {
78 using SPSSig = SPSSequence<SPSExecutorAddr>(SPSSequence<SPSExecutorAddr>);
79 return WrapperFunction<SPSSig>::handle(
80 ArgData, ArgSize,
81 Handler: [](std::vector<ExecutorAddr> Rs) {
82 std::vector<ExecutorAddr> Result;
83 Result.reserve(n: Rs.size());
84 for (auto &R : Rs)
85 Result.push_back(x: ExecutorAddr::fromPtr(Ptr: *R.toPtr<void **>()));
86 return Result;
87 })
88 .release();
89}
90
91static llvm::orc::shared::CWrapperFunctionResult
92readBuffersWrapper(const char *ArgData, size_t ArgSize) {
93 using SPSSig =
94 SPSSequence<SPSSequence<uint8_t>>(SPSSequence<SPSExecutorAddrRange>);
95 return WrapperFunction<SPSSig>::handle(
96 ArgData, ArgSize,
97 Handler: [](std::vector<ExecutorAddrRange> Rs) {
98 std::vector<std::vector<uint8_t>> Result;
99 Result.reserve(n: Rs.size());
100 for (auto &R : Rs) {
101 Result.push_back(x: {});
102 Result.back().resize(new_size: R.size());
103 memcpy(dest: reinterpret_cast<char *>(Result.back().data()),
104 src: R.Start.toPtr<char *>(), n: R.size());
105 }
106 return Result;
107 })
108 .release();
109}
110
111static llvm::orc::shared::CWrapperFunctionResult
112readStringsWrapper(const char *ArgData, size_t ArgSize) {
113 using SPSSig = SPSSequence<SPSString>(SPSSequence<SPSExecutorAddr>);
114 return WrapperFunction<SPSSig>::handle(ArgData, ArgSize,
115 Handler: [](std::vector<ExecutorAddr> Rs) {
116 std::vector<std::string> Result;
117 Result.reserve(n: Rs.size());
118 for (auto &R : Rs)
119 Result.push_back(
120 x: R.toPtr<char *>());
121 return Result;
122 })
123 .release();
124}
125
126static llvm::orc::shared::CWrapperFunctionResult
127runAsMainWrapper(const char *ArgData, size_t ArgSize) {
128 return WrapperFunction<rt::SPSRunAsMainSignature>::handle(
129 ArgData, ArgSize,
130 Handler: [](ExecutorAddr MainAddr,
131 std::vector<std::string> Args) -> int64_t {
132 return runAsMain(Main: MainAddr.toPtr<int (*)(int, char *[])>(), Args);
133 })
134 .release();
135}
136
137static llvm::orc::shared::CWrapperFunctionResult
138runAsVoidFunctionWrapper(const char *ArgData, size_t ArgSize) {
139 return WrapperFunction<rt::SPSRunAsVoidFunctionSignature>::handle(
140 ArgData, ArgSize,
141 Handler: [](ExecutorAddr MainAddr) -> int32_t {
142 return runAsVoidFunction(Func: MainAddr.toPtr<int32_t (*)(void)>());
143 })
144 .release();
145}
146
147static llvm::orc::shared::CWrapperFunctionResult
148runAsIntFunctionWrapper(const char *ArgData, size_t ArgSize) {
149 return WrapperFunction<rt::SPSRunAsIntFunctionSignature>::handle(
150 ArgData, ArgSize,
151 Handler: [](ExecutorAddr MainAddr, int32_t Arg) -> int32_t {
152 return runAsIntFunction(Func: MainAddr.toPtr<int32_t (*)(int32_t)>(),
153 Arg);
154 })
155 .release();
156}
157
158void addTo(StringMap<ExecutorAddr> &M) {
159 M[rt::MemoryWriteUInt8sWrapperName] = ExecutorAddr::fromPtr(
160 Ptr: &writeUIntsWrapper<tpctypes::UInt8Write,
161 shared::SPSMemoryAccessUInt8Write>);
162 M[rt::MemoryWriteUInt16sWrapperName] = ExecutorAddr::fromPtr(
163 Ptr: &writeUIntsWrapper<tpctypes::UInt16Write,
164 shared::SPSMemoryAccessUInt16Write>);
165 M[rt::MemoryWriteUInt32sWrapperName] = ExecutorAddr::fromPtr(
166 Ptr: &writeUIntsWrapper<tpctypes::UInt32Write,
167 shared::SPSMemoryAccessUInt32Write>);
168 M[rt::MemoryWriteUInt64sWrapperName] = ExecutorAddr::fromPtr(
169 Ptr: &writeUIntsWrapper<tpctypes::UInt64Write,
170 shared::SPSMemoryAccessUInt64Write>);
171 M[rt::MemoryWritePointersWrapperName] =
172 ExecutorAddr::fromPtr(Ptr: &writePointersWrapper);
173 M[rt::MemoryWriteBuffersWrapperName] =
174 ExecutorAddr::fromPtr(Ptr: &writeBuffersWrapper);
175 M[rt::MemoryReadUInt8sWrapperName] =
176 ExecutorAddr::fromPtr(Ptr: &readUIntsWrapper<uint8_t>);
177 M[rt::MemoryReadUInt16sWrapperName] =
178 ExecutorAddr::fromPtr(Ptr: &readUIntsWrapper<uint16_t>);
179 M[rt::MemoryReadUInt32sWrapperName] =
180 ExecutorAddr::fromPtr(Ptr: &readUIntsWrapper<uint32_t>);
181 M[rt::MemoryReadUInt64sWrapperName] =
182 ExecutorAddr::fromPtr(Ptr: &readUIntsWrapper<uint64_t>);
183 M[rt::MemoryReadPointersWrapperName] =
184 ExecutorAddr::fromPtr(Ptr: &readPointersWrapper);
185 M[rt::MemoryReadBuffersWrapperName] =
186 ExecutorAddr::fromPtr(Ptr: &readBuffersWrapper);
187 M[rt::MemoryReadStringsWrapperName] =
188 ExecutorAddr::fromPtr(Ptr: &readStringsWrapper);
189 M[rt::RunAsMainWrapperName] = ExecutorAddr::fromPtr(Ptr: &runAsMainWrapper);
190 M[rt::RunAsVoidFunctionWrapperName] =
191 ExecutorAddr::fromPtr(Ptr: &runAsVoidFunctionWrapper);
192 M[rt::RunAsIntFunctionWrapperName] =
193 ExecutorAddr::fromPtr(Ptr: &runAsIntFunctionWrapper);
194}
195
196} // end namespace rt_bootstrap
197} // end namespace orc
198} // end namespace llvm
199