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