Commit 9ac3bcbb authored by Andrew Martin's avatar Andrew Martin Committed by Marge Bot
Browse files

Document the UnliftedFFITypes extension.

parent 9402608e
......@@ -71,13 +71,96 @@ GHC extensions to the FFI Chapter
The FFI features that are described in this section are specific to GHC.
Your code will not be portable to other compilers if you use them.
Unboxed types
~~~~~~~~~~~~~
Unlifted FFI Types
~~~~~~~~~~~~~~~~~~
.. extension:: UnliftedFFITypes
:shortdesc: Enable unlifted FFI types
:since: 6.8.1
The following unlifted unboxed types may be used as basic foreign
types (see FFI Chapter, Section 8.6) for both ``safe`` and
``unsafe`` foreign calls: ``Int#``, ``Word#``, ``Char#``, ``Float#``,
``Double#``, ``Addr#``, and ``StablePtr# a``. The following unlifted
boxed types may be used as arguments to (not results of) ``unsafe``
foreign calls: ``Array#``, ``MutableArray#``, ``SmallArray#``,
``SmallMutableArray#``, ``ArrayArray#``, ``MutableArrayArray#``,
``ByteArray#``, and ``MutableByteArray#``. Additionally, ``ByteArray#``
and ``MutableByteArray#`` can be passed to ``safe`` foreign calls
if the object is pinned. (Such can be ascertained by judicious use of
``isByteArrayPinned#``, ``isMutableByteArrayPinned#``, or
``newPinnedByteArray#``.) Passing an unpinned argument to an ``safe``
foreign call results in undefined behavior. This table sums up the
restrictions:
+--------------+-----------------------+----------------------------------+
| Type | Safe FFI Argument | Unsafe FFI Argument |
+--------------+-----------------------+----------------------------------+
| Array# | No | Yes, but not useful with C calls |
| SmallArray# | No | Yes, but not useful with C calls |
| ArrayArray# | No | Yes |
| ByteArray# | Yes, only when pinned | Yes |
+--------------+-----------------------+----------------------------------+
When passing any of the unlifted array types as an argument to
a foreign C call, a foreign function sees a pointer that refers to the
payload of the array, not to the
``StgArrBytes``/``StgMutArrPtrs``/``StgSmallMutArrPtrs`` heap object
containing it [1]_. (By contrast, a foreign Cmm call sees the heap object,
not just the payload.) This means that, in some situations, the foreign C
function might not need any knowledge of the RTS closure types. The
following example sums the first three bytes in a
``MutableByteArray#`` [2]_ without using anything from ``Rts.h``::
// C source
uint8_t add_triplet(uint8_t* arr) {
return (arr[0] + arr[1] + arr[2]);
}
-- Haskell source
foreign import ccall unsafe "add_triplet"
addTriplet :: MutableByteArray# RealWorld -> IO Word8
In other situations, the C function may need knowledge of the RTS
closure types. The following example sums the first element of
each ``ByteArray#`` (interpreting the bytes as an array of ``CInt``)
element of an ``ArrayArray##`` [3]_::
// C source, must include the RTS
#include "Rts.h"
int sum_first (StgArrBytes **bufs) {
StgArrBytes **bufs = (StgArrBytes**)bufsTmp;
int res = 0;
for(StgWord ix = 0;ix < arr->ptrs;ix++) {
res = res + ((int*)(bufs[ix]->payload))[0];
}
return res;
}
The following unboxed types may be used as basic foreign types (see FFI
Chapter, Section 8.6): ``Int#``, ``Word#``, ``Char#``, ``Float#``,
``Double#``, ``Addr#``, ``StablePtr# a``, ``MutableByteArray#``,
``ForeignObj#``, and ``ByteArray#``.
-- Haskell source, all elements in the array must be
-- either ByteArray# or MutableByteArray#. This is not
-- enforced by the type system in this example.
foreign import ccall unsafe "sum_first"
sumFirst :: ArrayArray# -> IO CInt
Mutable arrays of heap objects record writes for the purpose of
garbage collection. ``MutableArray#`` uses a card table, and
``SmallMutableArray#`` uses only a dirty bit. When passing
an array of heap objects into a foreign function, GHC assumes
that the foreign import does not modify the contents. Consequently,
it is not safe to write to an array of heap objects in a foreign
function. Foreign functions must treat such arrays as read-only.
However, note that the runtime has no facilities for tracking
mutation of a ``MutableByteArray#``. It is safe to mutate these
in a foreign function.
Although GHC allows the user to pass all unlifted boxed types to
foreign functions, some of them are not amenable to useful work.
Although ``Array#`` is unlifted, the elements in its payload are
lifted, and a foreign C function cannot safely force thunks. Consequently,
a foreign C function do anything with the elements of an ``Array#``
other checking pointer equality as a shortcut.
.. _ffi-newtype-io:
......@@ -883,3 +966,11 @@ to the floating point state, so that if you really need to use
- It is safe to modify the floating-point unit state temporarily during
a foreign call, because foreign calls are never pre-empted by GHC.
.. [1] Prior to GHC 8.10, when passing an ``ArrayArray#`` argument
to a foreign function, the foreign function would see a pointer
to the ``StgMutArrPtrs`` rather than just the payload.
.. [2] In practice, the FFI should not be used for a task as simple
as reading bytes from a ``MutableByteArray#``. Users should prefer
``GHC.Exts.readWord8Array#`` for this.
.. [3] As in [2]_, the FFI is not actually needed for this. ``GHC.Exts``
includes primitives for reading from on ``ArrayArray#``.
......@@ -15,6 +15,7 @@
* :extension:`FunctionalDependencies`
* :extension:`GeneralizedNewtypeDeriving`
* :extension:`ImplicitParams`
* :extension:`InterruptibleFFI`
* :extension:`KindSignatures`
* :extension:`LiberalTypeSynonyms`
* :extension:`MagicHash`
......
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