diff --git a/stdlib/public/core/UnsafeRawPointer.swift b/stdlib/public/core/UnsafeRawPointer.swift index f3c4d16e04380..5e08d9302b6cf 100644 --- a/stdlib/public/core/UnsafeRawPointer.swift +++ b/stdlib/public/core/UnsafeRawPointer.swift @@ -442,7 +442,9 @@ extension UnsafeRawPointer { /// `offset`. The returned instance is memory-managed and unassociated /// with the value in the memory referenced by this pointer. @inlinable - public func load( + @_preInverseGenerics + @lifetime(borrow self) + public func load( fromByteOffset offset: Int = 0, as type: T.Type ) -> T { @@ -488,7 +490,9 @@ extension UnsafeRawPointer { /// with the value in the range of memory referenced by this pointer. @inlinable @_alwaysEmitIntoClient - public func loadUnaligned( + @_preInverseGenerics + @lifetime(borrow self) + public func loadUnaligned( fromByteOffset offset: Int = 0, as type: T.Type ) -> T { @@ -559,7 +563,7 @@ extension UnsafeRawPointer { /// - Returns: a pointer properly aligned to store a value of type `T`. @inlinable @_alwaysEmitIntoClient - public func alignedUp(for type: T.Type) -> Self { + public func alignedUp(for type: T.Type) -> Self { let mask = UInt(Builtin.alignof(T.self)) &- 1 let bits = (UInt(Builtin.ptrtoint_Word(_rawValue)) &+ mask) & ~mask _debugPrecondition(bits != 0, "Overflow in pointer arithmetic") @@ -577,7 +581,7 @@ extension UnsafeRawPointer { /// - Returns: a pointer properly aligned to store a value of type `T`. @inlinable @_alwaysEmitIntoClient - public func alignedDown(for type: T.Type) -> Self { + public func alignedDown(for type: T.Type) -> Self { let mask = UInt(Builtin.alignof(T.self)) &- 1 let bits = UInt(Builtin.ptrtoint_Word(_rawValue)) & ~mask _debugPrecondition(bits != 0, "Overflow in pointer arithmetic") @@ -1416,10 +1420,11 @@ extension UnsafeMutableRawPointer { /// - type: The type of `value`. @inlinable @_alwaysEmitIntoClient - public func storeBytes( + public func storeBytes( of value: T, toByteOffset offset: Int = 0, as type: T.Type ) { - unsafe Builtin.storeRaw(value, (self + offset)._rawValue) + let immortalValue = unsafe _overrideLifetime(value, borrowing: ()) + unsafe Builtin.storeRaw(immortalValue, (self + offset)._rawValue) } /// Stores the given value's bytes into raw memory at the specified offset. @@ -1563,7 +1568,7 @@ extension UnsafeMutableRawPointer { /// - Returns: a pointer properly aligned to store a value of type `T`. @inlinable @_alwaysEmitIntoClient - public func alignedUp(for type: T.Type) -> Self { + public func alignedUp(for type: T.Type) -> Self { let mask = UInt(Builtin.alignof(T.self)) &- 1 let bits = (UInt(Builtin.ptrtoint_Word(_rawValue)) &+ mask) & ~mask _debugPrecondition(bits != 0, "Overflow in pointer arithmetic") @@ -1581,7 +1586,7 @@ extension UnsafeMutableRawPointer { /// - Returns: a pointer properly aligned to store a value of type `T`. @inlinable @_alwaysEmitIntoClient - public func alignedDown(for type: T.Type) -> Self { + public func alignedDown(for type: T.Type) -> Self { let mask = UInt(Builtin.alignof(T.self)) &- 1 let bits = UInt(Builtin.ptrtoint_Word(_rawValue)) & ~mask _debugPrecondition(bits != 0, "Overflow in pointer arithmetic") diff --git a/test/SILOptimizer/lifetime_dependence/rawpointer_span.swift b/test/SILOptimizer/lifetime_dependence/rawpointer_span.swift new file mode 100644 index 0000000000000..d786130f5b6c3 --- /dev/null +++ b/test/SILOptimizer/lifetime_dependence/rawpointer_span.swift @@ -0,0 +1,93 @@ +// RUN: %target-swift-frontend -primary-file %s -parse-as-library -emit-sil \ +// RUN: -o /dev/null \ +// RUN: -verify \ +// RUN: -sil-verify-all \ +// RUN: -module-name test \ +// RUN: -define-availability "Span 0.1:macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999" \ +// RUN: -strict-memory-safety \ +// RUN: -enable-experimental-feature Lifetimes + +// REQUIRES: swift_in_compiler +// REQUIRES: swift_feature_Lifetimes + +@safe +@_silgen_name("getRawPointer") +func getRawPointer() -> UnsafeRawPointer + +@safe +@_silgen_name("getMutRawPointer") +func getMutRawPointer() -> UnsafeMutableRawPointer + +func useSpan(_: RawSpan) {} + +//===----------------------------------------------------------------------===// +// raw pointer .load() +//===----------------------------------------------------------------------===// + +@available(Span 0.1, *) +@_lifetime(immortal) +func badLoad() -> RawSpan { + let p = getRawPointer() + return unsafe p.load(as: RawSpan.self) // expected-error{{lifetime-dependent value escapes its scope}} + // expected-note@-2{{it depends on the lifetime of variable 'p'}} + // expected-note@-2{{this use causes the lifetime-dependent value to escape}} +} + +@available(Span 0.1, *) +@_lifetime(borrow p) +func goodLoad(p: UnsafeRawPointer) -> RawSpan { + unsafe useSpan(p.load(as: RawSpan.self)) + return unsafe p.load(as: RawSpan.self) +} + +//===----------------------------------------------------------------------===// +// raw pointer .loadUnaligned() +// +// TODO: test non-BitwiseCopyable loadUnaligned +//===----------------------------------------------------------------------===// + +@available(Span 0.1, *) +@_lifetime(immortal) +func badBitwiseLoadUnaligned() -> RawSpan { + let p = getRawPointer() + return unsafe p.loadUnaligned(as: RawSpan.self) // expected-error{{lifetime-dependent value escapes its scope}} + // expected-note@-2{{it depends on the lifetime of variable 'p'}} + // expected-note@-2{{this use causes the lifetime-dependent value to escape}} +} + +@available(Span 0.1, *) +@_lifetime(borrow p) +func goodBitwiseLoadUnaligned(p: UnsafeRawPointer) -> RawSpan { + unsafe useSpan(p.loadUnaligned(as: RawSpan.self)) + return unsafe p.loadUnaligned(as: RawSpan.self) +} + +/* TODO: support loadUnaligned +@_lifetime(immortal) +func badGenericLoadUnaligned(p: UnsafeRawPointer, _: T.Type) -> T { + let p = getRawPointer() + return unsafe p.loadUnaligned(as: T.self) // ERROR +} + +@_lifetime(borrow p) +func goodGenericLoadUnaligned(p: UnsafeRawPointer, _: T.Type) -> T { + return unsafe p.loadUnaligned(as: T.self) // OK +} +*/ + +//===----------------------------------------------------------------------===// +// raw pointer .storeBytes() +//===----------------------------------------------------------------------===// + +@available(Span 0.1, *) +func storeSpan(span: RawSpan) { + let p = getMutRawPointer() + unsafe p.storeBytes(of: span, as: RawSpan.self) +} + +/* TODO: support storeBytes +func storeGeneric(value: T) { + let p = getMutRawPointer() + unsafe p.storeBytes(of: value, as: T.self) +} +*/ diff --git a/test/api-digester/Outputs/stability-stdlib-source-base.swift.expected b/test/api-digester/Outputs/stability-stdlib-source-base.swift.expected index 4b8e01dec4137..2d0efddb719ac 100644 --- a/test/api-digester/Outputs/stability-stdlib-source-base.swift.expected +++ b/test/api-digester/Outputs/stability-stdlib-source-base.swift.expected @@ -293,6 +293,7 @@ Func UnsafePointer.deallocate() has generic signature change from to < Func UnsafeRawBufferPointer.bindMemory(to:) has generic signature change from to Func UnsafeRawPointer.assumingMemoryBound(to:) has generic signature change from to Func UnsafeRawPointer.bindMemory(to:capacity:) has generic signature change from to +Func UnsafeRawPointer.load(fromByteOffset:as:) has generic signature change from to Func swap(_:_:) has generic signature change from to Func withExtendedLifetime(_:_:) has parameter 0 changing from Default to Shared Func withUnsafeBytes(of:_:) has generic signature change from to diff --git a/test/api-digester/stability-stdlib-abi-without-asserts.test b/test/api-digester/stability-stdlib-abi-without-asserts.test index 1f3d391db78a3..97b3c05a5ad29 100644 --- a/test/api-digester/stability-stdlib-abi-without-asserts.test +++ b/test/api-digester/stability-stdlib-abi-without-asserts.test @@ -684,6 +684,9 @@ Func UnsafeRawPointer.assumingMemoryBound(to:) is now with @_preInverseGenerics Func UnsafeRawPointer.bindMemory(to:capacity:) has generic signature change from to Func UnsafeRawPointer.bindMemory(to:capacity:) has mangled name changing from 'Swift.UnsafeRawPointer.bindMemory(to: A.Type, capacity: Swift.Int) -> Swift.UnsafePointer' to 'Swift.UnsafeRawPointer.bindMemory(to: A.Type, capacity: Swift.Int) -> Swift.UnsafePointer' Func UnsafeRawPointer.bindMemory(to:capacity:) is now with @_preInverseGenerics +Func UnsafeRawPointer.load(fromByteOffset:as:) has generic signature change from to +Func UnsafeRawPointer.load(fromByteOffset:as:) has mangled name changing from 'Swift.UnsafeRawPointer.load(fromByteOffset: Swift.Int, as: A.Type) -> A' to 'Swift.UnsafeRawPointer.load(fromByteOffset: Swift.Int, as: A.Type) -> A' +Func UnsafeRawPointer.load(fromByteOffset:as:) is now with @_preInverseGenerics Func _fixLifetime(_:) has generic signature change from to Func _fixLifetime(_:) has mangled name changing from 'Swift._fixLifetime(A) -> ()' to 'Swift._fixLifetime(A) -> ()' Func _fixLifetime(_:) has parameter 0 changing from Default to Shared