Commit de1d4a16 authored by chak's avatar chak

[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.
parent cccb6444
......@@ -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
......
-----------------------------------------------------------------------------
-- $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 ),
......
......@@ -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
......
......@@ -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
......
......@@ -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
-----------------------------------------------------------------------------
......
......@@ -597,6 +597,8 @@ readIface file_path
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>
......@@ -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
......
......@@ -435,6 +435,19 @@
<entry>dynamic</entry>
<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>
......
......@@ -51,6 +51,30 @@ program), you may wish to check if there are libraries that provide a
</listitem>
</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>
......
......@@ -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">
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment