diff options
Diffstat (limited to 'compiler/prelude/primops.txt.pp')
-rw-r--r-- | compiler/prelude/primops.txt.pp | 505 |
1 files changed, 404 insertions, 101 deletions
diff --git a/compiler/prelude/primops.txt.pp b/compiler/prelude/primops.txt.pp index 97ae89cb84..2f8ced7de8 100644 --- a/compiler/prelude/primops.txt.pp +++ b/compiler/prelude/primops.txt.pp @@ -38,6 +38,14 @@ -- 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 @@ -83,10 +91,11 @@ section "The word size story." 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 + 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 30 or 31-bit code can be + 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 @@ -97,7 +106,7 @@ section "The word size story." 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 + 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 @@ -134,13 +143,8 @@ section "The word size story." -- Define synonyms for indexing ops. -#if WORD_SIZE_IN_BITS < 32 -#define INT32 Int32# -#define WORD32 Word32# -#else #define INT32 Int# #define WORD32 Word# -#endif #if WORD_SIZE_IN_BITS < 64 #define INT64 Int64# @@ -176,7 +180,7 @@ primop OrdOp "ord#" GenPrimOp Char# -> Int# ------------------------------------------------------------------------ section "Int#" - {Operations on native-size integers (30+ bits).} + {Operations on native-size integers (32+ bits).} ------------------------------------------------------------------------ primtype Int# @@ -257,6 +261,7 @@ primop IntAddCOp "addIntC#" GenPrimOp Int# -> Int# -> (# Int#, 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. @@ -312,7 +317,7 @@ primop ISrlOp "uncheckedIShiftRL#" GenPrimOp Int# -> Int# -> Int# ------------------------------------------------------------------------ section "Word#" - {Operations on native-sized unsigned words (30+ bits).} + {Operations on native-sized unsigned words (32+ bits).} ------------------------------------------------------------------------ primtype Word# @@ -320,15 +325,25 @@ 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 --- Returns (# high, low #) (or equivalently, (# carry, low #)) -primop WordAdd2Op "plusWord2#" GenPrimOp - Word# -> Word# -> (# Word#, Word# #) - with commutable = True +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# @@ -395,6 +410,28 @@ primop PopCnt64Op "popCnt64#" GenPrimOp WORD64 -> 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# @@ -439,28 +476,6 @@ primop Narrow16WordOp "narrow16Word#" Monadic Word# -> Word# primop Narrow32WordOp "narrow32Word#" Monadic Word# -> Word# -#if WORD_SIZE_IN_BITS < 32 ------------------------------------------------------------------------- -section "Int32#" - {Operations on 32-bit integers ({\tt Int32\#}). This type is only used - if plain {\tt Int\#} has less than 32 bits. In any case, the operations - are not primops; they are implemented (if needed) as ccalls instead.} ------------------------------------------------------------------------- - -primtype Int32# - ------------------------------------------------------------------------- -section "Word32#" - {Operations on 32-bit unsigned words. This type is only used - if plain {\tt Word\#} has less than 32 bits. In any case, the operations - are not primops; they are implemented (if needed) as ccalls instead.} ------------------------------------------------------------------------- - -primtype Word32# - -#endif - - #if WORD_SIZE_IN_BITS < 64 ------------------------------------------------------------------------ section "Int64#" @@ -603,6 +618,21 @@ primop DoubleTanhOp "tanhDouble#" Monadic 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.} @@ -729,6 +759,21 @@ primop FloatTanhOp "tanhFloat#" Monadic 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 @@ -788,8 +833,13 @@ primop SizeofMutableArrayOp "sizeofMutableArray#" GenPrimOp primop IndexArrayOp "indexArray#" GenPrimOp Array# a -> Int# -> (# a #) - {Read from specified index of immutable array. Result is packaged into - an unboxed singleton; the result itself is not yet evaluated.} + {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 @@ -1224,6 +1274,76 @@ primop IndexByteArrayOp_Word64 "indexWord64Array#" GenPrimOp {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.} @@ -1238,7 +1358,7 @@ primop ReadByteArrayOp_WideChar "readWideCharArray#" GenPrimOp primop ReadByteArrayOp_Int "readIntArray#" GenPrimOp MutableByteArray# s -> Int# -> State# s -> (# State# s, Int# #) - {Read intger; offset in words.} + {Read integer; offset in words.} with has_side_effects = True can_fail = True @@ -1308,6 +1428,76 @@ primop ReadByteArrayOp_Word64 "readWord64Array#" GenPrimOp 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.} @@ -1390,11 +1580,99 @@ primop WriteByteArrayOp_Word64 "writeWord64Array#" GenPrimOp 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 - {Copy a range of the ByteArray# to the specified region in the MutableByteArray#. - 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.} + {{\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} @@ -1402,7 +1680,7 @@ primop CopyByteArrayOp "copyByteArray#" GenPrimOp 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#. + {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.} @@ -1413,10 +1691,10 @@ primop CopyMutableByteArrayOp "copyMutableByteArray#" GenPrimOp 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 + {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 @@ -1425,10 +1703,10 @@ primop CopyByteArrayToAddrOp "copyByteArrayToAddr#" GenPrimOp 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 + {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 @@ -1437,10 +1715,10 @@ primop CopyMutableByteArrayToAddrOp "copyMutableByteArrayToAddr#" GenPrimOp 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), + {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 @@ -1620,7 +1898,7 @@ primop WriteArrayArrayOp_MutableArrayArray "writeMutableArrayArrayArray#" GenPr 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#. + {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 @@ -1950,25 +2228,37 @@ primop WriteMutVarOp "writeMutVar#" GenPrimOp primop SameMutVarOp "sameMutVar#" GenPrimOp MutVar# s a -> MutVar# s a -> Int# --- Note [Why not an unboxed tuple in atomicModifyMutVar#?] +-- Note [Why not an unboxed tuple in atomicModifyMutVar2#?] -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- --- Looking at the type of atomicModifyMutVar#, one might wonder why +-- 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, b #) +-- MutVar# s a -> (a -> (# a, b #)) -> State# s -> (# State# s, a, (# a, b #) #) -- --- The reason is that atomicModifyMutVar# relies on laziness for its atomicity. --- Given a MutVar# containing x, atomicModifyMutVar# merely replaces the +-- 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 AtomicModifyMutVarOp "atomicModifyMutVar#" GenPrimOp - MutVar# s a -> (a -> b) -> State# s -> (# State# s, c #) - { Modify the contents of a {\tt MutVar\#}. 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, b #)}, however - we don't know about pairs here. } +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 @@ -2094,7 +2384,7 @@ primop AtomicallyOp "atomically#" GenPrimOp out_of_line = True has_side_effects = True --- NB: retry#'s strictness information specifies it to return bottom. +-- NB: retry#'s strictness information specifies it to throw an exception -- This lets the compiler perform some extra simplifications, since retry# -- will technically never return. -- @@ -2104,10 +2394,13 @@ primop AtomicallyOp "atomically#" GenPrimOp -- with: -- retry# s1 -- where 'e' would be unreachable anyway. See Trac #8091. +-- +-- Note that it *does not* return botRes as the "exception" that is thrown may be +-- "caught" by catchRetry#. This mistake caused #14171. primop RetryOp "retry#" GenPrimOp State# RealWorld -> (# State# RealWorld, a #) with - strictness = { \ _arity -> mkClosedStrictSig [topDmd] botRes } + strictness = { \ _arity -> mkClosedStrictSig [topDmd] exnRes } out_of_line = True has_side_effects = True @@ -2116,7 +2409,7 @@ primop CatchRetryOp "catchRetry#" GenPrimOp -> (State# RealWorld -> (# State# RealWorld, a #) ) -> (State# RealWorld -> (# State# RealWorld, a #) ) with - strictness = { \ _arity -> mkClosedStrictSig [ catchArgDmd + strictness = { \ _arity -> mkClosedStrictSig [ lazyApply1Dmd , lazyApply1Dmd , topDmd ] topRes } -- See Note [Strictness for mask/unmask/catch] @@ -2135,13 +2428,6 @@ primop CatchSTMOp "catchSTM#" GenPrimOp out_of_line = True has_side_effects = True -primop Check "check#" GenPrimOp - (State# RealWorld -> (# State# RealWorld, a #) ) - -> (State# RealWorld -> State# RealWorld) - with - out_of_line = True - has_side_effects = True - primop NewTVarOp "newTVar#" GenPrimOp a -> State# s -> (# State# s, TVar# s a #) @@ -2352,7 +2638,6 @@ primop YieldOp "yield#" GenPrimOp primop MyThreadIdOp "myThreadId#" GenPrimOp State# RealWorld -> (# State# RealWorld, ThreadId# #) with - out_of_line = True has_side_effects = True primop LabelThreadOp "labelThread#" GenPrimOp @@ -2505,13 +2790,13 @@ primop CompactResizeOp "compactResize#" GenPrimOp primop CompactContainsOp "compactContains#" GenPrimOp Compact# -> a -> State# RealWorld -> (# State# RealWorld, Int# #) - { Returns 1# if the object is contained in the compact, 0# otherwise. } + { Returns 1\# if the object is contained in the compact, 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 compact at all, 0# otherwise. } + { Returns 1\# if the object is in any compact at all, 0\# otherwise. } with out_of_line = True @@ -2592,7 +2877,7 @@ section "Unsafe pointer equality" primop ReallyUnsafePtrEqualityOp "reallyUnsafePtrEquality#" GenPrimOp a -> a -> Int# - { Returns 1# if the given pointers are equal and 0# otherwise. } + { Returns {\texttt 1\#} if the given pointers are equal and {\texttt 0\#} otherwise. } with can_fail = True -- See Note [reallyUnsafePtrEquality#] @@ -2647,13 +2932,7 @@ primop SparkOp "spark#" GenPrimOp primop SeqOp "seq#" GenPrimOp a -> State# s -> (# State# s, a #) - - -- why return the value? So that we can control sharing of seq'd - -- values: in - -- let x = e in x `seq` ... x ... - -- we don't want to inline x, so better to represent it as - -- let x = e in case seq# x RW of (# _, x' #) -> ... x' ... - -- also it matches the type of rseq in the Eval monad. + -- See Note [seq# magic] in PrelRules primop GetSparkOp "getSpark#" GenPrimOp State# s -> (# State# s, Int#, a #) @@ -2675,7 +2954,7 @@ section "Tag to enum stuff" ------------------------------------------------------------------------ primop DataToTagOp "dataToTag#" GenPrimOp - a -> Int# + a -> Int# -- Zero-indexed; the first constructor has tag zero with can_fail = True -- See Note [dataToTag#] strictness = { \ _arity -> mkClosedStrictSig [evalDmd] topRes } @@ -2699,7 +2978,7 @@ binder-swap on the case, to give \z. case x of y -> let v = dataToTag# x in ... Now FloatOut might float that v-binding outside the \z. But that is -bad because that might mean x gest evaluated much too early! (CorePrep +bad because that might mean x gets evaluated much too early! (CorePrep adds an eval to a dataToTag# call, to ensure that the argument really is evaluated; see CorePrep Note [dataToTag magic].) @@ -2759,12 +3038,11 @@ primop NewBCOOp "newBCO#" GenPrimOp out_of_line = True primop UnpackClosureOp "unpackClosure#" GenPrimOp - a -> (# Addr#, Array# b, ByteArray# #) - { {\tt unpackClosure\# closure} copies non-pointers and pointers in the + 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 pointer array for the - pointers in the payload, and a non-pointer array for the non-pointers in - the payload. } + 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 @@ -2785,7 +3063,7 @@ 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 getCCCS\#} being floated out by the + avoid the call to {\tt getCurrentCCS\#} being floated out by the simplifier, which would result in an uninformative stack ("CAF"). } @@ -2817,8 +3095,9 @@ pseudoop "proxy#" 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}. {\tt seq} is usually introduced to - improve performance by avoiding unneeded laziness. + 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}. @@ -2857,7 +3136,7 @@ pseudoop "unsafeCoerce#" {\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 congnoscenti, data values + 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. @@ -2875,22 +3154,46 @@ 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 .eventlog file, + 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 .eventlog file, + 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 GetThreadAllocationCounter "getThreadAllocationCounter#" GenPrimOp + State# RealWorld -> (# State# RealWorld, INT64 #) + { Retrieves the allocation counter for the current thread. } + 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" ------------------------------------------------------------------------ |