Skip to content

Commit 5f65198

Browse files
committed
[stdlib] update UnsafeMutableRawPointer.storeBytes
- preserve previous version for ABI and source stability. - add new version without alignment restriction. - add explicit POD type enforcement in new version.
1 parent d93573c commit 5f65198

File tree

1 file changed

+42
-10
lines changed

1 file changed

+42
-10
lines changed

stdlib/public/core/UnsafeRawPointer.swift

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,9 +1189,8 @@ public struct UnsafeMutableRawPointer: _Pointer {
11891189

11901190
/// Stores the given value's bytes into raw memory at the specified offset.
11911191
///
1192-
/// The type `T` to be stored must be a trivial type. The memory at this
1193-
/// pointer plus `offset` must be properly aligned for accessing `T`. The
1194-
/// memory must also be uninitialized, initialized to `T`, or initialized to
1192+
/// The type `T` to be stored must be a trivial type. The memory
1193+
/// must also be uninitialized, initialized to `T`, or initialized to
11951194
/// another trivial type that is layout compatible with `T`.
11961195
///
11971196
/// After calling `storeBytes(of:toByteOffset:as:)`, the memory is
@@ -1205,14 +1204,14 @@ public struct UnsafeMutableRawPointer: _Pointer {
12051204
/// Swift types that do not contain strong or weak references or other
12061205
/// forms of indirection are trivial, as are imported C structs and enums.
12071206
///
1208-
/// If you need to store a copy of a nontrivial value into memory, or to
1209-
/// store a value into memory that contains a nontrivial value, you cannot
1210-
/// use the `storeBytes(of:toByteOffset:as:)` method. Instead, you must know
1211-
/// the type of value previously in memory and initialize or assign the
1212-
/// memory. For example, to replace a value stored in a raw pointer `p`,
1207+
/// If you need to store into memory a copy of a value of a type that isn't
1208+
/// trivial, you cannot use the `storeBytes(of:toByteOffset:as:)` method.
1209+
/// Instead, you must know either initialize the memory or,
1210+
/// if you know the memory was already bound to `type`, assign to the memory.
1211+
/// For example, to replace a value stored in a raw pointer `p`,
12131212
/// where `U` is the current type and `T` is the new type, use a typed
12141213
/// pointer to access and deinitialize the current value before initializing
1215-
/// the memory with a new value.
1214+
/// the memory with a new value:
12161215
///
12171216
/// let typedPointer = p.bindMemory(to: U.self, capacity: 1)
12181217
/// typedPointer.deinitialize(count: 1)
@@ -1224,8 +1223,41 @@ public struct UnsafeMutableRawPointer: _Pointer {
12241223
/// nonnegative. The default is zero.
12251224
/// - type: The type of `value`.
12261225
@inlinable
1226+
@_alwaysEmitIntoClient
1227+
@_silgen_name("_swift_se0349_UnsafeMutableRawPointer_storeBytes")
12271228
public func storeBytes<T>(
12281229
of value: T, toByteOffset offset: Int = 0, as type: T.Type
1230+
) {
1231+
_debugPrecondition(_isPOD(T.self))
1232+
1233+
withUnsafePointer(to: value) { source in
1234+
// FIXME: to be replaced by _memcpy when conversions are implemented.
1235+
Builtin.int_memcpy_RawPointer_RawPointer_Int64(
1236+
(self + offset)._rawValue,
1237+
source._rawValue,
1238+
UInt64(MemoryLayout<T>.size)._value,
1239+
/*volatile:*/ false._value
1240+
)
1241+
}
1242+
}
1243+
1244+
// This unavailable implementation uses the expected mangled name
1245+
// of `storeBytes<T>(of:toByteOffset:as:)`, and provides an entry point for
1246+
// any binary compiled against the stlib binary for Swift 5.6 and older.
1247+
@available(*, unavailable)
1248+
@_silgen_name("sSv10storeBytes2of12toByteOffset2asyx_SixmtlF")
1249+
@usableFromInline func _legacy_se0349_storeBytes<T>(
1250+
of value: T, toByteOffset offset: Int = 0, as type: T.Type
1251+
) {
1252+
_legacy_se0349_storeBytes_internal(
1253+
of: value, toByteOffset: offset, as: T.self
1254+
)
1255+
}
1256+
1257+
// This is the implementation of `storeBytes` from SwiftStdlib 5.6
1258+
@_alwaysEmitIntoClient
1259+
internal func _legacy_se0349_storeBytes_internal<T>(
1260+
of value: T, toByteOffset offset: Int = 0, as type: T.Type
12291261
) {
12301262
_debugPrecondition(0 == (UInt(bitPattern: self + offset)
12311263
& (UInt(MemoryLayout<T>.alignment) - 1)),
@@ -1240,7 +1272,7 @@ public struct UnsafeMutableRawPointer: _Pointer {
12401272
/*volatile:*/ false._value)
12411273
}
12421274
}
1243-
1275+
12441276
/// Copies the specified number of bytes from the given raw pointer's memory
12451277
/// into this pointer's memory.
12461278
///

0 commit comments

Comments
 (0)