[project @ 2002-05-15 08:59:58 by chak]
authorchak <unknown>
Wed, 15 May 2002 09:00:00 +0000 (09:00 +0000)
committerchak <unknown>
Wed, 15 May 2002 09:00:00 +0000 (09:00 +0000)
* 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
ghc/compiler/main/DriverFlags.hs
ghc/compiler/main/HscMain.lhs
ghc/compiler/main/ParsePkgConf.y
ghc/compiler/parser/Lex.lhs
ghc/compiler/rename/RnHiFiles.lhs
ghc/docs/users_guide/ffi-chap.sgml
ghc/docs/users_guide/flags.sgml
ghc/docs/users_guide/glasgow_exts.sgml
ghc/docs/users_guide/ug-ent.sgml

index c93dc2f..2f6c6a6 100644 (file)
@@ -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 
 
index 8a6f1a5..ba60961 100644 (file)
@@ -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 ),
index b3c1450..b174e5e 100644 (file)
@@ -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("<interactive>") 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("<interactive>") 1
 
index 995d300..44611e7 100644 (file)
@@ -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
index 26bcf9d..18acecf 100644 (file)
@@ -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
 
 -----------------------------------------------------------------------------
 
index b009cf1..d5fd399 100644 (file)
@@ -597,6 +597,8 @@ readIface file_path
 
   where
     exts = ExtFlags {glasgowExtsEF = True,
+                    ffiEF         = True,
+                    withEF        = True,
                     parrEF        = True}
     loc  = mkSrcLoc (mkFastString file_path) 1
 
index ce24313..9009a50 100644 (file)
@@ -1,40 +1,78 @@
 <!-- FFI docs as a chapter -->
 
 <Chapter id="ffi">
-<Title>Foreign function interface</Title>
+<Title>Foreign function interface (FFI)</Title>
 
-  <para>The foreign function interface consists of the following
-  components:</para>
+  <para>GHC (mostly) conforms to the Haskell 98 Foreign Function Interface
+  Addendum 1.0, whose definition is available from <ULink
+  URL="http://haskell.org/"><literal>http://haskell.org/</literal></ULink >.
+  The FFI support in GHC diverges from the Addendum in the following ways:
+  </para>
 
   <itemizedlist>
     <listitem>
-      <para>The Foreign Function Interface language specification
-      (which constitutes most of this Chapter, beginning with <xref
-      linkend="sec-ffi-intro">).  You must use the
-      <option>-fglasgow-exts</option> command-line option to make GHC
-      understand the <literal>foreign</literal> declarations defined
-      by the FFI.</para>
+      <para>The routines <literal>hs_init()</literal>,
+      <literal>hs_exit()</literal>, and <literal>hs_set_argv()</literal> from
+      Chapter 6.1 of the Addendum are not supported yet.</para>
     </listitem>
 
     <listitem>
-      <para>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 <xref linkend="sec-Foreign"> for
-      more details.  </para>
+      <para>Syntactic forms and library functions proposed in earlier versions
+      of the FFI are still supported for backwards compatibility.</para>
+    </listitem>
+
+    <listitem>
+      <para>GHC implements a number of GHC-specific extensions to the FFI
+      Addendum.  These extensions are described in <xref
+      linkend="sec-ffi-ghcexts">, but please note that programs using
+      these features are not portable.  Hence, these features should be
+      avoided where possible.</para>
     </listitem>
   </itemizedlist>
 
-&ffi-body;
+  <para>The FFI libraries are documented in <xref
+  linkend="sec-Foreign">.</para>
+
+
+  <sect1 id="sec-ffi-ghcexts">
+    <title>GHC extensions to the FFI Addendum</title>
+
+    <para>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.</para>
+
+    <sect2>
+      <title>Arrays</title>
+
+      <para>The types <literal>ByteArray</literal> and
+      <literal>MutableByteArray</literal> may be used as basic foreign types
+      (see FFI Addendum, Section 3.2).  In C land, they map to
+      <literal>(char *)</literal>.</para>
+    </sect2>
+
+    <sect2>
+      <title>Unboxed types</title>
+
+      <para>The following unboxed types may be used as basic foreign types
+      (see FFI Addendum, Section 3.2): <literal>Int#</literal>,
+      <literal>Word#</literal>, <literal>Char#</literal>,
+      <literal>Float#</literal>, <literal>Double#</literal>,
+      <literal>Addr#</literal>, <literal>StablePtr# a</literal>,
+      <literal>MutableByteArray#</literal>, <literal>ForeignObj#</literal>,
+      and <literal>ByteArray#</literal>.</para>
+    </sect2>
+
+  </sect1>
 
-  <sect1 id="ffi-ghc">
+  <sect1 id="sec-ffi-ghc">
     <title>Using the FFI with GHC</title>
 
     <para>The following sections also give some hints and tips on the
     use of the foreign function interface in GHC.</para>
 
     <sect2 id="foreign-export-ghc">
-      <title>Using <literal>foreign export</literal> with GHC</title>
+      <title>Using <literal>foreign export</literal> and <literal>foreign
+      import ccall "wrapper"</literal> with GHC</title>
 
       <indexterm><primary><literal>foreign export
       </literal></primary><secondary>with GHC</secondary>
@@ -42,7 +80,7 @@
 
       <para>When GHC compiles a module (say <filename>M.hs</filename>)
       which uses <literal>foreign export</literal> or <literal>foreign
-      export dynamic</literal>, it generates two
+      import "wrapper"</literal>, it generates two
       additional files, <filename>M_stub.c</filename> and
       <filename>M_stub.h</filename>.  GHC will automatically compile
       <filename>M_stub.c</filename> to generate
@@ -57,7 +95,7 @@
 <programlisting>
 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[])
       </sect3>
 
       <sect3 id="foreign-export-dynamic-ghc">
-       <title>Using <literal>foreign export dynamic</literal> with
+       <title>Using <literal>foreign import ccall "wrapper"</literal> with
        GHC</title>
 
-       <indexterm><primary><literal>foreign export
-       dynamic</literal></primary><secondary>with GHC</secondary>
+       <indexterm><primary><literal>foreign import
+       ccall "wrapper"</literal></primary><secondary>with GHC</secondary>
        </indexterm>
 
-       <para>When <literal>foreign export dynamic</literal> is used
-        in a Haskell module, The C stub file
-        <filename>M_stub.c</filename> generated by GHC contains small
-        helper functions used by the code generated for the
-        <literal>foreign export dynamic</literal>, so it must be
-        linked in to the final program.  When linking the program,
-        remember to include <filename>M_stub.o</filename> 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 <literal>ghc &ndash;&ndash;make</literal>, as GHC will automatically
-        link in the correct bits).</para>
+       <para>When <literal>foreign import ccall "wrapper"</literal> is used
+        in a Haskell module, The C stub file <filename>M_stub.c</filename>
+        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
+        <filename>M_stub.o</filename> 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 <literal>ghc
+        &ndash;&ndash;make</literal>, as GHC will automatically link in the
+        correct bits).</para>
       </sect3>
     </sect2>
     
@@ -209,8 +246,8 @@ HsInt        lookupEFS (HsForeignObj a, HsInt i);
 </programlisting>
 
       <para>The types <literal>HsInt</literal>,
-      <literal>HsForeignObj</literal> etc. are described in <xref
-      linkend="sec-ffi-mapping-table">.</para>
+      <literal>HsForeignObj</literal> etc. are described in the H98 FFI
+      Addendum.</para>
 
       <para>Note that this approach is only
       <emphasis>essential</emphasis> for returning
index f2ce65f..cf76694 100644 (file)
              <entry><option>-fno-glasgow-exts</option></entry>
            </row>
            <row>
+             <entry><option>-ffi</option> or <option>-fffi</option></entry>
+             <entry>Enable foreign function interface (implied by
+             <option>-fglasgow-exts</option>)</entry>
+             <entry>dynamic</entry>
+             <entry><option>-fno-ffi</option></entry>
+           </row>
+           <row>
+             <entry><option>-fwith</option></entry>
+             <entry>Enable deprecated <literal>with</literal> keyword</entry>
+             <entry>dynamic</entry>
+             <entry><option>-fno-with</option></entry>
+           </row>
+           <row>
              <entry><option>-fignore-asserts</option></entry>
              <entry>Ignore assertions</entry>
              <entry>dynamic</entry>
index 282df11..05b299a 100644 (file)
@@ -52,6 +52,30 @@ program), you may wish to check if there are libraries that provide a
       </varlistentry>
 
       <varlistentry>
+       <term><option>-ffi</option> and <option>-fffi</option>:</term>
+       <indexterm><primary><option>-ffi</option></primary></indexterm>
+       <indexterm><primary><option>-fffi</option></primary></indexterm>
+       <listitem>
+         <para>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.</para> 
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><option>-fwith</option>:</term>
+       <indexterm><primary><option>-fwith</option></primary></indexterm>
+       <listitem>
+         <para>This option enables the deprecated <literal>with</literal>
+         keyword for implicit parameters; it is merely provided for backwards
+         compatibility.
+          It is independent of the <option>-fglasgow-exts</option>
+          flag. </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
        <term><option>-fno-monomorphism-restriction</option>:</term>
        <indexterm><primary><option>-fno-monomorphism-restriction</option></primary></indexterm>
        <listitem>
index e370360..56b36f8 100644 (file)
@@ -21,5 +21,4 @@
 <!ENTITY wrong          SYSTEM "gone_wrong.sgml" >
 <!ENTITY utils          SYSTEM "utils.sgml" >
 <!ENTITY win32-dll      SYSTEM "win32-dlls.sgml">
-<!ENTITY ffi-body       SYSTEM "../../../docs/ffi.sgml">
 <!ENTITY ffi-chap       SYSTEM "ffi-chap.sgml">