From de1d4a16d94fa13e9d40a1ac755eae6249595e66 Mon Sep 17 00:00:00 2001 From: chak Date: Wed, 15 May 2002 09:00:00 +0000 Subject: [PATCH] [project @ 2002-05-15 08:59:58 by chak] * Added the options `-ffi' and `-fffi', which switch on FFI support (`-fglasgow-exts' implies `-fffi'). NB: Strictly speaking `-fffi' is the correct name; however, `-ffi' is supported as an alternative spelling. * `-fglasgow-exts' no longer enables the `with' keyword for implicit parameters. To use `with' as a keyword, the additional option `-fwith' has to be supplied. (Note that SimonM recently enabled the use of `let' instead of `with'.) NB: This might prompt some makefile tweaks in libraries or regression tests. * Renamed `Foreign.Marshal.Utils.withObject' to `Foreign.Marshal.Utils.with' as required by the FFI Addendum. (The old name is still available, but marked as deprecated.) * Added `realloc' to `Foreign.Marshal.Alloc' (tracking RC4 of the FFI Addendum). Docu ~~~~ * Added `-ffi', `-fffi', and `-fwith' to the flag reference and the section describing options for Glasgow extensions * Removed most of the FFI section in the User's Guide in favour of a reference to the Addendum plus a brief description of additional features supported by GHC. NB: The old material is still available at fptools/docs/, I merely removed the reference in the User's Guide. --- ghc/compiler/main/CmdLineOpts.lhs | 2 + ghc/compiler/main/DriverFlags.hs | 5 +- ghc/compiler/main/HscMain.lhs | 6 ++ ghc/compiler/main/ParsePkgConf.y | 2 + ghc/compiler/parser/Lex.lhs | 100 ++++++++++++++++------------- ghc/compiler/rename/RnHiFiles.lhs | 2 + ghc/docs/users_guide/ffi-chap.sgml | 107 +++++++++++++++++++++----------- ghc/docs/users_guide/flags.sgml | 13 ++++ ghc/docs/users_guide/glasgow_exts.sgml | 24 +++++++ ghc/docs/users_guide/ug-ent.sgml | 1 - 10 files changed, 182 insertions(+), 80 deletions(-) diff --git a/ghc/compiler/main/CmdLineOpts.lhs b/ghc/compiler/main/CmdLineOpts.lhs index c93dc2f..2f6c6a6 100644 --- a/ghc/compiler/main/CmdLineOpts.lhs +++ b/ghc/compiler/main/CmdLineOpts.lhs @@ -292,7 +292,9 @@ data DynFlag | Opt_AllowIncoherentInstances | Opt_NoMonomorphismRestriction | Opt_GlasgowExts + | Opt_FFI | Opt_PArr -- syntactic support for parallel arrays + | Opt_With -- deprecated keyword for implicit parms | Opt_Generics | Opt_NoImplicitPrelude diff --git a/ghc/compiler/main/DriverFlags.hs b/ghc/compiler/main/DriverFlags.hs index 8a6f1a5..ba60961 100644 --- a/ghc/compiler/main/DriverFlags.hs +++ b/ghc/compiler/main/DriverFlags.hs @@ -1,5 +1,5 @@ ----------------------------------------------------------------------------- --- $Id: DriverFlags.hs,v 1.93 2002/05/11 10:02:22 panne Exp $ +-- $Id: DriverFlags.hs,v 1.94 2002/05/15 08:59:59 chak Exp $ -- -- Driver flags -- @@ -457,6 +457,9 @@ fFlags = [ ( "warn-unused-matches", Opt_WarnUnusedMatches ), ( "warn-deprecations", Opt_WarnDeprecations ), ( "glasgow-exts", Opt_GlasgowExts ), + ( "fi", Opt_FFI ), -- support `-ffi'... + ( "ffi", Opt_FFI ), -- ...and also `-fffi' + ( "with", Opt_With ), -- with keyword ( "parr", Opt_PArr ), ( "allow-overlapping-instances", Opt_AllowOverlappingInstances ), ( "allow-undecidable-instances", Opt_AllowUndecidableInstances ), diff --git a/ghc/compiler/main/HscMain.lhs b/ghc/compiler/main/HscMain.lhs index b3c1450..b174e5e 100644 --- a/ghc/compiler/main/HscMain.lhs +++ b/ghc/compiler/main/HscMain.lhs @@ -499,6 +499,8 @@ myParseModule dflags src_filename buf <- hGetStringBuffer src_filename let exts = ExtFlags {glasgowExtsEF = dopt Opt_GlasgowExts dflags, + ffiEF = dopt Opt_FFI dflags, + withEF = dopt Opt_With dflags, parrEF = dopt Opt_PArr dflags} loc = mkSrcLoc (mkFastString src_filename) 1 @@ -672,6 +674,8 @@ hscParseStmt dflags str buf <- stringToStringBuffer str let exts = ExtFlags {glasgowExtsEF = dopt Opt_GlasgowExts dflags, + ffiEF = dopt Opt_FFI dflags, + withEF = dopt Opt_With dflags, parrEF = dopt Opt_PArr dflags} loc = mkSrcLoc FSLIT("") 1 @@ -756,6 +760,8 @@ myParseIdentifier dflags str = do buf <- stringToStringBuffer str let exts = ExtFlags {glasgowExtsEF = dopt Opt_GlasgowExts dflags, + ffiEF = dopt Opt_FFI dflags, + withEF = dopt Opt_With dflags, parrEF = dopt Opt_PArr dflags} loc = mkSrcLoc FSLIT("") 1 diff --git a/ghc/compiler/main/ParsePkgConf.y b/ghc/compiler/main/ParsePkgConf.y index 995d300..44611e7 100644 --- a/ghc/compiler/main/ParsePkgConf.y +++ b/ghc/compiler/main/ParsePkgConf.y @@ -83,6 +83,8 @@ loadPackageConfig conf_filename = do buf <- hGetStringBuffer conf_filename let loc = mkSrcLoc (mkFastString conf_filename) 1 exts = ExtFlags {glasgowExtsEF = False, + ffiEF = False, + withEF = False, parrEF = False} case parse buf (mkPState loc exts) of PFailed err -> do diff --git a/ghc/compiler/parser/Lex.lhs b/ghc/compiler/parser/Lex.lhs index 26bcf9d..18acecf 100644 --- a/ghc/compiler/parser/Lex.lhs +++ b/ghc/compiler/parser/Lex.lhs @@ -268,28 +268,37 @@ isSpecial ITccallconv = True isSpecial ITstdcallconv = True isSpecial _ = False --- IMPORTANT: Keep this in synch with ParseIface.y's var_fs production! (SUP) +-- the bitmap provided as the third component indicates whether the +-- corresponding extension keyword is valid under the extension options +-- provided to the compiler; if the extension corresponding to *any* of the +-- bits set in the bitmap is enabled, the keyword is valid (this setup +-- facilitates using a keyword in two different extensions that can be +-- activated independently) +-- ghcExtensionKeywordsFM = listToUFM $ - map (\ (x,y) -> (mkFastString x,y)) - [ ( "forall", ITforall ), - ( "foreign", ITforeign ), - ( "export", ITexport ), - ( "label", ITlabel ), - ( "dynamic", ITdynamic ), - ( "safe", ITsafe ), - ( "threadsafe", ITthreadsafe ), - ( "unsafe", ITunsafe ), - ( "with", ITwith ), - ( "stdcall", ITstdcallconv), - ( "ccall", ITccallconv), - ( "dotnet", ITdotnet), - ("_ccall_", ITccall (False, False, PlayRisky)), - ("_ccall_GC_", ITccall (False, False, PlaySafe False)), - ("_casm_", ITccall (False, True, PlayRisky)), - ("_casm_GC_", ITccall (False, True, PlaySafe False)) + map (\(x, y, z) -> (mkFastString x, (y, z))) + [ ( "forall", ITforall, bit glaExtsBit), + ( "foreign", ITforeign, bit ffiBit), + ( "export", ITexport, bit ffiBit), + ( "label", ITlabel, bit ffiBit), + ( "dynamic", ITdynamic, bit ffiBit), + ( "safe", ITsafe, bit ffiBit), + ( "threadsafe", ITthreadsafe, bit ffiBit), + ( "unsafe", ITunsafe, bit ffiBit), + ( "with", ITwith, bit withBit), + ( "stdcall", ITstdcallconv, bit ffiBit), + ( "ccall", ITccallconv, bit ffiBit), + ( "dotnet", ITdotnet, bit ffiBit), + ("_ccall_", ITccall (False, False, PlayRisky), + bit glaExtsBit), + ("_ccall_GC_", ITccall (False, False, PlaySafe False), + bit glaExtsBit), + ("_casm_", ITccall (False, True, PlayRisky), + bit glaExtsBit), + ("_casm_GC_", ITccall (False, True, PlaySafe False), + bit glaExtsBit) ] - haskellKeySymsFM = listToUFM $ map (\ (x,y) -> (mkFastString x,y)) [ ("..", ITdotdot) @@ -879,13 +888,10 @@ lex_id cont exts buf = let var_token = cont (ITvarid lexeme) buf' in - if not (glaExtsEnabled exts) - then var_token - else - case lookupUFM ghcExtensionKeywordsFM lexeme of { - Just kwd_token -> cont kwd_token buf'; - Nothing -> var_token + Just (kwd_token, validExts) + | validExts .&. (I# exts) /= 0 -> cont kwd_token buf'; + _ -> var_token }}} @@ -1197,12 +1203,14 @@ popContext = \ buf s@(PState{ context = ctx, loc = loc }) -> glaExtsBit, ffiBit, parrBit :: Int glaExtsBit = 0 -ffiBit = 1 -- FIXME: not used yet; still part of `glaExtsBit' +ffiBit = 1 parrBit = 2 +withBit = 3 glaExtsEnabled, ffiEnabled, parrEnabled :: Int# -> Bool glaExtsEnabled flags = testBit (toInt32 flags) glaExtsBit ffiEnabled flags = testBit (toInt32 flags) ffiBit +withEnabled flags = testBit (toInt32 flags) withBit parrEnabled flags = testBit (toInt32 flags) parrBit toInt32 :: Int# -> Int32 @@ -1210,30 +1218,36 @@ toInt32 x# = fromIntegral (I# x#) -- convenient record-based bitmap for the interface to the rest of the world -- +-- NB: `glasgowExtsEF' implies `ffiEF' (see `mkPState' below) +-- data ExtFlags = ExtFlags { glasgowExtsEF :: Bool, --- ffiEF :: Bool, -- commented out to avoid warnings - parrEF :: Bool -- while not used yet + ffiEF :: Bool, + withEF :: Bool, + parrEF :: Bool } -- create a parse state -- mkPState :: SrcLoc -> ExtFlags -> PState -mkPState loc exts = PState { - loc = loc, - extsBitmap = case (fromIntegral bitmap) of {I# bits -> bits}, - bol = 0#, - atbol = 1#, - context = [] - } - where - bitmap = glaExtsBit `setBitIf` glasgowExtsEF exts --- .|. ffiBit `setBitIf` ffiEF exts - .|. parrBit `setBitIf` parrEF exts - -- - setBitIf :: Int -> Bool -> Int32 - b `setBitIf` cond | cond = bit b - | otherwise = 0 +mkPState loc exts = + PState { + loc = loc, + extsBitmap = case (fromIntegral bitmap) of {I# bits -> bits}, + bol = 0#, + atbol = 1#, + context = [] + } + where + bitmap = glaExtsBit `setBitIf` glasgowExtsEF exts + .|. ffiBit `setBitIf` (ffiEF exts + || glasgowExtsEF exts) + .|. withBit `setBitIf` withEF exts + .|. parrBit `setBitIf` parrEF exts + -- + setBitIf :: Int -> Bool -> Int32 + b `setBitIf` cond | cond = bit b + | otherwise = 0 ----------------------------------------------------------------------------- diff --git a/ghc/compiler/rename/RnHiFiles.lhs b/ghc/compiler/rename/RnHiFiles.lhs index b009cf1..d5fd399 100644 --- a/ghc/compiler/rename/RnHiFiles.lhs +++ b/ghc/compiler/rename/RnHiFiles.lhs @@ -597,6 +597,8 @@ readIface file_path where exts = ExtFlags {glasgowExtsEF = True, + ffiEF = True, + withEF = True, parrEF = True} loc = mkSrcLoc (mkFastString file_path) 1 diff --git a/ghc/docs/users_guide/ffi-chap.sgml b/ghc/docs/users_guide/ffi-chap.sgml index ce24313..9009a50 100644 --- a/ghc/docs/users_guide/ffi-chap.sgml +++ b/ghc/docs/users_guide/ffi-chap.sgml @@ -1,40 +1,78 @@ -Foreign function interface +Foreign function interface (FFI) - The foreign function interface consists of the following - components: + GHC (mostly) conforms to the Haskell 98 Foreign Function Interface + Addendum 1.0, whose definition is available from http://haskell.org/. + The FFI support in GHC diverges from the Addendum in the following ways: + - The Foreign Function Interface language specification - (which constitutes most of this Chapter, beginning with ). You must use the - command-line option to make GHC - understand the foreign declarations defined - by the FFI. + The routines hs_init(), + hs_exit(), and hs_set_argv() from + Chapter 6.1 of the Addendum are not supported yet. - Several library modules which provide access to types used - by foreign languages and utilties for marshalling values to and - from foreign functions, and for converting errors in the foreign - language into Haskell IO errors. See for - more details. + Syntactic forms and library functions proposed in earlier versions + of the FFI are still supported for backwards compatibility. + + + + GHC implements a number of GHC-specific extensions to the FFI + Addendum. These extensions are described in , but please note that programs using + these features are not portable. Hence, these features should be + avoided where possible. -&ffi-body; + The FFI libraries are documented in . + + + + GHC extensions to the FFI Addendum + + The FFI features that are described in this section are specific to + GHC. Avoid them where possible to not compromise the portability of the + resulting code. + + + Arrays + + The types ByteArray and + MutableByteArray may be used as basic foreign types + (see FFI Addendum, Section 3.2). In C land, they map to + (char *). + + + + Unboxed types + + The following unboxed types may be used as basic foreign types + (see FFI Addendum, Section 3.2): Int#, + Word#, Char#, + Float#, Double#, + Addr#, StablePtr# a, + MutableByteArray#, ForeignObj#, + and ByteArray#. + + + - + Using the FFI with GHC The following sections also give some hints and tips on the use of the foreign function interface in GHC. - Using <literal>foreign export</literal> with GHC + Using <literal>foreign export</literal> and <literal>foreign + import ccall "wrapper"</literal> with GHC foreign export with GHC @@ -42,7 +80,7 @@ When GHC compiles a module (say M.hs) which uses foreign export or foreign - export dynamic, it generates two + import "wrapper", it generates two additional files, M_stub.c and M_stub.h. GHC will automatically compile M_stub.c to generate @@ -57,7 +95,7 @@ module Foo where -foreign export foo :: Int -> IO Int +foreign export ccall foo :: Int -> IO Int foo :: Int -> IO Int foo n = return (length (f n)) @@ -162,24 +200,23 @@ int main(int argc, char *argv[]) - Using <literal>foreign export dynamic</literal> with + <title>Using <literal>foreign import ccall "wrapper"</literal> with GHC - foreign export - dynamicwith GHC + foreign import + ccall "wrapper"with GHC - When foreign export dynamic is used - in a Haskell module, The C stub file - M_stub.c generated by GHC contains small - helper functions used by the code generated for the - foreign export dynamic, so it must be - linked in to the final program. When linking the program, - remember to include M_stub.o in the final - link command line, or you'll get link errors for the missing - function(s) (this isn't necessary when building your program - with ghc ––make, as GHC will automatically - link in the correct bits). + When foreign import ccall "wrapper" is used + in a Haskell module, The C stub file M_stub.c + generated by GHC contains small helper functions used by the code + generated for the imported wrapper, so it must be linked in to the + final program. When linking the program, remember to include + M_stub.o in the final link command line, or + you'll get link errors for the missing function(s) (this isn't + necessary when building your program with ghc + ––make, as GHC will automatically link in the + correct bits). @@ -209,8 +246,8 @@ HsInt lookupEFS (HsForeignObj a, HsInt i); The types HsInt, - HsForeignObj etc. are described in . + HsForeignObj etc. are described in the H98 FFI + Addendum. Note that this approach is only essential for returning diff --git a/ghc/docs/users_guide/flags.sgml b/ghc/docs/users_guide/flags.sgml index f2ce65f..cf76694 100644 --- a/ghc/docs/users_guide/flags.sgml +++ b/ghc/docs/users_guide/flags.sgml @@ -436,6 +436,19 @@ + or + Enable foreign function interface (implied by + ) + dynamic + + + + + Enable deprecated with keyword + dynamic + + + Ignore assertions dynamic diff --git a/ghc/docs/users_guide/glasgow_exts.sgml b/ghc/docs/users_guide/glasgow_exts.sgml index 282df11..05b299a 100644 --- a/ghc/docs/users_guide/glasgow_exts.sgml +++ b/ghc/docs/users_guide/glasgow_exts.sgml @@ -52,6 +52,30 @@ program), you may wish to check if there are libraries that provide a + and : + + + + This option enables the language extension defined in the + Haskell 98 Foreign Function Interface Addendum plus deprecated + syntax of previous versions of the FFI for backwards + compatibility. + + + + + : + + + This option enables the deprecated with + keyword for implicit parameters; it is merely provided for backwards + compatibility. + It is independent of the + flag. + + + + : diff --git a/ghc/docs/users_guide/ug-ent.sgml b/ghc/docs/users_guide/ug-ent.sgml index e370360..56b36f8 100644 --- a/ghc/docs/users_guide/ug-ent.sgml +++ b/ghc/docs/users_guide/ug-ent.sgml @@ -21,5 +21,4 @@ - -- 1.7.10.4