#11792: Optimised unsafe FFI call can get wrong argument -------------------------------------+------------------------------------- Reporter: Szunti | Owner: Type: bug | Status: new Priority: normal | 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 hsyl20): For the record, the unsafe foreign call in Cmm after sink assignments: {{{#!C (_s3N3::I64) = call "ccall" arg hints: [, , ,] result hints: [] third_arg(0, 0, 7457, %MO_UU_Conv_W32_W64(%MO_UU_Conv_W64_W32(%MO_UU_Conv_W32_W64(%MO_UU_Conv_W64_W32(%MO_UU_Conv_W32_W64(%MO_UU_Conv_W64_W32(%MO_UU_Conv_W32_W64(%MO_UU_Conv_W64_W32(I64[Sp + 16] * _s3MA::I64)) / 255 + %MO_UU_Conv_W32_W64(%MO_UU_Conv_W64_W32(%MO_UU_Conv_W32_W64(%MO_UU_Conv_W64_W32(%MO_UU_Conv_W32_W64(%MO_UU_Conv_W64_W32(I64[Sp + 24] * _s3MA::I64)) / 255 + %MO_UU_Conv_W32_W64(%MO_UU_Conv_W64_W32(%MO_UU_Conv_W32_W64(%MO_UU_Conv_W64_W32(I64[R1 + 7] * _s3MA::I64)) / 255 << 8)))) << 8)))) << 8)) + 255))); }}} Indeed edx doesn't seem to be in the clobber list when the code for the fourth argument is generated and we obtain: {{{#!asm 405dc9: ba 21 1d 00 00 mov $0x1d21,%edx ; 0x1d21 is the third arg 405dce: b9 ff 00 00 00 mov $0xff,%ecx 405dd3: 48 8b 5b 07 mov 0x7(%rbx),%rbx 405dd7: 48 0f af d8 imul %rax,%rbx 405ddb: 48 89 c2 mov %rax,%rdx ; problem ... 405e43: e8 82 03 00 00 callq 4061ca <third_arg> }}} The following note in compiler/cmm/CmmNode.hs seems to be relevant: {{{#!hs {- Note [Register parameter passing] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ On certain architectures, some registers are utilized for parameter passing in the C calling convention. For example, in x86-64 Linux convention, rdi, rsi, rdx and rcx (as well as r8 and r9) may be used for argument passing. These are registers R3-R6, which our generated code may also be using; as a result, it's necessary to save these values before doing a foreign call. This is done during initial code generation in callerSaveVolatileRegs in StgCmmUtils.hs. However, one result of doing this is that the contents of these registers may mysteriously change if referenced inside the arguments. This is dangerous, so you'll need to disable inlining much in the same way is done in cmm/CmmOpt.hs currently. We should fix this! -} }}} -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/11792#comment:2> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler