[swift-evolution] Proposal: Add Initializers For Converting UnsafePointers to Int and Unit

Dmitri Gribenko gribozavr at gmail.com
Thu Dec 10 23:15:46 CST 2015


Thanks Michael!  This looks good, please submit a pull request to
swift-evolution.

Dmitri

On Thu, Dec 10, 2015 at 9:04 PM, Michael Buckley via swift-evolution <
swift-evolution at swift.org> wrote:

> Thanks Dimitri, Brent, and Joe for the feedback. Your additional comments
> on the motivation were very helpful, Dimitri. If I'm not mistaken, there
> has been no negative feedback expressed towards the proposal, nor have
> there been any other alternatives proposed. I believe the next step in the
> Swift evolution process is to draft a proposal in the swift-evolution
> format and circulate it on this mailing list for refinement. So, without
> further ado,
>
> Introduction
>
> Just as users can create Unsafe[Mutable]Pointers from Ints and UInts, they
> should be able to create Ints and UInts from Unsafe[Mutable]Pointers. This
> will allow users to call C functions with intptr_t and uintptr_t
> parameters, and will allow users to perform more advanced pointer
> arithmetic than is allowed by UnsafePointers.
>
> Motivation
>
> Swift currently lacks the ability to perform many complex operations on
> pointers, such as checking pointer alignment, tagging pointers, or XORing
> pointers (for working with XOR linked lists, for example). As a systems
> programming language, Swift ought to be able to solve these problems
> natively and concisely.
>
> Additionally, since some C functions take intptr_t and uintptr_t
> parameters, Swift currently has no ability to call these functions
> directly. Users must wrap calls to these functions in C code.
>
> Proposed solution
>
> Initializers will be added to Int and UInt to convert from UnsafePointer
> and UnsafeMutablePointer.
>
> Currently, the only workaround which can solve these problems is to write
> any code that requires pointer arithmetic in C. Writing this code in Swift
> will be no safer than it is in C, as this is a fundamentally unsafe
> operation. However, it will be cleaner in that users will not be forced to
> write C code.
>
> Detailed design
>
> The initializers will be implemented using the built-in ptrtoint_Word
> function.
>
> extension UInt {
>   init<T>(_ bitPattern: UnsafePointer<T>) {
>     self = UInt(Builtin.ptrtoint_Word(bitPattern._rawValue))
>   }
>
>   init<T>(_ bitPattern: UnsafeMutablePointer<T>) {
>     self = UInt(Builtin.ptrtoint_Word(bitPattern._rawValue))
>   }
> }
>
> extension Int {
>   init<T>(_ bitPattern: UnsafePointer<T>) {
>     self = Int(Builtin.ptrtoint_Word(bitPattern._rawValue))
>   }
>
>   init<T>(_ bitPattern: UnsafeMutablePointer<T>) {
>     self = Int(Builtin.ptrtoint_Word(bitPattern._rawValue))
>   }
> }
>
> As an example, these initializers will allow the user to get the next
> address of an XOR linked list in Swift.
>
> struct XORLinkedList<T> {
>   let address: UnsafePointer<T>
>
>   ...
>
>   func successor(_ predecessor: XORLinkedList<T>) -> XORLinkedList<T> {
>     return XorLinkedList(UnsafePointer<T>(UInt(address) ^
> UInt(predecessor.address)))
>   }
> }
>
> Impact on existing code
>
> There is no impact on existing code.
>
> Alternatives considered
>
> Three alternatives were considered.
>
> The first alternative was to add an intValue function to
> Unsafe[Mutable]Pointer. This alternative was rejected because it is
> preferred that type conversions be implemented as initializers where
> possible.
>
> The next alternative was to add functions to Unsafe[Mutable]Pointer which
> covered the identified pointer arithmetic cases. This alternative was
> rejected because it either would have required us to imagine every use-case
> of pointer arithmetic and write functions for them, which is an impossible
> task, or it would have required adding a full suite of arithmetic and
> bitwise operators to Unsafe[Mutable]Pointer. Because some of these
> operations are defined only on signed integers, and others on unsigned, it
> would have required splitting Unsafe[Mutable]Pointer into signed and
> unsigned variants, which would have complicated things for users who did
> not need to do pointer arithmetic. Additionally, the implementations of
> these operations would have probably converted the pointers to integers,
> perform a single operation, and then convert them back. When chaining
> operations, this would create a lot of unnecessary conversions.
>
> The last alternative was to forgo these initializers and force users to
> write all their complicated pointer code in C. This alternative was
> rejected because it makes Swift less useful as a systems programming
> language.
>
> On Wed, Dec 9, 2015 at 1:55 PM, Dmitri Gribenko via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>> On Wed, Dec 9, 2015 at 1:15 PM, Brent Royal-Gordon via swift-evolution
>> <swift-evolution at swift.org> wrote:
>> >> On the off chance you're trying to do loads from unaligned
>> UnsafePointers, that's undefined in the current interface. You'll need to
>> memcpy to well-aligned memory first.
>> >
>> > The buffer I’m accessing is UInt8, which I believe is always aligned,
>> right?
>> >
>> > C:
>> >
>> >         typedef struct MIDIMetaEvent
>> >         {
>> >                 UInt8           metaEventType;
>> >                 UInt8           unused1;
>> >                 UInt8           unused2;
>> >                 UInt8           unused3;
>> >                 UInt32          dataLength;
>> >                 UInt8           data[1];
>> >         } MIDIMetaEvent;
>> >
>> > Swift:
>> >
>> >         public struct MIDIMetaEvent {
>> >
>> >             public var metaEventType: UInt8
>> >             public var unused1: UInt8
>> >             public var unused2: UInt8
>> >             public var unused3: UInt8
>> >             public var dataLength: UInt32
>> >             public var data: (UInt8)
>> >             public init()
>> >             public init(metaEventType: UInt8, unused1: UInt8, unused2:
>> UInt8, unused3: UInt8, dataLength: UInt32, data: (UInt8))
>> >         }
>>
>> FWIW, this problem looks very much like one for which we did the
>> CoreAudio overlay: stdlib/public/SDK/CoreAudio/CoreAudio.swift
>>
>> Dmitri
>>
>> --
>> main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
>> (j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr at gmail.com>*/
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>


-- 
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr at gmail.com>*/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151210/afdcfec7/attachment.html>


More information about the swift-evolution mailing list