6c537d47df3d1ee5443fd94d1b6faa3d0ad1bc35
[oota-llvm.git] / tools / lli / ChildTarget / ChildTarget.cpp
1 #include "llvm/Config/config.h"
2 #include "../RPCChannel.h"
3 #include "../RemoteTarget.h"
4 #include "../RemoteTargetMessage.h"
5 #include "llvm/Support/Memory.h"
6 #include <assert.h>
7 #include <map>
8 #include <stdint.h>
9 #include <string>
10 #include <vector>
11
12 using namespace llvm;
13
14 class LLIChildTarget {
15 public:
16   void initialize();
17   LLIMessageType waitForIncomingMessage();
18   void handleMessage(LLIMessageType messageType);
19   RemoteTarget *RT;
20   RPCChannel RPC;
21
22 private:
23   // Incoming message handlers
24   void handleAllocateSpace();
25   void handleLoadSection(bool IsCode);
26   void handleExecute();
27
28   // Outgoing message handlers
29   void sendChildActive();
30   void sendAllocationResult(uint64_t Addr);
31   void sendLoadStatus(uint32_t Status);
32   void sendExecutionComplete(int Result);
33
34   // OS-specific functions
35   void initializeConnection();
36   int WriteBytes(const void *Data, size_t Size) {
37     return RPC.WriteBytes(Data, Size) ? Size : -1;
38   }
39   int ReadBytes(void *Data, size_t Size) {
40     return RPC.ReadBytes(Data, Size) ? Size : -1;
41   }
42
43   // Communication handles (OS-specific)
44   void *ConnectionData;
45 };
46
47 int main() {
48   LLIChildTarget  ThisChild;
49   ThisChild.RT = new RemoteTarget();
50   ThisChild.initialize();
51   LLIMessageType MsgType;
52   do {
53     MsgType = ThisChild.waitForIncomingMessage();
54     ThisChild.handleMessage(MsgType);
55   } while (MsgType != LLI_Terminate &&
56            MsgType != LLI_Error);
57   delete ThisChild.RT;
58   return 0;
59 }
60
61 // Public methods
62 void LLIChildTarget::initialize() {
63   RPC.createClient();
64   sendChildActive();
65 }
66
67 LLIMessageType LLIChildTarget::waitForIncomingMessage() {
68   int32_t MsgType = -1;
69   if (ReadBytes(&MsgType, 4) > 0)
70     return (LLIMessageType)MsgType;
71   return LLI_Error;
72 }
73
74 void LLIChildTarget::handleMessage(LLIMessageType messageType) {
75   switch (messageType) {
76     case LLI_AllocateSpace:
77       handleAllocateSpace();
78       break;
79     case LLI_LoadCodeSection:
80       handleLoadSection(true);
81       break;
82     case LLI_LoadDataSection:
83       handleLoadSection(false);
84       break;
85     case LLI_Execute:
86       handleExecute();
87       break;
88     case LLI_Terminate:
89       RT->stop();
90       break;
91     default:
92       // FIXME: Handle error!
93       break;
94   }
95 }
96
97 // Incoming message handlers
98 void LLIChildTarget::handleAllocateSpace() {
99   // Read and verify the message data size.
100   uint32_t DataSize = 0;
101   int rc = ReadBytes(&DataSize, 4);
102   (void)rc;
103   assert(rc == 4);
104   assert(DataSize == 8);
105
106   // Read the message arguments.
107   uint32_t Alignment = 0;
108   uint32_t AllocSize = 0;
109   rc = ReadBytes(&Alignment, 4);
110   assert(rc == 4);
111   rc = ReadBytes(&AllocSize, 4);
112   assert(rc == 4);
113
114   // Allocate the memory.
115   uint64_t Addr;
116   RT->allocateSpace(AllocSize, Alignment, Addr);
117
118   // Send AllocationResult message.
119   sendAllocationResult(Addr);
120 }
121
122 void LLIChildTarget::handleLoadSection(bool IsCode) {
123   // Read the message data size.
124   uint32_t DataSize = 0;
125   int rc = ReadBytes(&DataSize, 4);
126   (void)rc;
127   assert(rc == 4);
128
129   // Read the target load address.
130   uint64_t Addr = 0;
131   rc = ReadBytes(&Addr, 8);
132   assert(rc == 8);
133   size_t BufferSize = DataSize - 8;
134
135   if (!RT->isAllocatedMemory(Addr, BufferSize))
136     return sendLoadStatus(LLI_Status_NotAllocated);
137
138   // Read section data into previously allocated buffer
139   rc = ReadBytes((void*)Addr, BufferSize);
140   if (rc != (int)(BufferSize))
141     return sendLoadStatus(LLI_Status_IncompleteMsg);
142
143   // If IsCode, mark memory executable
144   if (IsCode)
145     sys::Memory::InvalidateInstructionCache((void *)Addr, BufferSize);
146
147   // Send MarkLoadComplete message.
148   sendLoadStatus(LLI_Status_Success);
149 }
150
151 void LLIChildTarget::handleExecute() {
152   // Read the message data size.
153   uint32_t DataSize = 0;
154   int rc = ReadBytes(&DataSize, 4);
155   (void)rc;
156   assert(rc == 4);
157   assert(DataSize == 8);
158
159   // Read the target address.
160   uint64_t Addr = 0;
161   rc = ReadBytes(&Addr, 8);
162   assert(rc == 8);
163
164   // Call function
165   int32_t Result = -1;
166   RT->executeCode(Addr, Result);
167
168   // Send ExecutionResult message.
169   sendExecutionComplete(Result);
170 }
171
172 // Outgoing message handlers
173 void LLIChildTarget::sendChildActive() {
174   // Write the message type.
175   uint32_t MsgType = (uint32_t)LLI_ChildActive;
176   int rc = WriteBytes(&MsgType, 4);
177   (void)rc;
178   assert(rc == 4);
179
180   // Write the data size.
181   uint32_t DataSize = 0;
182   rc = WriteBytes(&DataSize, 4);
183   assert(rc == 4);
184 }
185
186 void LLIChildTarget::sendAllocationResult(uint64_t Addr) {
187   // Write the message type.
188   uint32_t MsgType = (uint32_t)LLI_AllocationResult;
189   int rc = WriteBytes(&MsgType, 4);
190   (void)rc;
191   assert(rc == 4);
192
193   // Write the data size.
194   uint32_t DataSize = 8;
195   rc = WriteBytes(&DataSize, 4);
196   assert(rc == 4);
197
198   // Write the allocated address.
199   rc = WriteBytes(&Addr, 8);
200   assert(rc == 8);
201 }
202
203 void LLIChildTarget::sendLoadStatus(uint32_t Status) {
204   // Write the message type.
205   uint32_t MsgType = (uint32_t)LLI_LoadResult;
206   int rc = WriteBytes(&MsgType, 4);
207   (void)rc;
208   assert(rc == 4);
209
210   // Write the data size.
211   uint32_t DataSize = 4;
212   rc = WriteBytes(&DataSize, 4);
213   assert(rc == 4);
214
215   // Write the result.
216   rc = WriteBytes(&Status, 4);
217   assert(rc == 4);
218 }
219
220 void LLIChildTarget::sendExecutionComplete(int Result) {
221   // Write the message type.
222   uint32_t MsgType = (uint32_t)LLI_ExecutionResult;
223   int rc = WriteBytes(&MsgType, 4);
224   (void)rc;
225   assert(rc == 4);
226
227
228   // Write the data size.
229   uint32_t DataSize = 4;
230   rc = WriteBytes(&DataSize, 4);
231   assert(rc == 4);
232
233   // Write the result.
234   rc = WriteBytes(&Result, 4);
235   assert(rc == 4);
236 }
237
238 #ifdef LLVM_ON_UNIX
239 #include "../Unix/RPCChannel.inc"
240 #endif
241
242 #ifdef LLVM_ON_WIN32
243 #include "../Windows/RPCChannel.inc"
244 #endif