
#11792: Optimised unsafe FFI call can get wrong argument -------------------------------------+------------------------------------- Reporter: Szunti | Owner: Type: bug | Status: new Priority: high | Milestone: Component: Compiler | Version: 7.10.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by osa1): I spent some time debugging this. Here are codes for FFI function arguments (before register allocation): {{{ first arg: [ xorl %edi,%edi] second arg: [ xorl %esi,%esi] third arg: [ movl $7457,%edx] fourth arg: [ movl $255,%vI_n4I8, movq 7(%rbx),%vI_n4Ia, imulq %vI_s4pW,%vI_n4Ia, movl %vI_n4Ia,%eax, xorq %rdx,%rdx, divq %vI_n4I8, movq %rax,%vI_n4Ib, shlq $8,%vI_n4Ib, movl %vI_n4Ib,%vI_n4Ic, movl $255,%vI_n4Id, movq 24(%rbp),%vI_n4If, imulq %vI_s4pW,%vI_n4If, movl %vI_n4If,%eax, xorq %rdx,%rdx, divq %vI_n4Id, movq %rax,%vI_n4Ih, addq %vI_n4Ic,%vI_n4Ih, movl %vI_n4Ih,%vI_n4Ii, shlq $8,%vI_n4Ii, movl %vI_n4Ii,%vI_n4Ij, movl $255,%vI_n4Ik, movq 16(%rbp),%vI_n4Im, imulq %vI_s4pW,%vI_n4Im, movl %vI_n4Im,%eax, xorq %rdx,%rdx, divq %vI_n4Ik, movq %rax,%vI_n4Io, addq %vI_n4Ij,%vI_n4Io, movl %vI_n4Io,%vI_n4Ip, shlq $8,%vI_n4Ip, movl %vI_n4Ip,%vI_n4Iq, leaq 255(%vI_n4Iq),%vI_n4Ir, movl %vI_n4Ir,%ecx] }}} These look correct to me. Since the code mostly uses virtual registers `%edx` isn't overridden at this point. So I think the problem may be in register allocation. I don't know how register allocation in GHC is working, but I looked at liveness information output, and it shows this for the `call third_arg` instruction: {{{ call third_arg # born: %r8 %r9 %r10 %r11 %r16 %r17 %r18 %r19 %r20 %r21 %r24 %r25 %r26 %r27 %r28 %r29 %r30 %r31 %r32 %r33 %r34 %r35 %r36 %r37 %r38 %r39 # w_dying: %r2 %r3 %r4 %r5 %r8 %r9 %r10 %r11 %r16 %r17 %r18 %r19 %r20 %r21 %r24 %r25 %r26 %r27 %r28 %r29 %r30 %r31 %r32 %r33 %r34 %r35 %r36 %r37 %r38 %r39 }}} I don't quite understand what's happening here (what are all those registers??), but I'd expect this instruction to "read" (or "use") `%edx`. So `%edx` would have to stay live between `third arg` and this call instruction, and so register allocation would have to generate some spill instructions when allocating registers for fourth argument if available registers are not enough. At least this is how my compiler is doing it. I may have another look tomorrow. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11792#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler