1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
|
#pragma once
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
//===--- SimpleRemoteEPCUtils.h - Utils for Simple Remote EPC ---*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Message definitions and other utilities for SimpleRemoteEPC and
// SimpleRemoteEPCServer.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEREMOTEEPCUTILS_H
#define LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEREMOTEEPCUTILS_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
#include "llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h"
#include "llvm/Support/Error.h"
#include <atomic>
#include <mutex>
#include <string>
#include <thread>
namespace llvm {
namespace orc {
namespace SimpleRemoteEPCDefaultBootstrapSymbolNames {
extern const char *ExecutorSessionObjectName;
extern const char *DispatchFnName;
} // end namespace SimpleRemoteEPCDefaultBootstrapSymbolNames
enum class SimpleRemoteEPCOpcode : uint8_t {
Setup,
Hangup,
Result,
CallWrapper,
LastOpC = CallWrapper
};
struct SimpleRemoteEPCExecutorInfo {
std::string TargetTriple;
uint64_t PageSize;
StringMap<ExecutorAddr> BootstrapSymbols;
};
using SimpleRemoteEPCArgBytesVector = SmallVector<char, 128>;
class SimpleRemoteEPCTransportClient {
public:
enum HandleMessageAction { ContinueSession, EndSession };
virtual ~SimpleRemoteEPCTransportClient();
/// Handle receipt of a message.
///
/// Returns an Error if the message cannot be handled, 'EndSession' if the
/// client will not accept any further messages, and 'ContinueSession'
/// otherwise.
virtual Expected<HandleMessageAction>
handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, ExecutorAddr TagAddr,
SimpleRemoteEPCArgBytesVector ArgBytes) = 0;
/// Handle a disconnection from the underlying transport. No further messages
/// should be sent to handleMessage after this is called.
/// Err may contain an Error value indicating unexpected disconnection. This
/// allows clients to log such errors, but no attempt should be made at
/// recovery (which should be handled inside the transport class, if it is
/// supported at all).
virtual void handleDisconnect(Error Err) = 0;
};
class SimpleRemoteEPCTransport {
public:
virtual ~SimpleRemoteEPCTransport();
/// Called during setup of the client to indicate that the client is ready
/// to receive messages.
///
/// Transport objects should not access the client until this method is
/// called.
virtual Error start() = 0;
/// Send a SimpleRemoteEPC message.
///
/// This function may be called concurrently. Subclasses should implement
/// locking if required for the underlying transport.
virtual Error sendMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,
ExecutorAddr TagAddr, ArrayRef<char> ArgBytes) = 0;
/// Trigger disconnection from the transport. The implementation should
/// respond by calling handleDisconnect on the client once disconnection
/// is complete. May be called more than once and from different threads.
virtual void disconnect() = 0;
};
/// Uses read/write on FileDescriptors for transport.
class FDSimpleRemoteEPCTransport : public SimpleRemoteEPCTransport {
public:
/// Create a FDSimpleRemoteEPCTransport using the given FDs for
/// reading (InFD) and writing (OutFD).
static Expected<std::unique_ptr<FDSimpleRemoteEPCTransport>>
Create(SimpleRemoteEPCTransportClient &C, int InFD, int OutFD);
/// Create a FDSimpleRemoteEPCTransport using the given FD for both
/// reading and writing.
static Expected<std::unique_ptr<FDSimpleRemoteEPCTransport>>
Create(SimpleRemoteEPCTransportClient &C, int FD) {
return Create(C, FD, FD);
}
~FDSimpleRemoteEPCTransport() override;
Error start() override;
Error sendMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,
ExecutorAddr TagAddr, ArrayRef<char> ArgBytes) override;
void disconnect() override;
private:
FDSimpleRemoteEPCTransport(SimpleRemoteEPCTransportClient &C, int InFD,
int OutFD)
: C(C), InFD(InFD), OutFD(OutFD) {}
Error readBytes(char *Dst, size_t Size, bool *IsEOF = nullptr);
int writeBytes(const char *Src, size_t Size);
void listenLoop();
std::mutex M;
SimpleRemoteEPCTransportClient &C;
std::thread ListenerThread;
int InFD, OutFD;
std::atomic<bool> Disconnected{false};
};
struct RemoteSymbolLookupSetElement {
std::string Name;
bool Required;
};
using RemoteSymbolLookupSet = std::vector<RemoteSymbolLookupSetElement>;
struct RemoteSymbolLookup {
uint64_t H;
RemoteSymbolLookupSet Symbols;
};
namespace shared {
using SPSRemoteSymbolLookupSetElement = SPSTuple<SPSString, bool>;
using SPSRemoteSymbolLookupSet = SPSSequence<SPSRemoteSymbolLookupSetElement>;
using SPSRemoteSymbolLookup = SPSTuple<uint64_t, SPSRemoteSymbolLookupSet>;
/// Tuple containing target triple, page size, and bootstrap symbols.
using SPSSimpleRemoteEPCExecutorInfo =
SPSTuple<SPSString, uint64_t,
SPSSequence<SPSTuple<SPSString, SPSExecutorAddr>>>;
template <>
class SPSSerializationTraits<SPSRemoteSymbolLookupSetElement,
RemoteSymbolLookupSetElement> {
public:
static size_t size(const RemoteSymbolLookupSetElement &V) {
return SPSArgList<SPSString, bool>::size(V.Name, V.Required);
}
static size_t serialize(SPSOutputBuffer &OB,
const RemoteSymbolLookupSetElement &V) {
return SPSArgList<SPSString, bool>::serialize(OB, V.Name, V.Required);
}
static size_t deserialize(SPSInputBuffer &IB,
RemoteSymbolLookupSetElement &V) {
return SPSArgList<SPSString, bool>::deserialize(IB, V.Name, V.Required);
}
};
template <>
class SPSSerializationTraits<SPSRemoteSymbolLookup, RemoteSymbolLookup> {
public:
static size_t size(const RemoteSymbolLookup &V) {
return SPSArgList<uint64_t, SPSRemoteSymbolLookupSet>::size(V.H, V.Symbols);
}
static size_t serialize(SPSOutputBuffer &OB, const RemoteSymbolLookup &V) {
return SPSArgList<uint64_t, SPSRemoteSymbolLookupSet>::serialize(OB, V.H,
V.Symbols);
}
static size_t deserialize(SPSInputBuffer &IB, RemoteSymbolLookup &V) {
return SPSArgList<uint64_t, SPSRemoteSymbolLookupSet>::deserialize(
IB, V.H, V.Symbols);
}
};
template <>
class SPSSerializationTraits<SPSSimpleRemoteEPCExecutorInfo,
SimpleRemoteEPCExecutorInfo> {
public:
static size_t size(const SimpleRemoteEPCExecutorInfo &SI) {
return SPSSimpleRemoteEPCExecutorInfo::AsArgList ::size(
SI.TargetTriple, SI.PageSize, SI.BootstrapSymbols);
}
static bool serialize(SPSOutputBuffer &OB,
const SimpleRemoteEPCExecutorInfo &SI) {
return SPSSimpleRemoteEPCExecutorInfo::AsArgList ::serialize(
OB, SI.TargetTriple, SI.PageSize, SI.BootstrapSymbols);
}
static bool deserialize(SPSInputBuffer &IB, SimpleRemoteEPCExecutorInfo &SI) {
return SPSSimpleRemoteEPCExecutorInfo::AsArgList ::deserialize(
IB, SI.TargetTriple, SI.PageSize, SI.BootstrapSymbols);
}
};
using SPSLoadDylibSignature = SPSExpected<SPSExecutorAddr>(SPSExecutorAddr,
SPSString, uint64_t);
using SPSLookupSymbolsSignature =
SPSExpected<SPSSequence<SPSSequence<SPSExecutorAddr>>>(
SPSExecutorAddr, SPSSequence<SPSRemoteSymbolLookup>);
} // end namespace shared
} // end namespace orc
} // end namespace llvm
#endif // LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEREMOTEEPCUTILS_H
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
|