Files
swift-mirror/stdlib/public/core/UnsafeRawPointer.swift.gyb
Andrew Trick a41484ea2b Add UnsafeRawPointer type and API. (#3677)
* Add UnsafeRawPointer type and API.

As proposed in SE-0107:   UnsafeRawPointer.
https://github.com/apple/swift-evolution/blob/master/proposals/0107-unsaferawpointer.md

The fundamental difference between Unsafe[Mutable]RawPointer and
Unsafe[Mutable]Pointer<Pointee> is simply that the former is used for "untyped"
memory access, and the later is used for "typed" memory access. Let's refer to
these as "raw pointers" and "typed pointers". Because operations on raw pointers
access untyped memory, the compiler cannot make assumptions about the underlying
type of memory and must be conservative. With operations on typed pointers, the
compiler may make strict assumptions about the type of the underlying memory,
which allows more aggressive optimization.

Memory can only be accessed by a typed pointer when it is currently
bound to the Pointee type. Memory can be bound to type `T` via:
- `UnsafePointer<T>.allocate(capacity: n)`
- `UnsafePointer<Pointee>.withMemoryRebound(to: T.self, capacity: n) {...}`
- `UnsafeMutableRawPointer.initializeMemory(as: T.self, at: i, count: n, to: x)`
- `UnsafeMutableRawPointer.initializeMemory(as: T.self, from: p, count: n)`
- `UnsafeMutableRawPointer.moveInitializeMemory(as: T.self, from: p, count: n)`
- `UnsafeMutableRawPointer.bindMemory(to: T.self, capacity: n)`

Mangle UnsafeRawPointer as predefined substitution 'Sv' for Swift void
pointer ([urp] are taken).

* UnsafeRawPointer minor improvements.

Incorporate Dmitri's feedback.

Properly use a _memmove helper.

Add load/storeBytes alignment precondition checks.

Reword comments.

Demangler tests.

* Fix name mangling test cases.

* Fix bind_memory specialization.
2016-07-22 13:32:08 -07:00

550 lines
18 KiB
Swift

//===--- UnsafeRawPointer.swift.gyb --------------------------*- swift -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
%import gyb
% for mutable in (True, False):
% Self = 'UnsafeMutableRawPointer' if mutable else 'UnsafeRawPointer'
% a_Self = 'an `UnsafeMutableRawPointer`' if mutable else 'an `UnsafeRawPointer`'
% Mutable = 'Mutable' if mutable else ''
/// A raw pointer for accessing untyped data. This provides no
/// automatic memory management, no type safety, and no alignment
/// guarantees. This implements Strideable to provide a view
/// of byte-addressable memory.
@_fixed_layout
public struct Unsafe${Mutable}RawPointer : Strideable, Hashable, _Pointer {
/// The underlying raw pointer.
/// Implements conformance to the public protocol `_Pointer`.
public let _rawValue: Builtin.RawPointer
/// Convert a builtin raw pointer to ${a_Self}.
@_transparent
public init(_ _rawValue: Builtin.RawPointer) {
self._rawValue = _rawValue
}
/// Convert an opaque pointer to ${a_Self}.
@_transparent
public init(_ other: OpaquePointer) {
_rawValue = other._rawValue
}
/// Convert an opaque pointer to ${a_Self}.
///
/// Returns nil if `from` is nil.
@_transparent
public init?(_ other: OpaquePointer?) {
guard let unwrapped = other else { return nil }
_rawValue = unwrapped._rawValue
}
/// Convert a pattern of bits to ${a_Self}.
@_transparent
public init?(bitPattern: Int) {
if bitPattern == 0 { return nil }
_rawValue = Builtin.inttoptr_Word(bitPattern._builtinWordValue)
}
/// Convert a pattern of bits to ${a_Self}.
@_transparent
public init?(bitPattern: UInt) {
if bitPattern == 0 { return nil }
_rawValue = Builtin.inttoptr_Word(bitPattern._builtinWordValue)
}
/// Convert an Unsafe${Mutable}Pointer to ${a_Self}.
@_transparent
public init<T>(_ other: Unsafe${Mutable}Pointer<T>) {
_rawValue = other._rawValue
}
/// Convert an Unsafe${Mutable}Pointer ${a_Self}.
///
/// Returns nil if `other` is nil.
@_transparent
public init?<T>(_ other: Unsafe${Mutable}Pointer<T>?) {
guard let unwrapped = other else { return nil }
_rawValue = unwrapped._rawValue
}
% if not mutable:
/// Convert an UnsafeMutableRawPointer ${a_Self}.
@_transparent
public init(_ other: UnsafeMutableRawPointer) {
_rawValue = other._rawValue
}
/// Convert an UnsafeMutableRawPointer ${a_Self}.
///
/// Returns nil if `other` is nil.
@_transparent
public init?(_ other: UnsafeMutableRawPointer?) {
guard let unwrapped = other else { return nil }
_rawValue = unwrapped._rawValue
}
/// Convert an UnsafeMutablePointer ${a_Self}.
@_transparent
public init<T>(_ other: UnsafeMutablePointer<T>) {
_rawValue = other._rawValue
}
/// Convert an UnsafeMutablePointer ${a_Self}.
///
/// Returns nil if `other` is nil.
@_transparent
public init?<T>(_ other: UnsafeMutablePointer<T>?) {
guard let unwrapped = other else { return nil }
_rawValue = unwrapped._rawValue
}
% end # !mutable
% if mutable:
/// Allocate and point at uninitialized memory for `size` bytes with
/// `alignedTo` alignment.
///
/// - Postcondition: The memory is allocated, but not initialized.
public static func allocate(bytes size: Int, alignedTo: Int)
-> UnsafeMutableRawPointer {
return UnsafeMutableRawPointer(Builtin.allocRaw(
size._builtinWordValue, alignedTo._builtinWordValue))
}
% end # mutable
/// Deallocate uninitialized memory allocated for `bytes` number of bytes with
/// `alignedTo` alignment.
///
/// - Precondition: The memory is not initialized.
///
/// - Postcondition: The memory has been deallocated.
public func deallocate(bytes: Int, alignedTo: Int) {
Builtin.deallocRaw(
_rawValue, bytes._builtinWordValue, alignedTo._builtinWordValue)
}
/// Binding the allocated memory to type `T`.
/// Returns an Unsafe${Mutable}Pointer<T> to the bound memory at `self`.
///
/// - Precondition: The memory is uninitialized.
///
/// - Postcondition: The memory is bound to 'T' starting at `self` continuing
/// through `self` + `count` * `strideof(T.self)`
///
/// - Warning: Binding memory to a type is potentially undefined if the
/// memory is ever accessed as an unrelated type.
@_transparent
public func bindMemory<T>(to type: T.Type, capacity count: Int)
-> Unsafe${Mutable}Pointer<T> {
Builtin.bindMemory(_rawValue, count._builtinWordValue, type)
return Unsafe${Mutable}Pointer<T>(_rawValue)
}
/// Convert from ${a_Self} to Unsafe${Mutable}Pointer<T> given that
/// the region of memory starting at `self` is already bound to type `T`.
///
/// - Precondition: The memory is bound to 'T' starting at `self` for some
/// unspecified capacity.
///
/// - Warning: Accessing memory via the returned pointer is undefined if the
/// if the memory has not been bound to `T`.
@_transparent
public func assumingMemoryBound<T>(to: T.Type) -> Unsafe${Mutable}Pointer<T> {
return Unsafe${Mutable}Pointer<T>(_rawValue)
}
% if mutable:
/// Initialize this memory location `self + strideof(T) * index`
/// with `count` consecutive copies `value`, and bind the
/// initialized memory to type `T`.
///
/// Returns an `UnsafeMutablePointer<T>` to this memory.
///
/// - Precondition: The memory at
/// `self + index * strideof(T)..<self + (index + count) * strideof(T)`
/// is uninitialized.
///
/// - Precondition: The underlying pointer is properly aligned for
/// accessing `T`.
///
/// - Precondition: `index` is non-negative.
///
/// - Precondition: `count` is non-negative.
///
/// - Postcondition: The memory at
/// `(self + strideof(T) * index)..<(self + strideof(T) * index) + count`
/// is bound to type `T` and initialized; the value should eventually be
/// destroyed or moved from to avoid leaks.
@discardableResult
public func initializeMemory<T>(as type: T.Type, at index: Int = 0,
count: Int = 1, to value: T
) -> UnsafeMutablePointer<T> {
_debugPrecondition(index >= 0,
"UnsafeMutableRawPointer.initializeMemory: negative index")
_debugPrecondition(count >= 0,
"UnsafeMutableRawPointer.initializeMemory: negative count")
Builtin.bindMemory(_rawValue, count._builtinWordValue, type)
var nextPtr = self + index * strideof(T.self)
for _ in 0..<count {
Builtin.initialize(value, nextPtr._rawValue)
nextPtr += strideof(T.self)
}
return UnsafeMutablePointer(_rawValue)
}
/// Initialize memory starting at `self` with `count` `T` values
/// beginning at `source`, and bind the initialized memory to type
/// `T`.
///
/// Returns an `UnsafeMutablePointer<T>` this memory.
///
/// - Precondition: `count >= 0`
///
/// - Precondition: The memory regions `source..<source + count` and
/// `self..<self + count * strideof(T.self)` do not overlap.
///
/// - Precondition: The memory at `self..<self + count * strideof(T.self)`
/// is uninitialized, and the `T` values at `source..<source + count` are
/// initialized.
///
/// - Precondition: The underlying pointer is properly aligned for
/// accessing `T`.
///
/// - Postcondition: The memory at `self..<self + count * strideof(T.self)`
/// is bound to type `T`.
///
/// - Postcondition: The `T` values at `self..<self + count *
/// strideof(T.self)` and `source..<source + count` are initialized.
@discardableResult
public func initializeMemory<T>(
as type: T.Type, from source: UnsafePointer<T>, count: Int
) -> UnsafeMutablePointer<T> {
_debugPrecondition(
count >= 0,
"UnsafeMutableRawPointer.initializeMemory with negative count")
_debugPrecondition(
(UnsafeRawPointer(self + count * strideof(T.self))
<= UnsafeRawPointer(source))
|| UnsafeRawPointer(source + count) <= UnsafeRawPointer(self),
"UnsafeMutableRawPointer.initializeMemory overlapping range")
Builtin.bindMemory(_rawValue, count._builtinWordValue, type)
Builtin.copyArray(
T.self, self._rawValue, source._rawValue, count._builtinWordValue)
// This builtin is equivalent to:
// for i in 0..<count {
// (self.assumingMemoryBound(to: T.self) + i).initialize(to: source[i])
// }
return UnsafeMutablePointer(_rawValue)
}
/// Initialize memory starting at `self` with the elements of
/// `source`, and bind the initialized memory to type `T`.
///
/// Returns an `UnsafeMutablePointer<T>` this memory.
///
/// - Precondition: The memory at `self..<self + source.count *
/// strideof(T.self)` is uninitialized.
///
/// - Postcondition: The memory at `self..<self + source.count *
/// strideof(T.self)` is bound to type `T`.
///
/// - Postcondition: The `T` values at `self..<self + source.count *
/// strideof(T.self)` are initialized.
///
/// TODO: Optimize where `C` is a `ContiguousArrayBuffer`.
@discardableResult
public func initializeMemory<C : Collection>(
as: C.Iterator.Element.Type, from source: C
) -> UnsafeMutablePointer<C.Iterator.Element> {
// Initialize and bind each element of the container.
for (index, element) in source.enumerated() {
self.initializeMemory(as: C.Iterator.Element.self, at: index, to: element)
}
return UnsafeMutablePointer(_rawValue)
}
/// Initialize memory starting at `self` with `count` `T` values
/// beginning at `source`, bind the initialized memory to type `T`,
/// and return the source memory to an uninitialized state.
///
/// Returns an `UnsafeMutablePointer<T>` this memory.
///
/// - Precondition: `count >= 0`
///
/// - Precondition: The memory at `self..<self + count *
/// strideof(T.self)` is uninitialized and the `T` values at
/// `source..<source + count` are initialized.
///
/// - Postcondition: The memory at `self..<self + count *
/// strideof(T.self)` is bound to type `T`.
///
/// - Postcondition: The `T` values at `self..<self + count *
/// strideof(T.self)` are initialized and the memory at
/// `source..<source + count` is uninitialized.
@discardableResult
public func moveInitializeMemory<T>(
as type: T.Type, from source: UnsafeMutablePointer<T>, count: Int
) -> UnsafeMutablePointer<T> {
_debugPrecondition(
count >= 0,
"UnsafeMutableRawPointer.moveInitializeMemory with negative count")
Builtin.bindMemory(_rawValue, count._builtinWordValue, type)
if self < UnsafeMutableRawPointer(source)
|| self >= UnsafeMutableRawPointer(source + count) {
// initialize forward from a disjoint or following overlapping range.
Builtin.takeArrayFrontToBack(
T.self, self._rawValue, source._rawValue, count._builtinWordValue)
// This builtin is equivalent to:
// for i in 0..<count {
// (self.assumingMemoryBound(to: T.self) + i)
// .initialize(to: (source + i).move())
// }
}
else {
// initialize backward from a non-following overlapping range.
Builtin.takeArrayBackToFront(
T.self, self._rawValue, source._rawValue, count._builtinWordValue)
// This builtin is equivalent to:
// var src = source + count
// var dst = self.assumingMemoryBound(to: T.self) + count
// while dst != self {
// (--dst).initialize(to: (--src).move())
// }
}
return UnsafeMutablePointer(_rawValue)
}
% end # mutable
/// Read raw bytes from memory at `self + offset` and construct a
/// value of type `T`.
///
/// - Precondition: The underlying pointer plus `offset` is properly
/// aligned for accessing `T`.
///
/// - Precondition: The memory is initialized to a value of some type, `U`,
/// such that `T` is layout compatible with `U`.
public func load<T>(fromByteOffset offset: Int = 0, as type: T.Type) -> T {
_debugPrecondition(0 == (UInt(bitPattern: self + offset)
& (UInt(alignof(T.self)) - 1)),
"load from misaligned raw pointer")
return Builtin.load((self + offset)._rawValue)
}
% if mutable:
/// Store a value's bytes into raw memory at `self + offset`.
///
/// - Precondition: The underlying pointer plus `offset` is properly
/// aligned for storing type `T`.
///
/// - Precondition: `T` is a trivial type.
///
/// - Precondition: The memory is uninitialized, or initialized to
/// some trivial type `U` such that `T` and `U` are mutually layout
/// compatible.
///
/// - Postcondition: The memory is initialized to raw bytes. If the
/// memory is bound to type `U`, then it now contains a value of
/// type `U`.
///
/// - Note: A trivial type can be copied with just a bit-for-bit
/// copy without any indirection or reference-counting operations.
/// Generally, native Swift types that do not contain strong or
/// weak references or other forms of indirection are trivial, as
/// are imported C structs and enums.
///
/// - Note: Storing a copy of a nontrivial value into memory
/// requires that the user know the type of value previously in
/// memory, and requires initialization or assignment of the
/// memory. This can be acheived via a typed `UnsafeMutablePointer`
/// or via a raw pointer `self`, as follows, where `U` is the
/// previous type and `T` is the copied value's type:
/// `let typedPtr = self.bindMemory(to: U.self, capacity: 1)`
/// `typedPtr.deinitialize(count: 1)`
/// `self.initializeMemory(as: T.self, to: newValue)`
public func storeBytes<T>(
of value: T, toByteOffset offset: Int = 0, as: T.Type
) {
_debugPrecondition(0 == (UInt(bitPattern: self + offset)
& (UInt(alignof(T.self)) - 1)),
"storeBytes to misaligned raw pointer")
var temp = value
withUnsafeMutablePointer(&temp) { source in
let rawSrc = UnsafeMutableRawPointer(source)._rawValue
// FIXME: to be replaced by _memcpy when conversions are implemented.
Builtin.int_memcpy_RawPointer_RawPointer_Int64(
(self + offset)._rawValue, rawSrc, UInt64(sizeof(T.self))._value,
/*alignment:*/ Int32(0)._value,
/*volatile:*/ false._value)
}
}
/// Copy `count` bytes from `source` into memory at `self`.
///
/// - Precondition: `count` is non-negative.
///
/// - Precondition: The memory at `source..<source + count` is
/// initialized to some trivial type `T`.
///
/// - Precondition: If the memory at `self..<self+count` is bound to
/// a type `U`, then `U` is a trivial type, the underlying
/// pointers `source` and `self` are properly aligned for type
/// `U`, and `count` is a multiple of `strideof(U.self)`.
///
/// - Postcondition: The memory at `self..<self+count` is
/// initialized to raw bytes. If the memory is bound to type `U`,
/// then it contains values of type `U`.
public func copyBytes(from source: UnsafeRawPointer, count: Int) {
_debugPrecondition(
count >= 0, "UnsafeMutableRawPointer.copyBytes with negative count")
_memmove(dest: self, src: source, size: UInt(count))
}
% end # mutable
//
// Protocol conformance
//
/// The hash value.
///
/// **Axiom:** `x == y` implies `x.hashValue == y.hashValue`.
///
/// - Note: The hash value is not guaranteed to be stable across
/// different invocations of the same program. Do not persist the
/// hash value across program runs.
public var hashValue: Int {
return Int(bitPattern: self)
}
/// Return `end - self`.
public func distance(to x: ${Self}) -> Int {
return x - self
}
/// Return `self + n`.
public func advanced(by n: Int) -> ${Self} {
return self + n
}
}
@_transparent
public func == (lhs: ${Self}, rhs: ${Self}) -> Bool {
return Bool(Builtin.cmp_eq_RawPointer(lhs._rawValue, rhs._rawValue))
}
@_transparent
public func < (lhs: ${Self}, rhs: ${Self}) -> Bool {
return Bool(Builtin.cmp_ult_RawPointer(lhs._rawValue, rhs._rawValue))
}
@_transparent
public func + (lhs: ${Self}, rhs: Int) -> ${Self} {
return ${Self}(Builtin.gep_Word(
lhs._rawValue, rhs._builtinWordValue))
}
@_transparent
public func + (lhs: Int, rhs: ${Self}) -> ${Self} {
return rhs + lhs
}
@_transparent
public func - (lhs: ${Self}, rhs: Int) -> ${Self} {
return lhs + -rhs
}
@_transparent
public func - (lhs: ${Self}, rhs: ${Self}) -> Int {
return
Int(Builtin.sub_Word(Builtin.ptrtoint_Word(lhs._rawValue),
Builtin.ptrtoint_Word(rhs._rawValue)))
}
@_transparent
public func += (lhs: inout ${Self}, rhs: Int) {
lhs = lhs + rhs
}
@_transparent
public func -= (lhs: inout ${Self}, rhs: Int) {
lhs = lhs - rhs
}
extension Unsafe${Mutable}RawPointer : CustomDebugStringConvertible {
/// A textual representation of `self`, suitable for debugging.
public var debugDescription: String {
return _rawPointerToString(_rawValue)
}
}
extension Unsafe${Mutable}RawPointer : CustomReflectable {
public var customMirror: Mirror {
let ptrValue = UInt64(
bitPattern: Int64(Int(Builtin.ptrtoint_Word(_rawValue))))
return Mirror(self, children: ["pointerValue": ptrValue])
}
}
extension Unsafe${Mutable}RawPointer : CustomPlaygroundQuickLookable {
var summary: String {
let selfType = "${Self}"
let ptrValue = UInt64(
bitPattern: Int64(Int(Builtin.ptrtoint_Word(_rawValue))))
return ptrValue == 0
? "\(selfType)(nil)"
: "\(selfType)(0x\(_uint64ToString(ptrValue, radix:16, uppercase:true)))"
}
public var customPlaygroundQuickLook: PlaygroundQuickLook {
return .text(summary)
}
}
extension OpaquePointer {
public init(_ from: Unsafe${Mutable}RawPointer) {
self._rawValue = from._rawValue
}
public init?(_ from: Unsafe${Mutable}RawPointer?) {
guard let unwrapped = from else { return nil }
self._rawValue = unwrapped._rawValue
}
}
extension Int {
public init(bitPattern: Unsafe${Mutable}RawPointer?) {
if let bitPattern = bitPattern {
self = Int(Builtin.ptrtoint_Word(bitPattern._rawValue))
} else {
self = 0
}
}
}
extension UInt {
public init(bitPattern: Unsafe${Mutable}RawPointer?) {
if let bitPattern = bitPattern {
self = UInt(Builtin.ptrtoint_Word(bitPattern._rawValue))
} else {
self = 0
}
}
}
% end # for mutable