+-- primop internal-name "name-in-program-text" type category {description} attributes
+
+-- The description is optional.
+
+-- The default attribute values which apply if you don't specify
+-- other ones. Attribute values can be True, False, or arbitrary
+-- text between curly brackets. This is a kludge to enable
+-- 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.
+
+defaults
+ has_side_effects = False
+ out_of_line = False
+ commutable = False
+ needs_wrapper = False
+ can_fail = False
+ strictness = { \ arity -> StrictnessInfo (replicate arity wwPrim) False }
+ usage = { nomangle other }
+
+-- Currently, documentation is produced using latex, so contents of description fields
+-- should be legal latex. Descriptions can contain matched pairs of embedded curly brackets.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+\f
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+\f
+
+
+
+
+
+\f
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+section "The word size story."
+ {Haskell98 specifies that signed integers (type {\tt Int}) must contain at least 30
+ bits. GHC always implements {\tt Int} using the primitive type {\tt Int\#}, whose
+ size equals the {\tt MachDeps.h} constant {\tt WORD\_SIZE\_IN\_BITS}. This
+ is normally set based on the {\tt config.h} parameter {\tt SIZEOF\_LONG},
+ i.e., 32 bits on 32-bit machines, 64 bits on 64-bit machines. However, it can
+ also be explicitly set to a smaller number, e.g., 31 bits, to allow the possibility
+ of using tag bits. Currently GHC itself has only 32-bit and 64-bit variants,
+ but 30 or 31-bit code can be exported as an external core file for use in
+ other back ends.
+
+ GHC also implements a primitive unsigned integer type {\tt Word\#} which always
+ has the same number of bits as {\tt Int\#}.
+
+ In addition, GHC supports families of explicit-sized integers and words at
+ 8, 16, 32, and 64 bits, with the usual arithmetic operations, comparisons,
+ and a range of conversions. The 8-bit and 16-bit sizes are always represented as
+ {\tt Int\#} and {\tt Word\#}, and the operations implemented in terms of the
+ the primops on these types, with suitable range restrictions on the results
+ (using the {\tt narrow$n$Int\#} and {\tt narrow$n$Word\#} families of primops.
+ The 32-bit sizes are represented using {\tt Int\#} and {\tt Word\#} when
+ {\tt WORD\_SIZE\_IN\_BITS} $\geq$ 32;
+ otherwise, these are represented using distinct primitive types {\tt Int32\#}
+ and {\tt Word32\#}. These (when needed) have a complete set of corresponding
+ operations; however, nearly all of these are implemented as external C functions
+ rather than as primops. Exactly the same story applies to the 64-bit sizes.
+ All of these details are hidden under the {\tt PrelInt} and {\tt PrelWord} modules,
+ which use {\tt \#if}-defs to invoke the appropriate types and operators.
+
+ Word size also matters for the families of primops
+ for indexing/reading/writing fixed-size quantities at offsets from
+ an array base, address, or foreign pointer. Here, a slightly different approach is taken.
+ The names of these primops are fixed, but their
+ {\it types} vary according to the value of {\tt WORD\_SIZE\_IN\_BITS}. For example, if
+ word size is at least 32 bits then an operator like \texttt{indexInt32Array\#}
+ has type {\tt ByteArr\# -> Int\# -> Int\#}; otherwise it has type
+ {\tt ByteArr\# -> Int\# -> Int32\#}. This approach confines the necessary {\tt \#if}-defs to this file;
+ no conditional compilation is needed in the files that expose these primops, namely \texttt{lib/std/PrelStorable.lhs},
+ \texttt{hslibs/lang/ArrayBase.hs}, and (in deprecated fashion) in \texttt{hslibs/lang/ForeignObj.lhs}
+ and \texttt{hslibs/lang/Addr.lhs}.
+
+ Finally, there are strongly deprecated primops for coercing between {\tt Addr\#}, the primitive
+ type of machine addresses, and {\tt Int\#}. These are pretty bogus anyway, but will work on
+ existing 32-bit and 64-bit GHC targets; they are completely bogus when tag bits are used in
+ {\tt Int\#}, so are not available in this case.
+}
+
+-- Define synonyms for indexing ops.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+------------------------------------------------------------------------
+section "Char#"
+ {Operations on 31-bit characters.}
+------------------------------------------------------------------------
+
+
+primop CharGtOp "gtChar#" Compare Char# -> Char# -> Bool
+primop CharGeOp "geChar#" Compare Char# -> Char# -> Bool
+
+primop CharEqOp "eqChar#" Compare
+ Char# -> Char# -> Bool
+ with commutable = True
+
+primop CharNeOp "neChar#" Compare
+ Char# -> Char# -> Bool
+ with commutable = True
+
+primop CharLtOp "ltChar#" Compare Char# -> Char# -> Bool
+primop CharLeOp "leChar#" Compare Char# -> Char# -> Bool
+
+primop OrdOp "ord#" GenPrimOp Char# -> Int#
+
+------------------------------------------------------------------------
+section "Int#"
+ {Operations on native-size integers (30+ bits).}
+------------------------------------------------------------------------
+
+primop IntAddOp "+#" Dyadic
+ Int# -> Int# -> Int#
+ with commutable = True
+
+primop IntSubOp "-#" Dyadic Int# -> Int# -> Int#
+
+primop IntMulOp "*#"
+ Dyadic Int# -> Int# -> Int#
+ with commutable = True
+
+primop IntQuotOp "quotInt#" Dyadic
+ Int# -> Int# -> Int#
+ {Rounds towards zero.}
+ with can_fail = True
+
+primop IntRemOp "remInt#" Dyadic
+ Int# -> Int# -> Int#
+ {Satisfies \texttt{(quotInt\# x y) *\# y +\# (remInt\# x y) == x}.}
+ with can_fail = True
+
+primop IntGcdOp "gcdInt#" Dyadic Int# -> Int# -> Int#
+primop IntNegOp "negateInt#" Monadic Int# -> Int#
+primop IntAddCOp "addIntC#" GenPrimOp Int# -> Int# -> (# Int#, Int# #)
+ {Add with carry. First member of result is (wrapped) sum; second member is 0 iff no overflow occured.}
+primop IntSubCOp "subIntC#" GenPrimOp Int# -> Int# -> (# Int#, Int# #)
+ {Subtract with carry. First member of result is (wrapped) difference; second member is 0 iff no overflow occured.}
+primop IntMulCOp "mulIntC#" GenPrimOp Int# -> Int# -> (# Int#, Int# #)
+ {Multiply with carry. First member of result is (wrapped) product; second member is 0 iff no overflow occured.}
+primop IntGtOp ">#" Compare Int# -> Int# -> Bool
+primop IntGeOp ">=#" Compare Int# -> Int# -> Bool
+
+primop IntEqOp "==#" Compare
+ Int# -> Int# -> Bool
+ with commutable = True
+
+primop IntNeOp "/=#" Compare
+ Int# -> Int# -> Bool
+ with commutable = True
+
+primop IntLtOp "<#" Compare Int# -> Int# -> Bool
+primop IntLeOp "<=#" Compare Int# -> Int# -> Bool
+
+primop ChrOp "chr#" GenPrimOp Int# -> Char#
+
+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 "iShiftL#" GenPrimOp Int# -> Int# -> Int#
+ {Shift left. Return 0 if shifted by more than size of an Int\#.}
+primop ISraOp "iShiftRA#" GenPrimOp Int# -> Int# -> Int#
+ {Shift right arithemetic. Return 0 if shifted by more than size of an Int\#.}
+primop ISrlOp "iShiftRL#" GenPrimOp Int# -> Int# -> Int#
+ {Shift right logical. Return 0 if shifted by more than size of an Int\#.}
+
+------------------------------------------------------------------------
+section "Word#"
+ {Operations on native-sized unsigned words (30+ bits).}
+------------------------------------------------------------------------
+
+primop WordAddOp "plusWord#" Dyadic Word# -> Word# -> Word#
+ with commutable = True