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