| 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
-----------------------------------------------------------------------------
--- $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
--
( "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 ),
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
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
= 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
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
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)
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
}}}
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
-- 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
-----------------------------------------------------------------------------
where
exts = ExtFlags {glasgowExtsEF = True,
+ ffiEF = True,
+ withEF = True,
parrEF = True}
loc = mkSrcLoc (mkFastString file_path) 1
<!-- 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>
<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
<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))
</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 ––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
+ ––make</literal>, as GHC will automatically link in the
+ correct bits).</para>
</sect3>
</sect2>
</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
<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>
</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>
<!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">