<div dir="ltr">Thanks Michael! This looks good, please submit a pull request to swift-evolution.<div><br></div><div>Dmitri<br><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Dec 10, 2015 at 9:04 PM, Michael Buckley via swift-evolution <span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">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,<div><br></div><div><div>Introduction</div><div><br></div><div>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.</div><div><br></div><div>Motivation</div><div><br></div><div>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.</div><div><br></div><div>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.</div><div><br></div><div>Proposed solution</div><div><br></div><div>Initializers will be added to Int and UInt to convert from UnsafePointer and UnsafeMutablePointer.</div><div><br></div><div>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.</div><div><br></div><div>Detailed design</div><div><br></div><div>The initializers will be implemented using the built-in ptrtoint_Word function.</div><div><br></div><div><div><div style="font-size:13px">extension UInt {</div><div style="font-size:13px"> init<T>(_ bitPattern: UnsafePointer<T>) {</div><div style="font-size:13px"> self = UInt(Builtin.ptrtoint_Word(bitPattern._rawValue))</div><div style="font-size:13px"> }</div><div style="font-size:13px"><br></div><div style="font-size:13px"> init<T>(_ bitPattern: UnsafeMutablePointer<T>) {</div><div style="font-size:13px"> self = UInt(Builtin.ptrtoint_Word(bitPattern._rawValue))</div><div style="font-size:13px"> }</div><div style="font-size:13px">}</div><div style="font-size:13px"><br></div><div style="font-size:13px">extension Int {</div><div style="font-size:13px"> init<T>(_ bitPattern: UnsafePointer<T>) {</div><div style="font-size:13px"> self = Int(Builtin.ptrtoint_Word(bitPattern._rawValue))</div><div style="font-size:13px"> }</div><div style="font-size:13px"><br></div><div style="font-size:13px"> init<T>(_ bitPattern: UnsafeMutablePointer<T>) {</div><div style="font-size:13px"> self = Int(Builtin.ptrtoint_Word(bitPattern._rawValue))</div><div style="font-size:13px"> }</div><div style="font-size:13px">}</div></div></div><div><br></div><div>As an example, these initializers will allow the user to get the next address of an XOR linked list in Swift.</div><div><br></div><div>struct XORLinkedList<T> {</div><div> let address: UnsafePointer<T></div><div><br></div><div> ...</div><div><br></div><div> func successor(_ predecessor: XORLinkedList<T>) -> XORLinkedList<T> {</div><div> return XorLinkedList(UnsafePointer<T>(UInt(address) ^ UInt(predecessor.address)))</div><div> }</div><div>}</div><div><br></div><div>Impact on existing code</div><div><br></div><div>There is no impact on existing code.</div><div><br></div><div>Alternatives considered</div><div><br></div><div>Three alternatives were considered.</div></div><div><br></div><div>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.</div><div><br></div><div>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.</div><div><br></div><div>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.</div><div class="gmail_extra"><br><div class="gmail_quote"><div><div class="h5">On Wed, Dec 9, 2015 at 1:55 PM, Dmitri Gribenko via swift-evolution <span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span> wrote:<br></div></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div><div class="h5"><span>On Wed, Dec 9, 2015 at 1:15 PM, Brent Royal-Gordon via swift-evolution<br>
<<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:<br>
>> 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.<br>
><br>
> The buffer I’m accessing is UInt8, which I believe is always aligned, right?<br>
><br>
> C:<br>
><br>
> typedef struct MIDIMetaEvent<br>
> {<br>
> UInt8 metaEventType;<br>
> UInt8 unused1;<br>
> UInt8 unused2;<br>
> UInt8 unused3;<br>
> UInt32 dataLength;<br>
> UInt8 data[1];<br>
> } MIDIMetaEvent;<br>
><br>
> Swift:<br>
><br>
> public struct MIDIMetaEvent {<br>
><br>
> public var metaEventType: UInt8<br>
> public var unused1: UInt8<br>
> public var unused2: UInt8<br>
> public var unused3: UInt8<br>
> public var dataLength: UInt32<br>
> public var data: (UInt8)<br>
> public init()<br>
> public init(metaEventType: UInt8, unused1: UInt8, unused2: UInt8, unused3: UInt8, dataLength: UInt32, data: (UInt8))<br>
> }<br>
<br>
</span>FWIW, this problem looks very much like one for which we did the<br>
CoreAudio overlay: stdlib/public/SDK/CoreAudio/CoreAudio.swift<br>
<span><br>
Dmitri<br>
<br>
--<br>
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if<br>
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <<a href="mailto:gribozavr@gmail.com" target="_blank">gribozavr@gmail.com</a>>*/<br>
</span></div></div><span class="">_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
</span></blockquote></div><br></div></div>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=HvbB2rNqe6WERAH1f5iSygoap13wP4MPscYBJZE6r41aphsDoBXQj5-2Fb8abNi9JPFyE4sjJ2Ysvog-2BWAzK2ozP-2BZ7Lrg587Mrt9Dau-2FwxaIgoms0mWuL1w1M4sBoBMQJvWp7clcnCsHiTHiRhaj23WIpIGcGDtv5qCGO2YMuzmKSCOFMo9G4SwnyEnoKwt-2FUgBEAFRW3K6Zcd3JInCtDaC3AVY-2BqL9mzUKUoBRYEYSo-3D" alt="" width="1" height="1" border="0" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important">
<br>_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
<br></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature">main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if<br>(j){printf("%d\n",i);}}} /*Dmitri Gribenko <<a href="mailto:gribozavr@gmail.com" target="_blank">gribozavr@gmail.com</a>>*/</div>
</div></div></div>