blob: c1bc8dfe99ca991144abbebd99b7bf2365445aac [file] [log] [blame]
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +00001//===---- RemoteTargetExternal.cpp - LLVM out-of-process JIT execution ----===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Implementation of the RemoteTargetExternal class which executes JITed code
11// in a separate process from where it was built.
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm/Config/config.h"
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +000016#include "RemoteTarget.h"
17#include "RemoteTargetExternal.h"
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +000018#include "llvm/ADT/StringRef.h"
19#include "llvm/Support/DataTypes.h"
Renato Golin695895c2014-01-14 22:43:43 +000020#include "llvm/Support/Debug.h"
21#include "llvm/Support/Format.h"
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +000022#include "llvm/Support/Memory.h"
23#include "llvm/Support/Program.h"
24#include "llvm/Support/raw_ostream.h"
25#include <string>
26
27using namespace llvm;
28
29bool RemoteTargetExternal::allocateSpace(size_t Size, unsigned Alignment,
30 uint64_t &Address) {
Renato Golin695895c2014-01-14 22:43:43 +000031 DEBUG(dbgs() << "Message [allocate space] size: " << Size <<
32 ", align: " << Alignment << "\n");
33 if (!SendAllocateSpace(Alignment, Size)) {
34 ErrorMsg += ", (RemoteTargetExternal::allocateSpace)";
35 return false;
36 }
37 if (!Receive(LLI_AllocationResult, Address)) {
38 ErrorMsg += ", (RemoteTargetExternal::allocateSpace)";
39 return false;
40 }
41 if (Address == 0) {
42 ErrorMsg += "failed allocation, (RemoteTargetExternal::allocateSpace)";
43 return false;
44 }
45 DEBUG(dbgs() << "Message [allocate space] addr: 0x" <<
46 format("%llx", Address) << "\n");
47 return true;
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +000048}
49
50bool RemoteTargetExternal::loadData(uint64_t Address, const void *Data, size_t Size) {
Renato Golin695895c2014-01-14 22:43:43 +000051 DEBUG(dbgs() << "Message [load data] addr: 0x" << format("%llx", Address) <<
52 ", size: " << Size << "\n");
53 if (!SendLoadSection(Address, Data, (uint32_t)Size, false)) {
54 ErrorMsg += ", (RemoteTargetExternal::loadData)";
55 return false;
56 }
57 int Status = LLI_Status_Success;
58 if (!Receive(LLI_LoadResult, Status)) {
59 ErrorMsg += ", (RemoteTargetExternal::loadData)";
60 return false;
61 }
62 if (Status == LLI_Status_IncompleteMsg) {
63 ErrorMsg += "incomplete load data, (RemoteTargetExternal::loadData)";
64 return false;
65 }
66 if (Status == LLI_Status_NotAllocated) {
67 ErrorMsg += "data memory not allocated, (RemoteTargetExternal::loadData)";
68 return false;
69 }
70 DEBUG(dbgs() << "Message [load data] complete\n");
71 return true;
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +000072}
73
74bool RemoteTargetExternal::loadCode(uint64_t Address, const void *Data, size_t Size) {
Renato Golin695895c2014-01-14 22:43:43 +000075 DEBUG(dbgs() << "Message [load code] addr: 0x" << format("%llx", Address) <<
76 ", size: " << Size << "\n");
77 if (!SendLoadSection(Address, Data, (uint32_t)Size, true)) {
78 ErrorMsg += ", (RemoteTargetExternal::loadCode)";
79 return false;
80 }
81 int Status = LLI_Status_Success;
82 if (!Receive(LLI_LoadResult, Status)) {
83 ErrorMsg += ", (RemoteTargetExternal::loadCode)";
84 return false;
85 }
86 if (Status == LLI_Status_IncompleteMsg) {
87 ErrorMsg += "incomplete load data, (RemoteTargetExternal::loadData)";
88 return false;
89 }
90 if (Status == LLI_Status_NotAllocated) {
91 ErrorMsg += "data memory not allocated, (RemoteTargetExternal::loadData)";
92 return false;
93 }
94 DEBUG(dbgs() << "Message [load code] complete\n");
95 return true;
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +000096}
97
Renato Golin695895c2014-01-14 22:43:43 +000098bool RemoteTargetExternal::executeCode(uint64_t Address, int32_t &RetVal) {
99 DEBUG(dbgs() << "Message [exectue code] addr: " << Address << "\n");
100 if (!SendExecute(Address)) {
101 ErrorMsg += ", (RemoteTargetExternal::executeCode)";
102 return false;
103 }
104 if (!Receive(LLI_ExecutionResult, RetVal)) {
105 ErrorMsg += ", (RemoteTargetExternal::executeCode)";
106 return false;
107 }
108 DEBUG(dbgs() << "Message [exectue code] return: " << RetVal << "\n");
109 return true;
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +0000110}
111
112void RemoteTargetExternal::stop() {
113 SendTerminate();
Alp Toker632c6cd2014-01-23 22:19:45 +0000114 RPC.Wait();
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +0000115}
116
Renato Golin695895c2014-01-14 22:43:43 +0000117bool RemoteTargetExternal::SendAllocateSpace(uint32_t Alignment, uint32_t Size) {
118 if (!SendHeader(LLI_AllocateSpace)) {
119 ErrorMsg += ", (RemoteTargetExternal::SendAllocateSpace)";
120 return false;
121 }
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +0000122
Renato Golin695895c2014-01-14 22:43:43 +0000123 AppendWrite((const void *)&Alignment, 4);
124 AppendWrite((const void *)&Size, 4);
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +0000125
Renato Golin695895c2014-01-14 22:43:43 +0000126 if (!SendPayload()) {
127 ErrorMsg += ", (RemoteTargetExternal::SendAllocateSpace)";
128 return false;
129 }
130 return true;
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +0000131}
132
Renato Golin695895c2014-01-14 22:43:43 +0000133bool RemoteTargetExternal::SendLoadSection(uint64_t Addr,
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +0000134 const void *Data,
135 uint32_t Size,
136 bool IsCode) {
Renato Golin695895c2014-01-14 22:43:43 +0000137 LLIMessageType MsgType = IsCode ? LLI_LoadCodeSection : LLI_LoadDataSection;
138 if (!SendHeader(MsgType)) {
139 ErrorMsg += ", (RemoteTargetExternal::SendLoadSection)";
140 return false;
141 }
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +0000142
Renato Golin695895c2014-01-14 22:43:43 +0000143 AppendWrite((const void *)&Addr, 8);
144 AppendWrite(Data, Size);
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +0000145
Renato Golin695895c2014-01-14 22:43:43 +0000146 if (!SendPayload()) {
147 ErrorMsg += ", (RemoteTargetExternal::SendLoadSection)";
148 return false;
149 }
150 return true;
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +0000151}
152
Renato Golin695895c2014-01-14 22:43:43 +0000153bool RemoteTargetExternal::SendExecute(uint64_t Addr) {
154 if (!SendHeader(LLI_Execute)) {
155 ErrorMsg += ", (RemoteTargetExternal::SendExecute)";
156 return false;
157 }
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +0000158
Renato Golin695895c2014-01-14 22:43:43 +0000159 AppendWrite((const void *)&Addr, 8);
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +0000160
Renato Golin695895c2014-01-14 22:43:43 +0000161 if (!SendPayload()) {
162 ErrorMsg += ", (RemoteTargetExternal::SendExecute)";
163 return false;
164 }
165 return true;
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +0000166}
167
Renato Golin695895c2014-01-14 22:43:43 +0000168bool RemoteTargetExternal::SendTerminate() {
169 return SendHeader(LLI_Terminate);
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +0000170 // No data or data size is sent with Terminate
171}
172
Renato Golin695895c2014-01-14 22:43:43 +0000173bool RemoteTargetExternal::Receive(LLIMessageType Msg) {
174 if (!ReceiveHeader(Msg))
175 return false;
176 int Unused;
177 AppendRead(&Unused, 0);
178 if (!ReceivePayload())
179 return false;
180 ReceiveData.clear();
181 Sizes.clear();
182 return true;
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +0000183}
184
Renato Golin695895c2014-01-14 22:43:43 +0000185bool RemoteTargetExternal::Receive(LLIMessageType Msg, int32_t &Data) {
186 if (!ReceiveHeader(Msg))
187 return false;
188 AppendRead(&Data, 4);
189 if (!ReceivePayload())
190 return false;
191 ReceiveData.clear();
192 Sizes.clear();
193 return true;
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +0000194}
195
Renato Golin695895c2014-01-14 22:43:43 +0000196bool RemoteTargetExternal::Receive(LLIMessageType Msg, uint64_t &Data) {
197 if (!ReceiveHeader(Msg))
198 return false;
199 AppendRead(&Data, 8);
200 if (!ReceivePayload())
201 return false;
202 ReceiveData.clear();
203 Sizes.clear();
204 return true;
205}
206
207bool RemoteTargetExternal::ReceiveHeader(LLIMessageType ExpectedMsgType) {
208 assert(ReceiveData.empty() && Sizes.empty() &&
209 "Payload vector not empty to receive header");
210
211 // Message header, with type to follow
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +0000212 uint32_t MsgType;
Renato Golin695895c2014-01-14 22:43:43 +0000213 if (!ReadBytes(&MsgType, 4)) {
214 ErrorMsg += ", (RemoteTargetExternal::ReceiveHeader)";
215 return false;
216 }
217 if (MsgType != (uint32_t)ExpectedMsgType) {
218 ErrorMsg = "received unexpected message type";
219 ErrorMsg += ". Expecting: ";
220 ErrorMsg += ExpectedMsgType;
221 ErrorMsg += ", Got: ";
222 ErrorMsg += MsgType;
223 return false;
224 }
225 return true;
226}
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +0000227
Renato Golin695895c2014-01-14 22:43:43 +0000228bool RemoteTargetExternal::ReceivePayload() {
229 assert(!ReceiveData.empty() &&
230 "Payload vector empty to receive");
231 assert(ReceiveData.size() == Sizes.size() &&
232 "Unexpected mismatch between data and size");
233
234 uint32_t TotalSize = 0;
235 for (int I=0, E=Sizes.size(); I < E; I++)
236 TotalSize += Sizes[I];
237
238 // Payload size header
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +0000239 uint32_t DataSize;
Renato Golin695895c2014-01-14 22:43:43 +0000240 if (!ReadBytes(&DataSize, 4)) {
241 ErrorMsg += ", invalid data size";
242 return false;
243 }
244 if (DataSize != TotalSize) {
245 ErrorMsg = "unexpected data size";
246 ErrorMsg += ". Expecting: ";
247 ErrorMsg += TotalSize;
248 ErrorMsg += ", Got: ";
249 ErrorMsg += DataSize;
250 return false;
251 }
252 if (DataSize == 0)
253 return true;
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +0000254
Renato Golin695895c2014-01-14 22:43:43 +0000255 // Payload itself
256 for (int I=0, E=Sizes.size(); I < E; I++) {
257 if (!ReadBytes(ReceiveData[I], Sizes[I])) {
258 ErrorMsg = "unexpected data while reading message";
259 return false;
260 }
261 }
262
263 return true;
264}
265
266bool RemoteTargetExternal::SendHeader(LLIMessageType MsgType) {
267 assert(SendData.empty() && Sizes.empty() &&
268 "Payload vector not empty to send header");
269
270 // Message header, with type to follow
271 if (!WriteBytes(&MsgType, 4)) {
272 ErrorMsg += ", (RemoteTargetExternal::SendHeader)";
273 return false;
274 }
275 return true;
276}
277
278bool RemoteTargetExternal::SendPayload() {
279 assert(!SendData.empty() && !Sizes.empty() &&
280 "Payload vector empty to send");
281 assert(SendData.size() == Sizes.size() &&
282 "Unexpected mismatch between data and size");
283
284 uint32_t TotalSize = 0;
285 for (int I=0, E=Sizes.size(); I < E; I++)
286 TotalSize += Sizes[I];
287
288 // Payload size header
289 if (!WriteBytes(&TotalSize, 4)) {
290 ErrorMsg += ", invalid data size";
291 return false;
292 }
293 if (TotalSize == 0)
294 return true;
295
296 // Payload itself
297 for (int I=0, E=Sizes.size(); I < E; I++) {
298 if (!WriteBytes(SendData[I], Sizes[I])) {
299 ErrorMsg = "unexpected data while writing message";
300 return false;
301 }
302 }
303
304 SendData.clear();
305 Sizes.clear();
306 return true;
307}
308
309void RemoteTargetExternal::AppendWrite(const void *Data, uint32_t Size) {
310 SendData.push_back(Data);
311 Sizes.push_back(Size);
312}
313
314void RemoteTargetExternal::AppendRead(void *Data, uint32_t Size) {
315 ReceiveData.push_back(Data);
316 Sizes.push_back(Size);
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +0000317}
318
319#ifdef LLVM_ON_UNIX
Alp Toker632c6cd2014-01-23 22:19:45 +0000320#include "Unix/RPCChannel.inc"
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +0000321#endif
322
323#ifdef LLVM_ON_WIN32
Alp Toker632c6cd2014-01-23 22:19:45 +0000324#include "Windows/RPCChannel.inc"
Andrew Kaylorc2ebf3f2013-10-02 17:12:36 +0000325#endif