21
21
22
22
#include " llvm/Support/BinaryStreamError.h"
23
23
#include " llvm/Support/BinaryStreamWriter.h"
24
+ #include " swift/Basic/ExponentialGrowthAppendingBinaryByteStream.h"
24
25
#include < map>
25
26
26
27
namespace {
@@ -35,7 +36,7 @@ class ByteTreeWriter;
35
36
36
37
using UserInfoMap = std::map<void *, void *>;
37
38
38
- // / Add a template specialization of \c ObjectTraits for any that type
39
+ // / Add a template specialization of \c ObjectTraits for any type that
39
40
// / serializes as an object consisting of multiple fields.
40
41
template <class T >
41
42
struct ObjectTraits {
@@ -55,7 +56,7 @@ struct ObjectTraits {
55
56
// UserInfoMap &UserInfo);
56
57
};
57
58
58
- // / Add a template specialization of \c ScalarTraits for any that type
59
+ // / Add a template specialization of \c ScalarTraits for any type that
59
60
// / serializes into a raw set of bytes.
60
61
template <class T >
61
62
struct ScalarTraits {
@@ -70,7 +71,17 @@ struct ScalarTraits {
70
71
// static llvm::Error write(llvm::BinaryStreamWriter &Writer, const T &Value);
71
72
};
72
73
73
- // / Add a template specialization of \c WrapperTypeTraits for any that type
74
+ // / Add a template specialization of \c DirectlyEncodable for any type whose
75
+ // / serialized form is equal to its binary representation on the serializing
76
+ // / machine.
77
+ template <class T >
78
+ struct DirectlyEncodable {
79
+ // Must provide:
80
+
81
+ // static bool const value = true;
82
+ };
83
+
84
+ // / Add a template specialization of \c WrapperTypeTraits for any type that
74
85
// / serializes as a type that already has a specialization of \c ScalarTypes.
75
86
// / This will typically be useful for types like enums that have a 1-to-1
76
87
// / mapping to e.g. an integer.
@@ -143,6 +154,12 @@ class ByteTreeWriter {
143
154
// / The writer to which the binary data is written.
144
155
llvm::BinaryStreamWriter &StreamWriter;
145
156
157
+ // / The underlying stream of the StreamWriter. We need this reference so that
158
+ // / we can call \c ExponentialGrowthAppendingBinaryByteStream.writeRaw
159
+ // / which is more efficient than the generic \c writeBytes of
160
+ // / \c llvm::BinaryStreamWriter since it avoids the arbitrary size memcopy.
161
+ ExponentialGrowthAppendingBinaryByteStream &Stream;
162
+
146
163
// / The number of fields this object contains. \c UINT_MAX if it has not been
147
164
// / set yet. No member may be written to the object if expected number of
148
165
// / fields has not been set yet.
@@ -157,8 +174,21 @@ class ByteTreeWriter {
157
174
158
175
// / The \c ByteTreeWriter can only be constructed internally. Use
159
176
// / \c ByteTreeWriter.write to serialize a new object.
160
- ByteTreeWriter (llvm::BinaryStreamWriter &StreamWriter, UserInfoMap &UserInfo)
161
- : StreamWriter(StreamWriter), UserInfo(UserInfo) {}
177
+ // / \p Stream must be the underlying stream of \p SteamWriter.
178
+ ByteTreeWriter (ExponentialGrowthAppendingBinaryByteStream &Stream,
179
+ llvm::BinaryStreamWriter &StreamWriter, UserInfoMap &UserInfo)
180
+ : StreamWriter(StreamWriter), Stream(Stream), UserInfo(UserInfo) {}
181
+
182
+ // / Write the given value to the ByteTree in the same form in which it is
183
+ // / represented on the serializing machine.
184
+ template <typename T>
185
+ llvm::Error writeRaw (T Value) {
186
+ // FIXME: We implicitly inherit the endianess of the serializing machine.
187
+ // Since we're currently only supporting macOS that's not a problem for now.
188
+ auto Error = Stream.writeRaw (StreamWriter.getOffset (), Value);
189
+ StreamWriter.setOffset (StreamWriter.getOffset () + sizeof (T));
190
+ return Error;
191
+ }
162
192
163
193
// / Set the expected number of fields the object written by this writer is
164
194
// / expected to have.
@@ -175,7 +205,7 @@ class ByteTreeWriter {
175
205
// Set the most significant bit to indicate that the next construct is an
176
206
// object and not a scalar.
177
207
uint32_t ToWrite = NumFields | (1 << 31 );
178
- auto Error = StreamWriter. writeInteger (ToWrite);
208
+ auto Error = writeRaw (ToWrite);
179
209
(void )Error;
180
210
assert (!Error);
181
211
@@ -205,11 +235,13 @@ class ByteTreeWriter {
205
235
// / the stream by the specified ProtocolVersion.
206
236
template <typename T>
207
237
typename std::enable_if<has_ObjectTraits<T>::value, void >::type
208
- static write (uint32_t ProtocolVersion, llvm::BinaryStreamWriter &StreamWriter,
209
- const T &Object, UserInfoMap &UserInfo) {
210
- ByteTreeWriter Writer (StreamWriter, UserInfo);
238
+ static write (ExponentialGrowthAppendingBinaryByteStream &Stream,
239
+ uint32_t ProtocolVersion, const T &Object,
240
+ UserInfoMap &UserInfo) {
241
+ llvm::BinaryStreamWriter StreamWriter (Stream);
242
+ ByteTreeWriter Writer (Stream, StreamWriter, UserInfo);
211
243
212
- auto Error = Writer.StreamWriter . writeInteger (ProtocolVersion);
244
+ auto Error = Writer.writeRaw (ProtocolVersion);
213
245
(void )Error;
214
246
assert (!Error);
215
247
@@ -224,7 +256,7 @@ class ByteTreeWriter {
224
256
write (const T &Object, unsigned Index) {
225
257
validateAndIncreaseFieldIndex (Index);
226
258
227
- auto ObjectWriter = ByteTreeWriter (StreamWriter, UserInfo);
259
+ auto ObjectWriter = ByteTreeWriter (Stream, StreamWriter, UserInfo);
228
260
ObjectWriter.setNumFields (ObjectTraits<T>::numFields (Object, UserInfo));
229
261
230
262
ObjectTraits<T>::write (ObjectWriter, Object, UserInfo);
@@ -240,7 +272,7 @@ class ByteTreeWriter {
240
272
// bitflag that indicates if the next construct in the tree is an object
241
273
// or a scalar.
242
274
assert ((ValueSize & ((uint32_t )1 << 31 )) == 0 && " Value size too large" );
243
- auto SizeError = StreamWriter. writeInteger (ValueSize);
275
+ auto SizeError = writeRaw (ValueSize);
244
276
(void )SizeError;
245
277
assert (!SizeError);
246
278
@@ -254,6 +286,21 @@ class ByteTreeWriter {
254
286
" ScalarTraits<T>::size" );
255
287
}
256
288
289
+ template <typename T>
290
+ typename std::enable_if<DirectlyEncodable<T>::value, void >::type
291
+ write (const T &Value, unsigned Index) {
292
+ validateAndIncreaseFieldIndex (Index);
293
+
294
+ uint32_t ValueSize = sizeof (T);
295
+ auto SizeError = writeRaw (ValueSize);
296
+ (void )SizeError;
297
+ assert (!SizeError);
298
+
299
+ auto ContentError = writeRaw (Value);
300
+ (void )ContentError;
301
+ assert (!ContentError);
302
+ }
303
+
257
304
template <typename T>
258
305
typename std::enable_if<has_WrapperTypeTraits<T>::value, void >::type
259
306
write (const T &Value, unsigned Index) {
@@ -268,30 +315,18 @@ class ByteTreeWriter {
268
315
// Define serialization schemes for common types
269
316
270
317
template <>
271
- struct ScalarTraits <uint8_t > {
272
- static unsigned size (const uint8_t &Value) { return 1 ; }
273
- static llvm::Error write (llvm::BinaryStreamWriter &Writer,
274
- const uint8_t &Value) {
275
- return Writer.writeInteger (Value);
276
- }
318
+ struct DirectlyEncodable <uint8_t > {
319
+ static bool const value = true ;
277
320
};
278
321
279
322
template <>
280
- struct ScalarTraits <uint16_t > {
281
- static unsigned size (const uint16_t &Value) { return 2 ; }
282
- static llvm::Error write (llvm::BinaryStreamWriter &Writer,
283
- const uint16_t &Value) {
284
- return Writer.writeInteger (Value);
285
- }
323
+ struct DirectlyEncodable <uint16_t > {
324
+ static bool const value = true ;
286
325
};
287
326
288
327
template <>
289
- struct ScalarTraits <uint32_t > {
290
- static unsigned size (const uint32_t &Value) { return 4 ; }
291
- static llvm::Error write (llvm::BinaryStreamWriter &Writer,
292
- const uint32_t &Value) {
293
- return Writer.writeInteger (Value);
294
- }
328
+ struct DirectlyEncodable <uint32_t > {
329
+ static bool const value = true ;
295
330
};
296
331
297
332
template <>
0 commit comments