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