1259698Sdim//===---- RemoteTargetExternal.cpp - LLVM out-of-process JIT execution ----===//
2259698Sdim//
3259698Sdim//                     The LLVM Compiler Infrastructure
4259698Sdim//
5259698Sdim// This file is distributed under the University of Illinois Open Source
6259698Sdim// License. See LICENSE.TXT for details.
7259698Sdim//
8259698Sdim//===----------------------------------------------------------------------===//
9259698Sdim//
10259698Sdim// Implementation of the RemoteTargetExternal class which executes JITed code
11259698Sdim// in a separate process from where it was built.
12259698Sdim//
13259698Sdim//===----------------------------------------------------------------------===//
14259698Sdim
15259698Sdim#include "llvm/Config/config.h"
16259698Sdim
17259698Sdim#include "RemoteTarget.h"
18259698Sdim#include "RemoteTargetExternal.h"
19259698Sdim
20259698Sdim#include "llvm/ADT/StringRef.h"
21259698Sdim#include "llvm/Support/DataTypes.h"
22259698Sdim#include "llvm/Support/Memory.h"
23259698Sdim#include "llvm/Support/Program.h"
24259698Sdim#include "llvm/Support/raw_ostream.h"
25259698Sdim#include <string>
26259698Sdim
27259698Sdimusing namespace llvm;
28259698Sdim
29259698Sdimbool RemoteTargetExternal::allocateSpace(size_t Size, unsigned Alignment,
30259698Sdim                                 uint64_t &Address) {
31259698Sdim  SendAllocateSpace(Alignment, Size);
32259698Sdim  Receive(LLI_AllocationResult, Address);
33259698Sdim  return false;
34259698Sdim}
35259698Sdim
36259698Sdimbool RemoteTargetExternal::loadData(uint64_t Address, const void *Data, size_t Size) {
37259698Sdim  SendLoadSection(Address, Data, (uint32_t)Size, false);
38259698Sdim  Receive(LLI_LoadComplete);
39259698Sdim  return false;
40259698Sdim}
41259698Sdim
42259698Sdimbool RemoteTargetExternal::loadCode(uint64_t Address, const void *Data, size_t Size) {
43259698Sdim  SendLoadSection(Address, Data, (uint32_t)Size, true);
44259698Sdim  Receive(LLI_LoadComplete);
45259698Sdim  return false;
46259698Sdim}
47259698Sdim
48259698Sdimbool RemoteTargetExternal::executeCode(uint64_t Address, int &RetVal) {
49259698Sdim  SendExecute(Address);
50259698Sdim
51259698Sdim  Receive(LLI_ExecutionResult, RetVal);
52259698Sdim  return false;
53259698Sdim}
54259698Sdim
55259698Sdimvoid RemoteTargetExternal::stop() {
56259698Sdim  SendTerminate();
57259698Sdim  Wait();
58259698Sdim}
59259698Sdim
60259698Sdimvoid RemoteTargetExternal::SendAllocateSpace(uint32_t Alignment, uint32_t Size) {
61259698Sdim  int rc;
62259698Sdim  uint32_t MsgType = (uint32_t)LLI_AllocateSpace;
63259698Sdim  rc = WriteBytes(&MsgType, 4);
64259698Sdim  assert(rc == 4 && "Error writing message type.");
65259698Sdim
66259698Sdim  uint32_t DataSize = 8;
67259698Sdim  rc = WriteBytes(&DataSize, 4);
68259698Sdim  assert(rc == 4 && "Error writing data size.");
69259698Sdim
70259698Sdim  rc = WriteBytes(&Alignment, 4);
71259698Sdim  assert(rc == 4 && "Error writing alignment data.");
72259698Sdim
73259698Sdim  rc = WriteBytes(&Size, 4);
74259698Sdim  assert(rc == 4 && "Error writing size data.");
75259698Sdim}
76259698Sdim
77259698Sdimvoid RemoteTargetExternal::SendLoadSection(uint64_t Addr,
78259698Sdim                                       const void *Data,
79259698Sdim                                       uint32_t Size,
80259698Sdim                                       bool IsCode) {
81259698Sdim  int rc;
82259698Sdim  uint32_t MsgType = IsCode ? LLI_LoadCodeSection : LLI_LoadDataSection;
83259698Sdim  rc = WriteBytes(&MsgType, 4);
84259698Sdim  assert(rc == 4 && "Error writing message type.");
85259698Sdim
86259698Sdim  uint32_t DataSize = Size + 8;
87259698Sdim  rc = WriteBytes(&DataSize, 4);
88259698Sdim  assert(rc == 4 && "Error writing data size.");
89259698Sdim
90259698Sdim  rc = WriteBytes(&Addr, 8);
91259698Sdim  assert(rc == 8 && "Error writing data.");
92259698Sdim
93259698Sdim  rc = WriteBytes(Data, Size);
94259698Sdim  assert(rc == (int)Size && "Error writing data.");
95259698Sdim}
96259698Sdim
97259698Sdimvoid RemoteTargetExternal::SendExecute(uint64_t Addr) {
98259698Sdim  int rc;
99259698Sdim  uint32_t MsgType = (uint32_t)LLI_Execute;
100259698Sdim  rc = WriteBytes(&MsgType, 4);
101259698Sdim  assert(rc == 4 && "Error writing message type.");
102259698Sdim
103259698Sdim  uint32_t DataSize = 8;
104259698Sdim  rc = WriteBytes(&DataSize, 4);
105259698Sdim  assert(rc == 4 && "Error writing data size.");
106259698Sdim
107259698Sdim  rc = WriteBytes(&Addr, 8);
108259698Sdim  assert(rc == 8 && "Error writing data.");
109259698Sdim}
110259698Sdim
111259698Sdimvoid RemoteTargetExternal::SendTerminate() {
112259698Sdim  int rc;
113259698Sdim  uint32_t MsgType = (uint32_t)LLI_Terminate;
114259698Sdim  rc = WriteBytes(&MsgType, 4);
115259698Sdim  assert(rc == 4 && "Error writing message type.");
116259698Sdim
117259698Sdim  // No data or data size is sent with Terminate
118259698Sdim}
119259698Sdim
120259698Sdim
121259698Sdimvoid RemoteTargetExternal::Receive(LLIMessageType ExpectedMsgType) {
122259698Sdim  int rc;
123259698Sdim  uint32_t MsgType;
124259698Sdim  rc = ReadBytes(&MsgType, 4);
125259698Sdim  assert(rc == 4 && "Error reading message type.");
126259698Sdim  assert(MsgType == (uint32_t)ExpectedMsgType && "Error: received unexpected message type.");
127259698Sdim
128259698Sdim  uint32_t DataSize;
129259698Sdim  rc = ReadBytes(&DataSize, 4);
130259698Sdim  assert(rc == 4 && "Error reading data size.");
131259698Sdim  assert(DataSize == 0 && "Error: unexpected data size.");
132259698Sdim}
133259698Sdim
134259698Sdimvoid RemoteTargetExternal::Receive(LLIMessageType ExpectedMsgType, int &Data) {
135259698Sdim  uint64_t Temp;
136259698Sdim  Receive(ExpectedMsgType, Temp);
137259698Sdim  Data = (int)(int64_t)Temp;
138259698Sdim}
139259698Sdim
140259698Sdimvoid RemoteTargetExternal::Receive(LLIMessageType ExpectedMsgType, uint64_t &Data) {
141259698Sdim  int rc;
142259698Sdim  uint32_t MsgType;
143259698Sdim  rc = ReadBytes(&MsgType, 4);
144259698Sdim  assert(rc == 4 && "Error reading message type.");
145259698Sdim  assert(MsgType == (uint32_t)ExpectedMsgType && "Error: received unexpected message type.");
146259698Sdim
147259698Sdim  uint32_t DataSize;
148259698Sdim  rc = ReadBytes(&DataSize, 4);
149259698Sdim  assert(rc == 4 && "Error reading data size.");
150259698Sdim  assert(DataSize == 8 && "Error: unexpected data size.");
151259698Sdim
152259698Sdim  rc = ReadBytes(&Data, 8);
153259698Sdim  assert(DataSize == 8 && "Error: unexpected data.");
154259698Sdim}
155259698Sdim
156259698Sdim#ifdef LLVM_ON_UNIX
157259698Sdim#include "Unix/RemoteTargetExternal.inc"
158259698Sdim#endif
159259698Sdim
160259698Sdim#ifdef LLVM_ON_WIN32
161259698Sdim#include "Windows/RemoteTargetExternal.inc"
162259698Sdim#endif
163