[swift-users] UnsafeMutablePointer Swift 3 conversion

Jacob Bandes-Storch jtbandes at gmail.com
Sat Sep 3 15:16:31 CDT 2016


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<ShadowPass>(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<
> ObjectData >.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/
> Metalbrot.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/d700d33e/attachment.html>


More information about the swift-users mailing list