summaryrefslogtreecommitdiff
path: root/compiler/GHC/Builtin/primops.txt.pp
diff options
context:
space:
mode:
authorSylvain Henry <sylvain@haskus.fr>2020-04-05 17:39:13 +0200
committerSylvain Henry <sylvain@haskus.fr>2020-04-18 20:04:46 +0200
commit15312bbb53f247c9ed2c5cf75100a9f44c1c7227 (patch)
tree8306dcc04a5b7c82464f903044dfdd589e7fdcd7 /compiler/GHC/Builtin/primops.txt.pp
parent3ca52151881451ce5b3a7740d003e811b586140d (diff)
downloadhaskell-15312bbb53f247c9ed2c5cf75100a9f44c1c7227.tar.gz
Modules (#13009)
* SysTools * Parser * GHC.Builtin * GHC.Iface.Recomp * Settings Update Haddock submodule Metric Decrease: Naperian parsing001
Diffstat (limited to 'compiler/GHC/Builtin/primops.txt.pp')
-rw-r--r--compiler/GHC/Builtin/primops.txt.pp3841
1 files changed, 3841 insertions, 0 deletions
diff --git a/compiler/GHC/Builtin/primops.txt.pp b/compiler/GHC/Builtin/primops.txt.pp
new file mode 100644
index 0000000000..a29fbf48d7
--- /dev/null
+++ b/compiler/GHC/Builtin/primops.txt.pp
@@ -0,0 +1,3841 @@
+-----------------------------------------------------------------------
+--
+-- (c) 2010 The University of Glasgow
+--
+-- Primitive Operations and Types
+--
+-- For more information on PrimOps, see
+-- https://gitlab.haskell.org/ghc/ghc/wikis/commentary/prim-ops
+--
+-----------------------------------------------------------------------
+
+-- This file is processed by the utility program genprimopcode to produce
+-- a number of include files within the compiler and optionally to produce
+-- human-readable documentation.
+--
+-- It should first be preprocessed.
+--
+-- Information on how PrimOps are implemented and the steps necessary to
+-- add a new one can be found in the Commentary:
+--
+-- https://gitlab.haskell.org/ghc/ghc/wikis/commentary/prim-ops
+--
+-- Note in particular that Haskell block-style comments are not recognized
+-- here, so stick to '--' (even for Notes spanning multiple lines).
+
+-- This file is divided into named sections, each containing or more
+-- primop entries. Section headers have the format:
+--
+-- section "section-name" {description}
+--
+-- This information is used solely when producing documentation; it is
+-- otherwise ignored. The description is optional.
+--
+-- The format of each primop entry is as follows:
+--
+-- primop internal-name "name-in-program-text" category type {description} attributes
+
+-- The default attribute values which apply if you don't specify
+-- other ones. Attribute values can be True, False, or arbitrary
+-- text between curly brackets. This is a kludge to enable
+-- processors of this file to easily get hold of simple info
+-- (eg, out_of_line), whilst avoiding parsing complex expressions
+-- needed for strictness info.
+--
+-- type refers to the general category of the primop. Valid settings include,
+--
+-- * Compare: A comparison operation of the shape a -> a -> Int#
+-- * Monadic: A unary operation of shape a -> a
+-- * Dyadic: A binary operation of shape a -> a -> a
+-- * GenPrimOp: Any other sort of primop
+--
+
+-- The vector attribute is rather special. It takes a list of 3-tuples, each of
+-- which is of the form <ELEM_TYPE,SCALAR_TYPE,LENGTH>. ELEM_TYPE is the type of
+-- the elements in the vector; LENGTH is the length of the vector; and
+-- SCALAR_TYPE is the scalar type used to inject to/project from vector
+-- element. Note that ELEM_TYPE and SCALAR_TYPE are not the same; for example,
+-- to broadcast a scalar value to a vector whose elements are of type Int8, we
+-- use an Int#.
+
+-- When a primtype or primop has a vector attribute, it is instantiated at each
+-- 3-tuple in the list of 3-tuples. That is, the vector attribute allows us to
+-- define a family of types or primops. Vector support also adds three new
+-- keywords: VECTOR, SCALAR, and VECTUPLE. These keywords are expanded to types
+-- derived from the 3-tuple. For the 3-tuple <Int64,INT64,2>, VECTOR expands to
+-- Int64X2#, SCALAR expands to INT64, and VECTUPLE expands to (# INT64, INT64
+-- #).
+
+defaults
+ has_side_effects = False
+ out_of_line = False -- See Note [When do out-of-line primops go in primops.txt.pp]
+ can_fail = False -- See Note [PrimOp can_fail and has_side_effects] in PrimOp
+ commutable = False
+ code_size = { primOpCodeSizeDefault }
+ strictness = { \ arity -> mkClosedStrictSig (replicate arity topDmd) topDiv }
+ fixity = Nothing
+ llvm_only = False
+ vector = []
+ deprecated_msg = {} -- A non-empty message indicates deprecation
+
+
+-- Note [When do out-of-line primops go in primops.txt.pp]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--
+-- Out of line primops are those with a C-- implementation. But that
+-- doesn't mean they *just* have an C-- implementation. As mentioned in
+-- Note [Inlining out-of-line primops and heap checks], some out-of-line
+-- primops also have additional internal implementations under certain
+-- conditions. Now that `foreign import prim` exists, only those primops
+-- which have both internal and external implementations ought to be
+-- this file. The rest aren't really primops, since they don't need
+-- bespoke compiler support but just a general way to interface with
+-- C--. They are just foreign calls.
+--
+-- Unfortunately, for the time being most of the primops which should be
+-- moved according to the previous paragraph can't yet. There are some
+-- superficial restrictions in `foreign import prim` which mus be fixed
+-- first. Specifically, `foreign import prim` always requires:
+--
+-- - No polymorphism in type
+-- - `strictness = <default>`
+-- - `can_fail = False`
+-- - `has_side_effects = True`
+--
+-- https://gitlab.haskell.org/ghc/ghc/issues/16929 tracks this issue,
+-- and has a table of which external-only primops are blocked by which
+-- of these. Hopefully those restrictions are relaxed so the rest of
+-- those can be moved over.
+--
+-- 'module GHC.Prim.Ext is a temporarily "holding ground" for primops
+-- that were formally in here, until they can be given a better home.
+-- Likewise, their underlying C-- implementation need not live in the
+-- RTS either. Best case (in my view), both the C-- and `foreign import
+-- prim` can be moved to a small library tailured to the features being
+-- implemented and dependencies of those features.
+
+-- Currently, documentation is produced using latex, so contents of
+-- description fields should be legal latex. Descriptions can contain
+-- matched pairs of embedded curly brackets.
+
+#include "MachDeps.h"
+
+section "The word size story."
+ {Haskell98 specifies that signed integers (type {\tt Int})
+ must contain at least 30 bits. GHC always implements {\tt
+ Int} using the primitive type {\tt Int\#}, whose size equals
+ the {\tt MachDeps.h} constant {\tt WORD\_SIZE\_IN\_BITS}.
+ This is normally set based on the {\tt config.h} parameter
+ {\tt SIZEOF\_HSWORD}, i.e., 32 bits on 32-bit machines, 64
+ bits on 64-bit machines. However, it can also be explicitly
+ set to a smaller number than 64, e.g., 62 bits, to allow the
+ possibility of using tag bits. Currently GHC itself has only
+ 32-bit and 64-bit variants, but 61, 62, or 63-bit code can be
+ exported as an external core file for use in other back ends.
+ 30 and 31-bit code is no longer supported.
+
+ GHC also implements a primitive unsigned integer type {\tt
+ Word\#} which always has the same number of bits as {\tt
+ Int\#}.
+
+ In addition, GHC supports families of explicit-sized integers
+ and words at 8, 16, 32, and 64 bits, with the usual
+ arithmetic operations, comparisons, and a range of
+ conversions. The 8-bit and 16-bit sizes are always
+ represented as {\tt Int\#} and {\tt Word\#}, and the
+ operations implemented in terms of the primops on these
+ types, with suitable range restrictions on the results (using
+ the {\tt narrow$n$Int\#} and {\tt narrow$n$Word\#} families
+ of primops. The 32-bit sizes are represented using {\tt
+ Int\#} and {\tt Word\#} when {\tt WORD\_SIZE\_IN\_BITS}
+ $\geq$ 32; otherwise, these are represented using distinct
+ primitive types {\tt Int32\#} and {\tt Word32\#}. These (when
+ needed) have a complete set of corresponding operations;
+ however, nearly all of these are implemented as external C
+ functions rather than as primops. Exactly the same story
+ applies to the 64-bit sizes. All of these details are hidden
+ under the {\tt PrelInt} and {\tt PrelWord} modules, which use
+ {\tt \#if}-defs to invoke the appropriate types and
+ operators.
+
+ Word size also matters for the families of primops for
+ indexing/reading/writing fixed-size quantities at offsets
+ from an array base, address, or foreign pointer. Here, a
+ slightly different approach is taken. The names of these
+ primops are fixed, but their {\it types} vary according to
+ the value of {\tt WORD\_SIZE\_IN\_BITS}. For example, if word
+ size is at least 32 bits then an operator like
+ \texttt{indexInt32Array\#} has type {\tt ByteArray\# -> Int\#
+ -> Int\#}; otherwise it has type {\tt ByteArray\# -> Int\# ->
+ Int32\#}. This approach confines the necessary {\tt
+ \#if}-defs to this file; no conditional compilation is needed
+ in the files that expose these primops.
+
+ Finally, there are strongly deprecated primops for coercing
+ between {\tt Addr\#}, the primitive type of machine
+ addresses, and {\tt Int\#}. These are pretty bogus anyway,
+ but will work on existing 32-bit and 64-bit GHC targets; they
+ are completely bogus when tag bits are used in {\tt Int\#},
+ so are not available in this case. }
+
+-- Define synonyms for indexing ops.
+
+#define INT32 Int#
+#define WORD32 Word#
+
+#if WORD_SIZE_IN_BITS < 64
+#define INT64 Int64#
+#define WORD64 Word64#
+#else
+#define INT64 Int#
+#define WORD64 Word#
+#endif
+
+-- This type won't be exported directly (since there is no concrete
+-- syntax for this sort of export) so we'll have to manually patch
+-- export lists in both GHC and Haddock.
+primtype (->) a b
+ {The builtin function type, written in infix form as {\tt a -> b} and
+ in prefix form as {\tt (->) a b}. Values of this type are functions
+ taking inputs of type {\tt a} and producing outputs of type {\tt b}.
+
+ Note that {\tt a -> b} permits levity-polymorphism in both {\tt a} and
+ {\tt b}, so that types like {\tt Int\# -> Int\#} can still be well-kinded.
+ }
+ with fixity = infixr -1
+ -- This fixity is only the one picked up by Haddock. If you
+ -- change this, do update 'ghcPrimIface' in 'GHC.Iface.Load'.
+
+------------------------------------------------------------------------
+section "Char#"
+ {Operations on 31-bit characters.}
+------------------------------------------------------------------------
+
+primtype Char#
+
+primop CharGtOp "gtChar#" Compare Char# -> Char# -> Int#
+primop CharGeOp "geChar#" Compare Char# -> Char# -> Int#
+
+primop CharEqOp "eqChar#" Compare
+ Char# -> Char# -> Int#
+ with commutable = True
+
+primop CharNeOp "neChar#" Compare
+ Char# -> Char# -> Int#
+ with commutable = True
+
+primop CharLtOp "ltChar#" Compare Char# -> Char# -> Int#
+primop CharLeOp "leChar#" Compare Char# -> Char# -> Int#
+
+primop OrdOp "ord#" GenPrimOp Char# -> Int#
+ with code_size = 0
+
+------------------------------------------------------------------------
+section "Int8#"
+ {Operations on 8-bit integers.}
+------------------------------------------------------------------------
+
+primtype Int8#
+
+primop Int8Extend "extendInt8#" GenPrimOp Int8# -> Int#
+primop Int8Narrow "narrowInt8#" GenPrimOp Int# -> Int8#
+
+primop Int8NegOp "negateInt8#" Monadic Int8# -> Int8#
+
+primop Int8AddOp "plusInt8#" Dyadic Int8# -> Int8# -> Int8#
+ with
+ commutable = True
+
+primop Int8SubOp "subInt8#" Dyadic Int8# -> Int8# -> Int8#
+
+primop Int8MulOp "timesInt8#" Dyadic Int8# -> Int8# -> Int8#
+ with
+ commutable = True
+
+primop Int8QuotOp "quotInt8#" Dyadic Int8# -> Int8# -> Int8#
+ with
+ can_fail = True
+
+primop Int8RemOp "remInt8#" Dyadic Int8# -> Int8# -> Int8#
+ with
+ can_fail = True
+
+primop Int8QuotRemOp "quotRemInt8#" GenPrimOp Int8# -> Int8# -> (# Int8#, Int8# #)
+ with
+ can_fail = True
+
+primop Int8EqOp "eqInt8#" Compare Int8# -> Int8# -> Int#
+primop Int8GeOp "geInt8#" Compare Int8# -> Int8# -> Int#
+primop Int8GtOp "gtInt8#" Compare Int8# -> Int8# -> Int#
+primop Int8LeOp "leInt8#" Compare Int8# -> Int8# -> Int#
+primop Int8LtOp "ltInt8#" Compare Int8# -> Int8# -> Int#
+primop Int8NeOp "neInt8#" Compare Int8# -> Int8# -> Int#
+
+------------------------------------------------------------------------
+section "Word8#"
+ {Operations on 8-bit unsigned integers.}
+------------------------------------------------------------------------
+
+primtype Word8#
+
+primop Word8Extend "extendWord8#" GenPrimOp Word8# -> Word#
+primop Word8Narrow "narrowWord8#" GenPrimOp Word# -> Word8#
+
+primop Word8NotOp "notWord8#" Monadic Word8# -> Word8#
+
+primop Word8AddOp "plusWord8#" Dyadic Word8# -> Word8# -> Word8#
+ with
+ commutable = True
+
+primop Word8SubOp "subWord8#" Dyadic Word8# -> Word8# -> Word8#
+
+primop Word8MulOp "timesWord8#" Dyadic Word8# -> Word8# -> Word8#
+ with
+ commutable = True
+
+primop Word8QuotOp "quotWord8#" Dyadic Word8# -> Word8# -> Word8#
+ with
+ can_fail = True
+
+primop Word8RemOp "remWord8#" Dyadic Word8# -> Word8# -> Word8#
+ with
+ can_fail = True
+
+primop Word8QuotRemOp "quotRemWord8#" GenPrimOp Word8# -> Word8# -> (# Word8#, Word8# #)
+ with
+ can_fail = True
+
+primop Word8EqOp "eqWord8#" Compare Word8# -> Word8# -> Int#
+primop Word8GeOp "geWord8#" Compare Word8# -> Word8# -> Int#
+primop Word8GtOp "gtWord8#" Compare Word8# -> Word8# -> Int#
+primop Word8LeOp "leWord8#" Compare Word8# -> Word8# -> Int#
+primop Word8LtOp "ltWord8#" Compare Word8# -> Word8# -> Int#
+primop Word8NeOp "neWord8#" Compare Word8# -> Word8# -> Int#
+
+------------------------------------------------------------------------
+section "Int16#"
+ {Operations on 16-bit integers.}
+------------------------------------------------------------------------
+
+primtype Int16#
+
+primop Int16Extend "extendInt16#" GenPrimOp Int16# -> Int#
+primop Int16Narrow "narrowInt16#" GenPrimOp Int# -> Int16#
+
+primop Int16NegOp "negateInt16#" Monadic Int16# -> Int16#
+
+primop Int16AddOp "plusInt16#" Dyadic Int16# -> Int16# -> Int16#
+ with
+ commutable = True
+
+primop Int16SubOp "subInt16#" Dyadic Int16# -> Int16# -> Int16#
+
+primop Int16MulOp "timesInt16#" Dyadic Int16# -> Int16# -> Int16#
+ with
+ commutable = True
+
+primop Int16QuotOp "quotInt16#" Dyadic Int16# -> Int16# -> Int16#
+ with
+ can_fail = True
+
+primop Int16RemOp "remInt16#" Dyadic Int16# -> Int16# -> Int16#
+ with
+ can_fail = True
+
+primop Int16QuotRemOp "quotRemInt16#" GenPrimOp Int16# -> Int16# -> (# Int16#, Int16# #)
+ with
+ can_fail = True
+
+primop Int16EqOp "eqInt16#" Compare Int16# -> Int16# -> Int#
+primop Int16GeOp "geInt16#" Compare Int16# -> Int16# -> Int#
+primop Int16GtOp "gtInt16#" Compare Int16# -> Int16# -> Int#
+primop Int16LeOp "leInt16#" Compare Int16# -> Int16# -> Int#
+primop Int16LtOp "ltInt16#" Compare Int16# -> Int16# -> Int#
+primop Int16NeOp "neInt16#" Compare Int16# -> Int16# -> Int#
+
+------------------------------------------------------------------------
+section "Word16#"
+ {Operations on 16-bit unsigned integers.}
+------------------------------------------------------------------------
+
+primtype Word16#
+
+primop Word16Extend "extendWord16#" GenPrimOp Word16# -> Word#
+primop Word16Narrow "narrowWord16#" GenPrimOp Word# -> Word16#
+
+primop Word16NotOp "notWord16#" Monadic Word16# -> Word16#
+
+primop Word16AddOp "plusWord16#" Dyadic Word16# -> Word16# -> Word16#
+ with
+ commutable = True
+
+primop Word16SubOp "subWord16#" Dyadic Word16# -> Word16# -> Word16#
+
+primop Word16MulOp "timesWord16#" Dyadic Word16# -> Word16# -> Word16#
+ with
+ commutable = True
+
+primop Word16QuotOp "quotWord16#" Dyadic Word16# -> Word16# -> Word16#
+ with
+ can_fail = True
+
+primop Word16RemOp "remWord16#" Dyadic Word16# -> Word16# -> Word16#
+ with
+ can_fail = True
+
+primop Word16QuotRemOp "quotRemWord16#" GenPrimOp Word16# -> Word16# -> (# Word16#, Word16# #)
+ with
+ can_fail = True
+
+primop Word16EqOp "eqWord16#" Compare Word16# -> Word16# -> Int#
+primop Word16GeOp "geWord16#" Compare Word16# -> Word16# -> Int#
+primop Word16GtOp "gtWord16#" Compare Word16# -> Word16# -> Int#
+primop Word16LeOp "leWord16#" Compare Word16# -> Word16# -> Int#
+primop Word16LtOp "ltWord16#" Compare Word16# -> Word16# -> Int#
+primop Word16NeOp "neWord16#" Compare Word16# -> Word16# -> Int#
+
+#if WORD_SIZE_IN_BITS < 64
+------------------------------------------------------------------------
+section "Int64#"
+ {Operations on 64-bit unsigned words. This type is only used
+ if plain {\tt Int\#} has less than 64 bits. In any case, the operations
+ are not primops; they are implemented (if needed) as ccalls instead.}
+------------------------------------------------------------------------
+
+primtype Int64#
+
+------------------------------------------------------------------------
+section "Word64#"
+ {Operations on 64-bit unsigned words. This type is only used
+ if plain {\tt Word\#} has less than 64 bits. In any case, the operations
+ are not primops; they are implemented (if needed) as ccalls instead.}
+------------------------------------------------------------------------
+
+primtype Word64#
+
+#endif
+
+------------------------------------------------------------------------
+section "Int#"
+ {Operations on native-size integers (32+ bits).}
+------------------------------------------------------------------------
+
+primtype Int#
+
+primop IntAddOp "+#" Dyadic
+ Int# -> Int# -> Int#
+ with commutable = True
+ fixity = infixl 6
+
+primop IntSubOp "-#" Dyadic Int# -> Int# -> Int#
+ with fixity = infixl 6
+
+primop IntMulOp "*#"
+ Dyadic Int# -> Int# -> Int#
+ {Low word of signed integer multiply.}
+ with commutable = True
+ fixity = infixl 7
+
+primop IntMul2Op "timesInt2#" GenPrimOp
+ Int# -> Int# -> (# Int#, Int#, Int# #)
+ {Return a triple (isHighNeeded,high,low) where high and low are respectively
+ the high and low bits of the double-word result. isHighNeeded is a cheap way
+ to test if the high word is a sign-extension of the low word (isHighNeeded =
+ 0#) or not (isHighNeeded = 1#).}
+
+primop IntMulMayOfloOp "mulIntMayOflo#"
+ Dyadic Int# -> Int# -> Int#
+ {Return non-zero if there is any possibility that the upper word of a
+ signed integer multiply might contain useful information. Return
+ zero only if you are completely sure that no overflow can occur.
+ On a 32-bit platform, the recommended implementation is to do a
+ 32 x 32 -> 64 signed multiply, and subtract result[63:32] from
+ (result[31] >>signed 31). If this is zero, meaning that the
+ upper word is merely a sign extension of the lower one, no
+ overflow can occur.
+
+ On a 64-bit platform it is not always possible to
+ acquire the top 64 bits of the result. Therefore, a recommended
+ implementation is to take the absolute value of both operands, and
+ return 0 iff bits[63:31] of them are zero, since that means that their
+ magnitudes fit within 31 bits, so the magnitude of the product must fit
+ into 62 bits.
+
+ If in doubt, return non-zero, but do make an effort to create the
+ correct answer for small args, since otherwise the performance of
+ \texttt{(*) :: Integer -> Integer -> Integer} will be poor.
+ }
+ with commutable = True
+
+primop IntQuotOp "quotInt#" Dyadic
+ Int# -> Int# -> Int#
+ {Rounds towards zero. The behavior is undefined if the second argument is
+ zero.
+ }
+ with can_fail = True
+
+primop IntRemOp "remInt#" Dyadic
+ Int# -> Int# -> Int#
+ {Satisfies \texttt{(quotInt\# x y) *\# y +\# (remInt\# x y) == x}. The
+ behavior is undefined if the second argument is zero.
+ }
+ with can_fail = True
+
+primop IntQuotRemOp "quotRemInt#" GenPrimOp
+ Int# -> Int# -> (# Int#, Int# #)
+ {Rounds towards zero.}
+ with can_fail = True
+
+primop AndIOp "andI#" Dyadic Int# -> Int# -> Int#
+ {Bitwise "and".}
+ with commutable = True
+
+primop OrIOp "orI#" Dyadic Int# -> Int# -> Int#
+ {Bitwise "or".}
+ with commutable = True
+
+primop XorIOp "xorI#" Dyadic Int# -> Int# -> Int#
+ {Bitwise "xor".}
+ with commutable = True
+
+primop NotIOp "notI#" Monadic Int# -> Int#
+ {Bitwise "not", also known as the binary complement.}
+
+primop IntNegOp "negateInt#" Monadic Int# -> Int#
+ {Unary negation.
+ Since the negative {\tt Int#} range extends one further than the
+ positive range, {\tt negateInt#} of the most negative number is an
+ identity operation. This way, {\tt negateInt#} is always its own inverse.}
+
+primop IntAddCOp "addIntC#" GenPrimOp Int# -> Int# -> (# Int#, Int# #)
+ {Add signed integers reporting overflow.
+ First member of result is the sum truncated to an {\tt Int#};
+ second member is zero if the true sum fits in an {\tt Int#},
+ nonzero if overflow occurred (the sum is either too large
+ or too small to fit in an {\tt Int#}).}
+ with code_size = 2
+ commutable = True
+
+primop IntSubCOp "subIntC#" GenPrimOp Int# -> Int# -> (# Int#, Int# #)
+ {Subtract signed integers reporting overflow.
+ First member of result is the difference truncated to an {\tt Int#};
+ second member is zero if the true difference fits in an {\tt Int#},
+ nonzero if overflow occurred (the difference is either too large
+ or too small to fit in an {\tt Int#}).}
+ with code_size = 2
+
+primop IntGtOp ">#" Compare Int# -> Int# -> Int#
+ with fixity = infix 4
+
+primop IntGeOp ">=#" Compare Int# -> Int# -> Int#
+ with fixity = infix 4
+
+primop IntEqOp "==#" Compare
+ Int# -> Int# -> Int#
+ with commutable = True
+ fixity = infix 4
+
+primop IntNeOp "/=#" Compare
+ Int# -> Int# -> Int#
+ with commutable = True
+ fixity = infix 4
+
+primop IntLtOp "<#" Compare Int# -> Int# -> Int#
+ with fixity = infix 4
+
+primop IntLeOp "<=#" Compare Int# -> Int# -> Int#
+ with fixity = infix 4
+
+primop ChrOp "chr#" GenPrimOp Int# -> Char#
+ with code_size = 0
+
+primop Int2WordOp "int2Word#" GenPrimOp Int# -> Word#
+ with code_size = 0
+
+primop Int2FloatOp "int2Float#" GenPrimOp Int# -> Float#
+primop Int2DoubleOp "int2Double#" GenPrimOp Int# -> Double#
+
+primop Word2FloatOp "word2Float#" GenPrimOp Word# -> Float#
+primop Word2DoubleOp "word2Double#" GenPrimOp Word# -> Double#
+
+primop ISllOp "uncheckedIShiftL#" GenPrimOp Int# -> Int# -> Int#
+ {Shift left. Result undefined if shift amount is not
+ in the range 0 to word size - 1 inclusive.}
+primop ISraOp "uncheckedIShiftRA#" GenPrimOp Int# -> Int# -> Int#
+ {Shift right arithmetic. Result undefined if shift amount is not
+ in the range 0 to word size - 1 inclusive.}
+primop ISrlOp "uncheckedIShiftRL#" GenPrimOp Int# -> Int# -> Int#
+ {Shift right logical. Result undefined if shift amount is not
+ in the range 0 to word size - 1 inclusive.}
+
+------------------------------------------------------------------------
+section "Word#"
+ {Operations on native-sized unsigned words (32+ bits).}
+------------------------------------------------------------------------
+
+primtype Word#
+
+primop WordAddOp "plusWord#" Dyadic Word# -> Word# -> Word#
+ with commutable = True
+
+primop WordAddCOp "addWordC#" GenPrimOp Word# -> Word# -> (# Word#, Int# #)
+ {Add unsigned integers reporting overflow.
+ The first element of the pair is the result. The second element is
+ the carry flag, which is nonzero on overflow. See also {\tt plusWord2#}.}
+ with code_size = 2
+ commutable = True
+
+primop WordSubCOp "subWordC#" GenPrimOp Word# -> Word# -> (# Word#, Int# #)
+ {Subtract unsigned integers reporting overflow.
+ The first element of the pair is the result. The second element is
+ the carry flag, which is nonzero on overflow.}
+ with code_size = 2
+
+primop WordAdd2Op "plusWord2#" GenPrimOp Word# -> Word# -> (# Word#, Word# #)
+ {Add unsigned integers, with the high part (carry) in the first
+ component of the returned pair and the low part in the second
+ component of the pair. See also {\tt addWordC#}.}
+ with code_size = 2
+ commutable = True
+
+primop WordSubOp "minusWord#" Dyadic Word# -> Word# -> Word#
+
+primop WordMulOp "timesWord#" Dyadic Word# -> Word# -> Word#
+ with commutable = True
+
+-- Returns (# high, low #)
+primop WordMul2Op "timesWord2#" GenPrimOp
+ Word# -> Word# -> (# Word#, Word# #)
+ with commutable = True
+
+primop WordQuotOp "quotWord#" Dyadic Word# -> Word# -> Word#
+ with can_fail = True
+
+primop WordRemOp "remWord#" Dyadic Word# -> Word# -> Word#
+ with can_fail = True
+
+primop WordQuotRemOp "quotRemWord#" GenPrimOp
+ Word# -> Word# -> (# Word#, Word# #)
+ with can_fail = True
+
+primop WordQuotRem2Op "quotRemWord2#" GenPrimOp
+ Word# -> Word# -> Word# -> (# Word#, Word# #)
+ { Takes high word of dividend, then low word of dividend, then divisor.
+ Requires that high word < divisor.}
+ with can_fail = True
+
+primop AndOp "and#" Dyadic Word# -> Word# -> Word#
+ with commutable = True
+
+primop OrOp "or#" Dyadic Word# -> Word# -> Word#
+ with commutable = True
+
+primop XorOp "xor#" Dyadic Word# -> Word# -> Word#
+ with commutable = True
+
+primop NotOp "not#" Monadic Word# -> Word#
+
+primop SllOp "uncheckedShiftL#" GenPrimOp Word# -> Int# -> Word#
+ {Shift left logical. Result undefined if shift amount is not
+ in the range 0 to word size - 1 inclusive.}
+primop SrlOp "uncheckedShiftRL#" GenPrimOp Word# -> Int# -> Word#
+ {Shift right logical. Result undefined if shift amount is not
+ in the range 0 to word size - 1 inclusive.}
+
+primop Word2IntOp "word2Int#" GenPrimOp Word# -> Int#
+ with code_size = 0
+
+primop WordGtOp "gtWord#" Compare Word# -> Word# -> Int#
+primop WordGeOp "geWord#" Compare Word# -> Word# -> Int#
+primop WordEqOp "eqWord#" Compare Word# -> Word# -> Int#
+primop WordNeOp "neWord#" Compare Word# -> Word# -> Int#
+primop WordLtOp "ltWord#" Compare Word# -> Word# -> Int#
+primop WordLeOp "leWord#" Compare Word# -> Word# -> Int#
+
+primop PopCnt8Op "popCnt8#" Monadic Word# -> Word#
+ {Count the number of set bits in the lower 8 bits of a word.}
+primop PopCnt16Op "popCnt16#" Monadic Word# -> Word#
+ {Count the number of set bits in the lower 16 bits of a word.}
+primop PopCnt32Op "popCnt32#" Monadic Word# -> Word#
+ {Count the number of set bits in the lower 32 bits of a word.}
+primop PopCnt64Op "popCnt64#" GenPrimOp WORD64 -> Word#
+ {Count the number of set bits in a 64-bit word.}
+primop PopCntOp "popCnt#" Monadic Word# -> Word#
+ {Count the number of set bits in a word.}
+
+primop Pdep8Op "pdep8#" Dyadic Word# -> Word# -> Word#
+ {Deposit bits to lower 8 bits of a word at locations specified by a mask.}
+primop Pdep16Op "pdep16#" Dyadic Word# -> Word# -> Word#
+ {Deposit bits to lower 16 bits of a word at locations specified by a mask.}
+primop Pdep32Op "pdep32#" Dyadic Word# -> Word# -> Word#
+ {Deposit bits to lower 32 bits of a word at locations specified by a mask.}
+primop Pdep64Op "pdep64#" GenPrimOp WORD64 -> WORD64 -> WORD64
+ {Deposit bits to a word at locations specified by a mask.}
+primop PdepOp "pdep#" Dyadic Word# -> Word# -> Word#
+ {Deposit bits to a word at locations specified by a mask.}
+
+primop Pext8Op "pext8#" Dyadic Word# -> Word# -> Word#
+ {Extract bits from lower 8 bits of a word at locations specified by a mask.}
+primop Pext16Op "pext16#" Dyadic Word# -> Word# -> Word#
+ {Extract bits from lower 16 bits of a word at locations specified by a mask.}
+primop Pext32Op "pext32#" Dyadic Word# -> Word# -> Word#
+ {Extract bits from lower 32 bits of a word at locations specified by a mask.}
+primop Pext64Op "pext64#" GenPrimOp WORD64 -> WORD64 -> WORD64
+ {Extract bits from a word at locations specified by a mask.}
+primop PextOp "pext#" Dyadic Word# -> Word# -> Word#
+ {Extract bits from a word at locations specified by a mask.}
+
+primop Clz8Op "clz8#" Monadic Word# -> Word#
+ {Count leading zeros in the lower 8 bits of a word.}
+primop Clz16Op "clz16#" Monadic Word# -> Word#
+ {Count leading zeros in the lower 16 bits of a word.}
+primop Clz32Op "clz32#" Monadic Word# -> Word#
+ {Count leading zeros in the lower 32 bits of a word.}
+primop Clz64Op "clz64#" GenPrimOp WORD64 -> Word#
+ {Count leading zeros in a 64-bit word.}
+primop ClzOp "clz#" Monadic Word# -> Word#
+ {Count leading zeros in a word.}
+
+primop Ctz8Op "ctz8#" Monadic Word# -> Word#
+ {Count trailing zeros in the lower 8 bits of a word.}
+primop Ctz16Op "ctz16#" Monadic Word# -> Word#
+ {Count trailing zeros in the lower 16 bits of a word.}
+primop Ctz32Op "ctz32#" Monadic Word# -> Word#
+ {Count trailing zeros in the lower 32 bits of a word.}
+primop Ctz64Op "ctz64#" GenPrimOp WORD64 -> Word#
+ {Count trailing zeros in a 64-bit word.}
+primop CtzOp "ctz#" Monadic Word# -> Word#
+ {Count trailing zeros in a word.}
+
+primop BSwap16Op "byteSwap16#" Monadic Word# -> Word#
+ {Swap bytes in the lower 16 bits of a word. The higher bytes are undefined. }
+primop BSwap32Op "byteSwap32#" Monadic Word# -> Word#
+ {Swap bytes in the lower 32 bits of a word. The higher bytes are undefined. }
+primop BSwap64Op "byteSwap64#" Monadic WORD64 -> WORD64
+ {Swap bytes in a 64 bits of a word.}
+primop BSwapOp "byteSwap#" Monadic Word# -> Word#
+ {Swap bytes in a word.}
+
+primop BRev8Op "bitReverse8#" Monadic Word# -> Word#
+ {Reverse the order of the bits in a 8-bit word.}
+primop BRev16Op "bitReverse16#" Monadic Word# -> Word#
+ {Reverse the order of the bits in a 16-bit word.}
+primop BRev32Op "bitReverse32#" Monadic Word# -> Word#
+ {Reverse the order of the bits in a 32-bit word.}
+primop BRev64Op "bitReverse64#" Monadic WORD64 -> WORD64
+ {Reverse the order of the bits in a 64-bit word.}
+primop BRevOp "bitReverse#" Monadic Word# -> Word#
+ {Reverse the order of the bits in a word.}
+
+------------------------------------------------------------------------
+section "Narrowings"
+ {Explicit narrowing of native-sized ints or words.}
+------------------------------------------------------------------------
+
+primop Narrow8IntOp "narrow8Int#" Monadic Int# -> Int#
+primop Narrow16IntOp "narrow16Int#" Monadic Int# -> Int#
+primop Narrow32IntOp "narrow32Int#" Monadic Int# -> Int#
+primop Narrow8WordOp "narrow8Word#" Monadic Word# -> Word#
+primop Narrow16WordOp "narrow16Word#" Monadic Word# -> Word#
+primop Narrow32WordOp "narrow32Word#" Monadic Word# -> Word#
+
+------------------------------------------------------------------------
+section "Double#"
+ {Operations on double-precision (64 bit) floating-point numbers.}
+------------------------------------------------------------------------
+
+primtype Double#
+
+primop DoubleGtOp ">##" Compare Double# -> Double# -> Int#
+ with fixity = infix 4
+
+primop DoubleGeOp ">=##" Compare Double# -> Double# -> Int#
+ with fixity = infix 4
+
+primop DoubleEqOp "==##" Compare
+ Double# -> Double# -> Int#
+ with commutable = True
+ fixity = infix 4
+
+primop DoubleNeOp "/=##" Compare
+ Double# -> Double# -> Int#
+ with commutable = True
+ fixity = infix 4
+
+primop DoubleLtOp "<##" Compare Double# -> Double# -> Int#
+ with fixity = infix 4
+
+primop DoubleLeOp "<=##" Compare Double# -> Double# -> Int#
+ with fixity = infix 4
+
+primop DoubleAddOp "+##" Dyadic
+ Double# -> Double# -> Double#
+ with commutable = True
+ fixity = infixl 6
+
+primop DoubleSubOp "-##" Dyadic Double# -> Double# -> Double#
+ with fixity = infixl 6
+
+primop DoubleMulOp "*##" Dyadic
+ Double# -> Double# -> Double#
+ with commutable = True
+ fixity = infixl 7
+
+primop DoubleDivOp "/##" Dyadic
+ Double# -> Double# -> Double#
+ with can_fail = True
+ fixity = infixl 7
+
+primop DoubleNegOp "negateDouble#" Monadic Double# -> Double#
+
+primop DoubleFabsOp "fabsDouble#" Monadic Double# -> Double#
+
+primop Double2IntOp "double2Int#" GenPrimOp Double# -> Int#
+ {Truncates a {\tt Double#} value to the nearest {\tt Int#}.
+ Results are undefined if the truncation if truncation yields
+ a value outside the range of {\tt Int#}.}
+
+primop Double2FloatOp "double2Float#" GenPrimOp Double# -> Float#
+
+primop DoubleExpOp "expDouble#" Monadic
+ Double# -> Double#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop DoubleExpM1Op "expm1Double#" Monadic
+ Double# -> Double#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop DoubleLogOp "logDouble#" Monadic
+ Double# -> Double#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+ can_fail = True
+
+primop DoubleLog1POp "log1pDouble#" Monadic
+ Double# -> Double#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+ can_fail = True
+
+primop DoubleSqrtOp "sqrtDouble#" Monadic
+ Double# -> Double#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop DoubleSinOp "sinDouble#" Monadic
+ Double# -> Double#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop DoubleCosOp "cosDouble#" Monadic
+ Double# -> Double#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop DoubleTanOp "tanDouble#" Monadic
+ Double# -> Double#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop DoubleAsinOp "asinDouble#" Monadic
+ Double# -> Double#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+ can_fail = True
+
+primop DoubleAcosOp "acosDouble#" Monadic
+ Double# -> Double#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+ can_fail = True
+
+primop DoubleAtanOp "atanDouble#" Monadic
+ Double# -> Double#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop DoubleSinhOp "sinhDouble#" Monadic
+ Double# -> Double#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop DoubleCoshOp "coshDouble#" Monadic
+ Double# -> Double#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop DoubleTanhOp "tanhDouble#" Monadic
+ Double# -> Double#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop DoubleAsinhOp "asinhDouble#" Monadic
+ Double# -> Double#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop DoubleAcoshOp "acoshDouble#" Monadic
+ Double# -> Double#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop DoubleAtanhOp "atanhDouble#" Monadic
+ Double# -> Double#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop DoublePowerOp "**##" Dyadic
+ Double# -> Double# -> Double#
+ {Exponentiation.}
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop DoubleDecode_2IntOp "decodeDouble_2Int#" GenPrimOp
+ Double# -> (# Int#, Word#, Word#, Int# #)
+ {Convert to integer.
+ First component of the result is -1 or 1, indicating the sign of the
+ mantissa. The next two are the high and low 32 bits of the mantissa
+ respectively, and the last is the exponent.}
+ with out_of_line = True
+
+primop DoubleDecode_Int64Op "decodeDouble_Int64#" GenPrimOp
+ Double# -> (# INT64, Int# #)
+ {Decode {\tt Double\#} into mantissa and base-2 exponent.}
+ with out_of_line = True
+
+------------------------------------------------------------------------
+section "Float#"
+ {Operations on single-precision (32-bit) floating-point numbers.}
+------------------------------------------------------------------------
+
+primtype Float#
+
+primop FloatGtOp "gtFloat#" Compare Float# -> Float# -> Int#
+primop FloatGeOp "geFloat#" Compare Float# -> Float# -> Int#
+
+primop FloatEqOp "eqFloat#" Compare
+ Float# -> Float# -> Int#
+ with commutable = True
+
+primop FloatNeOp "neFloat#" Compare
+ Float# -> Float# -> Int#
+ with commutable = True
+
+primop FloatLtOp "ltFloat#" Compare Float# -> Float# -> Int#
+primop FloatLeOp "leFloat#" Compare Float# -> Float# -> Int#
+
+primop FloatAddOp "plusFloat#" Dyadic
+ Float# -> Float# -> Float#
+ with commutable = True
+
+primop FloatSubOp "minusFloat#" Dyadic Float# -> Float# -> Float#
+
+primop FloatMulOp "timesFloat#" Dyadic
+ Float# -> Float# -> Float#
+ with commutable = True
+
+primop FloatDivOp "divideFloat#" Dyadic
+ Float# -> Float# -> Float#
+ with can_fail = True
+
+primop FloatNegOp "negateFloat#" Monadic Float# -> Float#
+
+primop FloatFabsOp "fabsFloat#" Monadic Float# -> Float#
+
+primop Float2IntOp "float2Int#" GenPrimOp Float# -> Int#
+ {Truncates a {\tt Float#} value to the nearest {\tt Int#}.
+ Results are undefined if the truncation if truncation yields
+ a value outside the range of {\tt Int#}.}
+
+primop FloatExpOp "expFloat#" Monadic
+ Float# -> Float#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop FloatExpM1Op "expm1Float#" Monadic
+ Float# -> Float#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop FloatLogOp "logFloat#" Monadic
+ Float# -> Float#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+ can_fail = True
+
+primop FloatLog1POp "log1pFloat#" Monadic
+ Float# -> Float#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+ can_fail = True
+
+primop FloatSqrtOp "sqrtFloat#" Monadic
+ Float# -> Float#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop FloatSinOp "sinFloat#" Monadic
+ Float# -> Float#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop FloatCosOp "cosFloat#" Monadic
+ Float# -> Float#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop FloatTanOp "tanFloat#" Monadic
+ Float# -> Float#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop FloatAsinOp "asinFloat#" Monadic
+ Float# -> Float#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+ can_fail = True
+
+primop FloatAcosOp "acosFloat#" Monadic
+ Float# -> Float#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+ can_fail = True
+
+primop FloatAtanOp "atanFloat#" Monadic
+ Float# -> Float#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop FloatSinhOp "sinhFloat#" Monadic
+ Float# -> Float#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop FloatCoshOp "coshFloat#" Monadic
+ Float# -> Float#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop FloatTanhOp "tanhFloat#" Monadic
+ Float# -> Float#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop FloatAsinhOp "asinhFloat#" Monadic
+ Float# -> Float#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop FloatAcoshOp "acoshFloat#" Monadic
+ Float# -> Float#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop FloatAtanhOp "atanhFloat#" Monadic
+ Float# -> Float#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop FloatPowerOp "powerFloat#" Dyadic
+ Float# -> Float# -> Float#
+ with
+ code_size = { primOpCodeSizeForeignCall }
+
+primop Float2DoubleOp "float2Double#" GenPrimOp Float# -> Double#
+
+primop FloatDecode_IntOp "decodeFloat_Int#" GenPrimOp
+ Float# -> (# Int#, Int# #)
+ {Convert to integers.
+ First {\tt Int\#} in result is the mantissa; second is the exponent.}
+ with out_of_line = True
+
+------------------------------------------------------------------------
+section "Arrays"
+ {Operations on {\tt Array\#}.}
+------------------------------------------------------------------------
+
+primtype Array# a
+
+primtype MutableArray# s a
+
+primop NewArrayOp "newArray#" GenPrimOp
+ Int# -> a -> State# s -> (# State# s, MutableArray# s a #)
+ {Create a new mutable array with the specified number of elements,
+ in the specified state thread,
+ with each element containing the specified initial value.}
+ with
+ out_of_line = True
+ has_side_effects = True
+
+primop SameMutableArrayOp "sameMutableArray#" GenPrimOp
+ MutableArray# s a -> MutableArray# s a -> Int#
+
+primop ReadArrayOp "readArray#" GenPrimOp
+ MutableArray# s a -> Int# -> State# s -> (# State# s, a #)
+ {Read from specified index of mutable array. Result is not yet evaluated.}
+ with
+ has_side_effects = True
+ can_fail = True
+
+primop WriteArrayOp "writeArray#" GenPrimOp
+ MutableArray# s a -> Int# -> a -> State# s -> State# s
+ {Write to specified index of mutable array.}
+ with
+ has_side_effects = True
+ can_fail = True
+ code_size = 2 -- card update too
+
+primop SizeofArrayOp "sizeofArray#" GenPrimOp
+ Array# a -> Int#
+ {Return the number of elements in the array.}
+
+primop SizeofMutableArrayOp "sizeofMutableArray#" GenPrimOp
+ MutableArray# s a -> Int#
+ {Return the number of elements in the array.}
+
+primop IndexArrayOp "indexArray#" GenPrimOp
+ Array# a -> Int# -> (# a #)
+ {Read from the specified index of an immutable array. The result is packaged
+ into an unboxed unary tuple; the result itself is not yet
+ evaluated. Pattern matching on the tuple forces the indexing of the
+ array to happen but does not evaluate the element itself. Evaluating
+ the thunk prevents additional thunks from building up on the
+ heap. Avoiding these thunks, in turn, reduces references to the
+ argument array, allowing it to be garbage collected more promptly.}
+ with
+ can_fail = True
+
+primop UnsafeFreezeArrayOp "unsafeFreezeArray#" GenPrimOp
+ MutableArray# s a -> State# s -> (# State# s, Array# a #)
+ {Make a mutable array immutable, without copying.}
+ with
+ has_side_effects = True
+
+primop UnsafeThawArrayOp "unsafeThawArray#" GenPrimOp
+ Array# a -> State# s -> (# State# s, MutableArray# s a #)
+ {Make an immutable array mutable, without copying.}
+ with
+ out_of_line = True
+ has_side_effects = True
+
+primop CopyArrayOp "copyArray#" GenPrimOp
+ Array# a -> Int# -> MutableArray# s a -> Int# -> Int# -> State# s -> State# s
+ {Given a source array, an offset into the source array, a
+ destination array, an offset into the destination array, and a
+ number of elements to copy, copy the elements from the source array
+ to the destination array. Both arrays must fully contain the
+ specified ranges, but this is not checked. The two arrays must not
+ be the same array in different states, but this is not checked
+ either.}
+ with
+ out_of_line = True
+ has_side_effects = True
+ can_fail = True
+
+primop CopyMutableArrayOp "copyMutableArray#" GenPrimOp
+ MutableArray# s a -> Int# -> MutableArray# s a -> Int# -> Int# -> State# s -> State# s
+ {Given a source array, an offset into the source array, a
+ destination array, an offset into the destination array, and a
+ number of elements to copy, copy the elements from the source array
+ to the destination array. Both arrays must fully contain the
+ specified ranges, but this is not checked. In the case where
+ the source and destination are the same array the source and
+ destination regions may overlap.}
+ with
+ out_of_line = True
+ has_side_effects = True
+ can_fail = True
+
+primop CloneArrayOp "cloneArray#" GenPrimOp
+ Array# a -> Int# -> Int# -> Array# a
+ {Given a source array, an offset into the source array, and a number
+ of elements to copy, create a new array with the elements from the
+ source array. The provided array must fully contain the specified
+ range, but this is not checked.}
+ with
+ out_of_line = True
+ has_side_effects = True
+ can_fail = True
+
+primop CloneMutableArrayOp "cloneMutableArray#" GenPrimOp
+ MutableArray# s a -> Int# -> Int# -> State# s -> (# State# s, MutableArray# s a #)
+ {Given a source array, an offset into the source array, and a number
+ of elements to copy, create a new array with the elements from the
+ source array. The provided array must fully contain the specified
+ range, but this is not checked.}
+ with
+ out_of_line = True
+ has_side_effects = True
+ can_fail = True
+
+primop FreezeArrayOp "freezeArray#" GenPrimOp
+ MutableArray# s a -> Int# -> Int# -> State# s -> (# State# s, Array# a #)
+ {Given a source array, an offset into the source array, and a number
+ of elements to copy, create a new array with the elements from the
+ source array. The provided array must fully contain the specified
+ range, but this is not checked.}
+ with
+ out_of_line = True
+ has_side_effects = True
+ can_fail = True
+
+primop ThawArrayOp "thawArray#" GenPrimOp
+ Array# a -> Int# -> Int# -> State# s -> (# State# s, MutableArray# s a #)
+ {Given a source array, an offset into the source array, and a number
+ of elements to copy, create a new array with the elements from the
+ source array. The provided array must fully contain the specified
+ range, but this is not checked.}
+ with
+ out_of_line = True
+ has_side_effects = True
+ can_fail = True
+
+primop CasArrayOp "casArray#" GenPrimOp
+ MutableArray# s a -> Int# -> a -> a -> State# s -> (# State# s, Int#, a #)
+ {Given an array, an offset, the expected old value, and
+ the new value, perform an atomic compare and swap (i.e. write the new
+ value if the current value and the old value are the same pointer).
+ Returns 0 if the swap succeeds and 1 if it fails. Additionally, returns
+ the element at the offset after the operation completes. This means that
+ on a success the new value is returned, and on a failure the actual old
+ value (not the expected one) is returned. Implies a full memory barrier.
+ The use of a pointer equality on a lifted value makes this function harder
+ to use correctly than {\tt casIntArray\#}. All of the difficulties
+ of using {\tt reallyUnsafePtrEquality\#} correctly apply to
+ {\tt casArray\#} as well.
+ }
+ with
+ out_of_line = True
+ has_side_effects = True
+
+
+------------------------------------------------------------------------
+section "Small Arrays"
+
+ {Operations on {\tt SmallArray\#}. A {\tt SmallArray\#} works
+ just like an {\tt Array\#}, but with different space use and
+ performance characteristics (that are often useful with small
+ arrays). The {\tt SmallArray\#} and {\tt SmallMutableArray#}
+ lack a `card table'. The purpose of a card table is to avoid
+ having to scan every element of the array on each GC by
+ keeping track of which elements have changed since the last GC
+ and only scanning those that have changed. So the consequence
+ of there being no card table is that the representation is
+ somewhat smaller and the writes are somewhat faster (because
+ the card table does not need to be updated). The disadvantage
+ of course is that for a {\tt SmallMutableArray#} the whole
+ array has to be scanned on each GC. Thus it is best suited for
+ use cases where the mutable array is not long lived, e.g.
+ where a mutable array is initialised quickly and then frozen
+ to become an immutable {\tt SmallArray\#}.
+ }
+
+------------------------------------------------------------------------
+
+primtype SmallArray# a
+
+primtype SmallMutableArray# s a
+
+primop NewSmallArrayOp "newSmallArray#" GenPrimOp
+ Int# -> a -> State# s -> (# State# s, SmallMutableArray# s a #)
+ {Create a new mutable array with the specified number of elements,
+ in the specified state thread,
+ with each element containing the specified initial value.}
+ with
+ out_of_line = True
+ has_side_effects = True
+
+primop SameSmallMutableArrayOp "sameSmallMutableArray#" GenPrimOp
+ SmallMutableArray# s a -> SmallMutableArray# s a -> Int#
+
+primop ShrinkSmallMutableArrayOp_Char "shrinkSmallMutableArray#" GenPrimOp
+ SmallMutableArray# s a -> Int# -> State# s -> State# s
+ {Shrink mutable array to new specified size, in
+ the specified state thread. The new size argument must be less than or
+ equal to the current size as reported by {\tt sizeofSmallMutableArray\#}.}
+ with out_of_line = True
+ has_side_effects = True
+
+primop ReadSmallArrayOp "readSmallArray#" GenPrimOp
+ SmallMutableArray# s a -> Int# -> State# s -> (# State# s, a #)
+ {Read from specified index of mutable array. Result is not yet evaluated.}
+ with
+ has_side_effects = True
+ can_fail = True
+
+primop WriteSmallArrayOp "writeSmallArray#" GenPrimOp
+ SmallMutableArray# s a -> Int# -> a -> State# s -> State# s
+ {Write to specified index of mutable array.}
+ with
+ has_side_effects = True
+ can_fail = True
+
+primop SizeofSmallArrayOp "sizeofSmallArray#" GenPrimOp
+ SmallArray# a -> Int#
+ {Return the number of elements in the array.}
+
+primop SizeofSmallMutableArrayOp "sizeofSmallMutableArray#" GenPrimOp
+ SmallMutableArray# s a -> Int#
+ {Return the number of elements in the array. Note that this is deprecated
+ as it is unsafe in the presence of resize operations on the
+ same byte array.}
+ with deprecated_msg = { Use 'getSizeofSmallMutableArray#' instead }
+
+primop GetSizeofSmallMutableArrayOp "getSizeofSmallMutableArray#" GenPrimOp
+ SmallMutableArray# s a -> State# s -> (# State# s, Int# #)
+ {Return the number of elements in the array.}
+
+primop IndexSmallArrayOp "indexSmallArray#" GenPrimOp
+ SmallArray# a -> Int# -> (# a #)
+ {Read from specified index of immutable array. Result is packaged into
+ an unboxed singleton; the result itself is not yet evaluated.}
+ with
+ can_fail = True
+
+primop UnsafeFreezeSmallArrayOp "unsafeFreezeSmallArray#" GenPrimOp
+ SmallMutableArray# s a -> State# s -> (# State# s, SmallArray# a #)
+ {Make a mutable array immutable, without copying.}
+ with
+ has_side_effects = True
+
+primop UnsafeThawSmallArrayOp "unsafeThawSmallArray#" GenPrimOp
+ SmallArray# a -> State# s -> (# State# s, SmallMutableArray# s a #)
+ {Make an immutable array mutable, without copying.}
+ with
+ out_of_line = True
+ has_side_effects = True
+
+-- The code_size is only correct for the case when the copy family of
+-- primops aren't inlined. It would be nice to keep track of both.
+
+primop CopySmallArrayOp "copySmallArray#" GenPrimOp
+ SmallArray# a -> Int# -> SmallMutableArray# s a -> Int# -> Int# -> State# s -> State# s
+ {Given a source array, an offset into the source array, a
+ destination array, an offset into the destination array, and a
+ number of elements to copy, copy the elements from the source array
+ to the destination array. Both arrays must fully contain the
+ specified ranges, but this is not checked. The two arrays must not
+ be the same array in different states, but this is not checked
+ either.}
+ with
+ out_of_line = True
+ has_side_effects = True
+ can_fail = True
+
+primop CopySmallMutableArrayOp "copySmallMutableArray#" GenPrimOp
+ SmallMutableArray# s a -> Int# -> SmallMutableArray# s a -> Int# -> Int# -> State# s -> State# s
+ {Given a source array, an offset into the source array, a
+ destination array, an offset into the destination array, and a
+ number of elements to copy, copy the elements from the source array
+ to the destination array. The source and destination arrays can
+ refer to the same array. Both arrays must fully contain the
+ specified ranges, but this is not checked.
+ The regions are allowed to overlap, although this is only possible when the same
+ array is provided as both the source and the destination. }
+ with
+ out_of_line = True
+ has_side_effects = True
+ can_fail = True
+
+primop CloneSmallArrayOp "cloneSmallArray#" GenPrimOp
+ SmallArray# a -> Int# -> Int# -> SmallArray# a
+ {Given a source array, an offset into the source array, and a number
+ of elements to copy, create a new array with the elements from the
+ source array. The provided array must fully contain the specified
+ range, but this is not checked.}
+ with
+ out_of_line = True
+ has_side_effects = True
+ can_fail = True
+
+primop CloneSmallMutableArrayOp "cloneSmallMutableArray#" GenPrimOp
+ SmallMutableArray# s a -> Int# -> Int# -> State# s -> (# State# s, SmallMutableArray# s a #)
+ {Given a source array, an offset into the source array, and a number
+ of elements to copy, create a new array with the elements from the
+ source array. The provided array must fully contain the specified
+ range, but this is not checked.}
+ with
+ out_of_line = True
+ has_side_effects = True
+ can_fail = True
+
+primop FreezeSmallArrayOp "freezeSmallArray#" GenPrimOp
+ SmallMutableArray# s a -> Int# -> Int# -> State# s -> (# State# s, SmallArray# a #)
+ {Given a source array, an offset into the source array, and a number
+ of elements to copy, create a new array with the elements from the
+ source array. The provided array must fully contain the specified
+ range, but this is not checked.}
+ with
+ out_of_line = True
+ has_side_effects = True
+ can_fail = True
+
+primop ThawSmallArrayOp "thawSmallArray#" GenPrimOp
+ SmallArray# a -> Int# -> Int# -> State# s -> (# State# s, SmallMutableArray# s a #)
+ {Given a source array, an offset into the source array, and a number
+ of elements to copy, create a new array with the elements from the
+ source array. The provided array must fully contain the specified
+ range, but this is not checked.}
+ with
+ out_of_line = True
+ has_side_effects = True
+ can_fail = True
+
+primop CasSmallArrayOp "casSmallArray#" GenPrimOp
+ SmallMutableArray# s a -> Int# -> a -> a -> State# s -> (# State# s, Int#, a #)
+ {Unsafe, machine-level atomic compare and swap on an element within an array.
+ See the documentation of {\tt casArray\#}.}
+ with
+ out_of_line = True
+ has_side_effects = True
+
+------------------------------------------------------------------------
+section "Byte Arrays"
+ {Operations on {\tt ByteArray\#}. A {\tt ByteArray\#} is a just a region of
+ raw memory in the garbage-collected heap, which is not
+ scanned for pointers. It carries its own size (in bytes).
+ There are
+ three sets of operations for accessing byte array contents:
+ index for reading from immutable byte arrays, and read/write
+ for mutable byte arrays. Each set contains operations for a
+ range of useful primitive data types. Each operation takes
+ an offset measured in terms of the size of the primitive type
+ being read or written.}
+
+------------------------------------------------------------------------
+
+primtype ByteArray#
+
+primtype MutableByteArray# s
+
+primop NewByteArrayOp_Char "newByteArray#" GenPrimOp
+ Int# -> State# s -> (# State# s, MutableByteArray# s #)
+ {Create a new mutable byte array of specified size (in bytes), in
+ the specified state thread.}
+ with out_of_line = True
+ has_side_effects = True
+
+primop NewPinnedByteArrayOp_Char "newPinnedByteArray#" GenPrimOp
+ Int# -> State# s -> (# State# s, MutableByteArray# s #)
+ {Create a mutable byte array that the GC guarantees not to move.}
+ with out_of_line = True
+ has_side_effects = True
+
+primop NewAlignedPinnedByteArrayOp_Char "newAlignedPinnedByteArray#" GenPrimOp
+ Int# -> Int# -> State# s -> (# State# s, MutableByteArray# s #)
+ {Create a mutable byte array, aligned by the specified amount, that the GC guarantees not to move.}
+ with out_of_line = True
+ has_side_effects = True
+
+primop MutableByteArrayIsPinnedOp "isMutableByteArrayPinned#" GenPrimOp
+ MutableByteArray# s -> Int#
+ {Determine whether a {\tt MutableByteArray\#} is guaranteed not to move
+ during GC.}
+ with out_of_line = True
+
+primop ByteArrayIsPinnedOp "isByteArrayPinned#" GenPrimOp
+ ByteArray# -> Int#
+ {Determine whether a {\tt ByteArray\#} is guaranteed not to move during GC.}
+ with out_of_line = True
+
+primop ByteArrayContents_Char "byteArrayContents#" GenPrimOp
+ ByteArray# -> Addr#
+ {Intended for use with pinned arrays; otherwise very unsafe!}
+
+primop SameMutableByteArrayOp "sameMutableByteArray#" GenPrimOp
+ MutableByteArray# s -> MutableByteArray# s -> Int#
+
+primop ShrinkMutableByteArrayOp_Char "shrinkMutableByteArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> State# s
+ {Shrink mutable byte array to new specified size (in bytes), in
+ the specified state thread. The new size argument must be less than or
+ equal to the current size as reported by {\tt sizeofMutableByteArray\#}.}
+ with out_of_line = True
+ has_side_effects = True
+
+primop ResizeMutableByteArrayOp_Char "resizeMutableByteArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s,MutableByteArray# s #)
+ {Resize (unpinned) mutable byte array to new specified size (in bytes).
+ The returned {\tt MutableByteArray\#} is either the original
+ {\tt MutableByteArray\#} resized in-place or, if not possible, a newly
+ allocated (unpinned) {\tt MutableByteArray\#} (with the original content
+ copied over).
+
+ To avoid undefined behaviour, the original {\tt MutableByteArray\#} shall
+ not be accessed anymore after a {\tt resizeMutableByteArray\#} has been
+ performed. Moreover, no reference to the old one should be kept in order
+ to allow garbage collection of the original {\tt MutableByteArray\#} in
+ case a new {\tt MutableByteArray\#} had to be allocated.}
+ with out_of_line = True
+ has_side_effects = True
+
+primop UnsafeFreezeByteArrayOp "unsafeFreezeByteArray#" GenPrimOp
+ MutableByteArray# s -> State# s -> (# State# s, ByteArray# #)
+ {Make a mutable byte array immutable, without copying.}
+ with
+ has_side_effects = True
+
+primop SizeofByteArrayOp "sizeofByteArray#" GenPrimOp
+ ByteArray# -> Int#
+ {Return the size of the array in bytes.}
+
+primop SizeofMutableByteArrayOp "sizeofMutableByteArray#" GenPrimOp
+ MutableByteArray# s -> Int#
+ {Return the size of the array in bytes. Note that this is deprecated as it is
+ unsafe in the presence of resize operations on the same byte
+ array.}
+ with deprecated_msg = { Use 'getSizeofMutableByteArray#' instead }
+
+primop GetSizeofMutableByteArrayOp "getSizeofMutableByteArray#" GenPrimOp
+ MutableByteArray# s -> State# s -> (# State# s, Int# #)
+ {Return the number of elements in the array.}
+
+primop IndexByteArrayOp_Char "indexCharArray#" GenPrimOp
+ ByteArray# -> Int# -> Char#
+ {Read 8-bit character; offset in bytes.}
+ with can_fail = True
+
+primop IndexByteArrayOp_WideChar "indexWideCharArray#" GenPrimOp
+ ByteArray# -> Int# -> Char#
+ {Read 31-bit character; offset in 4-byte words.}
+ with can_fail = True
+
+primop IndexByteArrayOp_Int "indexIntArray#" GenPrimOp
+ ByteArray# -> Int# -> Int#
+ with can_fail = True
+
+primop IndexByteArrayOp_Word "indexWordArray#" GenPrimOp
+ ByteArray# -> Int# -> Word#
+ with can_fail = True
+
+primop IndexByteArrayOp_Addr "indexAddrArray#" GenPrimOp
+ ByteArray# -> Int# -> Addr#
+ with can_fail = True
+
+primop IndexByteArrayOp_Float "indexFloatArray#" GenPrimOp
+ ByteArray# -> Int# -> Float#
+ with can_fail = True
+
+primop IndexByteArrayOp_Double "indexDoubleArray#" GenPrimOp
+ ByteArray# -> Int# -> Double#
+ with can_fail = True
+
+primop IndexByteArrayOp_StablePtr "indexStablePtrArray#" GenPrimOp
+ ByteArray# -> Int# -> StablePtr# a
+ with can_fail = True
+
+primop IndexByteArrayOp_Int8 "indexInt8Array#" GenPrimOp
+ ByteArray# -> Int# -> Int#
+ {Read 8-bit integer; offset in bytes.}
+ with can_fail = True
+
+primop IndexByteArrayOp_Int16 "indexInt16Array#" GenPrimOp
+ ByteArray# -> Int# -> Int#
+ {Read 16-bit integer; offset in 16-bit words.}
+ with can_fail = True
+
+primop IndexByteArrayOp_Int32 "indexInt32Array#" GenPrimOp
+ ByteArray# -> Int# -> INT32
+ {Read 32-bit integer; offset in 32-bit words.}
+ with can_fail = True
+
+primop IndexByteArrayOp_Int64 "indexInt64Array#" GenPrimOp
+ ByteArray# -> Int# -> INT64
+ {Read 64-bit integer; offset in 64-bit words.}
+ with can_fail = True
+
+primop IndexByteArrayOp_Word8 "indexWord8Array#" GenPrimOp
+ ByteArray# -> Int# -> Word#
+ {Read 8-bit word; offset in bytes.}
+ with can_fail = True
+
+primop IndexByteArrayOp_Word16 "indexWord16Array#" GenPrimOp
+ ByteArray# -> Int# -> Word#
+ {Read 16-bit word; offset in 16-bit words.}
+ with can_fail = True
+
+primop IndexByteArrayOp_Word32 "indexWord32Array#" GenPrimOp
+ ByteArray# -> Int# -> WORD32
+ {Read 32-bit word; offset in 32-bit words.}
+ with can_fail = True
+
+primop IndexByteArrayOp_Word64 "indexWord64Array#" GenPrimOp
+ ByteArray# -> Int# -> WORD64
+ {Read 64-bit word; offset in 64-bit words.}
+ with can_fail = True
+
+primop IndexByteArrayOp_Word8AsChar "indexWord8ArrayAsChar#" GenPrimOp
+ ByteArray# -> Int# -> Char#
+ {Read 8-bit character; offset in bytes.}
+ with can_fail = True
+
+primop IndexByteArrayOp_Word8AsWideChar "indexWord8ArrayAsWideChar#" GenPrimOp
+ ByteArray# -> Int# -> Char#
+ {Read 31-bit character; offset in bytes.}
+ with can_fail = True
+
+primop IndexByteArrayOp_Word8AsAddr "indexWord8ArrayAsAddr#" GenPrimOp
+ ByteArray# -> Int# -> Addr#
+ {Read address; offset in bytes.}
+ with can_fail = True
+
+primop IndexByteArrayOp_Word8AsFloat "indexWord8ArrayAsFloat#" GenPrimOp
+ ByteArray# -> Int# -> Float#
+ {Read float; offset in bytes.}
+ with can_fail = True
+
+primop IndexByteArrayOp_Word8AsDouble "indexWord8ArrayAsDouble#" GenPrimOp
+ ByteArray# -> Int# -> Double#
+ {Read double; offset in bytes.}
+ with can_fail = True
+
+primop IndexByteArrayOp_Word8AsStablePtr "indexWord8ArrayAsStablePtr#" GenPrimOp
+ ByteArray# -> Int# -> StablePtr# a
+ {Read stable pointer; offset in bytes.}
+ with can_fail = True
+
+primop IndexByteArrayOp_Word8AsInt16 "indexWord8ArrayAsInt16#" GenPrimOp
+ ByteArray# -> Int# -> Int#
+ {Read 16-bit int; offset in bytes.}
+ with can_fail = True
+
+primop IndexByteArrayOp_Word8AsInt32 "indexWord8ArrayAsInt32#" GenPrimOp
+ ByteArray# -> Int# -> INT32
+ {Read 32-bit int; offset in bytes.}
+ with can_fail = True
+
+primop IndexByteArrayOp_Word8AsInt64 "indexWord8ArrayAsInt64#" GenPrimOp
+ ByteArray# -> Int# -> INT64
+ {Read 64-bit int; offset in bytes.}
+ with can_fail = True
+
+primop IndexByteArrayOp_Word8AsInt "indexWord8ArrayAsInt#" GenPrimOp
+ ByteArray# -> Int# -> Int#
+ {Read int; offset in bytes.}
+ with can_fail = True
+
+primop IndexByteArrayOp_Word8AsWord16 "indexWord8ArrayAsWord16#" GenPrimOp
+ ByteArray# -> Int# -> Word#
+ {Read 16-bit word; offset in bytes.}
+ with can_fail = True
+
+primop IndexByteArrayOp_Word8AsWord32 "indexWord8ArrayAsWord32#" GenPrimOp
+ ByteArray# -> Int# -> WORD32
+ {Read 32-bit word; offset in bytes.}
+ with can_fail = True
+
+primop IndexByteArrayOp_Word8AsWord64 "indexWord8ArrayAsWord64#" GenPrimOp
+ ByteArray# -> Int# -> WORD64
+ {Read 64-bit word; offset in bytes.}
+ with can_fail = True
+
+primop IndexByteArrayOp_Word8AsWord "indexWord8ArrayAsWord#" GenPrimOp
+ ByteArray# -> Int# -> Word#
+ {Read word; offset in bytes.}
+ with can_fail = True
+
+primop ReadByteArrayOp_Char "readCharArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, Char# #)
+ {Read 8-bit character; offset in bytes.}
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_WideChar "readWideCharArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, Char# #)
+ {Read 31-bit character; offset in 4-byte words.}
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Int "readIntArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, Int# #)
+ {Read integer; offset in machine words.}
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Word "readWordArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, Word# #)
+ {Read word; offset in machine words.}
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Addr "readAddrArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, Addr# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Float "readFloatArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, Float# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Double "readDoubleArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, Double# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_StablePtr "readStablePtrArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, StablePtr# a #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Int8 "readInt8Array#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, Int# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Int16 "readInt16Array#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, Int# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Int32 "readInt32Array#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, INT32 #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Int64 "readInt64Array#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, INT64 #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Word8 "readWord8Array#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, Word# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Word16 "readWord16Array#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, Word# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Word32 "readWord32Array#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, WORD32 #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Word64 "readWord64Array#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, WORD64 #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Word8AsChar "readWord8ArrayAsChar#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, Char# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Word8AsWideChar "readWord8ArrayAsWideChar#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, Char# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Word8AsAddr "readWord8ArrayAsAddr#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, Addr# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Word8AsFloat "readWord8ArrayAsFloat#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, Float# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Word8AsDouble "readWord8ArrayAsDouble#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, Double# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Word8AsStablePtr "readWord8ArrayAsStablePtr#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, StablePtr# a #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Word8AsInt16 "readWord8ArrayAsInt16#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, Int# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Word8AsInt32 "readWord8ArrayAsInt32#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, INT32 #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Word8AsInt64 "readWord8ArrayAsInt64#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, INT64 #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Word8AsInt "readWord8ArrayAsInt#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, Int# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Word8AsWord16 "readWord8ArrayAsWord16#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, Word# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Word8AsWord32 "readWord8ArrayAsWord32#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, WORD32 #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Word8AsWord64 "readWord8ArrayAsWord64#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, WORD64 #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadByteArrayOp_Word8AsWord "readWord8ArrayAsWord#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, Word# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Char "writeCharArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> Char# -> State# s -> State# s
+ {Write 8-bit character; offset in bytes.}
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_WideChar "writeWideCharArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> Char# -> State# s -> State# s
+ {Write 31-bit character; offset in 4-byte words.}
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Int "writeIntArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> Int# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Word "writeWordArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Addr "writeAddrArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> Addr# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Float "writeFloatArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> Float# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Double "writeDoubleArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> Double# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_StablePtr "writeStablePtrArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> StablePtr# a -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Int8 "writeInt8Array#" GenPrimOp
+ MutableByteArray# s -> Int# -> Int# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Int16 "writeInt16Array#" GenPrimOp
+ MutableByteArray# s -> Int# -> Int# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Int32 "writeInt32Array#" GenPrimOp
+ MutableByteArray# s -> Int# -> INT32 -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Int64 "writeInt64Array#" GenPrimOp
+ MutableByteArray# s -> Int# -> INT64 -> State# s -> State# s
+ with can_fail = True
+ has_side_effects = True
+
+primop WriteByteArrayOp_Word8 "writeWord8Array#" GenPrimOp
+ MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Word16 "writeWord16Array#" GenPrimOp
+ MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Word32 "writeWord32Array#" GenPrimOp
+ MutableByteArray# s -> Int# -> WORD32 -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Word64 "writeWord64Array#" GenPrimOp
+ MutableByteArray# s -> Int# -> WORD64 -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Word8AsChar "writeWord8ArrayAsChar#" GenPrimOp
+ MutableByteArray# s -> Int# -> Char# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Word8AsWideChar "writeWord8ArrayAsWideChar#" GenPrimOp
+ MutableByteArray# s -> Int# -> Char# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Word8AsAddr "writeWord8ArrayAsAddr#" GenPrimOp
+ MutableByteArray# s -> Int# -> Addr# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Word8AsFloat "writeWord8ArrayAsFloat#" GenPrimOp
+ MutableByteArray# s -> Int# -> Float# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Word8AsDouble "writeWord8ArrayAsDouble#" GenPrimOp
+ MutableByteArray# s -> Int# -> Double# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Word8AsStablePtr "writeWord8ArrayAsStablePtr#" GenPrimOp
+ MutableByteArray# s -> Int# -> StablePtr# a -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Word8AsInt16 "writeWord8ArrayAsInt16#" GenPrimOp
+ MutableByteArray# s -> Int# -> Int# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Word8AsInt32 "writeWord8ArrayAsInt32#" GenPrimOp
+ MutableByteArray# s -> Int# -> INT32 -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Word8AsInt64 "writeWord8ArrayAsInt64#" GenPrimOp
+ MutableByteArray# s -> Int# -> INT64 -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Word8AsInt "writeWord8ArrayAsInt#" GenPrimOp
+ MutableByteArray# s -> Int# -> Int# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Word8AsWord16 "writeWord8ArrayAsWord16#" GenPrimOp
+ MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Word8AsWord32 "writeWord8ArrayAsWord32#" GenPrimOp
+ MutableByteArray# s -> Int# -> WORD32 -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Word8AsWord64 "writeWord8ArrayAsWord64#" GenPrimOp
+ MutableByteArray# s -> Int# -> WORD64 -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteByteArrayOp_Word8AsWord "writeWord8ArrayAsWord#" GenPrimOp
+ MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop CompareByteArraysOp "compareByteArrays#" GenPrimOp
+ ByteArray# -> Int# -> ByteArray# -> Int# -> Int# -> Int#
+ {{\tt compareByteArrays# src1 src1_ofs src2 src2_ofs n} compares
+ {\tt n} bytes starting at offset {\tt src1_ofs} in the first
+ {\tt ByteArray#} {\tt src1} to the range of {\tt n} bytes
+ (i.e. same length) starting at offset {\tt src2_ofs} of the second
+ {\tt ByteArray#} {\tt src2}. Both arrays must fully contain the
+ specified ranges, but this is not checked. Returns an {\tt Int#}
+ less than, equal to, or greater than zero if the range is found,
+ respectively, to be byte-wise lexicographically less than, to
+ match, or be greater than the second range.}
+ with
+ can_fail = True
+
+primop CopyByteArrayOp "copyByteArray#" GenPrimOp
+ ByteArray# -> Int# -> MutableByteArray# s -> Int# -> Int# -> State# s -> State# s
+ {{\tt copyByteArray# src src_ofs dst dst_ofs n} copies the range
+ starting at offset {\tt src_ofs} of length {\tt n} from the
+ {\tt ByteArray#} {\tt src} to the {\tt MutableByteArray#} {\tt dst}
+ starting at offset {\tt dst_ofs}. Both arrays must fully contain
+ the specified ranges, but this is not checked. The two arrays must
+ not be the same array in different states, but this is not checked
+ either.}
+ with
+ has_side_effects = True
+ code_size = { primOpCodeSizeForeignCall + 4}
+ can_fail = True
+
+primop CopyMutableByteArrayOp "copyMutableByteArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> MutableByteArray# s -> Int# -> Int# -> State# s -> State# s
+ {Copy a range of the first MutableByteArray\# to the specified region in the second MutableByteArray\#.
+ Both arrays must fully contain the specified ranges, but this is not checked. The regions are
+ allowed to overlap, although this is only possible when the same array is provided
+ as both the source and the destination.}
+ with
+ has_side_effects = True
+ code_size = { primOpCodeSizeForeignCall + 4 }
+ can_fail = True
+
+primop CopyByteArrayToAddrOp "copyByteArrayToAddr#" GenPrimOp
+ ByteArray# -> Int# -> Addr# -> Int# -> State# s -> State# s
+ {Copy a range of the ByteArray\# to the memory range starting at the Addr\#.
+ The ByteArray\# and the memory region at Addr\# must fully contain the
+ specified ranges, but this is not checked. The Addr\# must not point into the
+ ByteArray\# (e.g. if the ByteArray\# were pinned), but this is not checked
+ either.}
+ with
+ has_side_effects = True
+ code_size = { primOpCodeSizeForeignCall + 4}
+ can_fail = True
+
+primop CopyMutableByteArrayToAddrOp "copyMutableByteArrayToAddr#" GenPrimOp
+ MutableByteArray# s -> Int# -> Addr# -> Int# -> State# s -> State# s
+ {Copy a range of the MutableByteArray\# to the memory range starting at the
+ Addr\#. The MutableByteArray\# and the memory region at Addr\# must fully
+ contain the specified ranges, but this is not checked. The Addr\# must not
+ point into the MutableByteArray\# (e.g. if the MutableByteArray\# were
+ pinned), but this is not checked either.}
+ with
+ has_side_effects = True
+ code_size = { primOpCodeSizeForeignCall + 4}
+ can_fail = True
+
+primop CopyAddrToByteArrayOp "copyAddrToByteArray#" GenPrimOp
+ Addr# -> MutableByteArray# s -> Int# -> Int# -> State# s -> State# s
+ {Copy a memory range starting at the Addr\# to the specified range in the
+ MutableByteArray\#. The memory region at Addr\# and the ByteArray\# must fully
+ contain the specified ranges, but this is not checked. The Addr\# must not
+ point into the MutableByteArray\# (e.g. if the MutableByteArray\# were pinned),
+ but this is not checked either.}
+ with
+ has_side_effects = True
+ code_size = { primOpCodeSizeForeignCall + 4}
+ can_fail = True
+
+primop SetByteArrayOp "setByteArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> Int# -> Int# -> State# s -> State# s
+ {{\tt setByteArray# ba off len c} sets the byte range {\tt [off, off+len]} of
+ the {\tt MutableByteArray#} to the byte {\tt c}.}
+ with
+ has_side_effects = True
+ code_size = { primOpCodeSizeForeignCall + 4 }
+ can_fail = True
+
+-- Atomic operations
+
+primop AtomicReadByteArrayOp_Int "atomicReadIntArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, Int# #)
+ {Given an array and an offset in machine words, read an element. The
+ index is assumed to be in bounds. Implies a full memory barrier.}
+ with has_side_effects = True
+ can_fail = True
+
+primop AtomicWriteByteArrayOp_Int "atomicWriteIntArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> Int# -> State# s -> State# s
+ {Given an array and an offset in machine words, write an element. The
+ index is assumed to be in bounds. Implies a full memory barrier.}
+ with has_side_effects = True
+ can_fail = True
+
+primop CasByteArrayOp_Int "casIntArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> Int# -> Int# -> State# s -> (# State# s, Int# #)
+ {Given an array, an offset in machine words, the expected old value, and
+ the new value, perform an atomic compare and swap i.e. write the new
+ value if the current value matches the provided old value. Returns
+ the value of the element before the operation. Implies a full memory
+ barrier.}
+ with has_side_effects = True
+ can_fail = True
+
+primop FetchAddByteArrayOp_Int "fetchAddIntArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> Int# -> State# s -> (# State# s, Int# #)
+ {Given an array, and offset in machine words, and a value to add,
+ atomically add the value to the element. Returns the value of the
+ element before the operation. Implies a full memory barrier.}
+ with has_side_effects = True
+ can_fail = True
+
+primop FetchSubByteArrayOp_Int "fetchSubIntArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> Int# -> State# s -> (# State# s, Int# #)
+ {Given an array, and offset in machine words, and a value to subtract,
+ atomically subtract the value to the element. Returns the value of
+ the element before the operation. Implies a full memory barrier.}
+ with has_side_effects = True
+ can_fail = True
+
+primop FetchAndByteArrayOp_Int "fetchAndIntArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> Int# -> State# s -> (# State# s, Int# #)
+ {Given an array, and offset in machine words, and a value to AND,
+ atomically AND the value to the element. Returns the value of the
+ element before the operation. Implies a full memory barrier.}
+ with has_side_effects = True
+ can_fail = True
+
+primop FetchNandByteArrayOp_Int "fetchNandIntArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> Int# -> State# s -> (# State# s, Int# #)
+ {Given an array, and offset in machine words, and a value to NAND,
+ atomically NAND the value to the element. Returns the value of the
+ element before the operation. Implies a full memory barrier.}
+ with has_side_effects = True
+ can_fail = True
+
+primop FetchOrByteArrayOp_Int "fetchOrIntArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> Int# -> State# s -> (# State# s, Int# #)
+ {Given an array, and offset in machine words, and a value to OR,
+ atomically OR the value to the element. Returns the value of the
+ element before the operation. Implies a full memory barrier.}
+ with has_side_effects = True
+ can_fail = True
+
+primop FetchXorByteArrayOp_Int "fetchXorIntArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> Int# -> State# s -> (# State# s, Int# #)
+ {Given an array, and offset in machine words, and a value to XOR,
+ atomically XOR the value to the element. Returns the value of the
+ element before the operation. Implies a full memory barrier.}
+ with has_side_effects = True
+ can_fail = True
+
+
+------------------------------------------------------------------------
+section "Arrays of arrays"
+ {Operations on {\tt ArrayArray\#}. An {\tt ArrayArray\#} contains references to {\em unpointed}
+ arrays, such as {\tt ByteArray\#s}. Hence, it is not parameterised by the element types,
+ just like a {\tt ByteArray\#}, but it needs to be scanned during GC, just like an {\tt Array\#}.
+ We represent an {\tt ArrayArray\#} exactly as a {\tt Array\#}, but provide element-type-specific
+ indexing, reading, and writing.}
+------------------------------------------------------------------------
+
+primtype ArrayArray#
+
+primtype MutableArrayArray# s
+
+primop NewArrayArrayOp "newArrayArray#" GenPrimOp
+ Int# -> State# s -> (# State# s, MutableArrayArray# s #)
+ {Create a new mutable array of arrays with the specified number of elements,
+ in the specified state thread, with each element recursively referring to the
+ newly created array.}
+ with
+ out_of_line = True
+ has_side_effects = True
+
+primop SameMutableArrayArrayOp "sameMutableArrayArray#" GenPrimOp
+ MutableArrayArray# s -> MutableArrayArray# s -> Int#
+
+primop UnsafeFreezeArrayArrayOp "unsafeFreezeArrayArray#" GenPrimOp
+ MutableArrayArray# s -> State# s -> (# State# s, ArrayArray# #)
+ {Make a mutable array of arrays immutable, without copying.}
+ with
+ has_side_effects = True
+
+primop SizeofArrayArrayOp "sizeofArrayArray#" GenPrimOp
+ ArrayArray# -> Int#
+ {Return the number of elements in the array.}
+
+primop SizeofMutableArrayArrayOp "sizeofMutableArrayArray#" GenPrimOp
+ MutableArrayArray# s -> Int#
+ {Return the number of elements in the array.}
+
+primop IndexArrayArrayOp_ByteArray "indexByteArrayArray#" GenPrimOp
+ ArrayArray# -> Int# -> ByteArray#
+ with can_fail = True
+
+primop IndexArrayArrayOp_ArrayArray "indexArrayArrayArray#" GenPrimOp
+ ArrayArray# -> Int# -> ArrayArray#
+ with can_fail = True
+
+primop ReadArrayArrayOp_ByteArray "readByteArrayArray#" GenPrimOp
+ MutableArrayArray# s -> Int# -> State# s -> (# State# s, ByteArray# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadArrayArrayOp_MutableByteArray "readMutableByteArrayArray#" GenPrimOp
+ MutableArrayArray# s -> Int# -> State# s -> (# State# s, MutableByteArray# s #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadArrayArrayOp_ArrayArray "readArrayArrayArray#" GenPrimOp
+ MutableArrayArray# s -> Int# -> State# s -> (# State# s, ArrayArray# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadArrayArrayOp_MutableArrayArray "readMutableArrayArrayArray#" GenPrimOp
+ MutableArrayArray# s -> Int# -> State# s -> (# State# s, MutableArrayArray# s #)
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteArrayArrayOp_ByteArray "writeByteArrayArray#" GenPrimOp
+ MutableArrayArray# s -> Int# -> ByteArray# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteArrayArrayOp_MutableByteArray "writeMutableByteArrayArray#" GenPrimOp
+ MutableArrayArray# s -> Int# -> MutableByteArray# s -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteArrayArrayOp_ArrayArray "writeArrayArrayArray#" GenPrimOp
+ MutableArrayArray# s -> Int# -> ArrayArray# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteArrayArrayOp_MutableArrayArray "writeMutableArrayArrayArray#" GenPrimOp
+ MutableArrayArray# s -> Int# -> MutableArrayArray# s -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop CopyArrayArrayOp "copyArrayArray#" GenPrimOp
+ ArrayArray# -> Int# -> MutableArrayArray# s -> Int# -> Int# -> State# s -> State# s
+ {Copy a range of the ArrayArray\# to the specified region in the MutableArrayArray\#.
+ Both arrays must fully contain the specified ranges, but this is not checked.
+ The two arrays must not be the same array in different states, but this is not checked either.}
+ with
+ out_of_line = True
+ has_side_effects = True
+ can_fail = True
+
+primop CopyMutableArrayArrayOp "copyMutableArrayArray#" GenPrimOp
+ MutableArrayArray# s -> Int# -> MutableArrayArray# s -> Int# -> Int# -> State# s -> State# s
+ {Copy a range of the first MutableArrayArray# to the specified region in the second
+ MutableArrayArray#.
+ Both arrays must fully contain the specified ranges, but this is not checked.
+ The regions are allowed to overlap, although this is only possible when the same
+ array is provided as both the source and the destination.
+ }
+ with
+ out_of_line = True
+ has_side_effects = True
+ can_fail = True
+
+------------------------------------------------------------------------
+section "Addr#"
+------------------------------------------------------------------------
+
+primtype Addr#
+ { An arbitrary machine address assumed to point outside
+ the garbage-collected heap. }
+
+pseudoop "nullAddr#" Addr#
+ { The null address. }
+
+primop AddrAddOp "plusAddr#" GenPrimOp Addr# -> Int# -> Addr#
+primop AddrSubOp "minusAddr#" GenPrimOp Addr# -> Addr# -> Int#
+ {Result is meaningless if two {\tt Addr\#}s are so far apart that their
+ difference doesn't fit in an {\tt Int\#}.}
+primop AddrRemOp "remAddr#" GenPrimOp Addr# -> Int# -> Int#
+ {Return the remainder when the {\tt Addr\#} arg, treated like an {\tt Int\#},
+ is divided by the {\tt Int\#} arg.}
+primop Addr2IntOp "addr2Int#" GenPrimOp Addr# -> Int#
+ {Coerce directly from address to int.}
+ with code_size = 0
+ deprecated_msg = { This operation is strongly deprecated. }
+primop Int2AddrOp "int2Addr#" GenPrimOp Int# -> Addr#
+ {Coerce directly from int to address.}
+ with code_size = 0
+ deprecated_msg = { This operation is strongly deprecated. }
+
+primop AddrGtOp "gtAddr#" Compare Addr# -> Addr# -> Int#
+primop AddrGeOp "geAddr#" Compare Addr# -> Addr# -> Int#
+primop AddrEqOp "eqAddr#" Compare Addr# -> Addr# -> Int#
+primop AddrNeOp "neAddr#" Compare Addr# -> Addr# -> Int#
+primop AddrLtOp "ltAddr#" Compare Addr# -> Addr# -> Int#
+primop AddrLeOp "leAddr#" Compare Addr# -> Addr# -> Int#
+
+primop IndexOffAddrOp_Char "indexCharOffAddr#" GenPrimOp
+ Addr# -> Int# -> Char#
+ {Reads 8-bit character; offset in bytes.}
+ with can_fail = True
+
+primop IndexOffAddrOp_WideChar "indexWideCharOffAddr#" GenPrimOp
+ Addr# -> Int# -> Char#
+ {Reads 31-bit character; offset in 4-byte words.}
+ with can_fail = True
+
+primop IndexOffAddrOp_Int "indexIntOffAddr#" GenPrimOp
+ Addr# -> Int# -> Int#
+ with can_fail = True
+
+primop IndexOffAddrOp_Word "indexWordOffAddr#" GenPrimOp
+ Addr# -> Int# -> Word#
+ with can_fail = True
+
+primop IndexOffAddrOp_Addr "indexAddrOffAddr#" GenPrimOp
+ Addr# -> Int# -> Addr#
+ with can_fail = True
+
+primop IndexOffAddrOp_Float "indexFloatOffAddr#" GenPrimOp
+ Addr# -> Int# -> Float#
+ with can_fail = True
+
+primop IndexOffAddrOp_Double "indexDoubleOffAddr#" GenPrimOp
+ Addr# -> Int# -> Double#
+ with can_fail = True
+
+primop IndexOffAddrOp_StablePtr "indexStablePtrOffAddr#" GenPrimOp
+ Addr# -> Int# -> StablePtr# a
+ with can_fail = True
+
+primop IndexOffAddrOp_Int8 "indexInt8OffAddr#" GenPrimOp
+ Addr# -> Int# -> Int#
+ with can_fail = True
+
+primop IndexOffAddrOp_Int16 "indexInt16OffAddr#" GenPrimOp
+ Addr# -> Int# -> Int#
+ with can_fail = True
+
+primop IndexOffAddrOp_Int32 "indexInt32OffAddr#" GenPrimOp
+ Addr# -> Int# -> INT32
+ with can_fail = True
+
+primop IndexOffAddrOp_Int64 "indexInt64OffAddr#" GenPrimOp
+ Addr# -> Int# -> INT64
+ with can_fail = True
+
+primop IndexOffAddrOp_Word8 "indexWord8OffAddr#" GenPrimOp
+ Addr# -> Int# -> Word#
+ with can_fail = True
+
+primop IndexOffAddrOp_Word16 "indexWord16OffAddr#" GenPrimOp
+ Addr# -> Int# -> Word#
+ with can_fail = True
+
+primop IndexOffAddrOp_Word32 "indexWord32OffAddr#" GenPrimOp
+ Addr# -> Int# -> WORD32
+ with can_fail = True
+
+primop IndexOffAddrOp_Word64 "indexWord64OffAddr#" GenPrimOp
+ Addr# -> Int# -> WORD64
+ with can_fail = True
+
+primop ReadOffAddrOp_Char "readCharOffAddr#" GenPrimOp
+ Addr# -> Int# -> State# s -> (# State# s, Char# #)
+ {Reads 8-bit character; offset in bytes.}
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadOffAddrOp_WideChar "readWideCharOffAddr#" GenPrimOp
+ Addr# -> Int# -> State# s -> (# State# s, Char# #)
+ {Reads 31-bit character; offset in 4-byte words.}
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadOffAddrOp_Int "readIntOffAddr#" GenPrimOp
+ Addr# -> Int# -> State# s -> (# State# s, Int# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadOffAddrOp_Word "readWordOffAddr#" GenPrimOp
+ Addr# -> Int# -> State# s -> (# State# s, Word# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadOffAddrOp_Addr "readAddrOffAddr#" GenPrimOp
+ Addr# -> Int# -> State# s -> (# State# s, Addr# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadOffAddrOp_Float "readFloatOffAddr#" GenPrimOp
+ Addr# -> Int# -> State# s -> (# State# s, Float# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadOffAddrOp_Double "readDoubleOffAddr#" GenPrimOp
+ Addr# -> Int# -> State# s -> (# State# s, Double# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadOffAddrOp_StablePtr "readStablePtrOffAddr#" GenPrimOp
+ Addr# -> Int# -> State# s -> (# State# s, StablePtr# a #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadOffAddrOp_Int8 "readInt8OffAddr#" GenPrimOp
+ Addr# -> Int# -> State# s -> (# State# s, Int# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadOffAddrOp_Int16 "readInt16OffAddr#" GenPrimOp
+ Addr# -> Int# -> State# s -> (# State# s, Int# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadOffAddrOp_Int32 "readInt32OffAddr#" GenPrimOp
+ Addr# -> Int# -> State# s -> (# State# s, INT32 #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadOffAddrOp_Int64 "readInt64OffAddr#" GenPrimOp
+ Addr# -> Int# -> State# s -> (# State# s, INT64 #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadOffAddrOp_Word8 "readWord8OffAddr#" GenPrimOp
+ Addr# -> Int# -> State# s -> (# State# s, Word# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadOffAddrOp_Word16 "readWord16OffAddr#" GenPrimOp
+ Addr# -> Int# -> State# s -> (# State# s, Word# #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadOffAddrOp_Word32 "readWord32OffAddr#" GenPrimOp
+ Addr# -> Int# -> State# s -> (# State# s, WORD32 #)
+ with has_side_effects = True
+ can_fail = True
+
+primop ReadOffAddrOp_Word64 "readWord64OffAddr#" GenPrimOp
+ Addr# -> Int# -> State# s -> (# State# s, WORD64 #)
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteOffAddrOp_Char "writeCharOffAddr#" GenPrimOp
+ Addr# -> Int# -> Char# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteOffAddrOp_WideChar "writeWideCharOffAddr#" GenPrimOp
+ Addr# -> Int# -> Char# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteOffAddrOp_Int "writeIntOffAddr#" GenPrimOp
+ Addr# -> Int# -> Int# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteOffAddrOp_Word "writeWordOffAddr#" GenPrimOp
+ Addr# -> Int# -> Word# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteOffAddrOp_Addr "writeAddrOffAddr#" GenPrimOp
+ Addr# -> Int# -> Addr# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteOffAddrOp_Float "writeFloatOffAddr#" GenPrimOp
+ Addr# -> Int# -> Float# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteOffAddrOp_Double "writeDoubleOffAddr#" GenPrimOp
+ Addr# -> Int# -> Double# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteOffAddrOp_StablePtr "writeStablePtrOffAddr#" GenPrimOp
+ Addr# -> Int# -> StablePtr# a -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteOffAddrOp_Int8 "writeInt8OffAddr#" GenPrimOp
+ Addr# -> Int# -> Int# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteOffAddrOp_Int16 "writeInt16OffAddr#" GenPrimOp
+ Addr# -> Int# -> Int# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteOffAddrOp_Int32 "writeInt32OffAddr#" GenPrimOp
+ Addr# -> Int# -> INT32 -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteOffAddrOp_Int64 "writeInt64OffAddr#" GenPrimOp
+ Addr# -> Int# -> INT64 -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteOffAddrOp_Word8 "writeWord8OffAddr#" GenPrimOp
+ Addr# -> Int# -> Word# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteOffAddrOp_Word16 "writeWord16OffAddr#" GenPrimOp
+ Addr# -> Int# -> Word# -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteOffAddrOp_Word32 "writeWord32OffAddr#" GenPrimOp
+ Addr# -> Int# -> WORD32 -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+primop WriteOffAddrOp_Word64 "writeWord64OffAddr#" GenPrimOp
+ Addr# -> Int# -> WORD64 -> State# s -> State# s
+ with has_side_effects = True
+ can_fail = True
+
+------------------------------------------------------------------------
+section "Mutable variables"
+ {Operations on MutVar\#s.}
+------------------------------------------------------------------------
+
+primtype MutVar# s a
+ {A {\tt MutVar\#} behaves like a single-element mutable array.}
+
+primop NewMutVarOp "newMutVar#" GenPrimOp
+ a -> State# s -> (# State# s, MutVar# s a #)
+ {Create {\tt MutVar\#} with specified initial value in specified state thread.}
+ with
+ out_of_line = True
+ has_side_effects = True
+
+-- Note [Why MutVar# ops can't fail]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--
+-- We don't label readMutVar# or writeMutVar# as can_fail.
+-- This may seem a bit peculiar, because they surely *could*
+-- fail spectacularly if passed a pointer to unallocated memory.
+-- But MutVar#s are always correct by construction; we never
+-- test if a pointer is valid before using it with these operations.
+-- So we never have to worry about floating the pointer reference
+-- outside a validity test. At the moment, has_side_effects blocks
+-- up the relevant optimizations anyway, but we hope to draw finer
+-- distinctions soon, which should improve matters for readMutVar#
+-- at least.
+
+primop ReadMutVarOp "readMutVar#" GenPrimOp
+ MutVar# s a -> State# s -> (# State# s, a #)
+ {Read contents of {\tt MutVar\#}. Result is not yet evaluated.}
+ with
+ -- See Note [Why MutVar# ops can't fail]
+ has_side_effects = True
+
+primop WriteMutVarOp "writeMutVar#" GenPrimOp
+ MutVar# s a -> a -> State# s -> State# s
+ {Write contents of {\tt MutVar\#}.}
+ with
+ -- See Note [Why MutVar# ops can't fail]
+ has_side_effects = True
+ code_size = { primOpCodeSizeForeignCall } -- for the write barrier
+
+primop SameMutVarOp "sameMutVar#" GenPrimOp
+ MutVar# s a -> MutVar# s a -> Int#
+
+-- Note [Why not an unboxed tuple in atomicModifyMutVar2#?]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--
+-- Looking at the type of atomicModifyMutVar2#, one might wonder why
+-- it doesn't return an unboxed tuple. e.g.,
+--
+-- MutVar# s a -> (a -> (# a, b #)) -> State# s -> (# State# s, a, (# a, b #) #)
+--
+-- The reason is that atomicModifyMutVar2# relies on laziness for its atomicity.
+-- Given a MutVar# containing x, atomicModifyMutVar2# merely replaces
+-- its contents with a thunk of the form (fst (f x)). This can be done using an
+-- atomic compare-and-swap as it is merely replacing a pointer.
+
+primop AtomicModifyMutVar2Op "atomicModifyMutVar2#" GenPrimOp
+ MutVar# s a -> (a -> c) -> State# s -> (# State# s, a, c #)
+ { Modify the contents of a {\tt MutVar\#}, returning the previous
+ contents and the result of applying the given function to the
+ previous contents. Note that this isn't strictly
+ speaking the correct type for this function; it should really be
+ {\tt MutVar\# s a -> (a -> (a,b)) -> State\# s -> (\# State\# s, a, (a, b) \#)},
+ but we don't know about pairs here. }
+ with
+ out_of_line = True
+ has_side_effects = True
+ can_fail = True
+
+primop AtomicModifyMutVar_Op "atomicModifyMutVar_#" GenPrimOp
+ MutVar# s a -> (a -> a) -> State# s -> (# State# s, a, a #)
+ { Modify the contents of a {\tt MutVar\#}, returning the previous
+ contents and the result of applying the given function to the
+ previous contents. }
+ with
+ out_of_line = True
+ has_side_effects = True
+ can_fail = True
+
+primop CasMutVarOp "casMutVar#" GenPrimOp
+ MutVar# s a -> a -> a -> State# s -> (# State# s, Int#, a #)
+ with
+ out_of_line = True
+ has_side_effects = True
+
+------------------------------------------------------------------------
+section "Exceptions"
+------------------------------------------------------------------------
+
+-- Note [Strictness for mask/unmask/catch]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-- Consider this example, which comes from GHC.IO.Handle.Internals:
+-- wantReadableHandle3 f ma b st
+-- = case ... of
+-- DEFAULT -> case ma of MVar a -> ...
+-- 0# -> maskAsynchExceptions# (\st -> case ma of MVar a -> ...)
+-- The outer case just decides whether to mask exceptions, but we don't want
+-- thereby to hide the strictness in 'ma'! Hence the use of strictApply1Dmd.
+
+primop CatchOp "catch#" GenPrimOp
+ (State# RealWorld -> (# State# RealWorld, a #) )
+ -> (b -> State# RealWorld -> (# State# RealWorld, a #) )
+ -> State# RealWorld
+ -> (# State# RealWorld, a #)
+ with
+ strictness = { \ _arity -> mkClosedStrictSig [ lazyApply1Dmd
+ , lazyApply2Dmd
+ , topDmd] topDiv }
+ -- See Note [Strictness for mask/unmask/catch]
+ out_of_line = True
+ has_side_effects = True
+
+primop RaiseOp "raise#" GenPrimOp
+ b -> o
+ -- NB: the type variable "o" is "a", but with OpenKind
+ with
+ strictness = { \ _arity -> mkClosedStrictSig [topDmd] botDiv }
+ out_of_line = True
+ has_side_effects = True
+ -- raise# certainly throws a Haskell exception and hence has_side_effects
+ -- It doesn't actually make much difference because the fact that it
+ -- returns bottom independently ensures that we are careful not to discard
+ -- it. But still, it's better to say the Right Thing.
+
+-- Note [Arithmetic exception primops]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--
+-- The RTS provides several primops to raise specific exceptions (raiseDivZero#,
+-- raiseUnderflow#, raiseOverflow#). These primops are meant to be used by the
+-- package implementing arbitrary precision numbers (Natural,Integer). It can't
+-- depend on `base` package to raise exceptions in a normal way because it would
+-- create a package dependency circle (base <-> bignum package).
+--
+-- See #14664
+
+primtype Void#
+
+primop RaiseDivZeroOp "raiseDivZero#" GenPrimOp
+ Void# -> o
+ {Raise a 'DivideByZero' arithmetic exception.}
+ -- NB: the type variable "o" is "a", but with OpenKind
+ -- See Note [Arithmetic exception primops]
+ with
+ strictness = { \ _arity -> mkClosedStrictSig [topDmd] botDiv }
+ out_of_line = True
+ has_side_effects = True
+
+primop RaiseUnderflowOp "raiseUnderflow#" GenPrimOp
+ Void# -> o
+ {Raise an 'Underflow' arithmetic exception.}
+ -- NB: the type variable "o" is "a", but with OpenKind
+ -- See Note [Arithmetic exception primops]
+ with
+ strictness = { \ _arity -> mkClosedStrictSig [topDmd] botDiv }
+ out_of_line = True
+ has_side_effects = True
+
+primop RaiseOverflowOp "raiseOverflow#" GenPrimOp
+ Void# -> o
+ {Raise an 'Overflow' arithmetic exception.}
+ -- NB: the type variable "o" is "a", but with OpenKind
+ -- See Note [Arithmetic exception primops]
+ with
+ strictness = { \ _arity -> mkClosedStrictSig [topDmd] botDiv }
+ out_of_line = True
+ has_side_effects = True
+
+primop RaiseIOOp "raiseIO#" GenPrimOp
+ a -> State# RealWorld -> (# State# RealWorld, b #)
+ with
+ -- See Note [Precise exceptions and strictness analysis] in Demand.hs
+ -- for why we give it topDiv
+ -- strictness = { \ _arity -> mkClosedStrictSig [topDmd, topDmd] topDiv }
+ out_of_line = True
+ has_side_effects = True
+
+primop MaskAsyncExceptionsOp "maskAsyncExceptions#" GenPrimOp
+ (State# RealWorld -> (# State# RealWorld, a #))
+ -> (State# RealWorld -> (# State# RealWorld, a #))
+ with
+ strictness = { \ _arity -> mkClosedStrictSig [strictApply1Dmd,topDmd] topDiv }
+ -- See Note [Strictness for mask/unmask/catch]
+ out_of_line = True
+ has_side_effects = True
+
+primop MaskUninterruptibleOp "maskUninterruptible#" GenPrimOp
+ (State# RealWorld -> (# State# RealWorld, a #))
+ -> (State# RealWorld -> (# State# RealWorld, a #))
+ with
+ strictness = { \ _arity -> mkClosedStrictSig [strictApply1Dmd,topDmd] topDiv }
+ out_of_line = True
+ has_side_effects = True
+
+primop UnmaskAsyncExceptionsOp "unmaskAsyncExceptions#" GenPrimOp
+ (State# RealWorld -> (# State# RealWorld, a #))
+ -> (State# RealWorld -> (# State# RealWorld, a #))
+ with
+ strictness = { \ _arity -> mkClosedStrictSig [strictApply1Dmd,topDmd] topDiv }
+ -- See Note [Strictness for mask/unmask/catch]
+ out_of_line = True
+ has_side_effects = True
+
+primop MaskStatus "getMaskingState#" GenPrimOp
+ State# RealWorld -> (# State# RealWorld, Int# #)
+ with
+ out_of_line = True
+ has_side_effects = True
+
+------------------------------------------------------------------------
+section "STM-accessible Mutable Variables"
+------------------------------------------------------------------------
+
+primtype TVar# s a
+
+primop AtomicallyOp "atomically#" GenPrimOp
+ (State# RealWorld -> (# State# RealWorld, a #) )
+ -> State# RealWorld -> (# State# RealWorld, a #)
+ with
+ strictness = { \ _arity -> mkClosedStrictSig [strictApply1Dmd,topDmd] topDiv }
+ -- See Note [Strictness for mask/unmask/catch]
+ out_of_line = True
+ has_side_effects = True
+
+-- NB: retry#'s strictness information specifies it to diverge.
+-- This lets the compiler perform some extra simplifications, since retry#
+-- will technically never return.
+--
+-- This allows the simplifier to replace things like:
+-- case retry# s1
+-- (# s2, a #) -> e
+-- with:
+-- retry# s1
+-- where 'e' would be unreachable anyway. See #8091.
+primop RetryOp "retry#" GenPrimOp
+ State# RealWorld -> (# State# RealWorld, a #)
+ with
+ strictness = { \ _arity -> mkClosedStrictSig [topDmd] botDiv }
+ out_of_line = True
+ has_side_effects = True
+
+primop CatchRetryOp "catchRetry#" GenPrimOp
+ (State# RealWorld -> (# State# RealWorld, a #) )
+ -> (State# RealWorld -> (# State# RealWorld, a #) )
+ -> (State# RealWorld -> (# State# RealWorld, a #) )
+ with
+ strictness = { \ _arity -> mkClosedStrictSig [ lazyApply1Dmd
+ , lazyApply1Dmd
+ , topDmd ] topDiv }
+ -- See Note [Strictness for mask/unmask/catch]
+ out_of_line = True
+ has_side_effects = True
+
+primop CatchSTMOp "catchSTM#" GenPrimOp
+ (State# RealWorld -> (# State# RealWorld, a #) )
+ -> (b -> State# RealWorld -> (# State# RealWorld, a #) )
+ -> (State# RealWorld -> (# State# RealWorld, a #) )
+ with
+ strictness = { \ _arity -> mkClosedStrictSig [ lazyApply1Dmd
+ , lazyApply2Dmd
+ , topDmd ] topDiv }
+ -- See Note [Strictness for mask/unmask/catch]
+ out_of_line = True
+ has_side_effects = True
+
+primop NewTVarOp "newTVar#" GenPrimOp
+ a
+ -> State# s -> (# State# s, TVar# s a #)
+ {Create a new {\tt TVar\#} holding a specified initial value.}
+ with
+ out_of_line = True
+ has_side_effects = True
+
+primop ReadTVarOp "readTVar#" GenPrimOp
+ TVar# s a
+ -> State# s -> (# State# s, a #)
+ {Read contents of {\tt TVar\#}. Result is not yet evaluated.}
+ with
+ out_of_line = True
+ has_side_effects = True
+
+primop ReadTVarIOOp "readTVarIO#" GenPrimOp
+ TVar# s a
+ -> State# s -> (# State# s, a #)
+ {Read contents of {\tt TVar\#} outside an STM transaction}
+ with
+ out_of_line = True
+ has_side_effects = True
+
+primop WriteTVarOp "writeTVar#" GenPrimOp
+ TVar# s a
+ -> a
+ -> State# s -> State# s
+ {Write contents of {\tt TVar\#}.}
+ with
+ out_of_line = True
+ has_side_effects = True
+
+primop SameTVarOp "sameTVar#" GenPrimOp
+ TVar# s a -> TVar# s a -> Int#
+
+
+------------------------------------------------------------------------
+section "Synchronized Mutable Variables"
+ {Operations on {\tt MVar\#}s. }
+------------------------------------------------------------------------
+
+primtype MVar# s a
+ { A shared mutable variable ({\it not} the same as a {\tt MutVar\#}!).
+ (Note: in a non-concurrent implementation, {\tt (MVar\# a)} can be
+ represented by {\tt (MutVar\# (Maybe a))}.) }
+
+primop NewMVarOp "newMVar#" GenPrimOp
+ State# s -> (# State# s, MVar# s a #)
+ {Create new {\tt MVar\#}; initially empty.}
+ with
+ out_of_line = True
+ has_side_effects = True
+
+primop TakeMVarOp "takeMVar#" GenPrimOp
+ MVar# s a -> State# s -> (# State# s, a #)
+ {If {\tt MVar\#} is empty, block until it becomes full.
+ Then remove and return its contents, and set it empty.}
+ with
+ out_of_line = True
+ has_side_effects = True
+
+primop TryTakeMVarOp "tryTakeMVar#" GenPrimOp
+ MVar# s a -> State# s -> (# State# s, Int#, a #)
+ {If {\tt MVar\#} is empty, immediately return with integer 0 and value undefined.
+ Otherwise, return with integer 1 and contents of {\tt MVar\#}, and set {\tt MVar\#} empty.}
+ with
+ out_of_line = True
+ has_side_effects = True
+
+primop PutMVarOp "putMVar#" GenPrimOp
+ MVar# s a -> a -> State# s -> State# s
+ {If {\tt MVar\#} is full, block until it becomes empty.
+ Then store value arg as its new contents.}
+ with
+ out_of_line = True
+ has_side_effects = True
+
+primop TryPutMVarOp "tryPutMVar#" GenPrimOp
+ MVar# s a -> a -> State# s -> (# State# s, Int# #)
+ {If {\tt MVar\#} is full, immediately return with integer 0.
+ Otherwise, store value arg as {\tt MVar\#}'s new contents, and return with integer 1.}
+ with
+ out_of_line = True
+ has_side_effects = True
+
+primop ReadMVarOp "readMVar#" GenPrimOp
+ MVar# s a -> State# s -> (# State# s, a #)
+ {If {\tt MVar\#} is empty, block until it becomes full.
+ Then read its contents without modifying the MVar, without possibility
+ of intervention from other threads.}
+ with
+ out_of_line = True
+ has_side_effects = True
+
+primop TryReadMVarOp "tryReadMVar#" GenPrimOp
+ MVar# s a -> State# s -> (# State# s, Int#, a #)
+ {If {\tt MVar\#} is empty, immediately return with integer 0 and value undefined.
+ Otherwise, return with integer 1 and contents of {\tt MVar\#}.}
+ with
+ out_of_line = True
+ has_side_effects = True
+
+primop SameMVarOp "sameMVar#" GenPrimOp
+ MVar# s a -> MVar# s a -> Int#
+
+primop IsEmptyMVarOp "isEmptyMVar#" GenPrimOp
+ MVar# s a -> State# s -> (# State# s, Int# #)
+ {Return 1 if {\tt MVar\#} is empty; 0 otherwise.}
+ with
+ out_of_line = True
+ has_side_effects = True
+
+------------------------------------------------------------------------
+section "Delay/wait operations"
+------------------------------------------------------------------------
+
+primop DelayOp "delay#" GenPrimOp
+ Int# -> State# s -> State# s
+ {Sleep specified number of microseconds.}
+ with
+ has_side_effects = True
+ out_of_line = True
+
+primop WaitReadOp "waitRead#" GenPrimOp
+ Int# -> State# s -> State# s
+ {Block until input is available on specified file descriptor.}
+ with
+ has_side_effects = True
+ out_of_line = True
+
+primop WaitWriteOp "waitWrite#" GenPrimOp
+ Int# -> State# s -> State# s
+ {Block until output is possible on specified file descriptor.}
+ with
+ has_side_effects = True
+ out_of_line = True
+
+------------------------------------------------------------------------
+section "Concurrency primitives"
+------------------------------------------------------------------------
+
+primtype State# s
+ { {\tt State\#} is the primitive, unlifted type of states. It has
+ one type parameter, thus {\tt State\# RealWorld}, or {\tt State\# s},
+ where s is a type variable. The only purpose of the type parameter
+ is to keep different state threads separate. It is represented by
+ nothing at all. }
+
+primtype RealWorld
+ { {\tt RealWorld} is deeply magical. It is {\it primitive}, but it is not
+ {\it unlifted} (hence {\tt ptrArg}). We never manipulate values of type
+ {\tt RealWorld}; it's only used in the type system, to parameterise {\tt State\#}. }
+
+primtype ThreadId#
+ {(In a non-concurrent implementation, this can be a singleton
+ type, whose (unique) value is returned by {\tt myThreadId\#}. The
+ other operations can be omitted.)}
+
+primop ForkOp "fork#" GenPrimOp
+ a -> State# RealWorld -> (# State# RealWorld, ThreadId# #)
+ with
+ has_side_effects = True
+ out_of_line = True
+
+primop ForkOnOp "forkOn#" GenPrimOp
+ Int# -> a -> State# RealWorld -> (# State# RealWorld, ThreadId# #)
+ with
+ has_side_effects = True
+ out_of_line = True
+
+primop KillThreadOp "killThread#" GenPrimOp
+ ThreadId# -> a -> State# RealWorld -> State# RealWorld
+ with
+ has_side_effects = True
+ out_of_line = True
+
+primop YieldOp "yield#" GenPrimOp
+ State# RealWorld -> State# RealWorld
+ with
+ has_side_effects = True
+ out_of_line = True
+
+primop MyThreadIdOp "myThreadId#" GenPrimOp
+ State# RealWorld -> (# State# RealWorld, ThreadId# #)
+ with
+ has_side_effects = True
+
+primop LabelThreadOp "labelThread#" GenPrimOp
+ ThreadId# -> Addr# -> State# RealWorld -> State# RealWorld
+ with
+ has_side_effects = True
+ out_of_line = True
+
+primop IsCurrentThreadBoundOp "isCurrentThreadBound#" GenPrimOp
+ State# RealWorld -> (# State# RealWorld, Int# #)
+ with
+ out_of_line = True
+ has_side_effects = True
+
+primop NoDuplicateOp "noDuplicate#" GenPrimOp
+ State# s -> State# s
+ with
+ out_of_line = True
+ has_side_effects = True
+
+primop ThreadStatusOp "threadStatus#" GenPrimOp
+ ThreadId# -> State# RealWorld -> (# State# RealWorld, Int#, Int#, Int# #)
+ with
+ out_of_line = True
+ has_side_effects = True
+
+------------------------------------------------------------------------
+section "Weak pointers"
+------------------------------------------------------------------------
+
+primtype Weak# b
+
+-- note that tyvar "o" denotes openAlphaTyVar
+
+primop MkWeakOp "mkWeak#" GenPrimOp
+ o -> b -> (State# RealWorld -> (# State# RealWorld, c #))
+ -> State# RealWorld -> (# State# RealWorld, Weak# b #)
+ { {\tt mkWeak# k v finalizer s} creates a weak reference to value {\tt k},
+ with an associated reference to some value {\tt v}. If {\tt k} is still
+ alive then {\tt v} can be retrieved using {\tt deRefWeak#}. Note that
+ the type of {\tt k} must be represented by a pointer (i.e. of kind {\tt
+ TYPE 'LiftedRep} or {\tt TYPE 'UnliftedRep}). }
+ with
+ has_side_effects = True
+ out_of_line = True
+
+primop MkWeakNoFinalizerOp "mkWeakNoFinalizer#" GenPrimOp
+ o -> b -> State# RealWorld -> (# State# RealWorld, Weak# b #)
+ with
+ has_side_effects = True
+ out_of_line = True
+
+primop AddCFinalizerToWeakOp "addCFinalizerToWeak#" GenPrimOp
+ Addr# -> Addr# -> Int# -> Addr# -> Weak# b
+ -> State# RealWorld -> (# State# RealWorld, Int# #)
+ { {\tt addCFinalizerToWeak# fptr ptr flag eptr w} attaches a C
+ function pointer {\tt fptr} to a weak pointer {\tt w} as a finalizer. If
+ {\tt flag} is zero, {\tt fptr} will be called with one argument,
+ {\tt ptr}. Otherwise, it will be called with two arguments,
+ {\tt eptr} and {\tt ptr}. {\tt addCFinalizerToWeak#} returns
+ 1 on success, or 0 if {\tt w} is already dead. }
+ with
+ has_side_effects = True
+ out_of_line = True
+
+primop DeRefWeakOp "deRefWeak#" GenPrimOp
+ Weak# a -> State# RealWorld -> (# State# RealWorld, Int#, a #)
+ with
+ has_side_effects = True
+ out_of_line = True
+
+primop FinalizeWeakOp "finalizeWeak#" GenPrimOp
+ Weak# a -> State# RealWorld -> (# State# RealWorld, Int#,
+ (State# RealWorld -> (# State# RealWorld, b #) ) #)
+ { Finalize a weak pointer. The return value is an unboxed tuple
+ containing the new state of the world and an "unboxed Maybe",
+ represented by an {\tt Int#} and a (possibly invalid) finalization
+ action. An {\tt Int#} of {\tt 1} indicates that the finalizer is valid. The
+ return value {\tt b} from the finalizer should be ignored. }
+ with
+ has_side_effects = True
+ out_of_line = True
+
+primop TouchOp "touch#" GenPrimOp
+ o -> State# RealWorld -> State# RealWorld
+ with
+ code_size = { 0 }
+ has_side_effects = True
+
+------------------------------------------------------------------------
+section "Stable pointers and names"
+------------------------------------------------------------------------
+
+primtype StablePtr# a
+
+primtype StableName# a
+
+primop MakeStablePtrOp "makeStablePtr#" GenPrimOp
+ a -> State# RealWorld -> (# State# RealWorld, StablePtr# a #)
+ with
+ has_side_effects = True
+ out_of_line = True
+
+primop DeRefStablePtrOp "deRefStablePtr#" GenPrimOp
+ StablePtr# a -> State# RealWorld -> (# State# RealWorld, a #)
+ with
+ has_side_effects = True
+ out_of_line = True
+
+primop EqStablePtrOp "eqStablePtr#" GenPrimOp
+ StablePtr# a -> StablePtr# a -> Int#
+ with
+ has_side_effects = True
+
+primop MakeStableNameOp "makeStableName#" GenPrimOp
+ a -> State# RealWorld -> (# State# RealWorld, StableName# a #)
+ with
+ has_side_effects = True
+ out_of_line = True
+
+primop EqStableNameOp "eqStableName#" GenPrimOp
+ StableName# a -> StableName# b -> Int#
+
+primop StableNameToIntOp "stableNameToInt#" GenPrimOp
+ StableName# a -> Int#
+
+------------------------------------------------------------------------
+section "Compact normal form"
+
+ {Primitives for working with compact regions. The {\tt ghc\-compact}
+ library and the {\tt compact} library demonstrate how to use these
+ primitives. The documentation below draws a distinction between
+ a CNF and a compact block. A CNF contains one or more compact
+ blocks. The source file {\tt rts\/sm\/CNF.c}
+ diagrams this relationship. When discussing a compact
+ block, an additional distinction is drawn between capacity and
+ utilized bytes. The capacity is the maximum number of bytes that
+ the compact block can hold. The utilized bytes is the number of
+ bytes that are actually used by the compact block.
+ }
+
+------------------------------------------------------------------------
+
+primtype Compact#
+
+primop CompactNewOp "compactNew#" GenPrimOp
+ Word# -> State# RealWorld -> (# State# RealWorld, Compact# #)
+ { Create a new CNF with a single compact block. The argument is
+ the capacity of the compact block (in bytes, not words).
+ The capacity is rounded up to a multiple of the allocator block size
+ and is capped to one mega block. }
+ with
+ has_side_effects = True
+ out_of_line = True
+
+primop CompactResizeOp "compactResize#" GenPrimOp
+ Compact# -> Word# -> State# RealWorld ->
+ State# RealWorld
+ { Set the new allocation size of the CNF. This value (in bytes)
+ determines the capacity of each compact block in the CNF. It
+ does not retroactively affect existing compact blocks in the CNF. }
+ with
+ has_side_effects = True
+ out_of_line = True
+
+primop CompactContainsOp "compactContains#" GenPrimOp
+ Compact# -> a -> State# RealWorld -> (# State# RealWorld, Int# #)
+ { Returns 1\# if the object is contained in the CNF, 0\# otherwise. }
+ with
+ out_of_line = True
+
+primop CompactContainsAnyOp "compactContainsAny#" GenPrimOp
+ a -> State# RealWorld -> (# State# RealWorld, Int# #)
+ { Returns 1\# if the object is in any CNF at all, 0\# otherwise. }
+ with
+ out_of_line = True
+
+primop CompactGetFirstBlockOp "compactGetFirstBlock#" GenPrimOp
+ Compact# -> State# RealWorld -> (# State# RealWorld, Addr#, Word# #)
+ { Returns the address and the utilized size (in bytes) of the
+ first compact block of a CNF.}
+ with
+ out_of_line = True
+
+primop CompactGetNextBlockOp "compactGetNextBlock#" GenPrimOp
+ Compact# -> Addr# -> State# RealWorld -> (# State# RealWorld, Addr#, Word# #)
+ { Given a CNF and the address of one its compact blocks, returns the
+ next compact block and its utilized size, or {\tt nullAddr\#} if the
+ argument was the last compact block in the CNF. }
+ with
+ out_of_line = True
+
+primop CompactAllocateBlockOp "compactAllocateBlock#" GenPrimOp
+ Word# -> Addr# -> State# RealWorld -> (# State# RealWorld, Addr# #)
+ { Attempt to allocate a compact block with the capacity (in
+ bytes) given by the first argument. The {\texttt Addr\#} is a pointer
+ to previous compact block of the CNF or {\texttt nullAddr\#} to create a
+ new CNF with a single compact block.
+
+ The resulting block is not known to the GC until
+ {\texttt compactFixupPointers\#} is called on it, and care must be taken
+ so that the address does not escape or memory will be leaked.
+ }
+ with
+ has_side_effects = True
+ out_of_line = True
+
+primop CompactFixupPointersOp "compactFixupPointers#" GenPrimOp
+ Addr# -> Addr# -> State# RealWorld -> (# State# RealWorld, Compact#, Addr# #)
+ { Given the pointer to the first block of a CNF and the
+ address of the root object in the old address space, fix up
+ the internal pointers inside the CNF to account for
+ a different position in memory than when it was serialized.
+ This method must be called exactly once after importing
+ a serialized CNF. It returns the new CNF and the new adjusted
+ root address. }
+ with
+ has_side_effects = True
+ out_of_line = True
+
+primop CompactAdd "compactAdd#" GenPrimOp
+ Compact# -> a -> State# RealWorld -> (# State# RealWorld, a #)
+ { Recursively add a closure and its transitive closure to a
+ {\texttt Compact\#} (a CNF), evaluating any unevaluated components
+ at the same time. Note: {\texttt compactAdd\#} is not thread-safe, so
+ only one thread may call {\texttt compactAdd\#} with a particular
+ {\texttt Compact\#} at any given time. The primop does not
+ enforce any mutual exclusion; the caller is expected to
+ arrange this. }
+ with
+ has_side_effects = True
+ out_of_line = True
+
+primop CompactAddWithSharing "compactAddWithSharing#" GenPrimOp
+ Compact# -> a -> State# RealWorld -> (# State# RealWorld, a #)
+ { Like {\texttt compactAdd\#}, but retains sharing and cycles
+ during compaction. }
+ with
+ has_side_effects = True
+ out_of_line = True
+
+primop CompactSize "compactSize#" GenPrimOp
+ Compact# -> State# RealWorld -> (# State# RealWorld, Word# #)
+ { Return the total capacity (in bytes) of all the compact blocks
+ in the CNF. }
+ with
+ has_side_effects = True
+ out_of_line = True
+
+------------------------------------------------------------------------
+section "Unsafe pointer equality"
+-- (#1 Bad Guy: Alastair Reid :)
+------------------------------------------------------------------------
+
+primop ReallyUnsafePtrEqualityOp "reallyUnsafePtrEquality#" GenPrimOp
+ a -> a -> Int#
+ { Returns {\texttt 1\#} if the given pointers are equal and {\texttt 0\#} otherwise. }
+ with
+ can_fail = True -- See Note [reallyUnsafePtrEquality#]
+
+
+-- Note [reallyUnsafePtrEquality#]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--
+-- reallyUnsafePtrEquality# can't actually fail, per se, but we mark it can_fail
+-- anyway. Until 5a9a1738023a, GHC considered primops okay for speculation only
+-- when their arguments were known to be forced. This was unnecessarily
+-- conservative, but it prevented reallyUnsafePtrEquality# from floating out of
+-- places where its arguments were known to be forced. Unfortunately, GHC could
+-- sometimes lose track of whether those arguments were forced, leading to let/app
+-- invariant failures (see #13027 and the discussion in #11444). Now that
+-- ok_for_speculation skips over lifted arguments, we need to explicitly prevent
+-- reallyUnsafePtrEquality# from floating out. Imagine if we had
+--
+-- \x y . case x of x'
+-- DEFAULT ->
+-- case y of y'
+-- DEFAULT ->
+-- let eq = reallyUnsafePtrEquality# x' y'
+-- in ...
+--
+-- If the let floats out, we'll get
+--
+-- \x y . let eq = reallyUnsafePtrEquality# x y
+-- in case x of ...
+--
+-- The trouble is that pointer equality between thunks is very different
+-- from pointer equality between the values those thunks reduce to, and the latter
+-- is typically much more precise.
+
+------------------------------------------------------------------------
+section "Parallelism"
+------------------------------------------------------------------------
+
+primop ParOp "par#" GenPrimOp
+ a -> Int#
+ with
+ -- Note that Par is lazy to avoid that the sparked thing
+ -- gets evaluated strictly, which it should *not* be
+ has_side_effects = True
+ code_size = { primOpCodeSizeForeignCall }
+ deprecated_msg = { Use 'spark#' instead }
+
+primop SparkOp "spark#" GenPrimOp
+ a -> State# s -> (# State# s, a #)
+ with has_side_effects = True
+ code_size = { primOpCodeSizeForeignCall }
+
+primop SeqOp "seq#" GenPrimOp
+ a -> State# s -> (# State# s, a #)
+ -- See Note [seq# magic] in GHC.Core.Op.ConstantFold
+
+primop GetSparkOp "getSpark#" GenPrimOp
+ State# s -> (# State# s, Int#, a #)
+ with
+ has_side_effects = True
+ out_of_line = True
+
+primop NumSparks "numSparks#" GenPrimOp
+ State# s -> (# State# s, Int# #)
+ { Returns the number of sparks in the local spark pool. }
+ with
+ has_side_effects = True
+ out_of_line = True
+
+------------------------------------------------------------------------
+section "Tag to enum stuff"
+ {Convert back and forth between values of enumerated types
+ and small integers.}
+------------------------------------------------------------------------
+
+primop DataToTagOp "dataToTag#" GenPrimOp
+ a -> Int# -- Zero-indexed; the first constructor has tag zero
+ with
+ strictness = { \ _arity -> mkClosedStrictSig [evalDmd] topDiv }
+ -- See Note [dataToTag# magic] in GHC.Core.Op.ConstantFold
+
+primop TagToEnumOp "tagToEnum#" GenPrimOp
+ Int# -> a
+
+------------------------------------------------------------------------
+section "Bytecode operations"
+ {Support for manipulating bytecode objects used by the interpreter and
+ linker.
+
+ Bytecode objects are heap objects which represent top-level bindings and
+ contain a list of instructions and data needed by these instructions.}
+------------------------------------------------------------------------
+
+primtype BCO
+ { Primitive bytecode type. }
+
+primop AddrToAnyOp "addrToAny#" GenPrimOp
+ Addr# -> (# a #)
+ { Convert an {\tt Addr\#} to a followable Any type. }
+ with
+ code_size = 0
+
+primop AnyToAddrOp "anyToAddr#" GenPrimOp
+ a -> State# RealWorld -> (# State# RealWorld, Addr# #)
+ { Retrieve the address of any Haskell value. This is
+ essentially an {\texttt unsafeCoerce\#}, but if implemented as such
+ the core lint pass complains and fails to compile.
+ As a primop, it is opaque to core/stg, and only appears
+ in cmm (where the copy propagation pass will get rid of it).
+ Note that "a" must be a value, not a thunk! It's too late
+ for strictness analysis to enforce this, so you're on your
+ own to guarantee this. Also note that {\texttt Addr\#} is not a GC
+ pointer - up to you to guarantee that it does not become
+ a dangling pointer immediately after you get it.}
+ with
+ code_size = 0
+
+primop MkApUpd0_Op "mkApUpd0#" GenPrimOp
+ BCO -> (# a #)
+ { Wrap a BCO in a {\tt AP_UPD} thunk which will be updated with the value of
+ the BCO when evaluated. }
+ with
+ out_of_line = True
+
+primop NewBCOOp "newBCO#" GenPrimOp
+ ByteArray# -> ByteArray# -> Array# a -> Int# -> ByteArray# -> State# s -> (# State# s, BCO #)
+ { {\tt newBCO\# instrs lits ptrs arity bitmap} creates a new bytecode object. The
+ resulting object encodes a function of the given arity with the instructions
+ encoded in {\tt instrs}, and a static reference table usage bitmap given by
+ {\tt bitmap}. }
+ with
+ has_side_effects = True
+ out_of_line = True
+
+primop UnpackClosureOp "unpackClosure#" GenPrimOp
+ a -> (# Addr#, ByteArray#, Array# b #)
+ { {\tt unpackClosure\# closure} copies the closure and pointers in the
+ payload of the given closure into two new arrays, and returns a pointer to
+ the first word of the closure's info table, a non-pointer array for the raw
+ bytes of the closure, and a pointer array for the pointers in the payload. }
+ with
+ out_of_line = True
+
+primop ClosureSizeOp "closureSize#" GenPrimOp
+ a -> Int#
+ { {\tt closureSize\# closure} returns the size of the given closure in
+ machine words. }
+ with
+ out_of_line = True
+
+primop GetApStackValOp "getApStackVal#" GenPrimOp
+ a -> Int# -> (# Int#, b #)
+ with
+ out_of_line = True
+
+------------------------------------------------------------------------
+section "Misc"
+ {These aren't nearly as wired in as Etc...}
+------------------------------------------------------------------------
+
+primop GetCCSOfOp "getCCSOf#" GenPrimOp
+ a -> State# s -> (# State# s, Addr# #)
+
+primop GetCurrentCCSOp "getCurrentCCS#" GenPrimOp
+ a -> State# s -> (# State# s, Addr# #)
+ { Returns the current {\tt CostCentreStack} (value is {\tt NULL} if
+ not profiling). Takes a dummy argument which can be used to
+ avoid the call to {\tt getCurrentCCS\#} being floated out by the
+ simplifier, which would result in an uninformative stack
+ ("CAF"). }
+
+primop ClearCCSOp "clearCCS#" GenPrimOp
+ (State# s -> (# State# s, a #)) -> State# s -> (# State# s, a #)
+ { Run the supplied IO action with an empty CCS. For example, this
+ is used by the interpreter to run an interpreted computation
+ without the call stack showing that it was invoked from GHC. }
+ with
+ out_of_line = True
+
+------------------------------------------------------------------------
+section "Etc"
+ {Miscellaneous built-ins}
+------------------------------------------------------------------------
+
+primtype Proxy# a
+ { The type constructor {\tt Proxy#} is used to bear witness to some
+ type variable. It's used when you want to pass around proxy values
+ for doing things like modelling type applications. A {\tt Proxy#}
+ is not only unboxed, it also has a polymorphic kind, and has no
+ runtime representation, being totally free. }
+
+pseudoop "proxy#"
+ Proxy# a
+ { Witness for an unboxed {\tt Proxy#} value, which has no runtime
+ representation. }
+
+pseudoop "seq"
+ a -> b -> b
+ { The value of {\tt seq a b} is bottom if {\tt a} is bottom, and
+ otherwise equal to {\tt b}. In other words, it evaluates the first
+ argument {\tt a} to weak head normal form (WHNF). {\tt seq} is usually
+ introduced to improve performance by avoiding unneeded laziness.
+
+ A note on evaluation order: the expression {\tt seq a b} does
+ {\it not} guarantee that {\tt a} will be evaluated before {\tt b}.
+ The only guarantee given by {\tt seq} is that the both {\tt a}
+ and {\tt b} will be evaluated before {\tt seq} returns a value.
+ In particular, this means that {\tt b} may be evaluated before
+ {\tt a}. If you need to guarantee a specific order of evaluation,
+ you must use the function {\tt pseq} from the "parallel" package. }
+ with fixity = infixr 0
+ -- This fixity is only the one picked up by Haddock. If you
+ -- change this, do update 'ghcPrimIface' in 'GHC.Iface.Load'.
+
+pseudoop "unsafeCoerce#"
+ a -> b
+ { The function {\tt unsafeCoerce\#} allows you to side-step the typechecker entirely. That
+ is, it allows you to coerce any type into any other type. If you use this function,
+ you had better get it right, otherwise segmentation faults await. It is generally
+ used when you want to write a program that you know is well-typed, but where Haskell's
+ type system is not expressive enough to prove that it is well typed.
+
+ The following uses of {\tt unsafeCoerce\#} are supposed to work (i.e. not lead to
+ spurious compile-time or run-time crashes):
+
+ * Casting any lifted type to {\tt Any}
+
+ * Casting {\tt Any} back to the real type
+
+ * Casting an unboxed type to another unboxed type of the same size.
+ (Casting between floating-point and integral types does not work.
+ See the {\tt GHC.Float} module for functions to do work.)
+
+ * Casting between two types that have the same runtime representation. One case is when
+ the two types differ only in "phantom" type parameters, for example
+ {\tt Ptr Int} to {\tt Ptr Float}, or {\tt [Int]} to {\tt [Float]} when the list is
+ known to be empty. Also, a {\tt newtype} of a type {\tt T} has the same representation
+ at runtime as {\tt T}.
+
+ Other uses of {\tt unsafeCoerce\#} are undefined. In particular, you should not use
+ {\tt unsafeCoerce\#} to cast a T to an algebraic data type D, unless T is also
+ an algebraic data type. For example, do not cast {\tt Int->Int} to {\tt Bool}, even if
+ you later cast that {\tt Bool} back to {\tt Int->Int} before applying it. The reasons
+ have to do with GHC's internal representation details (for the cognoscenti, data values
+ can be entered but function closures cannot). If you want a safe type to cast things
+ to, use {\tt Any}, which is not an algebraic data type.
+
+ }
+ with can_fail = True
+
+-- NB. It is tempting to think that casting a value to a type that it doesn't have is safe
+-- as long as you don't "do anything" with the value in its cast form, such as seq on it. This
+-- isn't the case: the compiler can insert seqs itself, and if these happen at the wrong type,
+-- Bad Things Might Happen. See bug #1616: in this case we cast a function of type (a,b) -> (a,b)
+-- to () -> () and back again. The strictness analyser saw that the function was strict, but
+-- the wrapper had type () -> (), and hence the wrapper de-constructed the (), the worker re-constructed
+-- a new (), with the result that the code ended up with "case () of (a,b) -> ...".
+
+primop TraceEventOp "traceEvent#" GenPrimOp
+ Addr# -> State# s -> State# s
+ { Emits an event via the RTS tracing framework. The contents
+ of the event is the zero-terminated byte string passed as the first
+ argument. The event will be emitted either to the {\tt .eventlog} file,
+ or to stderr, depending on the runtime RTS flags. }
+ with
+ has_side_effects = True
+ out_of_line = True
+
+primop TraceEventBinaryOp "traceBinaryEvent#" GenPrimOp
+ Addr# -> Int# -> State# s -> State# s
+ { Emits an event via the RTS tracing framework. The contents
+ of the event is the binary object passed as the first argument with
+ the the given length passed as the second argument. The event will be
+ emitted to the {\tt .eventlog} file. }
+ with
+ has_side_effects = True
+ out_of_line = True
+
+primop TraceMarkerOp "traceMarker#" GenPrimOp
+ Addr# -> State# s -> State# s
+ { Emits a marker event via the RTS tracing framework. The contents
+ of the event is the zero-terminated byte string passed as the first
+ argument. The event will be emitted either to the {\tt .eventlog} file,
+ or to stderr, depending on the runtime RTS flags. }
+ with
+ has_side_effects = True
+ out_of_line = True
+
+primop SetThreadAllocationCounter "setThreadAllocationCounter#" GenPrimOp
+ INT64 -> State# RealWorld -> State# RealWorld
+ { Sets the allocation counter for the current thread to the given value. }
+ with
+ has_side_effects = True
+ out_of_line = True
+
+------------------------------------------------------------------------
+section "Safe coercions"
+------------------------------------------------------------------------
+
+pseudoop "coerce"
+ Coercible a b => a -> b
+ { The function {\tt coerce} allows you to safely convert between values of
+ types that have the same representation with no run-time overhead. In the
+ simplest case you can use it instead of a newtype constructor, to go from
+ the newtype's concrete type to the abstract type. But it also works in
+ more complicated settings, e.g. converting a list of newtypes to a list of
+ concrete types.
+
+ This function is runtime-representation polymorphic, but the
+ {\tt RuntimeRep} type argument is marked as {\tt Inferred}, meaning
+ that it is not available for visible type application. This means
+ the typechecker will accept {\tt coerce @Int @Age 42}.
+ }
+
+------------------------------------------------------------------------
+section "SIMD Vectors"
+ {Operations on SIMD vectors.}
+------------------------------------------------------------------------
+
+#define ALL_VECTOR_TYPES \
+ [<Int8,Int#,16>,<Int16,Int#,8>,<Int32,INT32,4>,<Int64,INT64,2> \
+ ,<Int8,Int#,32>,<Int16,Int#,16>,<Int32,INT32,8>,<Int64,INT64,4> \
+ ,<Int8,Int#,64>,<Int16,Int#,32>,<Int32,INT32,16>,<Int64,INT64,8> \
+ ,<Word8,Word#,16>,<Word16,Word#,8>,<Word32,WORD32,4>,<Word64,WORD64,2> \
+ ,<Word8,Word#,32>,<Word16,Word#,16>,<Word32,WORD32,8>,<Word64,WORD64,4> \
+ ,<Word8,Word#,64>,<Word16,Word#,32>,<Word32,WORD32,16>,<Word64,WORD64,8> \
+ ,<Float,Float#,4>,<Double,Double#,2> \
+ ,<Float,Float#,8>,<Double,Double#,4> \
+ ,<Float,Float#,16>,<Double,Double#,8>]
+
+#define SIGNED_VECTOR_TYPES \
+ [<Int8,Int#,16>,<Int16,Int#,8>,<Int32,INT32,4>,<Int64,INT64,2> \
+ ,<Int8,Int#,32>,<Int16,Int#,16>,<Int32,INT32,8>,<Int64,INT64,4> \
+ ,<Int8,Int#,64>,<Int16,Int#,32>,<Int32,INT32,16>,<Int64,INT64,8> \
+ ,<Float,Float#,4>,<Double,Double#,2> \
+ ,<Float,Float#,8>,<Double,Double#,4> \
+ ,<Float,Float#,16>,<Double,Double#,8>]
+
+#define FLOAT_VECTOR_TYPES \
+ [<Float,Float#,4>,<Double,Double#,2> \
+ ,<Float,Float#,8>,<Double,Double#,4> \
+ ,<Float,Float#,16>,<Double,Double#,8>]
+
+#define INT_VECTOR_TYPES \
+ [<Int8,Int#,16>,<Int16,Int#,8>,<Int32,INT32,4>,<Int64,INT64,2> \
+ ,<Int8,Int#,32>,<Int16,Int#,16>,<Int32,INT32,8>,<Int64,INT64,4> \
+ ,<Int8,Int#,64>,<Int16,Int#,32>,<Int32,INT32,16>,<Int64,INT64,8> \
+ ,<Word8,Word#,16>,<Word16,Word#,8>,<Word32,WORD32,4>,<Word64,WORD64,2> \
+ ,<Word8,Word#,32>,<Word16,Word#,16>,<Word32,WORD32,8>,<Word64,WORD64,4> \
+ ,<Word8,Word#,64>,<Word16,Word#,32>,<Word32,WORD32,16>,<Word64,WORD64,8>]
+
+primtype VECTOR
+ with llvm_only = True
+ vector = ALL_VECTOR_TYPES
+
+primop VecBroadcastOp "broadcast#" GenPrimOp
+ SCALAR -> VECTOR
+ { Broadcast a scalar to all elements of a vector. }
+ with llvm_only = True
+ vector = ALL_VECTOR_TYPES
+
+primop VecPackOp "pack#" GenPrimOp
+ VECTUPLE -> VECTOR
+ { Pack the elements of an unboxed tuple into a vector. }
+ with llvm_only = True
+ vector = ALL_VECTOR_TYPES
+
+primop VecUnpackOp "unpack#" GenPrimOp
+ VECTOR -> VECTUPLE
+ { Unpack the elements of a vector into an unboxed tuple. #}
+ with llvm_only = True
+ vector = ALL_VECTOR_TYPES
+
+primop VecInsertOp "insert#" GenPrimOp
+ VECTOR -> SCALAR -> Int# -> VECTOR
+ { Insert a scalar at the given position in a vector. }
+ with can_fail = True
+ llvm_only = True
+ vector = ALL_VECTOR_TYPES
+
+primop VecAddOp "plus#" Dyadic
+ VECTOR -> VECTOR -> VECTOR
+ { Add two vectors element-wise. }
+ with commutable = True
+ llvm_only = True
+ vector = ALL_VECTOR_TYPES
+
+primop VecSubOp "minus#" Dyadic
+ VECTOR -> VECTOR -> VECTOR
+ { Subtract two vectors element-wise. }
+ with llvm_only = True
+ vector = ALL_VECTOR_TYPES
+
+primop VecMulOp "times#" Dyadic
+ VECTOR -> VECTOR -> VECTOR
+ { Multiply two vectors element-wise. }
+ with commutable = True
+ llvm_only = True
+ vector = ALL_VECTOR_TYPES
+
+primop VecDivOp "divide#" Dyadic
+ VECTOR -> VECTOR -> VECTOR
+ { Divide two vectors element-wise. }
+ with can_fail = True
+ llvm_only = True
+ vector = FLOAT_VECTOR_TYPES
+
+primop VecQuotOp "quot#" Dyadic
+ VECTOR -> VECTOR -> VECTOR
+ { Rounds towards zero element-wise. }
+ with can_fail = True
+ llvm_only = True
+ vector = INT_VECTOR_TYPES
+
+primop VecRemOp "rem#" Dyadic
+ VECTOR -> VECTOR -> VECTOR
+ { Satisfies \texttt{(quot\# x y) times\# y plus\# (rem\# x y) == x}. }
+ with can_fail = True
+ llvm_only = True
+ vector = INT_VECTOR_TYPES
+
+primop VecNegOp "negate#" Monadic
+ VECTOR -> VECTOR
+ { Negate element-wise. }
+ with llvm_only = True
+ vector = SIGNED_VECTOR_TYPES
+
+primop VecIndexByteArrayOp "indexArray#" GenPrimOp
+ ByteArray# -> Int# -> VECTOR
+ { Read a vector from specified index of immutable array. }
+ with can_fail = True
+ llvm_only = True
+ vector = ALL_VECTOR_TYPES
+
+primop VecReadByteArrayOp "readArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, VECTOR #)
+ { Read a vector from specified index of mutable array. }
+ with has_side_effects = True
+ can_fail = True
+ llvm_only = True
+ vector = ALL_VECTOR_TYPES
+
+primop VecWriteByteArrayOp "writeArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> VECTOR -> State# s -> State# s
+ { Write a vector to specified index of mutable array. }
+ with has_side_effects = True
+ can_fail = True
+ llvm_only = True
+ vector = ALL_VECTOR_TYPES
+
+primop VecIndexOffAddrOp "indexOffAddr#" GenPrimOp
+ Addr# -> Int# -> VECTOR
+ { Reads vector; offset in bytes. }
+ with can_fail = True
+ llvm_only = True
+ vector = ALL_VECTOR_TYPES
+
+primop VecReadOffAddrOp "readOffAddr#" GenPrimOp
+ Addr# -> Int# -> State# s -> (# State# s, VECTOR #)
+ { Reads vector; offset in bytes. }
+ with has_side_effects = True
+ can_fail = True
+ llvm_only = True
+ vector = ALL_VECTOR_TYPES
+
+primop VecWriteOffAddrOp "writeOffAddr#" GenPrimOp
+ Addr# -> Int# -> VECTOR -> State# s -> State# s
+ { Write vector; offset in bytes. }
+ with has_side_effects = True
+ can_fail = True
+ llvm_only = True
+ vector = ALL_VECTOR_TYPES
+
+
+primop VecIndexScalarByteArrayOp "indexArrayAs#" GenPrimOp
+ ByteArray# -> Int# -> VECTOR
+ { Read a vector from specified index of immutable array of scalars; offset is in scalar elements. }
+ with can_fail = True
+ llvm_only = True
+ vector = ALL_VECTOR_TYPES
+
+primop VecReadScalarByteArrayOp "readArrayAs#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> (# State# s, VECTOR #)
+ { Read a vector from specified index of mutable array of scalars; offset is in scalar elements. }
+ with has_side_effects = True
+ can_fail = True
+ llvm_only = True
+ vector = ALL_VECTOR_TYPES
+
+primop VecWriteScalarByteArrayOp "writeArrayAs#" GenPrimOp
+ MutableByteArray# s -> Int# -> VECTOR -> State# s -> State# s
+ { Write a vector to specified index of mutable array of scalars; offset is in scalar elements. }
+ with has_side_effects = True
+ can_fail = True
+ llvm_only = True
+ vector = ALL_VECTOR_TYPES
+
+primop VecIndexScalarOffAddrOp "indexOffAddrAs#" GenPrimOp
+ Addr# -> Int# -> VECTOR
+ { Reads vector; offset in scalar elements. }
+ with can_fail = True
+ llvm_only = True
+ vector = ALL_VECTOR_TYPES
+
+primop VecReadScalarOffAddrOp "readOffAddrAs#" GenPrimOp
+ Addr# -> Int# -> State# s -> (# State# s, VECTOR #)
+ { Reads vector; offset in scalar elements. }
+ with has_side_effects = True
+ can_fail = True
+ llvm_only = True
+ vector = ALL_VECTOR_TYPES
+
+primop VecWriteScalarOffAddrOp "writeOffAddrAs#" GenPrimOp
+ Addr# -> Int# -> VECTOR -> State# s -> State# s
+ { Write vector; offset in scalar elements. }
+ with has_side_effects = True
+ can_fail = True
+ llvm_only = True
+ vector = ALL_VECTOR_TYPES
+
+------------------------------------------------------------------------
+
+section "Prefetch"
+ {Prefetch operations: Note how every prefetch operation has a name
+ with the pattern prefetch*N#, where N is either 0,1,2, or 3.
+
+ This suffix number, N, is the "locality level" of the prefetch, following the
+ convention in GCC and other compilers.
+ Higher locality numbers correspond to the memory being loaded in more
+ levels of the cpu cache, and being retained after initial use. The naming
+ convention follows the naming convention of the prefetch intrinsic found
+ in the GCC and Clang C compilers.
+
+ On the LLVM backend, prefetch*N# uses the LLVM prefetch intrinsic
+ with locality level N. The code generated by LLVM is target architecture
+ dependent, but should agree with the GHC NCG on x86 systems.
+
+ On the Sparc and PPC native backends, prefetch*N is a No-Op.
+
+ On the x86 NCG, N=0 will generate prefetchNTA,
+ N=1 generates prefetcht2, N=2 generates prefetcht1, and
+ N=3 generates prefetcht0.
+
+ For streaming workloads, the prefetch*0 operations are recommended.
+ For workloads which do many reads or writes to a memory location in a short period of time,
+ prefetch*3 operations are recommended.
+
+ For further reading about prefetch and associated systems performance optimization,
+ the instruction set and optimization manuals by Intel and other CPU vendors are
+ excellent starting place.
+
+
+ The "Intel 64 and IA-32 Architectures Optimization Reference Manual" is
+ especially a helpful read, even if your software is meant for other CPU
+ architectures or vendor hardware. The manual can be found at
+ http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-optimization-manual.html .
+
+ The {\tt prefetch*} family of operations has the order of operations
+ determined by passing around the {\tt State#} token.
+
+ To get a "pure" version of these operations, use {\tt inlinePerformIO} which is quite safe in this context.
+
+ It is important to note that while the prefetch operations will never change the
+ answer to a pure computation, They CAN change the memory locations resident
+ in a CPU cache and that may change the performance and timing characteristics
+ of an application. The prefetch operations are marked has_side_effects=True
+ to reflect that these operations have side effects with respect to the runtime
+ performance characteristics of the resulting code. Additionally, if the prefetchValue
+ operations did not have this attribute, GHC does a float out transformation that
+ results in a let/app violation, at least with the current design.
+ }
+
+
+
+------------------------------------------------------------------------
+
+
+--- the Int# argument for prefetch is the byte offset on the byteArray or Addr#
+
+---
+primop PrefetchByteArrayOp3 "prefetchByteArray3#" GenPrimOp
+ ByteArray# -> Int# -> State# s -> State# s
+ with has_side_effects = True
+
+primop PrefetchMutableByteArrayOp3 "prefetchMutableByteArray3#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> State# s
+ with has_side_effects = True
+
+primop PrefetchAddrOp3 "prefetchAddr3#" GenPrimOp
+ Addr# -> Int# -> State# s -> State# s
+ with has_side_effects = True
+
+primop PrefetchValueOp3 "prefetchValue3#" GenPrimOp
+ a -> State# s -> State# s
+ with strictness = { \ _arity -> mkClosedStrictSig [botDmd, topDmd] topDiv }
+ has_side_effects = True
+----
+
+primop PrefetchByteArrayOp2 "prefetchByteArray2#" GenPrimOp
+ ByteArray# -> Int# -> State# s -> State# s
+ with has_side_effects = True
+
+primop PrefetchMutableByteArrayOp2 "prefetchMutableByteArray2#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> State# s
+ with has_side_effects = True
+
+primop PrefetchAddrOp2 "prefetchAddr2#" GenPrimOp
+ Addr# -> Int# -> State# s -> State# s
+ with has_side_effects = True
+
+primop PrefetchValueOp2 "prefetchValue2#" GenPrimOp
+ a -> State# s -> State# s
+ with strictness = { \ _arity -> mkClosedStrictSig [botDmd, topDmd] topDiv }
+ has_side_effects = True
+----
+
+primop PrefetchByteArrayOp1 "prefetchByteArray1#" GenPrimOp
+ ByteArray# -> Int# -> State# s -> State# s
+ with has_side_effects = True
+
+primop PrefetchMutableByteArrayOp1 "prefetchMutableByteArray1#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> State# s
+ with has_side_effects = True
+
+primop PrefetchAddrOp1 "prefetchAddr1#" GenPrimOp
+ Addr# -> Int# -> State# s -> State# s
+ with has_side_effects = True
+
+primop PrefetchValueOp1 "prefetchValue1#" GenPrimOp
+ a -> State# s -> State# s
+ with strictness = { \ _arity -> mkClosedStrictSig [botDmd, topDmd] topDiv }
+ has_side_effects = True
+----
+
+primop PrefetchByteArrayOp0 "prefetchByteArray0#" GenPrimOp
+ ByteArray# -> Int# -> State# s -> State# s
+ with has_side_effects = True
+
+primop PrefetchMutableByteArrayOp0 "prefetchMutableByteArray0#" GenPrimOp
+ MutableByteArray# s -> Int# -> State# s -> State# s
+ with has_side_effects = True
+
+primop PrefetchAddrOp0 "prefetchAddr0#" GenPrimOp
+ Addr# -> Int# -> State# s -> State# s
+ with has_side_effects = True
+
+primop PrefetchValueOp0 "prefetchValue0#" GenPrimOp
+ a -> State# s -> State# s
+ with strictness = { \ _arity -> mkClosedStrictSig [botDmd, topDmd] topDiv }
+ has_side_effects = True
+
+------------------------------------------------------------------------
+--- ---
+------------------------------------------------------------------------
+
+thats_all_folks