-----------------------------------------------------------------------
--- $Id: primops.txt.pp,v 1.6 2001/09/11 09:02:43 simonpj Exp $
+-- $Id: primops.txt.pp,v 1.35 2005/03/07 15:16:41 simonmar Exp $
--
-- Primitive Operations
--
--
-- To add a new primop, you currently need to update the following files:
--
--- - this file (ghc/compiler/prelude/primops.txt), which includes
+-- - this file (ghc/compiler/prelude/primops.txt.pp), which includes
-- the type of the primop, and various other properties (its
-- strictness attributes, whether it is defined as a macro
-- or as out-of-line code, etc.)
--
--- - ghc/lib/std/PrelGHC.hi-boot, to declare the primop
---
-- - if the primop is inline (i.e. a macro), then:
--- ghc/includes/PrimOps.h
--- ghc/compiler/nativeGen/StixPrim.lhs
--- ghc/compiler/nativeGen/MachCode.lhs (if implementation is machine-dependent)
+-- ghc/compiler/AbsCUtils.lhs (dscCOpStmt)
+-- defines the translation of the primop into simpler
+-- abstract C operations.
--
-- - or, for an out-of-line primop:
-- ghc/includes/PrimOps.h (just add the declaration)
-- ghc/rts/PrimOps.hc (define it here)
+-- ghc/rts/Linker.c (declare the symbol for GHCi)
--
-- - the User's Guide
--
--- This file is divided into named sections, each containing or more primop entries.
--- Section headers have the format:
+-- 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.
+-- 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" type category {description} attributes
--- The description is optional.
-
-- 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
commutable = False
needs_wrapper = False
can_fail = False
- strictness = { \ arity -> StrictnessInfo (replicate arity wwPrim) False }
+ strictness = { \ arity -> mkStrictSig (mkTopDmdType (replicate arity lazyDmd) TopRes) }
usage = { nomangle other }
--- Currently, documentation is produced using latex, so contents of description fields
--- should be legal latex. Descriptions can contain matched pairs of embedded curly brackets.
+-- 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"
+-- We need platform defines (tests for mingw32 below). However, we only
+-- test the TARGET platform, which doesn't vary between stages, so the
+-- stage1 platform defines are fine:
+#include "../stage1/ghc_boot_platform.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\_LONG},
- 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, e.g., 31 bits, to allow the possibility
- of using tag bits. Currently GHC itself has only 32-bit and 64-bit variants,
- but 30 or 31-bit code can be exported as an external core file for use in
- other back ends.
-
- GHC also implements a primitive unsigned integer type {\tt Word\#} which always
- has the same number of bits as {\tt Int\#}.
+ {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, e.g., 31 bits, to allow the
+ possibility of using tag bits. Currently GHC itself has only
+ 32-bit and 64-bit variants, but 30 or 31-bit code can be
+ exported as an external core file for use in other back ends.
+
+ 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
- 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 ByteArr\# -> Int\# -> Int\#}; otherwise it has type
- {\tt ByteArr\# -> 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, namely \texttt{lib/std/PrelStorable.lhs},
- \texttt{hslibs/lang/ArrayBase.hs}, and (in deprecated fashion) in \texttt{hslibs/lang/ForeignObj.lhs}
- and \texttt{hslibs/lang/Addr.lhs}.
-
- 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.
-}
+ 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 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 ByteArr\# -> Int\#
+ -> Int\#}; otherwise it has type {\tt ByteArr\# -> 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, namely
+ \texttt{lib/std/PrelStorable.lhs},
+ \texttt{hslibs/lang/ArrayBase.hs}, and (in deprecated
+ fashion) in \texttt{hslibs/lang/ForeignObj.lhs} and
+ \texttt{hslibs/lang/Addr.lhs}.
+
+ 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.
primop IntMulOp "*#"
Dyadic Int# -> Int# -> Int#
+ {Low word of signed integer multiply.}
+ with commutable = True
+
+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 recommmended 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
+ (*) :: Integer -> Integer -> Integer will be poor.
+ }
with commutable = True
primop IntQuotOp "quotInt#" Dyadic
with can_fail = True
primop IntGcdOp "gcdInt#" Dyadic Int# -> Int# -> Int#
+ with out_of_line = True
+
primop IntNegOp "negateInt#" Monadic Int# -> Int#
primop IntAddCOp "addIntC#" GenPrimOp Int# -> Int# -> (# Int#, Int# #)
- {Add with carry. First member of result is (wrapped) sum; second member is 0 iff no overflow occured.}
+ {Add with carry. First member of result is (wrapped) sum;
+ second member is 0 iff no overflow occured.}
primop IntSubCOp "subIntC#" GenPrimOp Int# -> Int# -> (# Int#, Int# #)
- {Subtract with carry. First member of result is (wrapped) difference; second member is 0 iff no overflow occured.}
-primop IntMulCOp "mulIntC#" GenPrimOp Int# -> Int# -> (# Int#, Int# #)
- {Multiply with carry. First member of result is (wrapped) product; second member is 0 iff no overflow occured.}
+ {Subtract with carry. First member of result is (wrapped) difference;
+ second member is 0 iff no overflow occured.}
+
primop IntGtOp ">#" Compare Int# -> Int# -> Bool
primop IntGeOp ">=#" Compare Int# -> Int# -> Bool
GenPrimOp Int# -> (# Int#, ByteArr# #)
with out_of_line = True
-primop ISllOp "iShiftL#" GenPrimOp Int# -> Int# -> Int#
- {Shift left. Return 0 if shifted by more than size of an Int\#.}
-primop ISraOp "iShiftRA#" GenPrimOp Int# -> Int# -> Int#
- {Shift right arithemetic. Return 0 if shifted by more than size of an Int\#.}
-primop ISrlOp "iShiftRL#" GenPrimOp Int# -> Int# -> Int#
- {Shift right logical. Return 0 if shifted by more than size of an Int\#.}
+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#"
primop NotOp "not#" Monadic Word# -> Word#
-primop SllOp "shiftL#" GenPrimOp Word# -> Int# -> Word#
- {Shift left logical. Return 0 if shifted by more than number of bits in a Word\#.}
-primop SrlOp "shiftRL#" GenPrimOp Word# -> Int# -> Word#
- {Shift right logical. Return 0 if shifted by more than number of bits in a 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#
implemented via the GMP package. An integer is represented as a pair
consisting of an Int\# representing the number of 'limbs' in use and
the sign, and a ByteArr\# containing the 'limbs' themselves. Such pairs
-are returned as unboxed pairs, but must be passed as separate components.}
+are returned as unboxed pairs, but must be passed as separate
+components.
+
+For .NET these operations are implemented by foreign imports, so the
+primops are omitted.}
------------------------------------------------------------------------
+#ifndef ILX
+
primop IntegerAddOp "plusInteger#" GenPrimOp
Int# -> ByteArr# -> Int# -> ByteArr# -> (# Int#, ByteArr# #)
with commutable = True
primop IntegerIntGcdOp "gcdIntegerInt#" GenPrimOp
Int# -> ByteArr# -> Int# -> Int#
{Greatest common divisor, where second argument is an ordinary Int\#.}
- -- with commutable = True (surely not? APT 8/01)
+ with out_of_line = True
primop IntegerDivExactOp "divExactInteger#" GenPrimOp
Int# -> ByteArr# -> Int# -> ByteArr# -> (# Int#, ByteArr# #)
Int# -> ByteArr# -> Int# -> ByteArr# -> Int#
{Returns -1,0,1 according as first argument is less than, equal to, or greater than second argument.}
with needs_wrapper = True
+ out_of_line = True
primop IntegerCmpIntOp "cmpIntegerInt#" GenPrimOp
Int# -> ByteArr# -> Int# -> Int#
{Returns -1,0,1 according as first argument is less than, equal to, or greater than second argument, which
is an ordinary Int\#.}
with needs_wrapper = True
+ out_of_line = True
primop IntegerQuotRemOp "quotRemInteger#" GenPrimOp
Int# -> ByteArr# -> Int# -> ByteArr# -> (# Int#, ByteArr#, Int#, ByteArr# #)
primop Integer2IntOp "integer2Int#" GenPrimOp
Int# -> ByteArr# -> Int#
with needs_wrapper = True
+ out_of_line = True
primop Integer2WordOp "integer2Word#" GenPrimOp
Int# -> ByteArr# -> Word#
with needs_wrapper = True
+ out_of_line = True
#if WORD_SIZE_IN_BITS < 32
primop IntegerToInt32Op "integerToInt32#" GenPrimOp
Int# -> ByteArr# -> Word32#
#endif
-#if WORD_SIZE_IN_BITS < 64
-primop IntegerToInt64Op "integerToInt64#" GenPrimOp
- Int# -> ByteArr# -> Int64#
-
-primop IntegerToWord64Op "integerToWord64#" GenPrimOp
- Int# -> ByteArr# -> Word64#
-#endif
-
primop IntegerAndOp "andInteger#" GenPrimOp
Int# -> ByteArr# -> Int# -> ByteArr# -> (# Int#, ByteArr# #)
with out_of_line = True
Int# -> ByteArr# -> (# Int#, ByteArr# #)
with out_of_line = True
+#endif /* ndef ILX */
------------------------------------------------------------------------
section "Double#"
in the specified state thread,
with each element containing the specified initial value.}
with
- strictness = { \ arity -> StrictnessInfo [wwPrim, wwLazy, wwPrim] False }
usage = { mangle NewArrayOp [mkP, mkM, mkP] mkM }
out_of_line = True
{Write to specified index of mutable array.}
with
usage = { mangle WriteArrayOp [mkM, mkP, mkM, mkP] mkR }
- strictness = { \ arity -> StrictnessInfo [wwPrim, wwPrim, wwLazy, wwPrim] False }
has_side_effects = True
primop IndexArrayOp "indexArray#" GenPrimOp
------------------------------------------------------------------------
section "Addr#"
{Addr\# is an arbitrary machine address assumed to point outside
- the garbage-collected heap.}
+ the garbage-collected heap.
+
+ NB: {\tt nullAddr\#::Addr\#} is not a primop, but is defined in MkId.lhs.
+ It is the null address.}
------------------------------------------------------------------------
-primop AddrNullOp "nullAddr#" GenPrimOp Int# -> Addr#
- {Returns null address. Argument is ignored (nullary primops
- don't quite work!)}
primop AddrAddOp "plusAddr#" GenPrimOp Addr# -> Int# -> Addr#
primop AddrSubOp "minusAddr#" GenPrimOp Addr# -> Addr# -> Int#
{Result is meaningless if two Addr\#s are so far apart that their
o -> State# RealWorld -> State# RealWorld
with
has_side_effects = True
- strictness = { \ arity -> StrictnessInfo [wwLazy, wwPrim] False }
primop EqForeignObj "eqForeignObj#" GenPrimOp
ForeignObj# -> ForeignObj# -> Bool
{Create MutVar\# with specified initial value in specified state thread.}
with
usage = { mangle NewMutVarOp [mkM, mkP] mkM }
- strictness = { \ arity -> StrictnessInfo [wwLazy, wwPrim] False }
out_of_line = True
primop ReadMutVarOp "readMutVar#" GenPrimOp
MutVar# s a -> a -> State# s -> State# s
{Write contents of MutVar\#.}
with
- strictness = { \ arity -> StrictnessInfo [wwPrim, wwLazy, wwPrim] False }
usage = { mangle WriteMutVarOp [mkM, mkM, mkP] mkR }
has_side_effects = True
with
usage = { mangle SameMutVarOp [mkP, mkP] mkM }
+-- not really the right type, but we don't know about pairs here. The
+-- correct type is
+--
+-- MutVar# s a -> (a -> (a,b)) -> State# s -> (# State# s, b #)
+--
+primop AtomicModifyMutVarOp "atomicModifyMutVar#" GenPrimOp
+ MutVar# s a -> (a -> b) -> State# s -> (# State# s, c #)
+ with
+ usage = { mangle AtomicModifyMutVarOp [mkP, mkM, mkP] mkM }
+ has_side_effects = True
+ out_of_line = True
+
------------------------------------------------------------------------
section "Exceptions"
------------------------------------------------------------------------
-> State# RealWorld
-> (# State# RealWorld, a #)
with
- strictness = { \ arity -> StrictnessInfo [wwLazy, wwLazy, wwPrim] False }
-- Catch is actually strict in its first argument
-- but we don't want to tell the strictness
-- analyser about that!
primop RaiseOp "raise#" GenPrimOp
a -> b
with
- strictness = { \ arity -> StrictnessInfo [wwLazy] True }
- -- NB: True => result is bottom
+ strictness = { \ arity -> mkStrictSig (mkTopDmdType [lazyDmd] BotRes) }
+ -- NB: result is bottom
usage = { mangle RaiseOp [mkM] mkM }
out_of_line = True
+-- raiseIO# needs to be a primop, because exceptions in the IO monad
+-- must be *precise* - we don't want the strictness analyser turning
+-- one kind of bottom into another, as it is allowed to do in pure code.
+
+primop RaiseIOOp "raiseIO#" GenPrimOp
+ a -> State# RealWorld -> (# State# RealWorld, b #)
+ with
+ out_of_line = True
+
primop BlockAsyncExceptionsOp "blockAsyncExceptions#" GenPrimOp
(State# RealWorld -> (# State# RealWorld, a #))
-> (State# RealWorld -> (# State# RealWorld, a #))
with
- strictness = { \ arity -> StrictnessInfo [wwLazy, wwPrim] False }
out_of_line = True
primop UnblockAsyncExceptionsOp "unblockAsyncExceptions#" GenPrimOp
(State# RealWorld -> (# State# RealWorld, a #))
-> (State# RealWorld -> (# State# RealWorld, a #))
with
- strictness = { \ arity -> StrictnessInfo [wwLazy, wwPrim] False }
out_of_line = True
------------------------------------------------------------------------
+section "STM-accessible Mutable Variables"
+------------------------------------------------------------------------
+
+primop AtomicallyOp "atomically#" GenPrimOp
+ (State# RealWorld -> (# State# RealWorld, a #) )
+ -> State# RealWorld -> (# State# RealWorld, a #)
+ with
+ out_of_line = True
+ has_side_effects = True
+
+primop RetryOp "retry#" GenPrimOp
+ State# RealWorld -> (# State# RealWorld, a #)
+ with
+ 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
+ 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
+ out_of_line = True
+ has_side_effects = True
+
+primop NewTVarOp "newTVar#" GenPrimOp
+ a
+ -> State# s -> (# State# s, TVar# s a #)
+ {Create a new Tar\# holding a specified initial value.}
+ with
+ out_of_line = True
+
+primop ReadTVarOp "readTVar#" GenPrimOp
+ TVar# s a
+ -> State# s -> (# State# s, a #)
+ {Read contents of TVar\#. Result is not yet evaluated.}
+ with
+ out_of_line = True
+
+primop WriteTVarOp "writeTVar#" GenPrimOp
+ TVar# s a
+ -> a
+ -> State# s -> State# s
+ {Write contents of TVar\#.}
+ with
+ out_of_line = True
+ has_side_effects = True
+
+primop SameTVarOp "sameTVar#" GenPrimOp
+ TVar# s a -> TVar# s a -> Bool
+
+
+------------------------------------------------------------------------
section "Synchronized Mutable Variables"
{Operations on MVar\#s, which are shared mutable variables
({\it not} the same as MutVar\#s!). (Note: in a non-concurrent implementation,
{If mvar is full, block until it becomes empty.
Then store value arg as its new contents.}
with
- strictness = { \ arity -> StrictnessInfo [wwPrim, wwLazy, wwPrim] False }
usage = { mangle PutMVarOp [mkM, mkM, mkP] mkR }
has_side_effects = True
out_of_line = True
{If mvar is full, immediately return with integer 0.
Otherwise, store value arg as mvar's new contents, and return with integer 1.}
with
- strictness = { \ arity -> StrictnessInfo [wwPrim, wwLazy, wwPrim] False }
usage = { mangle TryPutMVarOp [mkM, mkM, mkP] mkR }
has_side_effects = True
out_of_line = True
{Return 1 if mvar is empty; 0 otherwise.}
with
usage = { mangle IsEmptyMVarOp [mkP, mkP] mkM }
-
+ out_of_line = True
------------------------------------------------------------------------
section "Delay/wait operations"
has_side_effects = True
out_of_line = True
+#ifdef mingw32_TARGET_OS
+primop AsyncReadOp "asyncRead#" GenPrimOp
+ Int# -> Int# -> Int# -> Addr# -> State# RealWorld-> (# State# RealWorld, Int#, Int# #)
+ {Asynchronously read bytes from specified file descriptor.}
+ with
+ needs_wrapper = True
+ has_side_effects = True
+ out_of_line = True
+
+primop AsyncWriteOp "asyncWrite#" GenPrimOp
+ Int# -> Int# -> Int# -> Addr# -> State# RealWorld-> (# State# RealWorld, Int#, Int# #)
+ {Asynchronously write bytes from specified file descriptor.}
+ with
+ needs_wrapper = True
+ has_side_effects = True
+ out_of_line = True
+
+primop AsyncDoProcOp "asyncDoProc#" GenPrimOp
+ Addr# -> Addr# -> State# RealWorld-> (# State# RealWorld, Int#, Int# #)
+ {Asynchronously perform procedure (first arg), passing it 2nd arg.}
+ with
+ needs_wrapper = True
+ has_side_effects = True
+ out_of_line = True
+
+#endif
+
------------------------------------------------------------------------
section "Concurrency primitives"
{(In a non-concurrent implementation, ThreadId\# can be as singleton
a -> State# RealWorld -> (# State# RealWorld, ThreadId# #)
with
usage = { mangle ForkOp [mkO, mkP] mkR }
- strictness = { \ arity -> StrictnessInfo [wwLazy, wwPrim] False }
has_side_effects = True
out_of_line = True
out_of_line = True
primop MyThreadIdOp "myThreadId#" GenPrimOp
- State# RealWorld -> (# State# RealWorld, ThreadId# #)
+ State# RealWorld -> (# State# RealWorld, ThreadId# #)
+ with
+ out_of_line = 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
------------------------------------------------------------------------
section "Weak pointers"
primop MkWeakOp "mkWeak#" GenPrimOp
o -> b -> c -> State# RealWorld -> (# State# RealWorld, Weak# b #)
with
- strictness = { \ arity -> StrictnessInfo [wwLazy, wwLazy, wwLazy, wwPrim] False }
usage = { mangle MkWeakOp [mkZ, mkM, mkM, mkP] mkM }
has_side_effects = True
out_of_line = True
with
usage = { mangle DeRefWeakOp [mkM, mkP] mkM }
has_side_effects = True
+ out_of_line = True
primop FinalizeWeakOp "finalizeWeak#" GenPrimOp
Weak# a -> State# RealWorld -> (# State# RealWorld, Int#,
- (State# RealWorld -> (# State# RealWorld, Unit #)) #)
+ (State# RealWorld -> (# State# RealWorld, () #)) #)
with
usage = { mangle FinalizeWeakOp [mkM, mkP]
(mkR . (inUB FinalizeWeakOp
primop MakeStablePtrOp "makeStablePtr#" GenPrimOp
a -> State# RealWorld -> (# State# RealWorld, StablePtr# a #)
with
- strictness = { \ arity -> StrictnessInfo [wwLazy, wwPrim] False }
usage = { mangle MakeStablePtrOp [mkM, mkP] mkM }
has_side_effects = True
+ out_of_line = True
primop DeRefStablePtrOp "deRefStablePtr#" GenPrimOp
StablePtr# a -> State# RealWorld -> (# State# RealWorld, a #)
usage = { mangle DeRefStablePtrOp [mkM, mkP] mkM }
needs_wrapper = True
has_side_effects = True
+ out_of_line = True
primop EqStablePtrOp "eqStablePtr#" GenPrimOp
StablePtr# a -> StablePtr# a -> Int#
a -> State# RealWorld -> (# State# RealWorld, StableName# a #)
with
usage = { mangle MakeStableNameOp [mkZ, mkP] mkR }
- strictness = { \ arity -> StrictnessInfo [wwLazy, wwPrim] False }
needs_wrapper = True
has_side_effects = True
out_of_line = True
section "Parallelism"
------------------------------------------------------------------------
-primop SeqOp "seq#" GenPrimOp
- a -> Int#
- with
- usage = { mangle SeqOp [mkO] mkR }
- strictness = { \ arity -> StrictnessInfo [wwStrict] False }
- -- Seq is strict in its argument; see notes in ConFold.lhs
- has_side_effects = True
-
primop ParOp "par#" GenPrimOp
a -> Int#
with
usage = { mangle ParOp [mkO] mkR }
- strictness = { \ arity -> StrictnessInfo [wwLazy] False }
-- Note that Par is lazy to avoid that the sparked thing
-- gets evaluted strictly, which it should *not* be
has_side_effects = True
primop DataToTagOp "dataToTag#" GenPrimOp
a -> Int#
with
- strictness = { \ arity -> StrictnessInfo [wwLazy] False }
+ strictness = { \ arity -> mkStrictSig (mkTopDmdType [seqDmd] TopRes) }
+ -- dataToTag# must have an evaluated argument
primop TagToEnumOp "tagToEnum#" GenPrimOp
Int# -> a
{Convert an Addr\# to a followable type.}
primop MkApUpd0_Op "mkApUpd0#" GenPrimOp
- a -> (# a #)
+ BCO# -> (# a #)
with
out_of_line = True
primop NewBCOOp "newBCO#" GenPrimOp
- ByteArr# -> ByteArr# -> Array# a -> ByteArr# -> State# s -> (# State# s, BCO# #)
+ ByteArr# -> ByteArr# -> Array# a -> ByteArr# -> Int# -> ByteArr# -> State# s -> (# State# s, BCO# #)
with
has_side_effects = True
out_of_line = True
------------------------------------------------------------------------
+section "Coercion"
+ {{\tt unsafeCoerce\# :: a -> b} is not a primop, but is defined in MkId.lhs.}
+
+------------------------------------------------------------------------
+
+
+------------------------------------------------------------------------
--- ---
------------------------------------------------------------------------