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