1259698Sdim#include "llvm/Config/config.h"
2259698Sdim
3259698Sdim#include "../RemoteTargetMessage.h"
4259698Sdim#include <assert.h>
5259698Sdim#include <map>
6259698Sdim#include <stdint.h>
7259698Sdim#include <string>
8259698Sdim#include <vector>
9259698Sdim
10259698Sdimusing namespace llvm;
11259698Sdim
12259698Sdimclass LLIChildTarget {
13259698Sdimpublic:
14259698Sdim  ~LLIChildTarget(); // OS-specific destructor
15259698Sdim  void initialize();
16259698Sdim  LLIMessageType waitForIncomingMessage();
17259698Sdim  void handleMessage(LLIMessageType messageType);
18259698Sdim
19259698Sdimprivate:
20259698Sdim  // Incoming message handlers
21259698Sdim  void handleAllocateSpace();
22259698Sdim  void handleLoadSection(bool IsCode);
23259698Sdim  void handleExecute();
24259698Sdim  void handleTerminate();
25259698Sdim
26259698Sdim  // Outgoing message handlers
27259698Sdim  void sendChildActive();
28259698Sdim  void sendAllocationResult(uint64_t Addr);
29259698Sdim  void sendLoadComplete();
30259698Sdim  void sendExecutionComplete(uint64_t Result);
31259698Sdim
32259698Sdim  // OS-specific functions
33259698Sdim  void initializeConnection();
34259698Sdim  int WriteBytes(const void *Data, size_t Size);
35259698Sdim  int ReadBytes(void *Data, size_t Size);
36259698Sdim  uint64_t allocate(uint32_t Alignment, uint32_t Size);
37259698Sdim  void makeSectionExecutable(uint64_t Addr, uint32_t Size);
38259698Sdim  void InvalidateInstructionCache(const void *Addr, size_t Len);
39259698Sdim  void releaseMemory(uint64_t Addr, uint32_t Size);
40259698Sdim
41259698Sdim  // Store a map of allocated buffers to sizes.
42259698Sdim  typedef std::map<uint64_t, uint32_t> AllocMapType;
43259698Sdim  AllocMapType m_AllocatedBufferMap;
44259698Sdim
45259698Sdim  // Communication handles (OS-specific)
46259698Sdim  void *ConnectionData;
47259698Sdim};
48259698Sdim
49259698Sdimint main() {
50259698Sdim  LLIChildTarget  ThisChild;
51259698Sdim  ThisChild.initialize();
52259698Sdim  LLIMessageType MsgType;
53259698Sdim  do {
54259698Sdim    MsgType = ThisChild.waitForIncomingMessage();
55259698Sdim    ThisChild.handleMessage(MsgType);
56259698Sdim  } while (MsgType != LLI_Terminate &&
57259698Sdim           MsgType != LLI_Error);
58259698Sdim  return 0;
59259698Sdim}
60259698Sdim
61259698Sdim// Public methods
62259698Sdimvoid LLIChildTarget::initialize() {
63259698Sdim  initializeConnection();
64259698Sdim  sendChildActive();
65259698Sdim}
66259698Sdim
67259698SdimLLIMessageType LLIChildTarget::waitForIncomingMessage() {
68259698Sdim  int32_t MsgType = -1;
69259698Sdim  if (ReadBytes(&MsgType, 4) > 0)
70259698Sdim    return (LLIMessageType)MsgType;
71259698Sdim  return LLI_Error;
72259698Sdim}
73259698Sdim
74259698Sdimvoid LLIChildTarget::handleMessage(LLIMessageType messageType) {
75259698Sdim  switch (messageType) {
76259698Sdim    case LLI_AllocateSpace:
77259698Sdim      handleAllocateSpace();
78259698Sdim      break;
79259698Sdim    case LLI_LoadCodeSection:
80259698Sdim      handleLoadSection(true);
81259698Sdim      break;
82259698Sdim    case LLI_LoadDataSection:
83259698Sdim      handleLoadSection(false);
84259698Sdim      break;
85259698Sdim    case LLI_Execute:
86259698Sdim      handleExecute();
87259698Sdim      break;
88259698Sdim    case LLI_Terminate:
89259698Sdim      handleTerminate();
90259698Sdim      break;
91259698Sdim    default:
92259698Sdim      // FIXME: Handle error!
93259698Sdim      break;
94259698Sdim  }
95259698Sdim}
96259698Sdim
97259698Sdim// Incoming message handlers
98259698Sdimvoid LLIChildTarget::handleAllocateSpace() {
99259698Sdim  // Read and verify the message data size.
100259698Sdim  uint32_t DataSize;
101259698Sdim  int rc = ReadBytes(&DataSize, 4);
102259698Sdim  assert(rc == 4);
103259698Sdim  assert(DataSize == 8);
104259698Sdim
105259698Sdim  // Read the message arguments.
106259698Sdim  uint32_t Alignment;
107259698Sdim  uint32_t AllocSize;
108259698Sdim  rc = ReadBytes(&Alignment, 4);
109259698Sdim  assert(rc == 4);
110259698Sdim  rc = ReadBytes(&AllocSize, 4);
111259698Sdim  assert(rc == 4);
112259698Sdim
113259698Sdim  // Allocate the memory.
114259698Sdim  uint64_t Addr = allocate(Alignment, AllocSize);
115259698Sdim
116259698Sdim  // Send AllocationResult message.
117259698Sdim  sendAllocationResult(Addr);
118259698Sdim}
119259698Sdim
120259698Sdimvoid LLIChildTarget::handleLoadSection(bool IsCode) {
121259698Sdim  // Read the message data size.
122259698Sdim  uint32_t DataSize;
123259698Sdim  int rc = ReadBytes(&DataSize, 4);
124259698Sdim  assert(rc == 4);
125259698Sdim
126259698Sdim  // Read the target load address.
127259698Sdim  uint64_t Addr;
128259698Sdim  rc = ReadBytes(&Addr, 8);
129259698Sdim  assert(rc == 8);
130259698Sdim
131259698Sdim  size_t BufferSize = DataSize - 8;
132259698Sdim
133259698Sdim  // FIXME: Verify that this is in allocated space
134259698Sdim
135259698Sdim  // Read section data into previously allocated buffer
136259698Sdim  rc = ReadBytes((void*)Addr, DataSize - 8);
137259698Sdim  assert(rc == (int)(BufferSize));
138259698Sdim
139259698Sdim  // If IsCode, mark memory executable
140259698Sdim  if (IsCode)
141259698Sdim    makeSectionExecutable(Addr, BufferSize);
142259698Sdim
143259698Sdim  // Send MarkLoadComplete message.
144259698Sdim  sendLoadComplete();
145259698Sdim}
146259698Sdim
147259698Sdimvoid LLIChildTarget::handleExecute() {
148259698Sdim  // Read the message data size.
149259698Sdim  uint32_t DataSize;
150259698Sdim  int rc = ReadBytes(&DataSize, 4);
151259698Sdim  assert(rc == 4);
152259698Sdim  assert(DataSize == 8);
153259698Sdim
154259698Sdim  // Read the target address.
155259698Sdim  uint64_t Addr;
156259698Sdim  rc = ReadBytes(&Addr, 8);
157259698Sdim  assert(rc == 8);
158259698Sdim
159259698Sdim  // Call function
160259698Sdim  int Result;
161259698Sdim  int (*fn)(void) = (int(*)(void))Addr;
162259698Sdim  Result = fn();
163259698Sdim
164259698Sdim  // Send ExecutionResult message.
165259698Sdim  sendExecutionComplete((int64_t)Result);
166259698Sdim}
167259698Sdim
168259698Sdimvoid LLIChildTarget::handleTerminate() {
169259698Sdim  // Release all allocated memory
170259698Sdim  AllocMapType::iterator Begin = m_AllocatedBufferMap.begin();
171259698Sdim  AllocMapType::iterator End = m_AllocatedBufferMap.end();
172259698Sdim  for (AllocMapType::iterator It = Begin; It != End; ++It) {
173259698Sdim    releaseMemory(It->first, It->second);
174259698Sdim  }
175259698Sdim  m_AllocatedBufferMap.clear();
176259698Sdim}
177259698Sdim
178259698Sdim// Outgoing message handlers
179259698Sdimvoid LLIChildTarget::sendChildActive() {
180259698Sdim  // Write the message type.
181259698Sdim  uint32_t MsgType = (uint32_t)LLI_ChildActive;
182259698Sdim  int rc = WriteBytes(&MsgType, 4);
183259698Sdim  assert(rc == 4);
184259698Sdim
185259698Sdim  // Write the data size.
186259698Sdim  uint32_t DataSize = 0;
187259698Sdim  rc = WriteBytes(&DataSize, 4);
188259698Sdim  assert(rc == 4);
189259698Sdim}
190259698Sdim
191259698Sdimvoid LLIChildTarget::sendAllocationResult(uint64_t Addr) {
192259698Sdim  // Write the message type.
193259698Sdim  uint32_t MsgType = (uint32_t)LLI_AllocationResult;
194259698Sdim  int rc = WriteBytes(&MsgType, 4);
195259698Sdim  assert(rc == 4);
196259698Sdim
197259698Sdim  // Write the data size.
198259698Sdim  uint32_t DataSize = 8;
199259698Sdim  rc = WriteBytes(&DataSize, 4);
200259698Sdim  assert(rc == 4);
201259698Sdim
202259698Sdim  // Write the allocated address.
203259698Sdim  rc = WriteBytes(&Addr, 8);
204259698Sdim  assert(rc == 8);
205259698Sdim}
206259698Sdim
207259698Sdimvoid LLIChildTarget::sendLoadComplete() {
208259698Sdim  // Write the message type.
209259698Sdim  uint32_t MsgType = (uint32_t)LLI_LoadComplete;
210259698Sdim  int rc = WriteBytes(&MsgType, 4);
211259698Sdim  assert(rc == 4);
212259698Sdim
213259698Sdim  // Write the data size.
214259698Sdim  uint32_t DataSize = 0;
215259698Sdim  rc = WriteBytes(&DataSize, 4);
216259698Sdim  assert(rc == 4);
217259698Sdim}
218259698Sdim
219259698Sdimvoid LLIChildTarget::sendExecutionComplete(uint64_t Result) {
220259698Sdim  // Write the message type.
221259698Sdim  uint32_t MsgType = (uint32_t)LLI_ExecutionResult;
222259698Sdim  int rc = WriteBytes(&MsgType, 4);
223259698Sdim  assert(rc == 4);
224259698Sdim
225259698Sdim
226259698Sdim  // Write the data size.
227259698Sdim  uint32_t DataSize = 8;
228259698Sdim  rc = WriteBytes(&DataSize, 4);
229259698Sdim  assert(rc == 4);
230259698Sdim
231259698Sdim  // Write the result.
232259698Sdim  rc = WriteBytes(&Result, 8);
233259698Sdim  assert(rc == 8);
234259698Sdim}
235259698Sdim
236259698Sdim#ifdef LLVM_ON_UNIX
237259698Sdim#include "Unix/ChildTarget.inc"
238259698Sdim#endif
239259698Sdim
240259698Sdim#ifdef LLVM_ON_WIN32
241259698Sdim#include "Windows/ChildTarget.inc"
242259698Sdim#endif
243