X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=compiler%2Fprelude%2Fprimops.txt.pp;h=49f7a97a61d699b34fb19e2e162d3eda049d831c;hp=ef5dfc9997829239ffec756cbbc01fb5655c6de6;hb=e11c554e94c39223ea55991a552ccb244dfe4364;hpb=9cef40bd4dd2536c7a370a1a9b78461c152805cc diff --git a/compiler/prelude/primops.txt.pp b/compiler/prelude/primops.txt.pp index ef5dfc9..49f7a97 100644 --- a/compiler/prelude/primops.txt.pp +++ b/compiler/prelude/primops.txt.pp @@ -1,7 +1,11 @@ ----------------------------------------------------------------------- --- $Id: primops.txt.pp,v 1.37 2005/11/25 09:46:19 simonmar Exp $ +-- +-- (c) 2010 The University of Glasgow -- --- Primitive Operations +-- Primitive Operations and Types +-- +-- For more information on PrimOps, see +-- http://hackage.haskell.org/trac/ghc/wiki/Commentary/PrimOps -- ----------------------------------------------------------------------- @@ -11,25 +15,10 @@ -- -- It should first be preprocessed. -- --- To add a new primop, you currently need to update the following files: --- --- - 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.) --- --- - if the primop is inline (i.e. a macro), then: --- 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/StgMiscClosures.h (just add the declaration) --- ghc/rts/PrimOps.cmm (define it here) --- ghc/rts/Linker.c (declare the symbol for GHCi) --- --- - the User's Guide +-- Information on how PrimOps are implemented and the steps necessary to +-- add a new one can be found in the Commentary: -- +-- http://hackage.haskell.org/trac/ghc/wiki/Commentary/PrimOps -- This file is divided into named sections, each containing or more -- primop entries. Section headers have the format: @@ -48,7 +37,7 @@ -- 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 and usage info. +-- needed for strictness info. defaults has_side_effects = False @@ -57,7 +46,6 @@ defaults needs_wrapper = False can_fail = 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 @@ -114,8 +102,8 @@ section "The word size story." 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\# -> + \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. @@ -150,6 +138,7 @@ section "Char#" {Operations on 31-bit characters.} ------------------------------------------------------------------------ +primtype Char# primop CharGtOp "gtChar#" Compare Char# -> Char# -> Bool primop CharGeOp "geChar#" Compare Char# -> Char# -> Bool @@ -172,6 +161,8 @@ section "Int#" {Operations on native-size integers (30+ bits).} ------------------------------------------------------------------------ +primtype Int# + primop IntAddOp "+#" Dyadic Int# -> Int# -> Int# with commutable = True @@ -203,7 +194,7 @@ primop IntMulMayOfloOp "mulIntMayOflo#" 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. + \texttt{(*) :: Integer -> Integer -> Integer} will be poor. } with commutable = True @@ -217,9 +208,6 @@ primop IntRemOp "remInt#" Dyadic {Satisfies \texttt{(quotInt\# x y) *\# y +\# (remInt\# x y) == x}.} 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; @@ -248,10 +236,6 @@ primop Int2WordOp "int2Word#" GenPrimOp Int# -> Word# primop Int2FloatOp "int2Float#" GenPrimOp Int# -> Float# primop Int2DoubleOp "int2Double#" GenPrimOp Int# -> Double# -primop Int2IntegerOp "int2Integer#" - GenPrimOp Int# -> (# Int#, ByteArr# #) - with out_of_line = True - 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.} @@ -267,6 +251,8 @@ section "Word#" {Operations on native-sized unsigned words (30+ bits).} ------------------------------------------------------------------------ +primtype Word# + primop WordAddOp "plusWord#" Dyadic Word# -> Word# -> Word# with commutable = True @@ -301,10 +287,6 @@ primop SrlOp "uncheckedShiftRL#" GenPrimOp Word# -> Int# -> Word# primop Word2IntOp "word2Int#" GenPrimOp Word# -> Int# -primop Word2IntegerOp "word2Integer#" GenPrimOp - Word# -> (# Int#, ByteArr# #) - with out_of_line = True - primop WordGtOp "gtWord#" Compare Word# -> Word# -> Bool primop WordGeOp "geWord#" Compare Word# -> Word# -> Bool primop WordEqOp "eqWord#" Compare Word# -> Word# -> Bool @@ -328,27 +310,21 @@ primop Narrow32WordOp "narrow32Word#" Monadic Word# -> Word# #if WORD_SIZE_IN_BITS < 32 ------------------------------------------------------------------------ section "Int32#" - {Operations on 32-bit integers (Int32\#). This type is only used - if plain Int\# has less than 32 bits. In any case, the operations + {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.} ------------------------------------------------------------------------ -primop Int32ToIntegerOp "int32ToInteger#" GenPrimOp - Int32# -> (# Int#, ByteArr# #) - with out_of_line = True - +primtype Int32# ------------------------------------------------------------------------ section "Word32#" {Operations on 32-bit unsigned words. This type is only used - if plain Word\# has less than 32 bits. In any case, the operations + 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.} ------------------------------------------------------------------------ -primop Word32ToIntegerOp "word32ToInteger#" GenPrimOp - Word32# -> (# Int#, ByteArr# #) - with out_of_line = True - +primtype Word32# #endif @@ -357,149 +333,30 @@ primop Word32ToIntegerOp "word32ToInteger#" GenPrimOp ------------------------------------------------------------------------ section "Int64#" {Operations on 64-bit unsigned words. This type is only used - if plain Int\# has less than 64 bits. In any case, the operations + 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.} ------------------------------------------------------------------------ -primop Int64ToIntegerOp "int64ToInteger#" GenPrimOp - Int64# -> (# Int#, ByteArr# #) - with out_of_line = True +primtype Int64# ------------------------------------------------------------------------ section "Word64#" {Operations on 64-bit unsigned words. This type is only used - if plain Word\# has less than 64 bits. In any case, the operations + 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.} ------------------------------------------------------------------------ -primop Word64ToIntegerOp "word64ToInteger#" GenPrimOp - Word64# -> (# Int#, ByteArr# #) - with out_of_line = True +primtype Word64# #endif ------------------------------------------------------------------------ -section "Integer#" - {Operations on arbitrary-precision integers. These operations are -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. - -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 - out_of_line = True - -primop IntegerSubOp "minusInteger#" GenPrimOp - Int# -> ByteArr# -> Int# -> ByteArr# -> (# Int#, ByteArr# #) - with out_of_line = True - -primop IntegerMulOp "timesInteger#" GenPrimOp - Int# -> ByteArr# -> Int# -> ByteArr# -> (# Int#, ByteArr# #) - with commutable = True - out_of_line = True - -primop IntegerGcdOp "gcdInteger#" GenPrimOp - Int# -> ByteArr# -> Int# -> ByteArr# -> (# Int#, ByteArr# #) - {Greatest common divisor.} - with commutable = True - out_of_line = True - -primop IntegerIntGcdOp "gcdIntegerInt#" GenPrimOp - Int# -> ByteArr# -> Int# -> Int# - {Greatest common divisor, where second argument is an ordinary Int\#.} - with out_of_line = True - -primop IntegerDivExactOp "divExactInteger#" GenPrimOp - Int# -> ByteArr# -> Int# -> ByteArr# -> (# Int#, ByteArr# #) - {Divisor is guaranteed to be a factor of dividend.} - with out_of_line = True - -primop IntegerQuotOp "quotInteger#" GenPrimOp - Int# -> ByteArr# -> Int# -> ByteArr# -> (# Int#, ByteArr# #) - {Rounds towards zero.} - with out_of_line = True - -primop IntegerRemOp "remInteger#" GenPrimOp - Int# -> ByteArr# -> Int# -> ByteArr# -> (# Int#, ByteArr# #) - {Satisfies \texttt{plusInteger\# (timesInteger\# (quotInteger\# x y) y) (remInteger\# x y) == x}.} - with out_of_line = True - -primop IntegerCmpOp "cmpInteger#" GenPrimOp - 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# #) - {Compute quot and rem simulaneously.} - with can_fail = True - out_of_line = True - -primop IntegerDivModOp "divModInteger#" GenPrimOp - Int# -> ByteArr# -> Int# -> ByteArr# -> (# Int#, ByteArr#, Int#, ByteArr# #) - {Compute div and mod simultaneously, where div rounds towards negative infinity - and\texttt{(q,r) = divModInteger\#(x,y)} implies \texttt{plusInteger\# (timesInteger\# q y) r = x}.} - with can_fail = True - out_of_line = True - -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# -> Int32# - -primop IntegerToWord32Op "integerToWord32#" GenPrimOp - Int# -> ByteArr# -> Word32# -#endif - -primop IntegerAndOp "andInteger#" GenPrimOp - Int# -> ByteArr# -> Int# -> ByteArr# -> (# Int#, ByteArr# #) - with out_of_line = True - -primop IntegerOrOp "orInteger#" GenPrimOp - Int# -> ByteArr# -> Int# -> ByteArr# -> (# Int#, ByteArr# #) - with out_of_line = True - -primop IntegerXorOp "xorInteger#" GenPrimOp - Int# -> ByteArr# -> Int# -> ByteArr# -> (# Int#, ByteArr# #) - with out_of_line = True - -primop IntegerComplementOp "complementInteger#" GenPrimOp - Int# -> ByteArr# -> (# Int#, ByteArr# #) - with out_of_line = True - -#endif /* ndef ILX */ - ------------------------------------------------------------------------- section "Double#" {Operations on double-precision (64 bit) floating-point numbers.} ------------------------------------------------------------------------ +primtype Double# + primop DoubleGtOp ">##" Compare Double# -> Double# -> Bool primop DoubleGeOp ">=##" Compare Double# -> Double# -> Bool @@ -531,6 +388,10 @@ primop DoubleDivOp "/##" Dyadic primop DoubleNegOp "negateDouble#" 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 @@ -593,11 +454,12 @@ primop DoublePowerOp "**##" Dyadic {Exponentiation.} with needs_wrapper = True -primop DoubleDecodeOp "decodeDouble#" GenPrimOp - Double# -> (# Int#, Int#, ByteArr# #) - {Convert to arbitrary-precision integer. - First Int\# in result is the exponent; second Int\# and ByteArr\# represent an Integer\# - holding the mantissa.} +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 ------------------------------------------------------------------------ @@ -605,6 +467,8 @@ section "Float#" {Operations on single-precision (32-bit) floating-point numbers.} ------------------------------------------------------------------------ +primtype Float# + primop FloatGtOp "gtFloat#" Compare Float# -> Float# -> Bool primop FloatGeOp "geFloat#" Compare Float# -> Float# -> Bool @@ -636,6 +500,9 @@ primop FloatDivOp "divideFloat#" Dyadic primop FloatNegOp "negateFloat#" 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# @@ -694,293 +561,330 @@ primop FloatPowerOp "powerFloat#" Dyadic primop Float2DoubleOp "float2Double#" GenPrimOp Float# -> Double# -primop FloatDecodeOp "decodeFloat#" GenPrimOp - Float# -> (# Int#, Int#, ByteArr# #) - {Convert to arbitrary-precision integer. - First Int\# in result is the exponent; second Int\# and ByteArr\# represent an Integer\# - holding the mantissa.} +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 Array\#.} + {Operations on {\tt Array\#}.} ------------------------------------------------------------------------ +primtype Array# a + +primtype MutableArray# s a + primop NewArrayOp "newArray#" GenPrimOp - Int# -> a -> State# s -> (# State# s, MutArr# s a #) - {Create a new mutable array of specified size (in bytes), + 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 - usage = { mangle NewArrayOp [mkP, mkM, mkP] mkM } out_of_line = True + has_side_effects = True primop SameMutableArrayOp "sameMutableArray#" GenPrimOp - MutArr# s a -> MutArr# s a -> Bool - with - usage = { mangle SameMutableArrayOp [mkP, mkP] mkM } + MutableArray# s a -> MutableArray# s a -> Bool primop ReadArrayOp "readArray#" GenPrimOp - MutArr# s a -> Int# -> State# s -> (# State# s, a #) + MutableArray# s a -> Int# -> State# s -> (# State# s, a #) {Read from specified index of mutable array. Result is not yet evaluated.} with - usage = { mangle ReadArrayOp [mkM, mkP, mkP] mkM } + has_side_effects = True primop WriteArrayOp "writeArray#" GenPrimOp - MutArr# s a -> Int# -> a -> State# s -> State# s + MutableArray# s a -> Int# -> a -> State# s -> State# s {Write to specified index of mutable array.} with - usage = { mangle WriteArrayOp [mkM, mkP, mkM, mkP] mkR } has_side_effects = True +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 specified index of immutable array. Result is packaged into an unboxed singleton; the result itself is not yet evaluated.} - with - usage = { mangle IndexArrayOp [mkM, mkP] mkM } primop UnsafeFreezeArrayOp "unsafeFreezeArray#" GenPrimOp - MutArr# s a -> State# s -> (# State# s, Array# a #) + MutableArray# s a -> State# s -> (# State# s, Array# a #) {Make a mutable array immutable, without copying.} with - usage = { mangle UnsafeFreezeArrayOp [mkM, mkP] mkM } has_side_effects = True primop UnsafeThawArrayOp "unsafeThawArray#" GenPrimOp - Array# a -> State# s -> (# State# s, MutArr# s a #) + Array# a -> State# s -> (# State# s, MutableArray# s a #) {Make an immutable array mutable, without copying.} with - usage = { mangle UnsafeThawArrayOp [mkM, mkP] mkM } out_of_line = True + has_side_effects = True ------------------------------------------------------------------------ section "Byte Arrays" - {Operations on ByteArray\#. A 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 fo the primitive type - being read or written.} + {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 fo the primitive type + being read or written.} ------------------------------------------------------------------------ +primtype ByteArray# + +primtype MutableByteArray# s + primop NewByteArrayOp_Char "newByteArray#" GenPrimOp - Int# -> State# s -> (# State# s, MutByteArr# s #) + 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, MutByteArr# s #) + 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 ByteArrayContents_Char "byteArrayContents#" GenPrimOp - ByteArr# -> Addr# + ByteArray# -> Addr# {Intended for use with pinned arrays; otherwise very unsafe!} primop SameMutableByteArrayOp "sameMutableByteArray#" GenPrimOp - MutByteArr# s -> MutByteArr# s -> Bool + MutableByteArray# s -> MutableByteArray# s -> Bool primop UnsafeFreezeByteArrayOp "unsafeFreezeByteArray#" GenPrimOp - MutByteArr# s -> State# s -> (# State# s, ByteArr# #) + MutableByteArray# s -> State# s -> (# State# s, ByteArray# #) {Make a mutable byte array immutable, without copying.} with has_side_effects = True primop SizeofByteArrayOp "sizeofByteArray#" GenPrimOp - ByteArr# -> Int# + ByteArray# -> Int# + {Return the size of the array in bytes.} primop SizeofMutableByteArrayOp "sizeofMutableByteArray#" GenPrimOp - MutByteArr# s -> Int# - + MutableByteArray# s -> Int# + {Return the size of the array in bytes.} primop IndexByteArrayOp_Char "indexCharArray#" GenPrimOp - ByteArr# -> Int# -> Char# + ByteArray# -> Int# -> Char# {Read 8-bit character; offset in bytes.} primop IndexByteArrayOp_WideChar "indexWideCharArray#" GenPrimOp - ByteArr# -> Int# -> Char# + ByteArray# -> Int# -> Char# {Read 31-bit character; offset in 4-byte words.} primop IndexByteArrayOp_Int "indexIntArray#" GenPrimOp - ByteArr# -> Int# -> Int# + ByteArray# -> Int# -> Int# primop IndexByteArrayOp_Word "indexWordArray#" GenPrimOp - ByteArr# -> Int# -> Word# + ByteArray# -> Int# -> Word# primop IndexByteArrayOp_Addr "indexAddrArray#" GenPrimOp - ByteArr# -> Int# -> Addr# + ByteArray# -> Int# -> Addr# primop IndexByteArrayOp_Float "indexFloatArray#" GenPrimOp - ByteArr# -> Int# -> Float# + ByteArray# -> Int# -> Float# primop IndexByteArrayOp_Double "indexDoubleArray#" GenPrimOp - ByteArr# -> Int# -> Double# + ByteArray# -> Int# -> Double# primop IndexByteArrayOp_StablePtr "indexStablePtrArray#" GenPrimOp - ByteArr# -> Int# -> StablePtr# a + ByteArray# -> Int# -> StablePtr# a primop IndexByteArrayOp_Int8 "indexInt8Array#" GenPrimOp - ByteArr# -> Int# -> Int# + ByteArray# -> Int# -> Int# primop IndexByteArrayOp_Int16 "indexInt16Array#" GenPrimOp - ByteArr# -> Int# -> Int# + ByteArray# -> Int# -> Int# primop IndexByteArrayOp_Int32 "indexInt32Array#" GenPrimOp - ByteArr# -> Int# -> INT32 + ByteArray# -> Int# -> INT32 primop IndexByteArrayOp_Int64 "indexInt64Array#" GenPrimOp - ByteArr# -> Int# -> INT64 + ByteArray# -> Int# -> INT64 primop IndexByteArrayOp_Word8 "indexWord8Array#" GenPrimOp - ByteArr# -> Int# -> Word# + ByteArray# -> Int# -> Word# primop IndexByteArrayOp_Word16 "indexWord16Array#" GenPrimOp - ByteArr# -> Int# -> Word# + ByteArray# -> Int# -> Word# primop IndexByteArrayOp_Word32 "indexWord32Array#" GenPrimOp - ByteArr# -> Int# -> WORD32 + ByteArray# -> Int# -> WORD32 primop IndexByteArrayOp_Word64 "indexWord64Array#" GenPrimOp - ByteArr# -> Int# -> WORD64 + ByteArray# -> Int# -> WORD64 primop ReadByteArrayOp_Char "readCharArray#" GenPrimOp - MutByteArr# s -> Int# -> State# s -> (# State# s, Char# #) + MutableByteArray# s -> Int# -> State# s -> (# State# s, Char# #) {Read 8-bit character; offset in bytes.} + with has_side_effects = True primop ReadByteArrayOp_WideChar "readWideCharArray#" GenPrimOp - MutByteArr# s -> Int# -> State# s -> (# State# s, Char# #) + MutableByteArray# s -> Int# -> State# s -> (# State# s, Char# #) {Read 31-bit character; offset in 4-byte words.} + with has_side_effects = True primop ReadByteArrayOp_Int "readIntArray#" GenPrimOp - MutByteArr# s -> Int# -> State# s -> (# State# s, Int# #) + MutableByteArray# s -> Int# -> State# s -> (# State# s, Int# #) + with has_side_effects = True primop ReadByteArrayOp_Word "readWordArray#" GenPrimOp - MutByteArr# s -> Int# -> State# s -> (# State# s, Word# #) + MutableByteArray# s -> Int# -> State# s -> (# State# s, Word# #) + with has_side_effects = True primop ReadByteArrayOp_Addr "readAddrArray#" GenPrimOp - MutByteArr# s -> Int# -> State# s -> (# State# s, Addr# #) + MutableByteArray# s -> Int# -> State# s -> (# State# s, Addr# #) + with has_side_effects = True primop ReadByteArrayOp_Float "readFloatArray#" GenPrimOp - MutByteArr# s -> Int# -> State# s -> (# State# s, Float# #) + MutableByteArray# s -> Int# -> State# s -> (# State# s, Float# #) + with has_side_effects = True primop ReadByteArrayOp_Double "readDoubleArray#" GenPrimOp - MutByteArr# s -> Int# -> State# s -> (# State# s, Double# #) + MutableByteArray# s -> Int# -> State# s -> (# State# s, Double# #) + with has_side_effects = True primop ReadByteArrayOp_StablePtr "readStablePtrArray#" GenPrimOp - MutByteArr# s -> Int# -> State# s -> (# State# s, StablePtr# a #) + MutableByteArray# s -> Int# -> State# s -> (# State# s, StablePtr# a #) + with has_side_effects = True primop ReadByteArrayOp_Int8 "readInt8Array#" GenPrimOp - MutByteArr# s -> Int# -> State# s -> (# State# s, Int# #) + MutableByteArray# s -> Int# -> State# s -> (# State# s, Int# #) + with has_side_effects = True primop ReadByteArrayOp_Int16 "readInt16Array#" GenPrimOp - MutByteArr# s -> Int# -> State# s -> (# State# s, Int# #) + MutableByteArray# s -> Int# -> State# s -> (# State# s, Int# #) + with has_side_effects = True primop ReadByteArrayOp_Int32 "readInt32Array#" GenPrimOp - MutByteArr# s -> Int# -> State# s -> (# State# s, INT32 #) + MutableByteArray# s -> Int# -> State# s -> (# State# s, INT32 #) + with has_side_effects = True primop ReadByteArrayOp_Int64 "readInt64Array#" GenPrimOp - MutByteArr# s -> Int# -> State# s -> (# State# s, INT64 #) + MutableByteArray# s -> Int# -> State# s -> (# State# s, INT64 #) + with has_side_effects = True primop ReadByteArrayOp_Word8 "readWord8Array#" GenPrimOp - MutByteArr# s -> Int# -> State# s -> (# State# s, Word# #) + MutableByteArray# s -> Int# -> State# s -> (# State# s, Word# #) + with has_side_effects = True primop ReadByteArrayOp_Word16 "readWord16Array#" GenPrimOp - MutByteArr# s -> Int# -> State# s -> (# State# s, Word# #) + MutableByteArray# s -> Int# -> State# s -> (# State# s, Word# #) + with has_side_effects = True primop ReadByteArrayOp_Word32 "readWord32Array#" GenPrimOp - MutByteArr# s -> Int# -> State# s -> (# State# s, WORD32 #) + MutableByteArray# s -> Int# -> State# s -> (# State# s, WORD32 #) + with has_side_effects = True primop ReadByteArrayOp_Word64 "readWord64Array#" GenPrimOp - MutByteArr# s -> Int# -> State# s -> (# State# s, WORD64 #) + MutableByteArray# s -> Int# -> State# s -> (# State# s, WORD64 #) + with has_side_effects = True primop WriteByteArrayOp_Char "writeCharArray#" GenPrimOp - MutByteArr# s -> Int# -> Char# -> State# s -> State# s + MutableByteArray# s -> Int# -> Char# -> State# s -> State# s {Write 8-bit character; offset in bytes.} with has_side_effects = True primop WriteByteArrayOp_WideChar "writeWideCharArray#" GenPrimOp - MutByteArr# s -> Int# -> Char# -> State# s -> State# s + MutableByteArray# s -> Int# -> Char# -> State# s -> State# s {Write 31-bit character; offset in 4-byte words.} with has_side_effects = True primop WriteByteArrayOp_Int "writeIntArray#" GenPrimOp - MutByteArr# s -> Int# -> Int# -> State# s -> State# s + MutableByteArray# s -> Int# -> Int# -> State# s -> State# s with has_side_effects = True primop WriteByteArrayOp_Word "writeWordArray#" GenPrimOp - MutByteArr# s -> Int# -> Word# -> State# s -> State# s + MutableByteArray# s -> Int# -> Word# -> State# s -> State# s with has_side_effects = True primop WriteByteArrayOp_Addr "writeAddrArray#" GenPrimOp - MutByteArr# s -> Int# -> Addr# -> State# s -> State# s + MutableByteArray# s -> Int# -> Addr# -> State# s -> State# s with has_side_effects = True primop WriteByteArrayOp_Float "writeFloatArray#" GenPrimOp - MutByteArr# s -> Int# -> Float# -> State# s -> State# s + MutableByteArray# s -> Int# -> Float# -> State# s -> State# s with has_side_effects = True primop WriteByteArrayOp_Double "writeDoubleArray#" GenPrimOp - MutByteArr# s -> Int# -> Double# -> State# s -> State# s + MutableByteArray# s -> Int# -> Double# -> State# s -> State# s with has_side_effects = True primop WriteByteArrayOp_StablePtr "writeStablePtrArray#" GenPrimOp - MutByteArr# s -> Int# -> StablePtr# a -> State# s -> State# s + MutableByteArray# s -> Int# -> StablePtr# a -> State# s -> State# s with has_side_effects = True primop WriteByteArrayOp_Int8 "writeInt8Array#" GenPrimOp - MutByteArr# s -> Int# -> Int# -> State# s -> State# s + MutableByteArray# s -> Int# -> Int# -> State# s -> State# s with has_side_effects = True primop WriteByteArrayOp_Int16 "writeInt16Array#" GenPrimOp - MutByteArr# s -> Int# -> Int# -> State# s -> State# s + MutableByteArray# s -> Int# -> Int# -> State# s -> State# s with has_side_effects = True primop WriteByteArrayOp_Int32 "writeInt32Array#" GenPrimOp - MutByteArr# s -> Int# -> INT32 -> State# s -> State# s + MutableByteArray# s -> Int# -> INT32 -> State# s -> State# s with has_side_effects = True primop WriteByteArrayOp_Int64 "writeInt64Array#" GenPrimOp - MutByteArr# s -> Int# -> INT64 -> State# s -> State# s + MutableByteArray# s -> Int# -> INT64 -> State# s -> State# s with has_side_effects = True primop WriteByteArrayOp_Word8 "writeWord8Array#" GenPrimOp - MutByteArr# s -> Int# -> Word# -> State# s -> State# s + MutableByteArray# s -> Int# -> Word# -> State# s -> State# s with has_side_effects = True primop WriteByteArrayOp_Word16 "writeWord16Array#" GenPrimOp - MutByteArr# s -> Int# -> Word# -> State# s -> State# s + MutableByteArray# s -> Int# -> Word# -> State# s -> State# s with has_side_effects = True primop WriteByteArrayOp_Word32 "writeWord32Array#" GenPrimOp - MutByteArr# s -> Int# -> WORD32 -> State# s -> State# s + MutableByteArray# s -> Int# -> WORD32 -> State# s -> State# s with has_side_effects = True primop WriteByteArrayOp_Word64 "writeWord64Array#" GenPrimOp - MutByteArr# s -> Int# -> WORD64 -> State# s -> State# s + MutableByteArray# s -> Int# -> WORD64 -> State# s -> State# s with has_side_effects = True ------------------------------------------------------------------------ section "Addr#" - {Addr\# is an arbitrary machine address assumed to point outside - the garbage-collected heap. - - NB: {\tt nullAddr\#::Addr\#} is not a primop, but is defined in MkId.lhs. - It is the null address.} ------------------------------------------------------------------------ +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 Addr\#s are so far apart that their - difference doesn't fit in an 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 Addr\# arg, treated like an Int\#, - is divided by the Int\# arg.} + {Return the remainder when the {\tt Addr\#} arg, treated like an {\tt Int\#}, + is divided by the {\tt Int\#} arg.} #if (WORD_SIZE_IN_BITS == 32 || WORD_SIZE_IN_BITS == 64) primop Addr2IntOp "addr2Int#" GenPrimOp Addr# -> Int# {Coerce directly from address to int. Strongly deprecated.} @@ -1048,52 +952,68 @@ primop IndexOffAddrOp_Word64 "indexWord64OffAddr#" GenPrimOp primop ReadOffAddrOp_Char "readCharOffAddr#" GenPrimOp Addr# -> Int# -> State# s -> (# State# s, Char# #) {Reads 8-bit character; offset in bytes.} + with has_side_effects = 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 primop ReadOffAddrOp_Int "readIntOffAddr#" GenPrimOp Addr# -> Int# -> State# s -> (# State# s, Int# #) + with has_side_effects = True primop ReadOffAddrOp_Word "readWordOffAddr#" GenPrimOp Addr# -> Int# -> State# s -> (# State# s, Word# #) + with has_side_effects = True primop ReadOffAddrOp_Addr "readAddrOffAddr#" GenPrimOp Addr# -> Int# -> State# s -> (# State# s, Addr# #) + with has_side_effects = True primop ReadOffAddrOp_Float "readFloatOffAddr#" GenPrimOp Addr# -> Int# -> State# s -> (# State# s, Float# #) + with has_side_effects = True primop ReadOffAddrOp_Double "readDoubleOffAddr#" GenPrimOp Addr# -> Int# -> State# s -> (# State# s, Double# #) + with has_side_effects = True primop ReadOffAddrOp_StablePtr "readStablePtrOffAddr#" GenPrimOp Addr# -> Int# -> State# s -> (# State# s, StablePtr# a #) + with has_side_effects = True primop ReadOffAddrOp_Int8 "readInt8OffAddr#" GenPrimOp Addr# -> Int# -> State# s -> (# State# s, Int# #) + with has_side_effects = True primop ReadOffAddrOp_Int16 "readInt16OffAddr#" GenPrimOp Addr# -> Int# -> State# s -> (# State# s, Int# #) + with has_side_effects = True primop ReadOffAddrOp_Int32 "readInt32OffAddr#" GenPrimOp Addr# -> Int# -> State# s -> (# State# s, INT32 #) + with has_side_effects = True primop ReadOffAddrOp_Int64 "readInt64OffAddr#" GenPrimOp Addr# -> Int# -> State# s -> (# State# s, INT64 #) + with has_side_effects = True primop ReadOffAddrOp_Word8 "readWord8OffAddr#" GenPrimOp Addr# -> Int# -> State# s -> (# State# s, Word# #) + with has_side_effects = True primop ReadOffAddrOp_Word16 "readWord16OffAddr#" GenPrimOp Addr# -> Int# -> State# s -> (# State# s, Word# #) + with has_side_effects = True primop ReadOffAddrOp_Word32 "readWord32OffAddr#" GenPrimOp Addr# -> Int# -> State# s -> (# State# s, WORD32 #) + with has_side_effects = True primop ReadOffAddrOp_Word64 "readWord64OffAddr#" GenPrimOp Addr# -> Int# -> State# s -> (# State# s, WORD64 #) + with has_side_effects = True primop WriteOffAddrOp_Char "writeCharOffAddr#" GenPrimOp @@ -1162,33 +1082,33 @@ primop WriteOffAddrOp_Word64 "writeWord64OffAddr#" GenPrimOp ------------------------------------------------------------------------ section "Mutable variables" - {Operations on MutVar\#s, which behave like single-element mutable arrays.} + {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 MutVar\# with specified initial value in specified state thread.} + {Create {\tt MutVar\#} with specified initial value in specified state thread.} with - usage = { mangle NewMutVarOp [mkM, mkP] mkM } out_of_line = True + has_side_effects = True primop ReadMutVarOp "readMutVar#" GenPrimOp MutVar# s a -> State# s -> (# State# s, a #) - {Read contents of MutVar\#. Result is not yet evaluated.} + {Read contents of {\tt MutVar\#}. Result is not yet evaluated.} with - usage = { mangle ReadMutVarOp [mkM, mkP] mkM } + has_side_effects = True primop WriteMutVarOp "writeMutVar#" GenPrimOp MutVar# s a -> a -> State# s -> State# s - {Write contents of MutVar\#.} + {Write contents of {\tt MutVar\#}.} with - usage = { mangle WriteMutVarOp [mkM, mkM, mkP] mkR } has_side_effects = True primop SameMutVarOp "sameMutVar#" GenPrimOp MutVar# s a -> MutVar# s a -> Bool - with - usage = { mangle SameMutVarOp [mkP, mkP] mkM } -- not really the right type, but we don't know about pairs here. The -- correct type is @@ -1198,9 +1118,14 @@ primop SameMutVarOp "sameMutVar#" GenPrimOp primop AtomicModifyMutVarOp "atomicModifyMutVar#" GenPrimOp MutVar# s a -> (a -> b) -> State# s -> (# State# s, c #) with - usage = { mangle AtomicModifyMutVarOp [mkP, mkM, mkP] mkM } + out_of_line = True has_side_effects = 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" @@ -1215,44 +1140,64 @@ primop CatchOp "catch#" GenPrimOp -- Catch is actually strict in its first argument -- but we don't want to tell the strictness -- analyser about that! - usage = { mangle CatchOp [mkM, mkM . (inFun CatchOp mkM mkM), mkP] mkM } - -- [mkO, mkO . (inFun mkM mkO)] mkO -- might use caught action multiply out_of_line = True + has_side_effects = True primop RaiseOp "raise#" GenPrimOp a -> b with - strictness = { \ arity -> mkStrictSig (mkTopDmdType [lazyDmd] BotRes) } + 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. +-- +-- But we *do* want to know that it returns bottom after +-- being applied to two arguments primop RaiseIOOp "raiseIO#" GenPrimOp a -> State# RealWorld -> (# State# RealWorld, b #) with + strictness = { \ _arity -> mkStrictSig (mkTopDmdType [lazyDmd,lazyDmd] BotRes) } out_of_line = True + has_side_effects = True -primop BlockAsyncExceptionsOp "blockAsyncExceptions#" GenPrimOp +primop MaskAsyncExceptionsOp "maskAsyncExceptions#" GenPrimOp (State# RealWorld -> (# State# RealWorld, a #)) -> (State# RealWorld -> (# State# RealWorld, a #)) with out_of_line = True + has_side_effects = True -primop UnblockAsyncExceptionsOp "unblockAsyncExceptions#" GenPrimOp +primop MaskUninterruptibleOp "maskUninterruptible#" GenPrimOp (State# RealWorld -> (# State# RealWorld, a #)) -> (State# RealWorld -> (# State# RealWorld, a #)) with out_of_line = True + has_side_effects = True + +primop UnmaskAsyncExceptionsOp "unmaskAsyncExceptions#" GenPrimOp + (State# RealWorld -> (# State# RealWorld, a #)) + -> (State# RealWorld -> (# State# RealWorld, a #)) + with + 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 #) @@ -1292,22 +1237,32 @@ primop Check "check#" GenPrimOp primop NewTVarOp "newTVar#" GenPrimOp a -> State# s -> (# State# s, TVar# s a #) - {Create a new Tar\# holding a specified initial value.} + {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 TVar\#. Result is not yet evaluated.} + {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 TVar\#.} + {Write contents of {\tt TVar\#}.} with out_of_line = True has_side_effects = True @@ -1318,66 +1273,62 @@ primop SameTVarOp "sameTVar#" GenPrimOp ------------------------------------------------------------------------ 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, - (MVar\# a) can be represented by (MutVar\# (Maybe a)).)} + {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 mvar; initially empty.} + {Create new {\tt MVar\#}; initially empty.} with - usage = { mangle NewMVarOp [mkP] mkR } out_of_line = True + has_side_effects = True primop TakeMVarOp "takeMVar#" GenPrimOp MVar# s a -> State# s -> (# State# s, a #) - {If mvar is empty, block until it becomes full. + {If {\tt MVar\#} is empty, block until it becomes full. Then remove and return its contents, and set it empty.} with - usage = { mangle TakeMVarOp [mkM, mkP] mkM } - has_side_effects = True out_of_line = True + has_side_effects = True primop TryTakeMVarOp "tryTakeMVar#" GenPrimOp MVar# s a -> State# s -> (# State# s, Int#, a #) - {If mvar is empty, immediately return with integer 0 and value undefined. - Otherwise, return with integer 1 and contents of mvar, and set mvar empty.} + {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 - usage = { mangle TryTakeMVarOp [mkM, mkP] mkM } - has_side_effects = True out_of_line = True + has_side_effects = True primop PutMVarOp "putMVar#" GenPrimOp MVar# s a -> a -> State# s -> State# s - {If mvar is full, block until it becomes empty. + {If {\tt MVar\#} is full, block until it becomes empty. Then store value arg as its new contents.} with - usage = { mangle PutMVarOp [mkM, mkM, mkP] mkR } - has_side_effects = True out_of_line = True + has_side_effects = True primop TryPutMVarOp "tryPutMVar#" GenPrimOp MVar# s a -> a -> State# s -> (# State# s, Int# #) - {If mvar is full, immediately return with integer 0. - Otherwise, store value arg as mvar's new contents, and return with integer 1.} + {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 - usage = { mangle TryPutMVarOp [mkM, mkM, mkP] mkR } - has_side_effects = True out_of_line = True + has_side_effects = True primop SameMVarOp "sameMVar#" GenPrimOp MVar# s a -> MVar# s a -> Bool - with - usage = { mangle SameMVarOp [mkP, mkP] mkM } primop IsEmptyMVarOp "isEmptyMVar#" GenPrimOp MVar# s a -> State# s -> (# State# s, Int# #) - {Return 1 if mvar is empty; 0 otherwise.} + {Return 1 if {\tt MVar\#} is empty; 0 otherwise.} with - usage = { mangle IsEmptyMVarOp [mkP, mkP] mkM } out_of_line = True + has_side_effects = True ------------------------------------------------------------------------ section "Delay/wait operations" @@ -1436,29 +1387,40 @@ primop AsyncDoProcOp "asyncDoProc#" GenPrimOp ------------------------------------------------------------------------ section "Concurrency primitives" - {(In a non-concurrent implementation, ThreadId\# can be as singleton - type, whose (unique) value is returned by myThreadId\#. The - other operations can be omitted.)} ------------------------------------------------------------------------ +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 - usage = { mangle ForkOp [mkO, mkP] mkR } has_side_effects = True out_of_line = True primop ForkOnOp "forkOn#" GenPrimOp Int# -> a -> State# RealWorld -> (# State# RealWorld, ThreadId# #) with - usage = { mangle ForkOnOp [mkO, mkP] mkR } has_side_effects = True out_of_line = True primop KillThreadOp "killThread#" GenPrimOp ThreadId# -> a -> State# RealWorld -> State# RealWorld with - usage = { mangle KillThreadOp [mkP, mkM, mkP] mkR } has_side_effects = True out_of_line = True @@ -1472,6 +1434,7 @@ primop MyThreadIdOp "myThreadId#" GenPrimOp State# RealWorld -> (# State# RealWorld, ThreadId# #) with out_of_line = True + has_side_effects = True primop LabelThreadOp "labelThread#" GenPrimOp ThreadId# -> Addr# -> State# RealWorld -> State# RealWorld @@ -1483,24 +1446,43 @@ primop IsCurrentThreadBoundOp "isCurrentThreadBound#" GenPrimOp State# RealWorld -> (# State# RealWorld, Int# #) with out_of_line = True + has_side_effects = True + +primop NoDuplicateOp "noDuplicate#" GenPrimOp + State# RealWorld -> State# RealWorld + 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 -> c -> State# RealWorld -> (# State# RealWorld, Weak# b #) with - usage = { mangle MkWeakOp [mkZ, mkM, mkM, mkP] mkM } + has_side_effects = True + out_of_line = True + +primop MkWeakForeignEnvOp "mkWeakForeignEnv#" GenPrimOp + o -> b -> Addr# -> Addr# -> Int# -> Addr# -> State# RealWorld -> (# State# RealWorld, Weak# b #) + with has_side_effects = True out_of_line = True primop DeRefWeakOp "deRefWeak#" GenPrimOp Weak# a -> State# RealWorld -> (# State# RealWorld, Int#, a #) with - usage = { mangle DeRefWeakOp [mkM, mkP] mkM } has_side_effects = True out_of_line = True @@ -1508,9 +1490,6 @@ primop FinalizeWeakOp "finalizeWeak#" GenPrimOp Weak# a -> State# RealWorld -> (# State# RealWorld, Int#, (State# RealWorld -> (# State# RealWorld, () #)) #) with - usage = { mangle FinalizeWeakOp [mkM, mkP] - (mkR . (inUB FinalizeWeakOp - [id,id,inFun FinalizeWeakOp mkR mkM])) } has_side_effects = True out_of_line = True @@ -1523,17 +1502,19 @@ primop TouchOp "touch#" GenPrimOp section "Stable pointers and names" ------------------------------------------------------------------------ +primtype StablePtr# a + +primtype StableName# a + primop MakeStablePtrOp "makeStablePtr#" GenPrimOp a -> State# RealWorld -> (# State# RealWorld, StablePtr# a #) with - 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 #) with - usage = { mangle DeRefStablePtrOp [mkM, mkP] mkM } needs_wrapper = True has_side_effects = True out_of_line = True @@ -1541,26 +1522,20 @@ primop DeRefStablePtrOp "deRefStablePtr#" GenPrimOp primop EqStablePtrOp "eqStablePtr#" GenPrimOp StablePtr# a -> StablePtr# a -> Int# with - usage = { mangle EqStablePtrOp [mkP, mkP] mkR } has_side_effects = True primop MakeStableNameOp "makeStableName#" GenPrimOp a -> State# RealWorld -> (# State# RealWorld, StableName# a #) with - usage = { mangle MakeStableNameOp [mkZ, mkP] mkR } needs_wrapper = True has_side_effects = True out_of_line = True primop EqStableNameOp "eqStableName#" GenPrimOp StableName# a -> StableName# a -> Int# - with - usage = { mangle EqStableNameOp [mkP, mkP] mkR } primop StableNameToIntOp "stableNameToInt#" GenPrimOp StableName# a -> Int# - with - usage = { mangle StableNameToIntOp [mkP] mkR } ------------------------------------------------------------------------ section "Unsafe pointer equality" @@ -1569,8 +1544,6 @@ section "Unsafe pointer equality" primop ReallyUnsafePtrEqualityOp "reallyUnsafePtrEquality#" GenPrimOp a -> a -> Int# - with - usage = { mangle ReallyUnsafePtrEqualityOp [mkZ, mkZ] mkR } ------------------------------------------------------------------------ section "Parallelism" @@ -1579,11 +1552,23 @@ section "Parallelism" primop ParOp "par#" GenPrimOp a -> Int# with - usage = { mangle ParOp [mkO] mkR } -- Note that Par is lazy to avoid that the sparked thing -- gets evaluted strictly, which it should *not* be has_side_effects = True +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 + -- HWL: The first 4 Int# in all par... annotations denote: -- name, granularity info, size of result, degree of parallelism -- Same structure as _seq_ i.e. returns Int# @@ -1593,37 +1578,31 @@ primop ParOp "par#" GenPrimOp primop ParGlobalOp "parGlobal#" GenPrimOp a -> Int# -> Int# -> Int# -> Int# -> b -> Int# with - usage = { mangle ParGlobalOp [mkO, mkP, mkP, mkP, mkP, mkM] mkM } has_side_effects = True primop ParLocalOp "parLocal#" GenPrimOp a -> Int# -> Int# -> Int# -> Int# -> b -> Int# with - usage = { mangle ParLocalOp [mkO, mkP, mkP, mkP, mkP, mkM] mkM } has_side_effects = True primop ParAtOp "parAt#" GenPrimOp b -> a -> Int# -> Int# -> Int# -> Int# -> c -> Int# with - usage = { mangle ParAtOp [mkO, mkZ, mkP, mkP, mkP, mkP, mkM] mkM } has_side_effects = True primop ParAtAbsOp "parAtAbs#" GenPrimOp a -> Int# -> Int# -> Int# -> Int# -> Int# -> b -> Int# with - usage = { mangle ParAtAbsOp [mkO, mkP, mkP, mkP, mkP, mkM] mkM } has_side_effects = True primop ParAtRelOp "parAtRel#" GenPrimOp a -> Int# -> Int# -> Int# -> Int# -> Int# -> b -> Int# with - usage = { mangle ParAtRelOp [mkO, mkP, mkP, mkP, mkP, mkM] mkM } has_side_effects = True primop ParAtForNowOp "parAtForNow#" GenPrimOp b -> a -> Int# -> Int# -> Int# -> Int# -> c -> Int# with - usage = { mangle ParAtForNowOp [mkO, mkZ, mkP, mkP, mkP, mkP, mkM] mkM } has_side_effects = True -- copyable# and noFollow# are yet to be implemented (for GpH) @@ -1631,13 +1610,11 @@ primop ParAtForNowOp "parAtForNow#" GenPrimOp --primop CopyableOp "copyable#" GenPrimOp -- a -> Int# -- with --- usage = { mangle CopyableOp [mkZ] mkR } -- has_side_effects = True -- --primop NoFollowOp "noFollow#" GenPrimOp -- a -> Int# -- with --- usage = { mangle NoFollowOp [mkZ] mkR } -- has_side_effects = True @@ -1650,7 +1627,7 @@ section "Tag to enum stuff" primop DataToTagOp "dataToTag#" GenPrimOp a -> Int# with - strictness = { \ arity -> mkStrictSig (mkTopDmdType [seqDmd] TopRes) } + strictness = { \ _arity -> mkStrictSig (mkTopDmdType [seqDmd] TopRes) } -- dataToTag# must have an evaluated argument primop TagToEnumOp "tagToEnum#" GenPrimOp @@ -1661,10 +1638,12 @@ section "Bytecode operations" {Support for the bytecode interpreter and linker.} ------------------------------------------------------------------------ +primtype BCO# + {Primitive bytecode type.} primop AddrToHValueOp "addrToHValue#" GenPrimOp Addr# -> (# a #) - {Convert an Addr\# to a followable type.} + {Convert an {\tt Addr\#} to a followable type.} primop MkApUpd0_Op "mkApUpd0#" GenPrimOp BCO# -> (# a #) @@ -1672,17 +1651,164 @@ primop MkApUpd0_Op "mkApUpd0#" GenPrimOp out_of_line = True primop NewBCOOp "newBCO#" GenPrimOp - ByteArr# -> ByteArr# -> Array# a -> ByteArr# -> Int# -> ByteArr# -> State# s -> (# State# s, BCO# #) + ByteArray# -> ByteArray# -> Array# a -> Int# -> ByteArray# -> State# s -> (# State# s, BCO# #) with has_side_effects = True out_of_line = True +primop UnpackClosureOp "unpackClosure#" GenPrimOp + a -> (# Addr#, Array# b, ByteArray# #) + 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...} ------------------------------------------------------------------------ -section "Coercion" - {{\tt unsafeCoerce\# :: a -> b} is not a primop, but is defined in MkId.lhs.} + +primop TraceCcsOp "traceCcs#" GenPrimOp + a -> b -> b + with + has_side_effects = True + out_of_line = True ------------------------------------------------------------------------ +section "Etc" + {Miscellaneous built-ins} +------------------------------------------------------------------------ + +pseudoop "seq" + a -> b -> b + { Evaluates its first argument to head normal form, and then returns its second + argument as the result. } + +pseudoop "inline" + a -> a + { The call {\tt (inline f)} arranges that f is inlined, regardless of its size. + More precisely, the call {\tt (inline f)} rewrites to the right-hand side of + {\tt f}'s definition. This allows the programmer to control inlining from a + particular call site rather than the definition site of the function (c.f. + {\tt INLINE} pragmas in User's Guide, Section 7.10.3, "INLINE and NOINLINE + pragmas"). + + This inlining occurs regardless of the argument to the call or the size of + {\tt f}'s definition; it is unconditional. The main caveat is that {\tt f}'s + definition must be visible to the compiler. That is, {\tt f} must be + {\tt let}-bound in the current scope. If no inlining takes place, the + {\tt inline} function expands to the identity function in Phase zero; so its + use imposes no overhead. + + It is good practice to mark the function with an INLINABLE pragma at + its definition, (a) so that GHC guarantees to expose its unfolding regardless + of size, and (b) so that you have control over exactly what is inlined. } + +pseudoop "lazy" + a -> a + { The {\tt lazy} function restrains strictness analysis a little. The call + {\tt (lazy e)} means the same as {\tt e}, but {\tt lazy} has a magical + property so far as strictness analysis is concerned: it is lazy in its first + argument, even though its semantics is strict. After strictness analysis has + run, calls to {\tt lazy} are inlined to be the identity function. + + This behaviour is occasionally useful when controlling evaluation order. + Notably, {\tt lazy} is used in the library definition of {\tt Control.Parallel.par}: + + {\tt par :: a -> b -> b} + + {\tt par x y = case (par\# x) of \_ -> lazy y} + + If {\tt lazy} were not lazy, {\tt par} would look strict in {\tt y} which + would defeat the whole purpose of {\tt par}. + + Like {\tt seq}, the argument of {\tt lazy} can have an unboxed type. } + +primtype Any a + { The type constructor {\tt Any} is type to which you can unsafely coerce any + lifted type, and back. + * It is lifted, and hence represented by a pointer + + * It does not claim to be a {\it data} type, and that's important for + the code generator, because the code gen may {\it enter} a data value + but never enters a function value. + + It's also used to instantiate un-constrained type variables after type + checking. For example, {\tt length} has type + + {\tt length :: forall a. [a] -> Int} + + and the list datacon for the empty list has type + + {\tt [] :: forall a. [a]} + + In order to compose these two terms as {\tt length []} a type + application is required, but there is no constraint on the + choice. In this situation GHC uses {\tt Any}: + + {\tt length Any ([] Any)} + + Annoyingly, we sometimes need {\tt Any}s of other kinds, such as {\tt (* -> *)} etc. + This is a bit like tuples. We define a couple of useful ones here, + and make others up on the fly. If any of these others end up being exported + into interface files, we'll get a crash; at least until we add interface-file + syntax to support them. } + +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 + (but not coercions between floating-point and integral types) + + * 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 congnoscenti, 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. + + } + +-- 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 .eventlog file, + or to stderr, depending on the runtime RTS flags. } + with + has_side_effects = True + out_of_line = True ------------------------------------------------------------------------ --- ---