summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Martin <andrew.thaddeus@gmail.com>2019-05-07 10:13:21 -0400
committerMarge Bot <ben+marge-bot@smart-cactus.org>2019-10-08 13:24:52 -0400
commit9ac3bcbb3605fa8ff2481806a3a87a0d9654cd87 (patch)
tree1834c3356e79f9ea02cafbaad36fd95380b084dd
parent9402608ea5955c70fee51f8b892d418252846a9b (diff)
downloadhaskell-9ac3bcbb3605fa8ff2481806a3a87a0d9654cd87.tar.gz
Document the UnliftedFFITypes extension.
-rw-r--r--docs/users_guide/ffi-chap.rst103
-rw-r--r--docs/users_guide/what_glasgow_exts_does.rst1
2 files changed, 98 insertions, 6 deletions
diff --git a/docs/users_guide/ffi-chap.rst b/docs/users_guide/ffi-chap.rst
index a34b0286dd..944ceb478c 100644
--- a/docs/users_guide/ffi-chap.rst
+++ b/docs/users_guide/ffi-chap.rst
@@ -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#``.
diff --git a/docs/users_guide/what_glasgow_exts_does.rst b/docs/users_guide/what_glasgow_exts_does.rst
index 1c1d3a2a7b..47ba6313b0 100644
--- a/docs/users_guide/what_glasgow_exts_does.rst
+++ b/docs/users_guide/what_glasgow_exts_does.rst
@@ -15,6 +15,7 @@
* :extension:`FunctionalDependencies`
* :extension:`GeneralizedNewtypeDeriving`
* :extension:`ImplicitParams`
+ * :extension:`InterruptibleFFI`
* :extension:`KindSignatures`
* :extension:`LiberalTypeSynonyms`
* :extension:`MagicHash`