@@ -424,7 +424,6 @@ public struct UnsafeRawPointer: _Pointer {
424
424
let rawPointer = ( self + offset) . _rawValue
425
425
426
426
#if compiler(>=5.5) && $BuiltinAssumeAlignment
427
- // TODO: to support misaligned raw loads, simply remove this assumption.
428
427
let alignedPointer =
429
428
Builtin . assumeAlignment ( rawPointer,
430
429
MemoryLayout < T > . alignment. _builtinWordValue)
@@ -434,6 +433,36 @@ public struct UnsafeRawPointer: _Pointer {
434
433
#endif
435
434
}
436
435
436
+ /// Returns a new instance of the given type, constructed from the raw memory
437
+ /// at the specified offset.
438
+ ///
439
+ /// This function only supports loading trivial types,
440
+ /// and will trap if this precondition is not met.
441
+ /// A trivial type does not contain any reference-counted property
442
+ /// within its in-memory representation.
443
+ /// The memory at this pointer plus `offset` must be laid out
444
+ /// identically to the in-memory representation of `T`.
445
+ ///
446
+ /// - Note: A trivial type can be copied with just a bit-for-bit copy without
447
+ /// any indirection or reference-counting operations. Generally, native
448
+ /// Swift types that do not contain strong or weak references or other
449
+ /// forms of indirection are trivial, as are imported C structs and enums.
450
+ ///
451
+ /// - Parameters:
452
+ /// - offset: The offset from this pointer, in bytes. `offset` must be
453
+ /// nonnegative. The default is zero.
454
+ /// - type: The type of the instance to create.
455
+ /// - Returns: A new instance of type `T`, read from the raw bytes at
456
+ /// `offset`. The returned instance isn't associated
457
+ /// with the value in the range of memory referenced by this pointer.
458
+ @_alwaysEmitIntoClient
459
+ public func loadUnaligned< T> (
460
+ fromByteOffset offset: Int = 0 ,
461
+ as type: T . Type
462
+ ) -> T {
463
+ _debugPrecondition ( _isPOD ( T . self) )
464
+ return Builtin . loadRaw ( ( self + offset) . _rawValue)
465
+ }
437
466
}
438
467
439
468
extension UnsafeRawPointer : Strideable {
@@ -1120,7 +1149,6 @@ public struct UnsafeMutableRawPointer: _Pointer {
1120
1149
let rawPointer = ( self + offset) . _rawValue
1121
1150
1122
1151
#if compiler(>=5.5) && $BuiltinAssumeAlignment
1123
- // TODO: to support misaligned raw loads, simply remove this assumption.
1124
1152
let alignedPointer =
1125
1153
Builtin . assumeAlignment ( rawPointer,
1126
1154
MemoryLayout < T > . alignment. _builtinWordValue)
@@ -1130,11 +1158,41 @@ public struct UnsafeMutableRawPointer: _Pointer {
1130
1158
#endif
1131
1159
}
1132
1160
1161
+ /// Returns a new instance of the given type, constructed from the raw memory
1162
+ /// at the specified offset.
1163
+ ///
1164
+ /// This function only supports loading trivial types,
1165
+ /// and will trap if this precondition is not met.
1166
+ /// A trivial type does not contain any reference-counted property
1167
+ /// within its in-memory representation.
1168
+ /// The memory at this pointer plus `offset` must be laid out
1169
+ /// identically to the in-memory representation of `T`.
1170
+ ///
1171
+ /// - Note: A trivial type can be copied with just a bit-for-bit copy without
1172
+ /// any indirection or reference-counting operations. Generally, native
1173
+ /// Swift types that do not contain strong or weak references or other
1174
+ /// forms of indirection are trivial, as are imported C structs and enums.
1175
+ ///
1176
+ /// - Parameters:
1177
+ /// - offset: The offset from this pointer, in bytes. `offset` must be
1178
+ /// nonnegative. The default is zero.
1179
+ /// - type: The type of the instance to create.
1180
+ /// - Returns: A new instance of type `T`, read from the raw bytes at
1181
+ /// `offset`. The returned instance isn't associated
1182
+ /// with the value in the range of memory referenced by this pointer.
1183
+ @_alwaysEmitIntoClient
1184
+ public func loadUnaligned< T> (
1185
+ fromByteOffset offset: Int = 0 ,
1186
+ as type: T . Type
1187
+ ) -> T {
1188
+ _debugPrecondition ( _isPOD ( T . self) )
1189
+ return Builtin . loadRaw ( ( self + offset) . _rawValue)
1190
+ }
1191
+
1133
1192
/// Stores the given value's bytes into raw memory at the specified offset.
1134
1193
///
1135
- /// The type `T` to be stored must be a trivial type. The memory at this
1136
- /// pointer plus `offset` must be properly aligned for accessing `T`. The
1137
- /// memory must also be uninitialized, initialized to `T`, or initialized to
1194
+ /// The type `T` to be stored must be a trivial type. The memory
1195
+ /// must also be uninitialized, initialized to `T`, or initialized to
1138
1196
/// another trivial type that is layout compatible with `T`.
1139
1197
///
1140
1198
/// After calling `storeBytes(of:toByteOffset:as:)`, the memory is
@@ -1148,14 +1206,14 @@ public struct UnsafeMutableRawPointer: _Pointer {
1148
1206
/// Swift types that do not contain strong or weak references or other
1149
1207
/// forms of indirection are trivial, as are imported C structs and enums.
1150
1208
///
1151
- /// If you need to store a copy of a nontrivial value into memory, or to
1152
- /// store a value into memory that contains a nontrivial value, you cannot
1153
- /// use the `storeBytes(of:toByteOffset:as:)` method. Instead, you must know
1154
- /// the type of value previously in memory and initialize or assign the
1155
- /// memory. For example, to replace a value stored in a raw pointer `p`,
1209
+ /// If you need to store into memory a copy of a value of a type that isn't
1210
+ /// trivial, you cannot use the `storeBytes(of:toByteOffset:as:)` method.
1211
+ /// Instead, you must know either initialize the memory or,
1212
+ /// if you know the memory was already bound to `type`, assign to the memory.
1213
+ /// For example, to replace a value stored in a raw pointer `p`,
1156
1214
/// where `U` is the current type and `T` is the new type, use a typed
1157
1215
/// pointer to access and deinitialize the current value before initializing
1158
- /// the memory with a new value.
1216
+ /// the memory with a new value:
1159
1217
///
1160
1218
/// let typedPointer = p.bindMemory(to: U.self, capacity: 1)
1161
1219
/// typedPointer.deinitialize(count: 1)
@@ -1167,8 +1225,41 @@ public struct UnsafeMutableRawPointer: _Pointer {
1167
1225
/// nonnegative. The default is zero.
1168
1226
/// - type: The type of `value`.
1169
1227
@inlinable
1228
+ @_alwaysEmitIntoClient
1229
+ @_silgen_name ( " _swift_se0349_UnsafeMutableRawPointer_storeBytes " )
1170
1230
public func storeBytes< T> (
1171
1231
of value: T , toByteOffset offset: Int = 0 , as type: T . Type
1232
+ ) {
1233
+ _debugPrecondition ( _isPOD ( T . self) )
1234
+
1235
+ withUnsafePointer ( to: value) { source in
1236
+ // FIXME: to be replaced by _memcpy when conversions are implemented.
1237
+ Builtin . int_memcpy_RawPointer_RawPointer_Int64 (
1238
+ ( self + offset) . _rawValue,
1239
+ source. _rawValue,
1240
+ UInt64 ( MemoryLayout< T> . size) . _value,
1241
+ /*volatile:*/ false . _value
1242
+ )
1243
+ }
1244
+ }
1245
+
1246
+ // This unavailable implementation uses the expected mangled name
1247
+ // of `storeBytes<T>(of:toByteOffset:as:)`, and provides an entry point for
1248
+ // any binary compiled against the stlib binary for Swift 5.6 and older.
1249
+ @available ( * , unavailable)
1250
+ @_silgen_name ( " sSv10storeBytes2of12toByteOffset2asyx_SixmtlF " )
1251
+ @usableFromInline func _legacy_se0349_storeBytes< T> (
1252
+ of value: T , toByteOffset offset: Int = 0 , as type: T . Type
1253
+ ) {
1254
+ _legacy_se0349_storeBytes_internal (
1255
+ of: value, toByteOffset: offset, as: T . self
1256
+ )
1257
+ }
1258
+
1259
+ // This is the implementation of `storeBytes` from SwiftStdlib 5.6
1260
+ @_alwaysEmitIntoClient
1261
+ internal func _legacy_se0349_storeBytes_internal< T> (
1262
+ of value: T , toByteOffset offset: Int = 0 , as type: T . Type
1172
1263
) {
1173
1264
_debugPrecondition ( 0 == ( UInt ( bitPattern: self + offset)
1174
1265
& ( UInt ( MemoryLayout< T> . alignment) - 1 ) ) ,
@@ -1183,7 +1274,7 @@ public struct UnsafeMutableRawPointer: _Pointer {
1183
1274
/*volatile:*/ false . _value)
1184
1275
}
1185
1276
}
1186
-
1277
+
1187
1278
/// Copies the specified number of bytes from the given raw pointer's memory
1188
1279
/// into this pointer's memory.
1189
1280
///
0 commit comments