blob: f248b4799a9cd26ea68f7b2d2a99b68bd1871879 [file] [log] [blame]
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
/// A stdlib-internal protocol modeled by the intrinsic pointer types,
/// UnsafeMutablePointer, UnsafePointer, UnsafeRawPointer,
/// UnsafeMutableRawPointer, and AutoreleasingUnsafeMutablePointer.
public protocol _Pointer
: Hashable, Strideable, CustomDebugStringConvertible, CustomReflectable {
/// A type that represents the distance between two pointers.
typealias Distance = Int
associatedtype Pointee
/// The underlying raw pointer value.
var _rawValue: Builtin.RawPointer { get }
/// Creates a pointer from a raw value.
init(_ _rawValue: Builtin.RawPointer)
}
extension _Pointer {
/// Creates a new typed pointer from the given opaque pointer.
///
/// - Parameter from: The opaque pointer to convert to a typed pointer.
@_transparent
public init(_ from: OpaquePointer) {
self.init(from._rawValue)
}
/// Creates a new typed pointer from the given opaque pointer.
///
/// - Parameter from: The opaque pointer to convert to a typed pointer. If
/// `from` is `nil`, the result of this initializer is `nil`.
@_transparent
public init?(_ from: OpaquePointer?) {
guard let unwrapped = from else { return nil }
self.init(unwrapped)
}
/// Creates a new pointer from the given address, specified as a bit
/// pattern.
///
/// The address passed as `bitPattern` must have the correct alignment for
/// the pointer's `Pointee` type. That is,
/// `bitPattern % MemoryLayout<Pointee>.alignment` must be `0`.
///
/// - Parameter bitPattern: A bit pattern to use for the address of the new
/// pointer. If `bitPattern` is zero, the result is `nil`.
@_transparent
public init?(bitPattern: Int) {
if bitPattern == 0 { return nil }
self.init(Builtin.inttoptr_Word(bitPattern._builtinWordValue))
}
/// Creates a new pointer from the given address, specified as a bit
/// pattern.
///
/// The address passed as `bitPattern` must have the correct alignment for
/// the pointer's `Pointee` type. That is,
/// `bitPattern % MemoryLayout<Pointee>.alignment` must be `0`.
///
/// - Parameter bitPattern: A bit pattern to use for the address of the new
/// pointer. If `bitPattern` is zero, the result is `nil`.
@_transparent
public init?(bitPattern: UInt) {
if bitPattern == 0 { return nil }
self.init(Builtin.inttoptr_Word(bitPattern._builtinWordValue))
}
/// Creates a new pointer from the given pointer.
///
/// - Parameter other: The typed pointer to convert.
@_transparent
public init(@_nonEphemeral _ other: Self) {
self.init(other._rawValue)
}
/// Creates a new pointer from the given pointer.
///
/// - Parameter other: The typed pointer to convert. If `other` is `nil`, the
/// result is `nil`.
@_transparent
public init?(@_nonEphemeral _ other: Self?) {
guard let unwrapped = other else { return nil }
self.init(unwrapped._rawValue)
}
}
// well, this is pretty annoying
extension _Pointer /*: Equatable */ {
// - Note: This may be more efficient than Strideable's implementation
// calling self.distance().
/// Returns a Boolean value indicating whether two pointers are equal.
///
/// - Parameters:
/// - lhs: A pointer.
/// - rhs: Another pointer.
/// - Returns: `true` if `lhs` and `rhs` reference the same memory address;
/// otherwise, `false`.
@_transparent
public static func == (lhs: Self, rhs: Self) -> Bool {
return Bool(Builtin.cmp_eq_RawPointer(lhs._rawValue, rhs._rawValue))
}
}
extension _Pointer /*: Comparable */ {
// - Note: This is an unsigned comparison unlike Strideable's
// implementation.
/// Returns a Boolean value indicating whether the first pointer references
/// an earlier memory location than the second pointer.
///
/// - Parameters:
/// - lhs: A pointer.
/// - rhs: Another pointer.
/// - Returns: `true` if `lhs` references a memory address earlier than
/// `rhs`; otherwise, `false`.
@_transparent
public static func < (lhs: Self, rhs: Self) -> Bool {
return Bool(Builtin.cmp_ult_RawPointer(lhs._rawValue, rhs._rawValue))
}
}
extension _Pointer /*: Strideable*/ {
/// Returns a pointer to the next consecutive instance.
///
/// The resulting pointer must be within the bounds of the same allocation as
/// this pointer.
///
/// - Returns: A pointer advanced from this pointer by
/// `MemoryLayout<Pointee>.stride` bytes.
@_transparent
public func successor() -> Self {
return advanced(by: 1)
}
/// Returns a pointer to the previous consecutive instance.
///
/// The resulting pointer must be within the bounds of the same allocation as
/// this pointer.
///
/// - Returns: A pointer shifted backward from this pointer by
/// `MemoryLayout<Pointee>.stride` bytes.
@_transparent
public func predecessor() -> Self {
return advanced(by: -1)
}
/// Returns the distance from this pointer to the given pointer, counted as
/// instances of the pointer's `Pointee` type.
///
/// With pointers `p` and `q`, the result of `p.distance(to: q)` is
/// equivalent to `q - p`.
///
/// Typed pointers are required to be properly aligned for their `Pointee`
/// type. Proper alignment ensures that the result of `distance(to:)`
/// accurately measures the distance between the two pointers, counted in
/// strides of `Pointee`. To find the distance in bytes between two
/// pointers, convert them to `UnsafeRawPointer` instances before calling
/// `distance(to:)`.
///
/// - Parameter end: The pointer to calculate the distance to.
/// - Returns: The distance from this pointer to `end`, in strides of the
/// pointer's `Pointee` type. To access the stride, use
/// `MemoryLayout<Pointee>.stride`.
@_transparent
public func distance(to end: Self) -> Int {
return
Int(Builtin.sub_Word(Builtin.ptrtoint_Word(end._rawValue),
Builtin.ptrtoint_Word(_rawValue)))
/ MemoryLayout<Pointee>.stride
}
/// Returns a pointer offset from this pointer by the specified number of
/// instances.
///
/// With pointer `p` and distance `n`, the result of `p.advanced(by: n)` is
/// equivalent to `p + n`.
///
/// The resulting pointer must be within the bounds of the same allocation as
/// this pointer.
///
/// - Parameter n: The number of strides of the pointer's `Pointee` type to
/// offset this pointer. To access the stride, use
/// `MemoryLayout<Pointee>.stride`. `n` may be positive, negative, or
/// zero.
/// - Returns: A pointer offset from this pointer by `n` instances of the
/// `Pointee` type.
@_transparent
public func advanced(by n: Int) -> Self {
return Self(Builtin.gep_Word(
self._rawValue, n._builtinWordValue, Pointee.self))
}
}
extension _Pointer /*: Hashable */ {
@inlinable
public func hash(into hasher: inout Hasher) {
hasher.combine(UInt(bitPattern: self))
}
@inlinable
public func _rawHashValue(seed: Int) -> Int {
return Hasher._hash(seed: seed, UInt(bitPattern: self))
}
}
extension _Pointer /*: CustomDebugStringConvertible */ {
/// A textual representation of the pointer, suitable for debugging.
public var debugDescription: String {
return _rawPointerToString(_rawValue)
}
}
extension _Pointer /*: CustomReflectable */ {
public var customMirror: Mirror {
let ptrValue = UInt64(
bitPattern: Int64(Int(Builtin.ptrtoint_Word(_rawValue))))
return Mirror(self, children: ["pointerValue": ptrValue])
}
}
extension Int {
/// Creates a new value with the bit pattern of the given pointer.
///
/// The new value represents the address of the pointer passed as `pointer`.
/// If `pointer` is `nil`, the result is `0`.
///
/// - Parameter pointer: The pointer to use as the source for the new
/// integer.
@_transparent
public init<P: _Pointer>(bitPattern pointer: P?) {
if let pointer = pointer {
self = Int(Builtin.ptrtoint_Word(pointer._rawValue))
} else {
self = 0
}
}
}
extension UInt {
/// Creates a new value with the bit pattern of the given pointer.
///
/// The new value represents the address of the pointer passed as `pointer`.
/// If `pointer` is `nil`, the result is `0`.
///
/// - Parameter pointer: The pointer to use as the source for the new
/// integer.
@_transparent
public init<P: _Pointer>(bitPattern pointer: P?) {
if let pointer = pointer {
self = UInt(Builtin.ptrtoint_Word(pointer._rawValue))
} else {
self = 0
}
}
}
// Pointer arithmetic operators (formerly via Strideable)
extension Strideable where Self: _Pointer {
@_transparent
public static func + (@_nonEphemeral lhs: Self, rhs: Self.Stride) -> Self {
return lhs.advanced(by: rhs)
}
@_transparent
public static func + (lhs: Self.Stride, @_nonEphemeral rhs: Self) -> Self {
return rhs.advanced(by: lhs)
}
@_transparent
public static func - (@_nonEphemeral lhs: Self, rhs: Self.Stride) -> Self {
return lhs.advanced(by: -rhs)
}
@_transparent
public static func - (lhs: Self, rhs: Self) -> Self.Stride {
return rhs.distance(to: lhs)
}
@_transparent
public static func += (lhs: inout Self, rhs: Self.Stride) {
lhs = lhs.advanced(by: rhs)
}
@_transparent
public static func -= (lhs: inout Self, rhs: Self.Stride) {
lhs = lhs.advanced(by: -rhs)
}
}
/// Derive a pointer argument from a convertible pointer type.
@_transparent
public // COMPILER_INTRINSIC
func _convertPointerToPointerArgument<
FromPointer: _Pointer,
ToPointer: _Pointer
>(_ from: FromPointer) -> ToPointer {
return ToPointer(from._rawValue)
}
/// Derive a pointer argument from the address of an inout parameter.
@_transparent
public // COMPILER_INTRINSIC
func _convertInOutToPointerArgument<
ToPointer: _Pointer
>(_ from: Builtin.RawPointer) -> ToPointer {
return ToPointer(from)
}
/// Derive a pointer argument from a value array parameter.
///
/// This always produces a non-null pointer, even if the array doesn't have any
/// storage.
@_transparent
public // COMPILER_INTRINSIC
func _convertConstArrayToPointerArgument<
FromElement,
ToPointer: _Pointer
>(_ arr: [FromElement]) -> (AnyObject?, ToPointer) {
let (owner, opaquePointer) = arr._cPointerArgs()
let validPointer: ToPointer
if let addr = opaquePointer {
validPointer = ToPointer(addr._rawValue)
} else {
let lastAlignedValue = ~(MemoryLayout<FromElement>.alignment - 1)
let lastAlignedPointer = UnsafeRawPointer(bitPattern: lastAlignedValue)!
validPointer = ToPointer(lastAlignedPointer._rawValue)
}
return (owner, validPointer)
}
/// Derive a pointer argument from an inout array parameter.
///
/// This always produces a non-null pointer, even if the array's length is 0.
@_transparent
public // COMPILER_INTRINSIC
func _convertMutableArrayToPointerArgument<
FromElement,
ToPointer: _Pointer
>(_ a: inout [FromElement]) -> (AnyObject?, ToPointer) {
// TODO: Putting a canary at the end of the array in checked builds might
// be a good idea
// Call reserve to force contiguous storage.
a.reserveCapacity(0)
_debugPrecondition(a._baseAddressIfContiguous != nil || a.isEmpty)
return _convertConstArrayToPointerArgument(a)
}
/// Derive a UTF-8 pointer argument from a value string parameter.
@_transparent
public // COMPILER_INTRINSIC
func _convertConstStringToUTF8PointerArgument<
ToPointer: _Pointer
>(_ str: String) -> (AnyObject?, ToPointer) {
let utf8 = Array(str.utf8CString)
return _convertConstArrayToPointerArgument(utf8)
}