Ticket #1424 (closed bug: fixed)

Opened 6 years ago

Last modified 6 years ago

Argument corruption in FFI with many arguments (maybe 64-bit related)

Reported by: guest Owned by:
Priority: normal Milestone:
Component: Compiler (FFI) Version: 6.6.1
Keywords: ffi Cc: chris@…
Operating System: Linux Architecture: x86_64 (amd64)
Type of failure: Difficulty: Unknown
Test Case: ffi009 Blocked By:
Blocking: Related Tickets:

Description

With many arguments, something strange occurs in argument passing with FFI. The misbehaviour only occurs on my 64-bit machine; the program works correctly on my 32-bit one. It seems as though an extra value is inserted into the argument list.

First, here is the code. There's a foreign function that takes 10 doubles.


chris@mars:~/dev/haskell/ffi$ cat c.c
fC (double a,
    double b,
    double c,
    double d,
    double e,
    double f,
    double g,
    double h,
    double i,
    double j)
{
    printf("%f %f %f %f %f %f %f %f %f %f\n", a,b,c,d,e,f,g,h,i,j);
}
chris@mars:~/dev/haskell/ffi$ cat Ffi.hs
{-# OPTIONS_GHC -fglasgow-exts #-}

f :: Double -> Double -> Double -> Double -> Double -> Double -> Double -> Double -> Double -> Double -> IO ()
f a b c d e f g h i j = do
  print [a, b, c, d, e, f, g, h, i, j]
  fC a b c d e f g h i j

foreign import ccall unsafe "fC" fC ::
      Double -> Double -> Double
   -> Double -> Double -> Double
   -> Double -> Double -> Double -> Double -> IO ()

main = do
  f 1 2 3 4 5 6 7 8 9 10

Here is the correct behaviour, on my 32-bit machine. The important output is the line starting with "1.000000 2.000000 3.00[...]"


chris@loki:~/tmp/ffi$ gcc -c c.c
c.c: In function ‘fC’:
c.c:12: warning: incompatible implicit declaration of built-in function ‘printf’
chris@loki:~/tmp/ffi$ ghc --make Ffi c.o
[1 of 1] Compiling Main             ( Ffi.hs, Ffi.o )
Linking Ffi ...
./chris@loki:~/tmp/ffi$ ./Ffi 
[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0]
1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 7.000000 8.000000 9.000000 10.000000
chris@loki:~/tmp/ffi$ ghc -v
Glasgow Haskell Compiler, Version 6.6.1, for Haskell 98, compiled by GHC version 6.6.1
Using package config file: /usr/lib/ghc-6.6.1/package.conf
Using package config file: /home/chris/.ghc/i386-linux-6.6.1/package.conf
wired-in package base mapped to base-2.1.1
wired-in package rts mapped to rts-1.0
wired-in package haskell98 mapped to haskell98-1.0
wired-in package template-haskell mapped to template-haskell-2.1
Hsc static flags: -static
*** Deleting temp files:
Deleting: 
*** Deleting temp dirs:
Deleting: 
ghc-6.6.1: no input files
Usage: For basic information, try the `--help' option.
chris@loki:~/tmp/ffi$ gcc -v
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++,treelang --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.1.3 --program-suffix=-4.1 --enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug --enable-mpfr --with-tune=i686 --enable-checking=release i486-linux-gnu
Thread model: posix
gcc version 4.1.3 20070601 (prerelease) (Debian 4.1.2-12)

Here is the bad behaviour, on my 64-bit machine. Note that the Haskell list has the values [1..10], but the C arguments are 1,2,3,4,5,6,7,8,0,9 (a zero is inserted between 8 and 9).


chris@mars:~/dev/haskell/ffi$ gcc -c c.c
c.c: In function ‘fC’:
c.c:12: warning: incompatible implicit declaration of built-in function ‘printf’
chris@mars:~/dev/haskell/ffi$ ghc --make Ffi c.o
[1 of 1] Compiling Main             ( Ffi.hs, Ffi.o )
Linking Ffi ...
chris@mars:~/dev/haskell/ffi$ ./Ffi 
[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0]
1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 7.000000 8.000000 0.000000 9.000000
chris@mars:~/dev/haskell/ffi$ ghc -v
Glasgow Haskell Compiler, Version 6.6.1, for Haskell 98, compiled by GHC version 6.6.1
Using package config file: /usr/lib/ghc-6.6.1/package.conf
Using package config file: /home/chris/.ghc/x86_64-linux-6.6.1/package.conf
wired-in package base mapped to base-2.1.1
wired-in package rts mapped to rts-1.0
wired-in package haskell98 mapped to haskell98-1.0
wired-in package template-haskell mapped to template-haskell-2.1
Hsc static flags: -static
*** Deleting temp files:
Deleting: 
*** Deleting temp dirs:
Deleting: 
ghc-6.6.1: no input files
Usage: For basic information, try the `--help' option.
chris@mars:~/dev/haskell/ffi$ gcc -v
Using built-in specs.
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++,treelang --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.1.3 --program-suffix=-4.1 --enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug --enable-mpfr --enable-checking=release x86_64-linux-gnu
Thread model: posix
gcc version 4.1.3 20070429 (prerelease) (Debian 4.1.2-5)

Change History

Changed 6 years ago by Isaac Dupree

See the warning from gcc warning: incompatible implicit declaration of built-in function ‘printf’: it may be forced to use the wrong calling convention (var-arg functions are at least allowed to be special): try putting #include <stdio.h> at the beginning of your .c file (may not help, but at least it'll be more correct and less that "could" be going wrong). Also compare -fasm versus -fvia-C flags to GHC (for the latter, you may need to include a C function prototype somehow, though).

Changed 6 years ago by Isaac Dupree

Just as another data point, on powerpc (32-bit) (ghc 6.6.1) it works as expected with or without #include <stdio.h> and/or -fvia-C.

Changed 6 years ago by guest

Thanks Isaac, you're spot on. The stdio.h didn't change anything, but -fvia-C did. I changed the ghc invocation to "ghc --make Ffi c.o -fvia-C" and it gives the correct output:

chris@mars:~/dev/haskell/ffi$ gcc -c c.c
chris@mars:~/dev/haskell/ffi$ ghc --make Ffi c.o -fvia-C
[1 of 1] Compiling Main             ( Ffi.hs, Ffi.o )
/tmp/ghc6721_0/ghc6721_0.hc: In function ‘sYX_entry’:

/tmp/ghc6721_0/ghc6721_0.hc:762:0:
     warning: implicit declaration of function ‘fC’
Linking Ffi ...
chris@mars:~/dev/haskell/ffi$ ./Ffi 
[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0]
1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 7.000000 8.000000 9.000000 10.000000

Using -fasm instead of -fvia-C gives the incorrect output.

Changed 6 years ago by Isaac Dupree

Okay, since fC is a normal C function with doubles as arguments, a function prototype shouldn't really be needed (arguments being promoted to double-precision... annoying C stuff), so this looks like a GHC bug.

Changed 6 years ago by simonmar

  • status changed from new to closed
  • testcase set to ffi009
  • resolution set to fixed

Thanks for the report: this was indeed a bug in the native code generator, I've fixed the bug and added the missing testcase.

Wed Jun 13 07:24:31 PDT 2007  Simon Marlow <simonmar@microsoft.com>
  * FIX #1424: x86_64 NCG generated wrong code for foreign call with >8 double args
  I guess we have a missing test... I'll add one
Wed Jun 13 07:45:05 PDT 2007  Simon Marlow <simonmar@microsoft.com>
  * I didn't quite fix #1424 completely - hopefully this gets it right
Note: See TracTickets for help on using tickets.