represent an {\tt Integer\#} holding the mantissa.}
with out_of_line = True
+primop DoubleDecode_2IntOp "decodeDouble_2Int#" GenPrimOp
+ Double# -> (# Int#, Int#, Int# #)
+ {Convert to arbitrary-precision integer.
+ First {\tt Int\#} in result is the high 32 bits of the mantissa, and the
+ second is the low 32. The third is the exponent.}
+ with out_of_line = True
+
------------------------------------------------------------------------
section "Float#"
{Operations on single-precision (32-bit) floating-point numbers.}
represent an {\tt Integer\#} holding the mantissa.}
with out_of_line = True
+primop FloatDecode_IntOp "decodeFloat_Int#" GenPrimOp
+ Float# -> (# Int#, Int# #)
+ {Convert to arbitrary-precision integer.
+ First {\tt Int\#} in result is the mantissa; second is the exponent.}
+ with out_of_line = True
+
------------------------------------------------------------------------
section "Arrays"
{Operations on {\tt Array\#}.}
primop RaiseOp "raise#" GenPrimOp
a -> b
with
- strictness = { \ arity -> mkStrictSig (mkTopDmdType [lazyDmd] BotRes) }
+ strictness = { \ _arity -> mkStrictSig (mkTopDmdType [lazyDmd] BotRes) }
-- NB: result is bottom
out_of_line = True
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
* 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
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.
+ 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