@@ -424,7 +424,6 @@ public struct UnsafeRawPointer: _Pointer {
424424 let rawPointer = ( self + offset) . _rawValue
425425
426426#if compiler(>=5.5) && $BuiltinAssumeAlignment
427- // TODO: to support misaligned raw loads, simply remove this assumption.
428427 let alignedPointer =
429428 Builtin . assumeAlignment ( rawPointer,
430429 MemoryLayout < T > . alignment. _builtinWordValue)
@@ -434,6 +433,36 @@ public struct UnsafeRawPointer: _Pointer {
434433#endif
435434 }
436435
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+ }
437466}
438467
439468extension UnsafeRawPointer : Strideable {
@@ -1120,7 +1149,6 @@ public struct UnsafeMutableRawPointer: _Pointer {
11201149 let rawPointer = ( self + offset) . _rawValue
11211150
11221151#if compiler(>=5.5) && $BuiltinAssumeAlignment
1123- // TODO: to support misaligned raw loads, simply remove this assumption.
11241152 let alignedPointer =
11251153 Builtin . assumeAlignment ( rawPointer,
11261154 MemoryLayout < T > . alignment. _builtinWordValue)
@@ -1130,11 +1158,41 @@ public struct UnsafeMutableRawPointer: _Pointer {
11301158#endif
11311159 }
11321160
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+
11331192 /// Stores the given value's bytes into raw memory at the specified offset.
11341193 ///
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
11381196 /// another trivial type that is layout compatible with `T`.
11391197 ///
11401198 /// After calling `storeBytes(of:toByteOffset:as:)`, the memory is
@@ -1148,14 +1206,14 @@ public struct UnsafeMutableRawPointer: _Pointer {
11481206 /// Swift types that do not contain strong or weak references or other
11491207 /// forms of indirection are trivial, as are imported C structs and enums.
11501208 ///
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`,
11561214 /// where `U` is the current type and `T` is the new type, use a typed
11571215 /// pointer to access and deinitialize the current value before initializing
1158- /// the memory with a new value.
1216+ /// the memory with a new value:
11591217 ///
11601218 /// let typedPointer = p.bindMemory(to: U.self, capacity: 1)
11611219 /// typedPointer.deinitialize(count: 1)
@@ -1167,8 +1225,41 @@ public struct UnsafeMutableRawPointer: _Pointer {
11671225 /// nonnegative. The default is zero.
11681226 /// - type: The type of `value`.
11691227 @inlinable
1228+ @_alwaysEmitIntoClient
1229+ @_silgen_name ( " _swift_se0349_UnsafeMutableRawPointer_storeBytes " )
11701230 public func storeBytes< T> (
11711231 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
11721263 ) {
11731264 _debugPrecondition ( 0 == ( UInt ( bitPattern: self + offset)
11741265 & ( UInt ( MemoryLayout< T> . alignment) - 1 ) ) ,
@@ -1183,7 +1274,7 @@ public struct UnsafeMutableRawPointer: _Pointer {
11831274 /*volatile:*/ false . _value)
11841275 }
11851276 }
1186-
1277+
11871278 /// Copies the specified number of bytes from the given raw pointer's memory
11881279 /// into this pointer's memory.
11891280 ///
0 commit comments