1 //===---- RemoteTargetExternal.cpp - LLVM out-of-process JIT execution ----===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Implementation of the RemoteTargetExternal class which executes JITed code
11 // in a separate process from where it was built.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/Config/config.h"
16 #include "RemoteTarget.h"
17 #include "RemoteTargetExternal.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/Support/DataTypes.h"
20 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/Format.h"
22 #include "llvm/Support/Memory.h"
23 #include "llvm/Support/Program.h"
24 #include "llvm/Support/raw_ostream.h"
29 #define DEBUG_TYPE "lli"
31 bool RemoteTargetExternal::allocateSpace(size_t Size, unsigned Alignment,
33 DEBUG(dbgs() << "Message [allocate space] size: " << Size <<
34 ", align: " << Alignment << "\n");
35 if (!SendAllocateSpace(Alignment, Size)) {
36 ErrorMsg += ", (RemoteTargetExternal::allocateSpace)";
39 if (!Receive(LLI_AllocationResult, Address)) {
40 ErrorMsg += ", (RemoteTargetExternal::allocateSpace)";
44 ErrorMsg += "failed allocation, (RemoteTargetExternal::allocateSpace)";
47 DEBUG(dbgs() << "Message [allocate space] addr: 0x" <<
48 format("%llx", Address) << "\n");
52 bool RemoteTargetExternal::loadData(uint64_t Address, const void *Data, size_t Size) {
53 DEBUG(dbgs() << "Message [load data] addr: 0x" << format("%llx", Address) <<
54 ", size: " << Size << "\n");
55 if (!SendLoadSection(Address, Data, (uint32_t)Size, false)) {
56 ErrorMsg += ", (RemoteTargetExternal::loadData)";
59 int Status = LLI_Status_Success;
60 if (!Receive(LLI_LoadResult, Status)) {
61 ErrorMsg += ", (RemoteTargetExternal::loadData)";
64 if (Status == LLI_Status_IncompleteMsg) {
65 ErrorMsg += "incomplete load data, (RemoteTargetExternal::loadData)";
68 if (Status == LLI_Status_NotAllocated) {
69 ErrorMsg += "data memory not allocated, (RemoteTargetExternal::loadData)";
72 DEBUG(dbgs() << "Message [load data] complete\n");
76 bool RemoteTargetExternal::loadCode(uint64_t Address, const void *Data, size_t Size) {
77 DEBUG(dbgs() << "Message [load code] addr: 0x" << format("%llx", Address) <<
78 ", size: " << Size << "\n");
79 if (!SendLoadSection(Address, Data, (uint32_t)Size, true)) {
80 ErrorMsg += ", (RemoteTargetExternal::loadCode)";
83 int Status = LLI_Status_Success;
84 if (!Receive(LLI_LoadResult, Status)) {
85 ErrorMsg += ", (RemoteTargetExternal::loadCode)";
88 if (Status == LLI_Status_IncompleteMsg) {
89 ErrorMsg += "incomplete load data, (RemoteTargetExternal::loadData)";
92 if (Status == LLI_Status_NotAllocated) {
93 ErrorMsg += "data memory not allocated, (RemoteTargetExternal::loadData)";
96 DEBUG(dbgs() << "Message [load code] complete\n");
100 bool RemoteTargetExternal::executeCode(uint64_t Address, int32_t &RetVal) {
101 DEBUG(dbgs() << "Message [exectue code] addr: " << Address << "\n");
102 if (!SendExecute(Address)) {
103 ErrorMsg += ", (RemoteTargetExternal::executeCode)";
106 if (!Receive(LLI_ExecutionResult, RetVal)) {
107 ErrorMsg += ", (RemoteTargetExternal::executeCode)";
110 DEBUG(dbgs() << "Message [exectue code] return: " << RetVal << "\n");
114 void RemoteTargetExternal::stop() {
119 bool RemoteTargetExternal::SendAllocateSpace(uint32_t Alignment, uint32_t Size) {
120 if (!SendHeader(LLI_AllocateSpace)) {
121 ErrorMsg += ", (RemoteTargetExternal::SendAllocateSpace)";
125 AppendWrite((const void *)&Alignment, 4);
126 AppendWrite((const void *)&Size, 4);
128 if (!SendPayload()) {
129 ErrorMsg += ", (RemoteTargetExternal::SendAllocateSpace)";
135 bool RemoteTargetExternal::SendLoadSection(uint64_t Addr,
139 LLIMessageType MsgType = IsCode ? LLI_LoadCodeSection : LLI_LoadDataSection;
140 if (!SendHeader(MsgType)) {
141 ErrorMsg += ", (RemoteTargetExternal::SendLoadSection)";
145 AppendWrite((const void *)&Addr, 8);
146 AppendWrite(Data, Size);
148 if (!SendPayload()) {
149 ErrorMsg += ", (RemoteTargetExternal::SendLoadSection)";
155 bool RemoteTargetExternal::SendExecute(uint64_t Addr) {
156 if (!SendHeader(LLI_Execute)) {
157 ErrorMsg += ", (RemoteTargetExternal::SendExecute)";
161 AppendWrite((const void *)&Addr, 8);
163 if (!SendPayload()) {
164 ErrorMsg += ", (RemoteTargetExternal::SendExecute)";
170 bool RemoteTargetExternal::SendTerminate() {
171 return SendHeader(LLI_Terminate);
172 // No data or data size is sent with Terminate
175 bool RemoteTargetExternal::Receive(LLIMessageType Msg) {
176 if (!ReceiveHeader(Msg))
179 AppendRead(&Unused, 0);
180 if (!ReceivePayload())
187 bool RemoteTargetExternal::Receive(LLIMessageType Msg, int32_t &Data) {
188 if (!ReceiveHeader(Msg))
190 AppendRead(&Data, 4);
191 if (!ReceivePayload())
198 bool RemoteTargetExternal::Receive(LLIMessageType Msg, uint64_t &Data) {
199 if (!ReceiveHeader(Msg))
201 AppendRead(&Data, 8);
202 if (!ReceivePayload())
209 bool RemoteTargetExternal::ReceiveHeader(LLIMessageType ExpectedMsgType) {
210 assert(ReceiveData.empty() && Sizes.empty() &&
211 "Payload vector not empty to receive header");
213 // Message header, with type to follow
215 if (!ReadBytes(&MsgType, 4)) {
216 ErrorMsg += ", (RemoteTargetExternal::ReceiveHeader)";
219 if (MsgType != (uint32_t)ExpectedMsgType) {
220 ErrorMsg = "received unexpected message type";
221 ErrorMsg += ". Expecting: ";
222 ErrorMsg += ExpectedMsgType;
223 ErrorMsg += ", Got: ";
230 bool RemoteTargetExternal::ReceivePayload() {
231 assert(!ReceiveData.empty() &&
232 "Payload vector empty to receive");
233 assert(ReceiveData.size() == Sizes.size() &&
234 "Unexpected mismatch between data and size");
236 uint32_t TotalSize = 0;
237 for (int I=0, E=Sizes.size(); I < E; I++)
238 TotalSize += Sizes[I];
240 // Payload size header
242 if (!ReadBytes(&DataSize, 4)) {
243 ErrorMsg += ", invalid data size";
246 if (DataSize != TotalSize) {
247 ErrorMsg = "unexpected data size";
248 ErrorMsg += ". Expecting: ";
249 ErrorMsg += TotalSize;
250 ErrorMsg += ", Got: ";
251 ErrorMsg += DataSize;
258 for (int I=0, E=Sizes.size(); I < E; I++) {
259 if (!ReadBytes(ReceiveData[I], Sizes[I])) {
260 ErrorMsg = "unexpected data while reading message";
268 bool RemoteTargetExternal::SendHeader(LLIMessageType MsgType) {
269 assert(SendData.empty() && Sizes.empty() &&
270 "Payload vector not empty to send header");
272 // Message header, with type to follow
273 if (!WriteBytes(&MsgType, 4)) {
274 ErrorMsg += ", (RemoteTargetExternal::SendHeader)";
280 bool RemoteTargetExternal::SendPayload() {
281 assert(!SendData.empty() && !Sizes.empty() &&
282 "Payload vector empty to send");
283 assert(SendData.size() == Sizes.size() &&
284 "Unexpected mismatch between data and size");
286 uint32_t TotalSize = 0;
287 for (int I=0, E=Sizes.size(); I < E; I++)
288 TotalSize += Sizes[I];
290 // Payload size header
291 if (!WriteBytes(&TotalSize, 4)) {
292 ErrorMsg += ", invalid data size";
299 for (int I=0, E=Sizes.size(); I < E; I++) {
300 if (!WriteBytes(SendData[I], Sizes[I])) {
301 ErrorMsg = "unexpected data while writing message";
311 void RemoteTargetExternal::AppendWrite(const void *Data, uint32_t Size) {
312 SendData.push_back(Data);
313 Sizes.push_back(Size);
316 void RemoteTargetExternal::AppendRead(void *Data, uint32_t Size) {
317 ReceiveData.push_back(Data);
318 Sizes.push_back(Size);
322 #include "Unix/RPCChannel.inc"
326 #include "Windows/RPCChannel.inc"