Skip to content

Commit 436b861

Browse files
[stdlib][WIP] Factor out common parts of pointer types and de-gyb (#17951)
* Add conformances to _Pointer and remove from pointer types * De-gyb pointer files
1 parent 44088fa commit 436b861

File tree

7 files changed

+937
-698
lines changed

7 files changed

+937
-698
lines changed

stdlib/public/core/BridgeObjectiveC.swift

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -490,16 +490,6 @@ public struct AutoreleasingUnsafeMutablePointer<Pointee /* TODO : class */>
490490
}
491491
}
492492

493-
extension AutoreleasingUnsafeMutablePointer: Equatable {
494-
@_transparent
495-
public static func == (
496-
lhs: AutoreleasingUnsafeMutablePointer,
497-
rhs: AutoreleasingUnsafeMutablePointer
498-
) -> Bool {
499-
return Bool(Builtin.cmp_eq_RawPointer(lhs._rawValue, rhs._rawValue))
500-
}
501-
}
502-
503493
extension UnsafeMutableRawPointer {
504494
/// Creates a new raw pointer from an `AutoreleasingUnsafeMutablePointer`
505495
/// instance.
@@ -544,14 +534,6 @@ extension UnsafeRawPointer {
544534
}
545535
}
546536

547-
extension AutoreleasingUnsafeMutablePointer : CustomDebugStringConvertible {
548-
/// A textual representation of `self`, suitable for debugging.
549-
@inlinable
550-
public var debugDescription: String {
551-
return _rawPointerToString(_rawValue)
552-
}
553-
}
554-
555537
@_fixed_layout
556538
@usableFromInline
557539
internal struct _CocoaFastEnumerationStackBuf {

stdlib/public/core/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,8 @@ set(SWIFTLIB_ESSENTIAL
157157
UnsafeBitMap.swift
158158
UnsafeBufferPointer.swift.gyb
159159
UnsafeRawBufferPointer.swift.gyb
160-
UnsafePointer.swift.gyb
161-
UnsafeRawPointer.swift.gyb
160+
UnsafePointer.swift
161+
UnsafeRawPointer.swift
162162
UTFEncoding.swift
163163
UTF8.swift
164164
UTF16.swift

stdlib/public/core/Pointer.swift

Lines changed: 246 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,259 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
/// A stdlib-internal protocol modeled by the intrinsic pointer types,
14-
/// UnsafeMutablePointer, UnsafePointer, and
15-
/// AutoreleasingUnsafeMutablePointer.
16-
public protocol _Pointer {
14+
/// UnsafeMutablePointer, UnsafePointer, UnsafeRawPointer,
15+
/// UnsafeMutableRawPointer, and AutoreleasingUnsafeMutablePointer.
16+
public protocol _Pointer
17+
: Hashable, Strideable, CustomDebugStringConvertible, CustomReflectable {
18+
/// A type that represents the distance between two pointers.
19+
typealias Distance = Int
20+
21+
associatedtype Pointee
22+
1723
/// The underlying raw pointer value.
1824
var _rawValue: Builtin.RawPointer { get }
1925

2026
/// Creates a pointer from a raw value.
2127
init(_ _rawValue: Builtin.RawPointer)
2228
}
2329

30+
extension _Pointer {
31+
/// Creates a new typed pointer from the given opaque pointer.
32+
///
33+
/// - Parameter from: The opaque pointer to convert to a typed pointer.
34+
@_transparent
35+
public init(_ from : OpaquePointer) {
36+
self.init(from._rawValue)
37+
}
38+
39+
/// Creates a new typed pointer from the given opaque pointer.
40+
///
41+
/// - Parameter from: The opaque pointer to convert to a typed pointer. If
42+
/// `from` is `nil`, the result of this initializer is `nil`.
43+
@_transparent
44+
public init?(_ from : OpaquePointer?) {
45+
guard let unwrapped = from else { return nil }
46+
self.init(unwrapped)
47+
}
48+
49+
/// Creates a new pointer from the given address, specified as a bit
50+
/// pattern.
51+
///
52+
/// The address passed as `bitPattern` must have the correct alignment for
53+
/// the pointer's `Pointee` type. That is,
54+
/// `bitPattern % MemoryLayout<Pointee>.alignment` must be `0`.
55+
///
56+
/// - Parameter bitPattern: A bit pattern to use for the address of the new
57+
/// pointer. If `bitPattern` is zero, the result is `nil`.
58+
@_transparent
59+
public init?(bitPattern: Int) {
60+
if bitPattern == 0 { return nil }
61+
self.init(Builtin.inttoptr_Word(bitPattern._builtinWordValue))
62+
}
63+
64+
/// Creates a new pointer from the given address, specified as a bit
65+
/// pattern.
66+
///
67+
/// The address passed as `bitPattern` must have the correct alignment for
68+
/// the pointer's `Pointee` type. That is,
69+
/// `bitPattern % MemoryLayout<Pointee>.alignment` must be `0`.
70+
///
71+
/// - Parameter bitPattern: A bit pattern to use for the address of the new
72+
/// pointer. If `bitPattern` is zero, the result is `nil`.
73+
@_transparent
74+
public init?(bitPattern: UInt) {
75+
if bitPattern == 0 { return nil }
76+
self.init(Builtin.inttoptr_Word(bitPattern._builtinWordValue))
77+
}
78+
79+
/// Creates a new pointer from the given pointer.
80+
///
81+
/// - Parameter other: The typed pointer to convert.
82+
@_transparent
83+
public init(_ other: Self) {
84+
self.init(other._rawValue)
85+
}
86+
87+
/// Creates a new pointer from the given pointer.
88+
///
89+
/// - Parameter other: The typed pointer to convert. If `other` is `nil`, the
90+
/// result is `nil`.
91+
@_transparent
92+
public init?(_ other: Self?) {
93+
guard let unwrapped = other else { return nil }
94+
self.init(unwrapped._rawValue)
95+
}
96+
}
97+
98+
// well, this is pretty annoying
99+
extension _Pointer /*: Equatable */ {
100+
// - Note: This may be more efficient than Strideable's implementation
101+
// calling self.distance().
102+
/// Returns a Boolean value indicating whether two pointers are equal.
103+
///
104+
/// - Parameters:
105+
/// - lhs: A pointer.
106+
/// - rhs: Another pointer.
107+
/// - Returns: `true` if `lhs` and `rhs` reference the same memory address;
108+
/// otherwise, `false`.
109+
@_transparent
110+
public static func == (lhs: Self, rhs: Self) -> Bool {
111+
return Bool(Builtin.cmp_eq_RawPointer(lhs._rawValue, rhs._rawValue))
112+
}
113+
}
114+
115+
extension _Pointer /*: Comparable */ {
116+
// - Note: This is an unsigned comparison unlike Strideable's
117+
// implementation.
118+
/// Returns a Boolean value indicating whether the first pointer references
119+
/// an earlier memory location than the second pointer.
120+
///
121+
/// - Parameters:
122+
/// - lhs: A pointer.
123+
/// - rhs: Another pointer.
124+
/// - Returns: `true` if `lhs` references a memory address earlier than
125+
/// `rhs`; otherwise, `false`.
126+
@_transparent
127+
public static func < (lhs: Self, rhs: Self) -> Bool {
128+
return Bool(Builtin.cmp_ult_RawPointer(lhs._rawValue, rhs._rawValue))
129+
}
130+
}
131+
132+
extension _Pointer /*: Strideable*/ {
133+
/// Returns a pointer to the next consecutive instance.
134+
///
135+
/// The resulting pointer must be within the bounds of the same allocation as
136+
/// this pointer.
137+
///
138+
/// - Returns: A pointer advanced from this pointer by
139+
/// `MemoryLayout<Pointee>.stride` bytes.
140+
@inlinable
141+
public func successor() -> Self {
142+
return advanced(by: 1)
143+
}
144+
145+
/// Returns a pointer to the previous consecutive instance.
146+
///
147+
/// The resulting pointer must be within the bounds of the same allocation as
148+
/// this pointer.
149+
///
150+
/// - Returns: A pointer shifted backward from this pointer by
151+
/// `MemoryLayout<Pointee>.stride` bytes.
152+
@inlinable
153+
public func predecessor() -> Self {
154+
return advanced(by: -1)
155+
}
156+
157+
/// Returns the distance from this pointer to the given pointer, counted as
158+
/// instances of the pointer's `Pointee` type.
159+
///
160+
/// With pointers `p` and `q`, the result of `p.distance(to: q)` is
161+
/// equivalent to `q - p`.
162+
///
163+
/// Typed pointers are required to be properly aligned for their `Pointee`
164+
/// type. Proper alignment ensures that the result of `distance(to:)`
165+
/// accurately measures the distance between the two pointers, counted in
166+
/// strides of `Pointee`. To find the distance in bytes between two
167+
/// pointers, convert them to `UnsafeRawPointer` instances before calling
168+
/// `distance(to:)`.
169+
///
170+
/// - Parameter end: The pointer to calculate the distance to.
171+
/// - Returns: The distance from this pointer to `end`, in strides of the
172+
/// pointer's `Pointee` type. To access the stride, use
173+
/// `MemoryLayout<Pointee>.stride`.
174+
@inlinable
175+
public func distance(to end: Self) -> Int {
176+
return
177+
Int(Builtin.sub_Word(Builtin.ptrtoint_Word(end._rawValue),
178+
Builtin.ptrtoint_Word(_rawValue)))
179+
/ MemoryLayout<Pointee>.stride
180+
}
181+
182+
/// Returns a pointer offset from this pointer by the specified number of
183+
/// instances.
184+
///
185+
/// With pointer `p` and distance `n`, the result of `p.advanced(by: n)` is
186+
/// equivalent to `p + n`.
187+
///
188+
/// The resulting pointer must be within the bounds of the same allocation as
189+
/// this pointer.
190+
///
191+
/// - Parameter n: The number of strides of the pointer's `Pointee` type to
192+
/// offset this pointer. To access the stride, use
193+
/// `MemoryLayout<Pointee>.stride`. `n` may be positive, negative, or
194+
/// zero.
195+
/// - Returns: A pointer offset from this pointer by `n` instances of the
196+
/// `Pointee` type.
197+
@inlinable
198+
public func advanced(by n: Int) -> Self {
199+
return Self(Builtin.gep_Word(
200+
self._rawValue, n._builtinWordValue, Pointee.self))
201+
}
202+
}
203+
204+
extension _Pointer /*: Hashable */ {
205+
@inlinable
206+
public func hash(into hasher: inout Hasher) {
207+
hasher.combine(UInt(bitPattern: self))
208+
}
209+
210+
@inlinable
211+
public func _rawHashValue(seed: (UInt64, UInt64)) -> Int {
212+
return Hasher._hash(seed: seed, UInt(bitPattern: self))
213+
}
214+
}
215+
216+
extension _Pointer /*: CustomDebugStringConvertible */ {
217+
/// A textual representation of the pointer, suitable for debugging.
218+
public var debugDescription: String {
219+
return _rawPointerToString(_rawValue)
220+
}
221+
}
222+
223+
extension _Pointer /*: CustomReflectable */ {
224+
public var customMirror: Mirror {
225+
let ptrValue = UInt64(
226+
bitPattern: Int64(Int(Builtin.ptrtoint_Word(_rawValue))))
227+
return Mirror(self, children: ["pointerValue": ptrValue])
228+
}
229+
}
230+
231+
extension Int {
232+
/// Creates a new value with the bit pattern of the given pointer.
233+
///
234+
/// The new value represents the address of the pointer passed as `pointer`.
235+
/// If `pointer` is `nil`, the result is `0`.
236+
///
237+
/// - Parameter pointer: The pointer to use as the source for the new
238+
/// integer.
239+
@inlinable
240+
public init<P: _Pointer>(bitPattern pointer: P?) {
241+
if let pointer = pointer {
242+
self = Int(Builtin.ptrtoint_Word(pointer._rawValue))
243+
} else {
244+
self = 0
245+
}
246+
}
247+
}
248+
249+
extension UInt {
250+
/// Creates a new value with the bit pattern of the given pointer.
251+
///
252+
/// The new value represents the address of the pointer passed as `pointer`.
253+
/// If `pointer` is `nil`, the result is `0`.
254+
///
255+
/// - Parameter pointer: The pointer to use as the source for the new
256+
/// integer.
257+
@inlinable
258+
public init<P: _Pointer>(bitPattern pointer: P?) {
259+
if let pointer = pointer {
260+
self = UInt(Builtin.ptrtoint_Word(pointer._rawValue))
261+
} else {
262+
self = 0
263+
}
264+
}
265+
}
266+
24267
/// Derive a pointer argument from a convertible pointer type.
25268
@_transparent
26269
public // COMPILER_INTRINSIC

0 commit comments

Comments
 (0)