Admin message

Due to a large amount of spam we do not allow new users to create repositories, they are "external" users. If you are a new user and want to create a repository, for example for forking GHC, open a new issue on ghc/ghc using the "get-verified" issue template

Integer division can overwrite other arguments to foreign call
If you call a foreign function, GHC can generate incorrect code while passing the arguments to the function, overwriting the 3rd argument if a later argument contains an integer division. Main.hs: ``` {-# LANGUAGE ForeignFunctionInterface #-} module Main where {-# NOINLINE foo #-} foo :: Int -> IO () foo x = c_foo 0 0 x $ x + x `quot` 10 foreign import ccall "foo" c_foo :: Int -> Int -> Int -> Int -> IO () main :: IO () main = do foo 202 foo 203 foo 204 ``` foo.c: ``` #include <stdio.h> void foo(int a, int b, int c, int d) { printf("%d, %d, %d, %d\n", a, b, c, d); } ``` Expected output: ``` 0, 0, 202, 222 0, 0, 203, 223 0, 0, 204, 224 ``` Actual output: ``` 0, 0, 2, 222 0, 0, 3, 223 0, 0, 4, 224 ``` The bug has to be somewhere in the code generator. The cmm reads: ``` call "ccall" arg hints: [‘signed’, ‘signed’, ‘signed’, ‘signed’] result hints: [] foo(0, 0, _s3nE::I64, _s3nE::I64 + %MO_S_Quot_W64(_s3nE::I64, 10)); ``` This generates the following assembler code: ``` xorl %edi,%edi xorl %esi,%esi movq %rbx,%rdx movl $10,%ecx movq %rax,%rdx <-- move 3rd argument into rdx movq %rbx,%rax movq %rdx,%r8 cqto idivq %rcx <-- rax := rax / rcx; rdx := rax % rcx movq %rbx,%rcx addq %rax,%rcx subq $8,%rsp xorl %eax,%eax movq %r8,%rbx call foo ``` Thus rdx is overwritten again before the call, leading to incorrect results. <details><summary>Trac metadata</summary> | Trac field | Value | | ---------------------- | -------------- | | Version | 8.0.1 | | Type | Bug | | TypeOfFailure | OtherFailure | | Priority | normal | | Resolution | Unresolved | | Component | Compiler (NCG) | | Test case | | | Differential revisions | | | BlockedBy | | | Related | | | Blocking | | | CC | | | Operating system | | | Architecture | | </details> <!-- {"blocked_by":[],"summary":"Integer division can overwrite other arguments to foreign call","status":"New","operating_system":"","component":"Compiler (NCG)","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.0.1","keywords":["division","integer"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"If you call a foreign function, GHC can generate incorrect code while passing the arguments to the function, overwriting the 3rd argument if a later argument contains an integer division.\r\n\r\nMain.hs:\r\n\r\n{{{\r\n{-# LANGUAGE ForeignFunctionInterface #-}\r\nmodule Main where\r\n\r\n{-# NOINLINE foo #-}\r\nfoo :: Int -> IO ()\r\nfoo x = c_foo 0 0 x $ x + x `quot` 10\r\n\r\nforeign import ccall \"foo\" c_foo :: Int -> Int -> Int -> Int -> IO ()\r\n\r\nmain :: IO ()\r\nmain = do\r\n foo 202\r\n foo 203\r\n foo 204\r\n}}}\r\n\r\nfoo.c:\r\n\r\n{{{\r\n#include <stdio.h>\r\n\r\nvoid foo(int a, int b, int c, int d) {\r\n printf(\"%d, %d, %d, %d\\n\", a, b, c, d);\r\n}\r\n}}}\r\n\r\nExpected output:\r\n{{{\r\n0, 0, 202, 222\r\n0, 0, 203, 223\r\n0, 0, 204, 224\r\n}}}\r\n\r\nActual output:\r\n{{{\r\n0, 0, 2, 222\r\n0, 0, 3, 223\r\n0, 0, 4, 224\r\n}}}\r\n\r\nThe bug has to be somewhere in the code generator. The cmm reads:\r\n\r\n{{{\r\ncall \"ccall\" arg hints: [‘signed’, ‘signed’, ‘signed’, ‘signed’] result hints: [] foo(0, 0, _s3nE::I64, _s3nE::I64 + %MO_S_Quot_W64(_s3nE::I64, 10));\r\n}}}\r\n\r\nThis generates the following assembler code:\r\n\r\n{{{\r\n xorl %edi,%edi\r\n xorl %esi,%esi\r\n movq %rbx,%rdx\r\n movl $10,%ecx\r\n movq %rax,%rdx <-- move 3rd argument into rdx\r\n movq %rbx,%rax\r\n movq %rdx,%r8\r\n cqto\r\n idivq %rcx <-- rax := rax / rcx; rdx := rax % rcx\r\n movq %rbx,%rcx\r\n addq %rax,%rcx\r\n subq $8,%rsp\r\n xorl %eax,%eax\r\n movq %r8,%rbx\r\n call foo\r\n}}}\r\n\r\nThus rdx is overwritten again before the call, leading to incorrect results.","type_of_failure":"OtherFailure","blocking":[]} -->
issue