[swift-users] UnsafeMutablePointer Swift 3 conversion

Jacob Bandes-Storch jtbandes at gmail.com
Sat Sep 3 20:27:21 CDT 2016


I was referring to this:

        let mainPtr : UnsafeMutablePointer<MainPass> = shadowPtr.advanced
(by: 1).withMemoryRebound(to: MainPass.self, capacity: 1) {$0}
        mainPtr.pointee = mainPassFrameData

The result of $0 is being returned from the block and used later.

cc'ing Andrew Trick on this conversation because his input would be quite
useful :-)

Jacob

On Sat, Sep 3, 2016 at 2:03 PM, Patrice Kouame <pkouame at me.com> wrote:

>
> Not sure what you mean?
> The positional arg $0 is never used outside the closure whatever the
> version...
> No attempt is ever made to save and reuse after withMemoryRebound?
> Why would I use a separate function?
>
> Are we looking at the same code? 🤓
>
> rédigé sur mon iPhone.
>
> On Sep 3, 2016, at 4:16 PM, Jacob Bandes-Storch <jtbandes at gmail.com>
> wrote:
>
> Yikes! That's unsafe! When using withMemoryRebound, I think you're only
> supposed to use the argument $0 inside the block. Saving it and using it
> after withMemoryRebound is probably undefined behavior. But maybe you can
> move your ".pointee = x" into a separate function rather than using a
> closure?
>
> On Sat, Sep 3, 2016 at 1:12 PM, Patrice Kouame via swift-users <
> swift-users at swift.org> wrote:
>
>> Finally Success!  I’m seeing my pretty little 3D twirling Metal Renderer
>> cubes again… Here’s how
>>
>> Snippet of old  sample code which no longer compiles in Xcode 8 beta 6
>> with stricter Swift3 unsafe type casting restrictions
>> (in MetalView.swift from # Adopting Metal II: Designing and Implementing
>> a Real-World Metal Renderer)
>>
>> let shadowPtr = UnsafeMutablePointer<ShadowPas
>> s>(constantBufferForFrame.contents())
>> let mainPtr = UnsafeMutablePointer<MainPass>(shadowPtr.advanced(by: 1))
>> mainPtr.pointee = mainPassFrameData
>> var ptr = UnsafeMutablePointer<ObjectData>(mainPtr.advanced(by: 1))
>>
>> My conversion attempt that crashes Swift 3 Xcode 8 beta 6 (see  RADAR 28150447
>> - Swift 3 UnsafeMutablePointer conversion crashes the compiler and IDE)
>>
>>         let shadowPtr = constantBufferForFrame.contents().bindMemory(to:
>> ShadowPass.self, capacity: MemoryLayout<shadowPassData>.size)
>>         let mainPtr : UnsafeMutablePointer<MainPass> = shadowPtr.advanced(by:
>> 1).withMemoryRebound(to: MainPass.self, capacity: 1) {
>> $0.pointee = mainPassFrameData
>> }
>>         var ptr : UnsafeMutablePointer<ObjectData> = mainPtr.advanced(by:
>> 1).withMemoryRebound(to: ObjectData.self, capacity: MemoryLayout< Object
>> Data >.size) {$0}
>>
>> Latest conversion that make Xcode and Swift 3 smile again...
>>
>>         let shadowPtr = constantBufferForFrame.contents().bindMemory(to:
>> ShadowPass.self, capacity: shadowPassData.count)
>>         let mainPtr : UnsafeMutablePointer<MainPass> = shadowPtr.advanced(by:
>> 1).withMemoryRebound(to: MainPass.self, capacity: 1) {$0}
>>         mainPtr.pointee = mainPassFrameData
>>         var ptr : UnsafeMutablePointer<ObjectData> = mainPtr.advanced(by:
>> 1).withMemoryRebound(to: ObjectData.self, capacity: objectsToRender) {$0}
>>
>> Yes… Xcode/Swift3 SIL generation definitely did NOT like my "$0.pointee =
>> mainPassFrameData" statement.
>> Apparently, reassigning the pointee within the closure makes Swift gag
>> out of disgust. Sorry ;-(
>> That’s what I get for trying to be fancy…
>> And fixed my “capacity” issues thanks to some previous posters.
>>
>> Hope this helps anyone trying to get the Metal projects to compile again.
>>
>> At least I got a Radar out of this ;-) Compilers should never burn and
>> crash out like this...
>>
>> Regards to all, Patrice
>>
>>
>> On Sep 3, 2016, at 1:22 PM, Patrice Kouame via swift-users <
>> swift-users at swift.org> wrote:
>>
>> Gerard-
>>
>> Excellent!  Looking forward to seeing your fix (hoping you get your book
>> back soon ;-) )
>>
>> I think Xcode/Swift gags on the last ptr advance to objectData.  I
>> recently tried another variant using withUnsafeMutablePointer like this:
>>
>>         var ptr : UnsafeMutablePointer<ObjectData>  =
>> withUnsafeMutablePointer(to: &mainPtr) {
>>             $0.withMemoryRebound(to: ObjectData.self, capacity:
>> objectsToRender) {
>>                 $0.pointee = renderables[0].objectData
>>             }
>>         }
>>
>> ..but still crashes with no hints.
>>
>> My bug report also mentions that the Xcode migration/conversion tool is
>> incomplete.
>> It handles the “simpler" UnsafeMutableRawPointer<X> to
>> UnsafeMutablePonter<Y> with bindMemory cases correctly (one still has to
>> mind the capacity value though)
>> In all fairness, migrating/converting automagically in these cases is
>> always a little bit tricky - the proposed Xcode fixes should always be
>> reviewed by a human...
>>
>> Patrice
>>
>> On Sep 3, 2016, at 1:05 PM, Gerard Iglesias via swift-users <
>> swift-users at swift.org> wrote:
>>
>> Ok
>>
>> For the record I succeeded this transformation phase last week
>>
>> I remember the tedious stuff to advance pointer from one struct to the
>> other kind of struct... it worked
>>
>> But I don't have my MacBook with me, only the phone, the six :)
>>
>> GĂ©rard
>>
>> Le 3 sept. 2016 Ă  18:22, Patrice Kouame <pkouame at me.com> a Ă©crit :
>>
>> Indeed. There is a difference between stride and size, but I interpreted
>> capacity incorrectly for my purposes.  It should indicate the number of <T>
>> elements (not their size - right?) and the snippets below should work.
>>
>> Still, compiler crashes and Xcode IDE is left in inconsistent state.  So
>> I filed this Apple radar against Developer Tools.
>>
>> 28150447 - Swift 3 UnsafeMutablePointer conversion crashes the compiler
>> and IDE
>> Should I file a Swift bug too? Would that be helpful?
>>
>> Regards, Patrice
>>
>> On Sep 3, 2016, at 11:39 AM, Gerard Iglesias via swift-users <
>> swift-users at swift.org> wrote:
>>
>> Hello,
>>
>> I think that it is more secure to use stride in place of size, sometimes
>> it is not the same value.
>>
>> I use it in my own use of raw bindings
>>
>> Regards
>>
>> GĂ©rard
>>
>> Le 3 sept. 2016 Ă  10:03, Patrice Kouame via swift-users <
>> swift-users at swift.org> a Ă©crit :
>>
>> Hi Jacob -
>>
>> I think you’re right. “capacity” should be the count of type T elements
>> in my buffer.  So in my case that line should read
>>
>>         let shadowPtr = constantBufferForFrame.contents().bindMemory(to:
>> ShadowPass.self, capacity: shadowPassData.count)
>>
>> The withMemoryRebound calls need similar adjustments. The pointer to
>> MainPass is actually a single structure to it should be safe to do this
>>
>>         let mainPtr : UnsafeMutablePointer<MainPass> =
>> shadowPtr.advanced(by: 1).withMemoryRebound(to: MainPass.self, capacity:
>> 1) {
>>             $0.pointee = mainPassFrameData
>>         }
>>
>> Whereas the unsafe pointer to <ObjectData> is actually a buffer of
>> renderable objects, so this should work:
>>
>>         var ptr : UnsafeMutablePointer<ObjectData> =
>> mainPtr.advanced(by: 1).withMemoryRebound(to: ObjectData.self, capacity:
>> objectsToRender) {_ in
>> }
>>
>> There are surely ways to refactor and simplify this, but I’m trying to
>> retain as much of the original sample code approach as possible.
>>
>> However, the compiler still segs badly.
>> Xcode also borks an internal error often. Only cleaning or restarting
>> the project can clear up that state.
>> Compilers (or Playgrounds for that matter) should never crash, and I’m
>> not sure where to file this bug : Swift or Apple radar against Xcode or
>> both? I now Xcode 8 is beta but…it’s been doing this for quite a while
>> now...
>>
>> In both our “close to the metal” (no pun intended) cases, it seems like a
>> lot of churning for very little gain. Don’t you think? The easier, but
>> “unsafe” casting afforded previously did the trick with the normal caveats.
>> Don’t get me wrong, I love Swift and “get" all the neat type safety
>> features. Guess we can’t have our cake and eat it too, especially when
>> interfacing with “unsafe” C APIs.
>>
>> Anyway, back to rtfm … maybe some of the Swift Gods can chime in?  ;-)
>>
>> I must be doing something stupid...Patrice
>>
>> On Sep 3, 2016, at 2:32 AM, Jacob Bandes-Storch <jtbandes at gmail.com>
>> wrote:
>>
>> Hi Patrice,
>> I don't have a solution for you, but I just wanted to point out what I
>> think may be an error with your use of the new UnsafeRawPointer APIs:
>>
>> constantBufferForFrame.contents().bindMemory(to: ShadowPass.self,
>> capacity: MemoryLayout<ShadowPass>.size)
>>
>> I believe the `capacity` should actually be the number of ShadowPass
>> elements in the buffer, not the size of each element. Using `bindMemory(to:
>> ShadowPass.self` already implies that MemoryLayout<ShadowPass>.size is the
>> size of each element.
>>
>> More info at https://developer.apple.com/reference/swift/unsaferawpointer
>> /2428875-bindmemory
>>
>> I just updated a small Metal project of mine to Swift 3. I ran into some
>> compiler (playground) crashes, but it does seem to work most of the time.
>> Although I only have 1 buffer :-) https://github.com/jtbandes/Me
>> talbrot.playground
>>
>> Jacob
>>
>> On Fri, Sep 2, 2016 at 11:00 AM, Patrice Kouame via swift-users <
>> swift-users at swift.org> wrote:
>>
>>> Hi all -
>>>
>>> I’m converting Apple’s Swift Sample "Adopting Metal II: Designing and
>>> Implementing a Real-World Metal Renderer” in Xcode 8 beta6 to the latest
>>> UnsafeMutablePointer API for untyped memory access.
>>> Changes are necessary in MetalView.swift (Apple hasn’t updated their
>>> sample code for the latest beta yet…)
>>> The Swift Compiler crashes (Segmentation Fault: 11) on the attempt:
>>>
>>>         // Grab a pointer to the constant buffer's data store
>>>         // Since we are using Swift, it is easier to cast the pointer
>>> to the ShadowPass type to fill the constant buffer
>>>         // We need to make a copy of these so the block captures the
>>> correct data
>>>
>>> //      let shadowPtr = UnsafeMutablePointer<ShadowPas
>>> s>(constantBufferForFrame.contents())
>>>         let shadowPtr = constantBufferForFrame.contents().bindMemory(to:
>>> ShadowPass.self, capacity: MemoryLayout<ShadowPass>.size)
>>>         shadowPtr.pointee = shadowPassData[0]
>>>
>>>         //More Swift specific stuff - advance pointer and cast to
>>> MainPass
>>>
>>> //      let mainPtr = UnsafeMutablePointer<MainPass>(shadowPtr.advanced(by:
>>> 1))
>>> //      mainPtr.pointee = mainPassFrameData
>>>         let mainPtr : UnsafeMutablePointer<MainPass>  =
>>> shadowPtr.advanced(by: 1).withMemoryRebound(to: MainPass.self,
>>> capacity: MemoryLayout<MainPass>.size) {
>>>             $0.pointee = mainPassFrameData
>>>         }
>>>
>>>         //Advance and cast to ObjectData
>>>
>>> //      var ptr = UnsafeMutablePointer<ObjectData>(mainPtr.advanced(by:
>>> 1))
>>>         var ptr : UnsafeMutablePointer<ObjectData> =
>>> mainPtr.advanced(by: 1).withMemoryRebound(to: ObjectData.self,
>>> capacity: MemoryLayout<ObjectData>.size) {_ in
>>>         }
>>>
>>>         let shadowOffset = 0
>>>         let mainPassOffset = MemoryLayout<ShadowPass>.size +
>>> shadowOffset
>>>         let objectDataOffset = MemoryLayout<MainPass>.size +
>>> mainPassOffset
>>>
>>>         // Update position of all the objects
>>>         if multithreadedUpdate {
>>>             DispatchQueue.concurrentPerform(iterations:
>>> objectsToRender) { i in
>>>                 let thisPtr = ptr.advanced(by: i)
>>>                 _ = self.renderables[i].UpdateData(ptr, deltaTime: 1.0/
>>> 60.0)
>>>             }
>>>         }
>>>         else {
>>>             for index in 0..<objectsToRender {
>>>                 ptr = renderables[index].UpdateData(ptr, deltaTime: 1.0/
>>> 60.0)
>>>             }
>>>         }
>>>
>>>         ptr = ptr.advanced(by: objectsToRender)
>>>
>>>         _ = groundPlane!.UpdateData(ptr, deltaTime: 1.0/60.0)
>>>
>>> Any help is appreciated.  I have the latest Xcode log handy if
>>> necessary.  Here’s a clip of the stack trace.
>>>
>>> 0  swift                    0x000000010714a99d
>>> PrintStackTraceSignalHandler(void*) + 45
>>> 1  swift                    0x000000010714a3e6 SignalHandler(int) + 470
>>> 2  libsystem_platform.dylib 0x00007fff91461bba _sigtramp + 26
>>> 3  libsystem_platform.dylib 000000000000000000 _sigtramp + 1857676384
>>> 4  swift                    0x00000001047207b3 (anonymous
>>> namespace)::SILGenApply::visitExpr(swift::Expr*) + 51
>>> 5  swift                    0x0000000104723ace (anonymous
>>> namespace)::SILGenApply::visitApplyExpr(swift::ApplyExpr*) + 5182
>>> 6  swift                    0x0000000104711cc1
>>> prepareApplyExpr(swift::Lowering::SILGenFunction&, swift::Expr*) + 273
>>> 7  swift                    0x00000001047624e7
>>> swift::ASTVisitor<(anonymous namespace)::RValueEmitter,
>>> swift::Lowering::RValue, void, void, void, void, void,
>>> swift::Lowering::SGFContext>::visit(swift::Expr*,
>>> swift::Lowering::SGFContext) + 103
>>> 8  swift                    0x0000000104762313
>>> swift::Lowering::SILGenFunction::emitExprInto(swift::Expr*,
>>> swift::Lowering::Initialization*) + 195
>>> 9  swift                    0x000000010474fbc3
>>> swift::Lowering::SILGenFunction::emitPatternBinding(swift::PatternBindingDecl*,
>>> unsigned int) + 195
>>> 10 swift                    0x00000001047077bd
>>> swift::ASTVisitor<swift::Lowering::SILGenFunction, void, void, void,
>>> void, void, void>::visit(swift::Decl*) + 125
>>> 11 swift                    0x00000001047c0019
>>> swift::ASTVisitor<(anonymous namespace)::StmtEmitter, void, void, void,
>>> void, void, void>::visit(swift::Stmt*) + 4169
>>> 12 swift                    0x00000001047809ba
>>> swift::Lowering::SILGenFunction::emitFunction(swift::FuncDecl*) + 314
>>> 13 swift                    0x00000001046fd775
>>> swift::Lowering::SILGenModule::emitFunction(swift::FuncDecl*
>>> )::$_1::operator()(swift::SILFunction*) const + 1877
>>> 14 swift                    0x00000001046fc322
>>> swift::Lowering::SILGenModule::emitFunction(swift::FuncDecl*) + 626
>>> 15 swift                    0x00000001047c7007 (anonymous
>>> namespace)::SILGenType::emitType() + 1271
>>> 16 swift                    0x00000001047c6a9e
>>> swift::Lowering::SILGenModule::visitNominalTypeDecl(swift::NominalTypeDecl*)
>>> + 30
>>> 17 swift                    0x0000000104709093
>>> swift::Lowering::SILGenModule::emitSourceFile(swift::SourceFile*,
>>> unsigned int) + 1795
>>> 18 swift                    0x000000010470ad4d
>>> swift::SILModule::constructSIL(swift::ModuleDecl*, swift::SILOptions&,
>>> swift::FileUnit*, llvm::Optional<unsigned int>, bool, bool) + 1629
>>> 19 swift                    0x00000001045621bf
>>> performCompile(swift::CompilerInstance&, swift::CompilerInvocation&,
>>> llvm::ArrayRef<char const*>, int&, swift::FrontendObserver*) + 19487
>>> 20 swift                    0x000000010455b2c5
>>> swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*,
>>> swift::FrontendObserver*) + 17029
>>> 21 swift                    0x000000010451888d main + 8685
>>> 22 libdyld.dylib            0x00007fff91255255 start + 1
>>>
>>>
>>> Patrice
>>>
>>>
>>> _______________________________________________
>>> swift-users mailing list
>>> swift-users at swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-users
>>>
>>>
>>
>> _______________________________________________
>> swift-users mailing list
>> swift-users at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-users
>>
>> _______________________________________________
>> swift-users mailing list
>> swift-users at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-users
>>
>>
>> _______________________________________________
>> swift-users mailing list
>> swift-users at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-users
>>
>>
>> _______________________________________________
>> swift-users mailing list
>> swift-users at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-users
>>
>>
>>
>> _______________________________________________
>> swift-users mailing list
>> swift-users at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-users
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20160903/b3f3ba33/attachment.html>


More information about the swift-users mailing list