Re: Possible runtime overhead of wrapping the IO monad?

On Tue, 2006-03-28 at 01:37 +0100, Brian Hulley wrote:
Hi Duncan - I just declared duma_vertex3f (in another module) by:
foreign import ccall duma_vertex3f :: Float -> Float -> Float -> IO ()
I thought this means that the C function prototype must be:
void duma_vertex3f(HsFloat, HsFloat, HsFloat);
so I don't understand why GHC (or any other Haskell compiler) would ever need to see a C header file to generate the correct code. What info could be in the header that is not already in the Haskell type?
Because ghc does compile via C and does use the C header files to get the C function prototype. Well it can compile via C and it's recommended when compiling FFI code since it allows the Haskell type you've declared to be checked against the C prototype. The warning you saw was coming from gcc as it compiled the C code emitted by ghc. So it's mostly as a sanity check but actually there is some information in the C prototype that is not reflected in the Haskell type. For example 'const'ness, which is why you might sometimes see warnings from gcc about casting away the const attribute. More seriously there is the single/double issue. In the absence of a prototype C will promote single to double. If the function really was declared as single then using double will probably cause a crash. There are probably other examples where not using a C prototype can lead to trouble. There are more probably details on this issue in the emails during the FFI standardisation process. Interestingly that particular issue is less of a problem when not compiling via C since the Haskell type does provide enough information for making a call using the standard system ABI. C's type sytem (such as it is) has slightly more information in it than just the system ABI needs (such as const). Duncan

Duncan Coutts wrote:
On Tue, 2006-03-28 at 01:37 +0100, Brian Hulley wrote:
Hi Duncan - I just declared duma_vertex3f (in another module) by:
foreign import ccall duma_vertex3f :: Float -> Float -> Float -> IO ()
I thought this means that the C function prototype must be:
void duma_vertex3f(HsFloat, HsFloat, HsFloat);
so I don't understand why GHC (or any other Haskell compiler) would ever need to see a C header file to generate the correct code. What info could be in the header that is not already in the Haskell type?
Because ghc does compile via C and does use the C header files to get the C function prototype. Well it can compile via C and it's recommended when compiling FFI code since it allows the Haskell type you've declared to be checked against the C prototype.
The warning you saw was coming from gcc as it compiled the C code emitted by ghc.
So it's mostly as a sanity check but actually there is some information in the C prototype that is not reflected in the Haskell type. For example 'const'ness, which is why you might sometimes see warnings from gcc about casting away the const attribute. More seriously there is the single/double issue. In the absence of a prototype C will promote single to double. If the function really was declared as single then using double will probably cause a crash. There are probably other examples where not using a C prototype can lead to trouble.
There are more probably details on this issue in the emails during the FFI standardisation process.
Also the User's Guide has a snippet about it: http://www.haskell.org/ghc/docs/latest/html/users_guide/sec-ffi-ghc.html#gla... and this FAQ entry: http://haskell.org/haskellwiki/GHC/FAQ#When_I_use_a_foreign_function_that_ta.... Cheers, Simon

Simon Marlow wrote:
Also the User's Guide has a snippet about it:
http://www.haskell.org/ghc/docs/latest/html/users_guide/sec-ffi-ghc.html#gla...
and this FAQ entry:
http://haskell.org/haskellwiki/GHC/FAQ#When_I_use_a_foreign_function_that_ta....
I've tried various command lines to try to get GHC to actually include the header when compiling, but nothing seems to work, and I still get the error message about implicit function declarations, for example when using: C:\ghc\ghc-6.4\bin\ghc.exe -fglasgow-exts -fffi -#include Duma.h --make main.hs -ddump-simpl -O2 -fvia-C -optl-mwindows -optl-lDuma -optl-L"c:\dll" #ifdef __DUMA_H #define __DUMA_H #ifdef __cplusplus extern "C" { #endif void duma_vertex3f(HsFloat x, HsFloat y, HsFloat z); #ifdef __cplusplus } #endif #endif // __DUMA_H -- declared in Duma.hs foreign import ccall "Duma.h" duma_vertex3f :: Float -> Float -> Float -> IO () I've tried removing the "Duma.h" from the foreign import but that doesn't help. Also, according to the FFI, for portability people are supposed to always specify the header in the foreign import, so the fact that when you do this, GHC disables cross module inlining is a real problem: you are forced to write non-portable code. Anyway all I'm interested in at the moment is trying to find a command line which will cause GHC to compile everything using the header "Duma.h" so that there will be no warning messages about implicit function declarations. Is there anything else I could try? Thanks, Brian.

Duncan Coutts wrote:
Because ghc does compile via C and does use the C header files to get the C function prototype. Well it can compile via C and it's recommended when compiling FFI code since it allows the Haskell type you've declared to be checked against the C prototype. [snip] There are more probably details on this issue in the emails during the FFI standardisation process.
I've found a thread at http://www.haskell.org//pipermail/ffi/2002-July/000554.html where someone else asked the same question, but apart from the problem of 'const' , and the desire to verify the actual type of the C function, I can't find any convincing case for requiring a header. Arg promotion would be solved if GHC just generated a prototype based on the Haskell type, and an explicit const_cast could be added by the writer of the C API when necessary. As for calling conventions, the FFI already specifies them (ccall versus stdcall etc). Even when I do specify a header, I still get the "warning: implicit declaration of function" message when my FFI functions are called from a different module, even when I use -#include "Duma.h" on the command line: C:\ghc\ghc-6.4\bin\ghc.exe -fglasgow-exts -fffi --make main.hs -ddump-simpl -O2 -#include Duma.h -optl-mwindows -optl-lDuma -optl-L"c:\dll" (Why does GHC not automatically #include the relevant header given by the foreign import decl at each call site?) Is there any solution to this problem? Thanks, Brian.

Brian Hulley wrote:
I've found a thread at http://www.haskell.org//pipermail/ffi/2002-July/000554.html where someone else asked the same question, but apart from the problem of 'const' , and the desire to verify the actual type of the C function, I can't find any convincing case for requiring a header. Arg promotion would be solved if GHC just generated a prototype based on the Haskell type, and an explicit const_cast could be added by the writer of the C API when necessary. As for calling conventions, the FFI already specifies them (ccall versus stdcall etc).
The reason that GHC doesn't generate the prototype is because it might clash with an existing prototype from a header. GHC doesn't know enough information (eg. const) to generate a correct prototype that won't clash.
Even when I do specify a header, I still get the "warning: implicit declaration of function" message when my FFI functions are called from a different module, even when I use -#include "Duma.h" on the command line:
C:\ghc\ghc-6.4\bin\ghc.exe -fglasgow-exts -fffi --make main.hs -ddump-simpl -O2 -#include Duma.h -optl-mwindows -optl-lDuma -optl-L"c:\dll"
I don't know. Try generating the .hc file and check whether it contains the correct #include?
(Why does GHC not automatically #include the relevant header given by the foreign import decl at each call site?)
No good reason, but we'd have to pass that information in the interface along with the unfolding of the foreign call, which we don't right now. Cheers, Simon
participants (3)
-
Brian Hulley
-
Duncan Coutts
-
Simon Marlow