[project @ 1998-12-02 13:17:09 by simonm]
[ghc-hetmet.git] / ghc / includes / StgMacros.lh
diff --git a/ghc/includes/StgMacros.lh b/ghc/includes/StgMacros.lh
deleted file mode 100644 (file)
index fbbc2e4..0000000
+++ /dev/null
@@ -1,2386 +0,0 @@
-%
-% (c) The GRASP/AQUA Project, Glasgow University, 1993-1994
-%
-\section[StgMacros]{C macros used in GHC-generated \tr{.hc} files}
-
-\begin{code}
-#ifndef STGMACROS_H
-#define STGMACROS_H
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[StgMacros-abbrev]{Abbreviatory(?) and general macros}
-%*                                                                     *
-%************************************************************************
-
-Mere abbreviations:
-\begin{code}
-/* for function declarations */
-#define STGFUN(f)  F_ f(STG_NO_ARGS)
-#define STATICFUN(f) static F_ f(STG_NO_ARGS)
-
-/* for functions/data that are really external to this module */
-#define EXTFUN(f)      extern F_ f(STG_NO_ARGS)
-#define EXTDATA(d)     extern W_ d[]
-#define EXTDATA_RO(d)  extern const W_ d[] /* read-only */
-
-/* for fwd decls to functions/data somewhere else in this module */
-/* (identical for the mo') */
-#define INTFUN(f)      static F_ f(STG_NO_ARGS)
-#define INTDATA(d)     extern W_ d[]
-#define INTDATA_RO(d)  extern const W_ d[] /* read-only */
-
-/* short forms of most of the above */
-
-#define FN_(f)         F_ f(STG_NO_ARGS)
-#define IFN_(f)                static F_ f(STG_NO_ARGS)
-#define EF_(f)         extern F_ f(STG_NO_ARGS)
-#define ED_(d)         extern W_ d[]
-#define ED_RO_(d)      extern const W_ d[] /* read-only */
-#define IF_(f)         static F_ f(STG_NO_ARGS)
-
-/* GCC is uncooperative about the next one: */
-/* But, the "extern" prevents initialisation... ADR */
-#if defined(__GNUC__)
-#define ID_(d)         extern W_ d[]
-#define ID_RO_(d)      extern const W_ d[] /* read-only */
-#else
-#define ID_(d)         static W_ d[]
-#define ID_RO_(d)      static const W_ d[] /* read-only */
-#endif /* not GCC */
-\end{code}
-
-General things; note: general-but-``machine-dependent'' macros are
-given in \tr{StgMachDeps.lh}.
-\begin{code}
-I_ STG_MAX PROTO((I_, I_)); /* GCC -Wall loves prototypes */
-
-extern STG_INLINE
-I_
-STG_MAX(I_ a, I_ b) { return((a >= b) ? a : b); }
-/* NB: the naive #define macro version of STG_MAX
-   can lead to exponential CPP explosion, if you
-   have very-nested STG_MAXes.
-*/
-
-/*
-Macros to combine two short words into a single
-word and split such a word back into two.
-
-Dependent on machine word size :-)
-*/
-
-#define        COMBINE_WORDS(word,short1,short2)               \
-       do {                                            \
-           ((packed_shorts *)&(word))->wu.s1 = short1; \
-           ((packed_shorts *)&(word))->wu.s2 = short2; \
-       } while(0)
-
-#define SPLIT_WORD(word,short1,short2)                 \
-       do {                                            \
-           short1 = ((packed_shorts *)&(word))->wu.s1; \
-           short2 = ((packed_shorts *)&(word))->wu.s2; \
-       } while(0)
-
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[StgMacros-gen-stg]{General STGish macros}
-%*                                                                     *
-%************************************************************************
-
-Common sizes of vector-return tables.
-
-Claim: don't need fwd decls for return pts in \tr{VECTBL*}, because
-the AbsC flattener ensures that things come out sufficiently
-``backwards''.
-
-\begin{code}
-#ifdef __STG_REV_TBLS__
-#define UNVECTBL(staticp,label,a)   /* nothing */
-#else
-#define UNVECTBL(staticp,label,a) \
-EXTFUN(a); \
-staticp const W_ label[] = { \
-  (W_) a \
-};
-#endif
-\end{code}
-
-\begin{code}
-#if defined(USE_SPLIT_MARKERS)
-#define __STG_SPLIT_MARKER(n) FN_(CAT2(__stg_split_marker,n)){ }
-#else
-#define __STG_SPLIT_MARKER(n) /* nothing */
-#endif
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[StgMacros-exceptions]{Exception-checking macros}
-%*                                                                     *
-%************************************************************************
-
-Argument-satisfaction check, stack(s) overflow check, heap overflow
-check.
-
-The @SUBTRACT(upper, lower)@ macros return a positive result in words
-indicating the amount by which upper is above lower on the stack.
-
-\begin{code}
-#define SUBTRACT_A_STK( upper, lower ) AREL( (lower) - (upper) )
-#define SUBTRACT_B_STK( upper, lower ) BREL( (lower) - (upper) )
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection[StgMacros-arg-satis]{Argument-satisfaction checks}
-%*                                                                     *
-%************************************************************************
-
-@ARGS_CHK(n)@ sees of there are @n@ words of args on the A/B stack.
-If not, it jumps to @UpdatePAP@.
-
-@ARGS_CHK@ args are pre-directionified.
-Notice that we do the comparisons in the form (x < a+n), for
-some constant n.  This generates more efficient code (with GCC at least)
-than (x-a < n).
-
-\begin{code}
-#define ARGS_CHK_A(n)                                          \
-       if (SuA /*SUBTRACT_A_STK( SpA, SuA )*/ < (SpA+(n))) {   \
-               JMP_( UpdatePAP );                              \
-       }
-
-#define ARGS_CHK_A_LOAD_NODE(n, closure_addr)                  \
-       if (SuA /*SUBTRACT_A_STK( SpA, SuA )*/ < (SpA+(n))) {   \
-               Node = (P_) closure_addr;                       \
-               JMP_( UpdatePAP );                              \
-       }
-
-#define ARGS_CHK_B(n)                                          \
-       if (SpB /*SUBTRACT_B_STK( SpB, SuB )*/ < (SuB-(n))) {   \
-               JMP_( UpdatePAP );                              \
-       }
-
-
-#define ARGS_CHK_B_LOAD_NODE(n, closure_addr)                  \
-       if (SpB /*SUBTRACT_B_STK( SpB, SuB )*/ < (SuB-(n))) {   \
-               Node = (P_) closure_addr;                       \
-               JMP_( UpdatePAP );                              \
-       }
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection[StgMacros-stk-chks]{Stack-overflow check}
-%*                                                                     *
-%************************************************************************
-
-@STK_CHK(a,b)@ [misc args omitted...] checks that we can allocate @a@
-words of A stack and @b@ words of B stack.  If not, it calls
-@StackOverflow@ (which dies).
-
-(It will be different in the parallel case.)
-
-NB: args @a@ and @b@ are pre-direction-ified!
-\begin{code}
-I_ SqueezeUpdateFrames PROTO((P_, P_, P_));
-int sanityChk_StkO (P_ stko); /* ToDo: move to a sane place */
-
-#if ! defined(CONCURRENT)
-
-extern void StackOverflow(STG_NO_ARGS) STG_NORETURN;
-
-#if STACK_CHECK_BY_PAGE_FAULT
-
-#define STACK_OVERFLOW(liveness,hda,hdb,spa,spb,rtype,reenter) \
-    /* use memory protection instead; still need ticky-ness */
-
-#else
-
-#define STACK_OVERFLOW(liveness,hda,hdb,spa,spb,rtype,reenter) \
-    ULTRASAFESTGCALL0(void,(void *),StackOverflow)
-
-#endif /* not using page-faulting */
-
-#else /* threaded */
-
-I_ StackOverflow PROTO((W_, W_));
-
-/*
- * On a uniprocessor, we do *NOT* context switch on a stack overflow 
- * (though we may GC).  Therefore, we never have to reenter node.
- */
-
-#define STACK_OVERFLOW(liveness,hda,hdb,spa,spb,rtype,reenter) \
-    DO_STACKOVERFLOW((hda+hdb)<<2|((rtype)<<1)|(reenter),((spa)<<20)|((spb)<<8)|(liveness))
-
-#define STACK_OVERFLOW_HEADROOM(args,y)            ((args) >> 2)
-#define STACK_OVERFLOW_PRIM_RETURN(args,y)  ((args) & 2)
-#define STACK_OVERFLOW_REENTER(args,y)     ((args) & 1)
-
-#define STACK_OVERFLOW_AWORDS(x,args)      (((args) >> 20) & 0x0fff)
-#define STACK_OVERFLOW_BWORDS(x,args)      (((args) >> 8) & 0x0fff)
-#define STACK_OVERFLOW_LIVENESS(x,args)            ((args) & 0xff)
-
-#endif /* CONCURRENT */
-
-#define STK_CHK(liveness_mask,a_headroom,b_headroom,spa,spb,ret_type,reenter)\
-do {                                                           \
-  DO_ASTK_HWM(); /* ticky-ticky profiling */                   \
-  DO_BSTK_HWM();                                               \
-  if (STKS_OVERFLOW_OP(((a_headroom) + 1), ((b_headroom) + 1))) {      \
-    STACK_OVERFLOW(liveness_mask,a_headroom,b_headroom,spa,spb,ret_type,reenter);\
-  }                                                            \
-}while(0)
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection[StgMacros-heap-chks]{Heap-overflow checks}
-%*                                                                     *
-%************************************************************************
-
-Please see the general discussion/commentary about ``what really
-happens in a GC,'' in \tr{SMinterface.lh}.
-
-\begin{code}
-void PerformGC PROTO((W_));
-void RealPerformGC PROTO((W_ liveness, W_ reqsize, W_  always_reenter_node, rtsBool do_full_collection));
-void checkInCCallGC(STG_NO_ARGS);
-
-#ifndef PAR
-void StgPerformGarbageCollection(STG_NO_ARGS);
-#endif
-
-#ifndef CONCURRENT
-
-#define OR_MSG_PENDING /* never */
-
-#define HEAP_OVERFLOW(liveness,n,reenter)      \
-    do {                                       \
-    DO_GC((((W_)n)<<8)|(liveness));            \
-    } while (0)
-
-#define REQSIZE_BITMASK        ((1L << ((BITS_IN(W_) - 8 + 1))) - 1)
-#define HEAP_OVERFLOW_REQSIZE(args)    (((args) >> 8) & REQSIZE_BITMASK)
-#define HEAP_OVERFLOW_REENTER(args)    0
-#define HEAP_OVERFLOW_LIVENESS(args)   ((args) & 0xff)
-
-#else /* CONCURRENT */
-
-void ReallyPerformThreadGC PROTO((W_, rtsBool));
-
-#define HEAP_OVERFLOW(liveness,n,reenter)      \
-    do {                                       \
-    DO_GC((((W_)(n))<<9)|((reenter)<<8)|(liveness)); \
-    } while (0)
-
-#define REQSIZE_BITMASK        ((1L << ((BITS_IN(W_) - 9 + 1))) - 1)
-#define HEAP_OVERFLOW_REQSIZE(args)    (((args) >> 9) & REQSIZE_BITMASK)
-#define HEAP_OVERFLOW_REENTER(args)    (((args) >> 8) & 0x1)
-#define HEAP_OVERFLOW_LIVENESS(args)   ((args) & 0xff)
-
-#ifndef PAR
-
-#define OR_MSG_PENDING /* never */
-
-#else 
-
-extern int PacketsWaiting;             /*Probes for incoming messages*/
-extern int heapChkCounter;             /*Not currently used! We check for messages when*/
-                                       /*a thread is resheduled PWT*/
-/* #define OR_MSG_PENDING      || (--heapChkCounter == 0 && PacketsWaiting())*/
-#define OR_MSG_PENDING /* never */
-
-#endif /* PAR */
-#endif /* CONCURRENT */
-
-#if 0 /* alpha_TARGET_ARCH */
-#define CACHE_LINE  4  /* words */
-#define LINES_AHEAD 3
-#define PRE_FETCH(n)                                   \
-do {                                                   \
- StgInt j;                                             \
- j = ((STG_VOLATILE StgInt *) Hp)[LINES_AHEAD * CACHE_LINE];   \
-} while(0);
-#define EXTRA_HEAP_WORDS (CACHE_LINE * LINES_AHEAD)
-#else
-#define PRE_FETCH(reg)
-#define EXTRA_HEAP_WORDS 0
-#endif
-
-#if defined(GRAN)
-#define HEAP_CHK(liveness_mask,n,reenter)                      \
-       do {                                                    \
-       /* TICKY_PARANOIA(__FILE__, __LINE__); */               \
-       /* THREAD_CONTEXT_SWITCH(liveness_mask,reenter); */             \
-       ALLOC_HEAP(n); /* ticky profiling */                    \
-        GRAN_ALLOC_HEAP(n,liveness_mask); /* Granularity Simulation */ \
-       if (((Hp = Hp + (n)) > HpLim)) {                        \
-           /* Old:  STGCALL3_GC(PerformGC,liveness_mask,n,StgFalse); */\
-           HEAP_OVERFLOW(liveness_mask,n,StgFalse); \
-       }}while(0)
-
-#else
-
-#define HEAP_CHK(liveness_mask,n,reenter)              \
-do {                                                   \
-  /* TICKY_PARANOIA(__FILE__, __LINE__); */            \
-  PRE_FETCH(n);                                                \
-  ALLOC_HEAP(n); /* ticky profiling */                 \
-  if (((Hp = Hp + (n)) > HpLim) OR_INTERVAL_EXPIRED OR_CONTEXT_SWITCH OR_MSG_PENDING) {        \
-    HEAP_OVERFLOW(liveness_mask,n,reenter);            \
-  }                                                    \
-} while(0)
-
-#endif  /* GRAN */
-
-#ifdef CONCURRENT
-
-#define HEAP_CHK_AND_RESTORE_N(liveness_mask,n,reenter)        \
-do {                                                   \
-  /* TICKY_PARANOIA(__FILE__, __LINE__); */            \
-  PRE_FETCH(n);                                                \
-  ALLOC_HEAP(n); /* ticky profiling */                 \
-  if (((Hp = Hp + (n)) > HpLim) OR_INTERVAL_EXPIRED OR_CONTEXT_SWITCH OR_MSG_PENDING) {        \
-    HEAP_OVERFLOW(liveness_mask,n,reenter);            \
-    n = TSO_ARG1(CurrentTSO);                          \
-  }} while(0)
-
-#else
-
-#define HEAP_CHK_AND_RESTORE_N(liveness_mask,n,reenter)            \
-    HEAP_CHK(liveness_mask,n,reenter)
-
-#endif
-
-\end{code}
-
-
-%************************************************************************
-%*                                                                     *
-\subsection[StgMacros-prim-ops]{Primitive operations}
-%*                                                                     *
-%************************************************************************
-
-One thing to be {\em very careful about} with these macros that assign
-to results is that the assignment must come {\em last}.         Some of the
-other arguments may be in terms of addressing modes that get clobbered
-by the assignment.  (Dirty imperative programming RULES!)
-
-The order here is roughly that in \tr{compiler/prelude/PrimOps.lhs}.
-
-%************************************************************************
-%*                                                                     *
-\subsubsection[StgMacros-compare-primops]{Primitive comparison ops on basic types}
-%*                                                                     *
-%************************************************************************
-
-We cast the chars in case one of them is a literal (so C things work right
-even for 8-bit chars).
-\begin{code}
-#define gtCharZh(r,a,b)        r=(I_)((a)> (b))
-#define geCharZh(r,a,b)        r=(I_)((a)>=(b))
-#define eqCharZh(r,a,b)        r=(I_)((a)==(b))
-#define neCharZh(r,a,b)        r=(I_)((a)!=(b))
-#define ltCharZh(r,a,b)        r=(I_)((a)< (b))
-#define leCharZh(r,a,b)        r=(I_)((a)<=(b))
-
-/* Int comparisons: >#, >=# etc */
-#define ZgZh(r,a,b)    r=(I_)((a) >(b))
-#define ZgZeZh(r,a,b)  r=(I_)((a)>=(b))
-#define ZeZeZh(r,a,b)  r=(I_)((a)==(b))
-#define ZdZeZh(r,a,b)  r=(I_)((a)!=(b))
-#define ZlZh(r,a,b)    r=(I_)((a) <(b))
-#define ZlZeZh(r,a,b)  r=(I_)((a)<=(b))
-
-#define gtWordZh(r,a,b)        r=(I_)((a) >(b))
-#define geWordZh(r,a,b)        r=(I_)((a)>=(b))
-#define eqWordZh(r,a,b)        r=(I_)((a)==(b))
-#define neWordZh(r,a,b)        r=(I_)((a)!=(b))
-#define ltWordZh(r,a,b)        r=(I_)((a) <(b))
-#define leWordZh(r,a,b)        r=(I_)((a)<=(b))
-
-#define gtAddrZh(r,a,b)        r=(I_)((a) >(b))
-#define geAddrZh(r,a,b)        r=(I_)((a)>=(b))
-#define eqAddrZh(r,a,b)        r=(I_)((a)==(b))
-#define neAddrZh(r,a,b)        r=(I_)((a)!=(b))
-#define ltAddrZh(r,a,b)        r=(I_)((a) <(b))
-#define leAddrZh(r,a,b)        r=(I_)((a)<=(b))
-
-#define gtFloatZh(r,a,b)  r=(I_)((a)> (b))
-#define geFloatZh(r,a,b)  r=(I_)((a)>=(b))
-#define eqFloatZh(r,a,b)  r=(I_)((a)==(b))
-#define neFloatZh(r,a,b)  r=(I_)((a)!=(b))
-#define ltFloatZh(r,a,b)  r=(I_)((a)< (b))
-#define leFloatZh(r,a,b)  r=(I_)((a)<=(b))
-
-/* Double comparisons: >##, >=#@ etc */
-#define ZgZhZh(r,a,b)  r=(I_)((a) >(b))
-#define ZgZeZhZh(r,a,b)        r=(I_)((a)>=(b))
-#define ZeZeZhZh(r,a,b)        r=(I_)((a)==(b))
-#define ZdZeZhZh(r,a,b)        r=(I_)((a)!=(b))
-#define ZlZhZh(r,a,b)  r=(I_)((a) <(b))
-#define ZlZeZhZh(r,a,b)        r=(I_)((a)<=(b))
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection[StgMacros-char-primops]{Primitive @Char#@ ops (and @LitString#@ish things, too)}
-%*                                                                     *
-%************************************************************************
-
-We cast the chars in case one of them is a literal (so C things work right
-even for 8-bit chars).
-\begin{code}
-#define ordZh(r,a)     r=(I_)((W_) (a))
-#define chrZh(r,a)     r=(StgChar)((W_)(a))
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection[StgMacros-int-primops]{Primitive @Int#@ ops}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-I_ stg_div PROTO((I_ a, I_ b));
-
-#define ZpZh(r,a,b)            r=(a)+(b)
-#define ZmZh(r,a,b)            r=(a)-(b)
-#define ZtZh(r,a,b)            r=(a)*(b)
-#define quotIntZh(r,a,b)       r=(a)/(b)
-/* ZdZh not used??? --SDM */
-#define ZdZh(r,a,b)            r=ULTRASAFESTGCALL2(I_,(void *, I_, I_),stg_div,(a),(b))
-#define remIntZh(r,a,b)                r=(a)%(b)
-#define negateIntZh(r,a)       r=-(a)
-
-/* Ever used ? -- SOF */
-#define absIntZh(a)            r=(( (a) >= 0 ) ? (a) : (-(a)))
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection[StgMacros-word-primops]{Primitive @Word#@ ops}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-#define quotWordZh(r,a,b)      r=((W_)a)/((W_)b)
-#define remWordZh(r,a,b)       r=((W_)a)%((W_)b)
-
-#define andZh(r,a,b)   r=(a)&(b)
-#define orZh(r,a,b)    r=(a)|(b)
-#define xorZh(r,a,b)   r=(a)^(b)
-#define notZh(r,a)     r=~(a)
-
-#define shiftLZh(r,a,b)          r=(a)<<(b)
-#define shiftRLZh(r,a,b)  r=(a)>>(b)
-#define iShiftLZh(r,a,b)  r=(a)<<(b)
-/* Right shifting of signed quantities is not portable in C, so
-   the behaviour you'll get from using these primops depends
-   on the whatever your C compiler is doing. ToDo: fix. -- sof 8/98
-*/
-#define iShiftRAZh(r,a,b) r=(a)>>(b)
-#define iShiftRLZh(r,a,b) r=(a)>>(b)
-
-#define int2WordZh(r,a) r=(W_)(a)
-#define word2IntZh(r,a) r=(I_)(a)
-
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection[StgMacros-addr-primops]{Primitive @Addr#@ ops}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-#define int2AddrZh(r,a) r=(A_)(a)
-#define addr2IntZh(r,a) r=(I_)(a)
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection[StgMacros-float-primops]{Primitive @Float#@ ops}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-#define plusFloatZh(r,a,b)     r=(a)+(b)
-#define minusFloatZh(r,a,b)    r=(a)-(b)
-#define timesFloatZh(r,a,b)    r=(a)*(b)
-#define divideFloatZh(r,a,b)   r=(a)/(b)
-#define negateFloatZh(r,a)     r=-(a)
-
-#define int2FloatZh(r,a)       r=(StgFloat)(a)
-#define float2IntZh(r,a)       r=(I_)(a)
-
-#define expFloatZh(r,a)                r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),exp,a)
-#define logFloatZh(r,a)                r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),log,a)
-#define sqrtFloatZh(r,a)       r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),sqrt,a)
-#define sinFloatZh(r,a)                r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),sin,a)
-#define cosFloatZh(r,a)                r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),cos,a)
-#define tanFloatZh(r,a)                r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),tan,a)
-#define asinFloatZh(r,a)       r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),asin,a)
-#define acosFloatZh(r,a)       r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),acos,a)
-#define atanFloatZh(r,a)       r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),atan,a)
-#define sinhFloatZh(r,a)       r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),sinh,a)
-#define coshFloatZh(r,a)       r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),cosh,a)
-#define tanhFloatZh(r,a)       r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),tanh,a)
-#define powerFloatZh(r,a,b)    r=(StgFloat) SAFESTGCALL2(StgDouble,(void *, StgDouble,StgDouble),pow,a,b)
-
-/* encoding/decoding given w/ Integer stuff */
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection[StgMacros-double-primops]{Primitive @Double#@ ops}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-#define ZpZhZh(r,a,b)          r=(a)+(b)
-#define ZmZhZh(r,a,b)          r=(a)-(b)
-#define ZtZhZh(r,a,b)          r=(a)*(b)
-#define ZdZhZh(r,a,b)          r=(a)/(b)
-#define negateDoubleZh(r,a)    r=-(a)
-
-#define int2DoubleZh(r,a)      r=(StgDouble)(a)
-#define double2IntZh(r,a)      r=(I_)(a)
-
-#define float2DoubleZh(r,a)    r=(StgDouble)(a)
-#define double2FloatZh(r,a)    r=(StgFloat)(a)
-
-#define expDoubleZh(r,a)       r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),exp,a)
-#define logDoubleZh(r,a)       r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),log,a)
-#define sqrtDoubleZh(r,a)      r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),sqrt,a)
-#define sinDoubleZh(r,a)       r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),sin,a)
-#define cosDoubleZh(r,a)       r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),cos,a)
-#define tanDoubleZh(r,a)       r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),tan,a)
-#define asinDoubleZh(r,a)      r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),asin,a)
-#define acosDoubleZh(r,a)      r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),acos,a)
-#define atanDoubleZh(r,a)      r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),atan,a)
-#define sinhDoubleZh(r,a)      r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),sinh,a)
-#define coshDoubleZh(r,a)      r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),cosh,a)
-#define tanhDoubleZh(r,a)      r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),tanh,a)
-/* Power: **## */
-#define ZtZtZhZh(r,a,b)        r=(StgDouble) SAFESTGCALL2(StgDouble,(void *, StgDouble,StgDouble),pow,a,b)
-\end{code}
-
-
-%************************************************************************
-%*                                                                     *
-\subsubsection[StgMacros-64-primops]{Primitive @Int64#@ and @Word64#@ ops}
-%*                                                                     *
-%************************************************************************
-
-Apart from the Integer casting primops, all primops over 64-bit (i.e., long long)
-@Int64#@ and @Word64#@s are defined out-of-line. We just give the prototype
-of these primops here:
-
-\begin{code}
-#ifdef HAVE_LONG_LONG
-I_ stg_gtWord64 PROTO((StgWord64, StgWord64));
-I_ stg_geWord64 PROTO((StgWord64, StgWord64));
-I_ stg_eqWord64 PROTO((StgWord64, StgWord64));
-I_ stg_neWord64 PROTO((StgWord64, StgWord64));
-I_ stg_ltWord64 PROTO((StgWord64, StgWord64));
-I_ stg_leWord64 PROTO((StgWord64, StgWord64));
-
-I_ stg_gtInt64 PROTO((StgInt64, StgInt64));
-I_ stg_geInt64 PROTO((StgInt64, StgInt64));
-I_ stg_eqInt64 PROTO((StgInt64, StgInt64));
-I_ stg_neInt64 PROTO((StgInt64, StgInt64));
-I_ stg_ltInt64 PROTO((StgInt64, StgInt64));
-I_ stg_leInt64 PROTO((StgInt64, StgInt64));
-
-LW_ stg_remWord64 PROTO((StgWord64, StgWord64));
-LW_ stg_quotWord64 PROTO((StgWord64, StgWord64));
-
-LI_ stg_remInt64 PROTO((StgInt64, StgInt64));
-LI_ stg_quotInt64 PROTO((StgInt64, StgInt64));
-LI_ stg_negateInt64 PROTO((StgInt64));
-LI_ stg_plusInt64 PROTO((StgInt64, StgInt64));
-LI_ stg_minusInt64 PROTO((StgInt64, StgInt64));
-LI_ stg_timesInt64 PROTO((StgInt64, StgInt64));
-
-LW_ stg_and64 PROTO((StgWord64, StgWord64));
-LW_ stg_or64 PROTO((StgWord64, StgWord64));
-LW_ stg_xor64 PROTO((StgWord64, StgWord64));
-LW_ stg_not64 PROTO((StgWord64));
-
-LW_ stg_shiftL64 PROTO((StgWord64, StgInt));
-LW_ stg_shiftRL64 PROTO((StgWord64, StgInt));
-LI_ stg_iShiftL64 PROTO((StgInt64, StgInt));
-LI_ stg_iShiftRL64 PROTO((StgInt64, StgInt));
-LI_ stg_iShiftRA64 PROTO((StgInt64, StgInt));
-
-LI_ stg_intToInt64 PROTO((StgInt));
-I_ stg_int64ToInt PROTO((StgInt64));
-LW_ stg_int64ToWord64 PROTO((StgInt64));
-
-LW_ stg_wordToWord64 PROTO((StgWord));
-W_ stg_word64ToWord PROTO((StgWord64));
-LI_ stg_word64ToInt64 PROTO((StgWord64));
-#endif
-\end{code}
-
-
-%************************************************************************
-%*                                                                     *
-\subsubsection[StgMacros-integer-primops]{Primitive @Integer@-related ops (GMP stuff)}
-%*                                                                     *
-%************************************************************************
-
-Dirty macros we use for the real business.
-
-INVARIANT: When one of these macros is called, the only live data is
-tidily on the STG stacks or in the STG registers (the code generator
-ensures this). If there are any pointer-arguments, they will be in
-the first \tr{Ret*} registers (e.g., \tr{da} arg of \tr{gmpTake1Return1}).
-
-OK, here are the real macros:
-\begin{code}
-#define gmpTake1Return1(size_chk_macro, liveness, mpz_op, ar,sr,dr, aa,sa,da)  \
-{ MP_INT arg;                                                                  \
-  MP_INT result;                                                               \
-  I_ space = size_chk_macro(sa);                                               \
-                                                                               \
-  /* Check that there will be enough heap & make Hp visible to GMP allocator */        \
-  GMP_HEAP_LOOKAHEAD(liveness,space);                                          \
-                                                                               \
-  /* Now we can initialise (post possible GC) */                               \
-  arg.alloc    = (aa);                                                         \
-  arg.size     = (sa);                                                         \
-  arg.d                = (unsigned long int *) (BYTE_ARR_CTS(da));                     \
-                                                                               \
-  SAFESTGCALL1(void,(void *, MP_INT *),mpz_init,&result);                      \
-                                                                               \
-  /* Perform the operation */                                                  \
-  SAFESTGCALL2(void,(void *, MP_INT *, MP_INT *),mpz_op,&result,&arg);         \
-                                                                               \
-  GMP_HEAP_HANDBACK();         /* restore Hp */                                \
-  (ar) = result.alloc;                                                         \
-  (sr) = result.size;                                                          \
-  (dr) = (B_) (result.d - DATA_HS);                                            \
-  /* pt to *beginning* of object (GMP has been monkeying around in the middle) */ \
-}
-
-
-#define gmpTake2Return1(size_chk_macro, liveness, mpz_op, ar,sr,dr, a1,s1,d1, a2,s2,d2)\
-{ MP_INT arg1;                                                                 \
-  MP_INT arg2;                                                                 \
-  MP_INT result;                                                               \
-  I_ space = size_chk_macro(s1,s2);                                            \
-                                                                               \
-  /* Check that there will be enough heap & make Hp visible to GMP allocator */        \
-  GMP_HEAP_LOOKAHEAD(liveness,space);                                          \
-                                                                               \
-  /* Now we can initialise (post possible GC) */                               \
-  arg1.alloc   = (a1);                                                         \
-  arg1.size    = (s1);                                                         \
-  arg1.d       = (unsigned long int *) (BYTE_ARR_CTS(d1));                     \
-  arg2.alloc   = (a2);                                                         \
-  arg2.size    = (s2);                                                         \
-  arg2.d       = (unsigned long int *) (BYTE_ARR_CTS(d2));                     \
-                                                                               \
-  SAFESTGCALL1(void,(void *, MP_INT *),mpz_init,&result);                      \
-                                                                               \
-  /* Perform the operation */                                                  \
-  SAFESTGCALL3(void,(void *, MP_INT *, MP_INT *, MP_INT *),mpz_op,&result,&arg1,&arg2); \
-                                                                               \
-  GMP_HEAP_HANDBACK();         /* restore Hp */                                \
-  (ar) = result.alloc;                                                         \
-  (sr) = result.size;                                                          \
-  (dr) = (B_) (result.d - DATA_HS);                                            \
-  /* pt to *beginning* of object (GMP has been monkeying around in the middle) */ \
-}
-
-#define gmpTake2Return2(size_chk_macro, liveness, mpz_op, ar1,sr1,dr1, ar2,sr2,dr2, a1,s1,d1, a2,s2,d2) \
-{ MP_INT arg1;                                                                 \
-  MP_INT arg2;                                                                 \
-  MP_INT result1;                                                              \
-  MP_INT result2;                                                              \
-  I_ space = size_chk_macro(s1,s2);                                            \
-                                                                               \
-  /* Check that there will be enough heap & make Hp visible to GMP allocator */        \
-  GMP_HEAP_LOOKAHEAD(liveness,space);                                          \
-                                                                               \
-  /* Now we can initialise (post possible GC) */                               \
-  arg1.alloc   = (a1);                                                         \
-  arg1.size    = (s1);                                                         \
-  arg1.d       = (unsigned long int *) (BYTE_ARR_CTS(d1));                     \
-  arg2.alloc   = (a2);                                                         \
-  arg2.size    = (s2);                                                         \
-  arg2.d       = (unsigned long int *) (BYTE_ARR_CTS(d2));                     \
-                                                                               \
-  SAFESTGCALL1(void,(void *, MP_INT *),mpz_init,&result1);                     \
-  SAFESTGCALL1(void,(void *, MP_INT *),mpz_init,&result2);                     \
-                                                                               \
-  /* Perform the operation */                                                  \
-  SAFESTGCALL4(void,(void *, MP_INT *, MP_INT *, MP_INT *, MP_INT *),mpz_op,&result1,&result2,&arg1,&arg2); \
-                                                                               \
-  GMP_HEAP_HANDBACK();         /* restore Hp */                                \
-  (ar1) = result1.alloc;                                                       \
-  (sr1) = result1.size;                                                                \
-  (dr1) = (B_) (result1.d - DATA_HS);                                          \
-  (ar2) = result2.alloc;                                                       \
-  (sr2) = result2.size;                                                                \
-  (dr2) = (B_) (result2.d - DATA_HS);                                          \
-}
-\end{code}
-
-Some handy size-munging macros: sometimes gratuitously {\em conservative}.
-The \tr{+16} is to allow for the initial allocation of \tr{MP_INT} results.
-The \tr{__abs} stuff is because negative-ness of GMP things is encoded
-in their ``size''...
-\begin{code}
-#define __abs(a)               (( (a) >= 0 ) ? (a) : (-(a)))
-#define GMP_SIZE_ONE()         (2 + DATA_HS + 16)
-#define GMP_SAME_SIZE(a)       (__abs(a) + DATA_HS + 16)
-#define GMP_MAX_SIZE(a,b)      ((__abs(a) > __abs(b) ? __abs(a) : __abs(b)) + 1 + DATA_HS + 16)
-                               /* NB: the +1 is for the carry (or whatever) */
-#define GMP_2MAX_SIZE(a,b)     (2 * GMP_MAX_SIZE(a,b))
-#define GMP_ADD_SIZES(a,b)     (__abs(a) + __abs(b) + 1 + DATA_HS + 16)
-                               /* the +1 may just be paranoia */
-\end{code}
-
-For the Integer/GMP stuff, we have macros that {\em look ahead} for
-some space, but don't actually grab it.
-
-If there are live pointers at the time of the lookahead, the caller
-must make sure they are in \tr{Ret1}, \tr{Ret2}, ..., so they can be
-handled normally.  We achieve this by having the code generator {\em
-always} pass args to may-invoke-GC primitives in registers, using the
-normal pointers-first policy.  This means that, if we do go to garbage
-collection, everything is already in the Right Place.
-
-Saving and restoring Hp register so the MP allocator can see them. If we are
-performing liftime profiling need to save and restore HpLim as well so that
-it can be bumped if allocation occurs.
-
-The second argument to @GMP_HEAP_LOOKAHEAD@ must be an lvalue so that
-it can be restored from @TSO_ARG1@ after a failed @HEAP_CHK@ in
-threaded land.
-
-\begin{code}
-#define GMP_HEAP_LOOKAHEAD(liveness,n)                 \
-       do {                                            \
-       HEAP_CHK_AND_RESTORE_N(liveness,n,0);           \
-       Hp = Hp - (n);                                  \
-       UN_ALLOC_HEAP(n);       /* Undo ticky-ticky */  \
-       SAVE_Hp = Hp;           /* Hand over the hp */  \
-       DEBUG_SetGMPAllocBudget(n)                      \
-       }while(0)
-
-#define GMP_HEAP_HANDBACK()                            \
-       Hp = SAVE_Hp;                                   \
-       DEBUG_ResetGMPAllocBudget()
-\end{code}
-
-\begin{code}
-void *stgAllocForGMP   PROTO((size_t size_in_bytes));
-void *stgReallocForGMP PROTO((void *ptr, size_t old_size, size_t new_size));
-void stgDeallocForGMP  PROTO((void *ptr, size_t size));
-
-#ifdef ALLOC_DEBUG
-extern StgInt DEBUG_GMPAllocBudget;
-#define DEBUG_SetGMPAllocBudget(n)  DEBUG_GMPAllocBudget = (n);
-#define DEBUG_ResetGMPAllocBudget() DEBUG_GMPAllocBudget = 0;
-#else
-#define DEBUG_SetGMPAllocBudget(n)  /*nothing*/
-#define DEBUG_ResetGMPAllocBudget() /*nothing*/
-#endif
-\end{code}
-
-The real business (defining Integer primops):
-\begin{code}
-#define negateIntegerZh(ar,sr,dr, liveness, aa,sa,da) \
-       gmpTake1Return1(GMP_SAME_SIZE, liveness, mpz_neg, ar,sr,dr, aa,sa,da)
-
-#define plusIntegerZh(ar,sr,dr, liveness, a1,s1,d1, a2,s2,d2) \
-       gmpTake2Return1(GMP_MAX_SIZE, liveness, mpz_add, ar,sr,dr, a1,s1,d1, a2,s2,d2)
-#define minusIntegerZh(ar,sr,dr, liveness, a1,s1,d1, a2,s2,d2) \
-       gmpTake2Return1(GMP_MAX_SIZE, liveness, mpz_sub, ar,sr,dr, a1,s1,d1, a2,s2,d2)
-#define timesIntegerZh(ar,sr,dr, liveness, a1,s1,d1, a2,s2,d2) \
-       gmpTake2Return1(GMP_ADD_SIZES, liveness, mpz_mul, ar,sr,dr, a1,s1,d1, a2,s2,d2)
-
-/* div, mod, quot, rem are defined w/ quotRem & divMod */
-
-#define quotRemIntegerZh(ar1,sr1,dr1, ar2,sr2,dr2, liveness, a1,s1,d1, a2,s2,d2) \
-       gmpTake2Return2(GMP_2MAX_SIZE, liveness, mpz_divmod, ar1,sr1,dr1, ar2,sr2,dr2, a1,s1,d1, a2,s2,d2)
-#define divModIntegerZh(ar1,sr1,dr1, ar2,sr2,dr2, liveness,  a1,s1,d1, a2,s2,d2) \
-       gmpTake2Return2(GMP_2MAX_SIZE, liveness, mpz_mdivmod, ar1,sr1,dr1, ar2,sr2,dr2, a1,s1,d1, a2,s2,d2)
-\end{code}
-
-Comparison ops (@<@, @>=@, etc.) are defined in terms of the cmp
-fellow (returns -ve, 0, or +ve).
-\begin{code}
-#define cmpIntegerZh(r, hp, a1,s1,d1, a2,s2,d2) /* calls mpz_cmp */            \
-{ MP_INT arg1;                                                                 \
-  MP_INT arg2;                                                                 \
-  /* Does not allocate memory */                                               \
-                                                                               \
-  arg1.alloc   = (a1);                                                         \
-  arg1.size    = (s1);                                                         \
-  arg1.d       = (unsigned long int *) (BYTE_ARR_CTS(d1));                     \
-  arg2.alloc   = (a2);                                                         \
-  arg2.size    = (s2);                                                         \
-  arg2.d       = (unsigned long int *) (BYTE_ARR_CTS(d2));                     \
-                                                                               \
-  (r) = SAFESTGCALL2(I_,(void *, MP_INT *, MP_INT *),mpz_cmp,&arg1,&arg2);     \
-}
-\end{code}
-
-Coercions:
-
-\begin{code}
-#define integer2IntZh(r, hp, aa,sa,da)                                         \
-{ MP_INT arg;                                                                  \
-  /* Does not allocate memory */                                               \
-                                                                               \
-  arg.alloc    = (aa);                                                         \
-  arg.size     = (sa);                                                         \
-  arg.d                = (unsigned long int *) (BYTE_ARR_CTS(da));                     \
-                                                                               \
-  (r) = SAFESTGCALL1(I_,(void *, MP_INT *),mpz_get_si,&arg);                   \
-}
-
-/* Since we're forced to know a little bit about MP_INT layout to do this with
-   pre-allocated heap, we just inline the whole of mpz_init_set_si here.
-       ** DIRE WARNING.  if mpz_init_set_si changes, so does this! ***
-*/
-
-#define int2IntegerZh(ar,sr,dr, hp, i)                                         \
-{ StgInt val; /* to snaffle arg to avoid aliasing */                           \
-                                                                               \
-  val = (i);  /* snaffle... */                                                 \
-                                                                               \
-  SET_DATA_HDR((hp),ArrayOfData_info,CCC,DATA_VHS+MIN_MP_INT_SIZE,0);          \
-                                                                               \
-  if     ((val) < 0) { (sr) = -1; (hp)[DATA_HS] = -(val); }                    \
-  else if ((val) > 0) { (sr) = 1; (hp)[DATA_HS] =  (val); }                    \
-  else /* val==0 */   { (sr) = 0; }                                            \
-  (ar) = 1;                                                                    \
-  (dr) = (B_)(hp);             /* dr is an StgByteArray */                     \
-}
-
-#define word2IntegerZh(ar,sr,dr, hp, i)                                                \
-{ StgWord val; /* to snaffle arg to avoid aliasing */                          \
-                                                                               \
-  val = (i);  /* snaffle... */                                                 \
-                                                                               \
-  SET_DATA_HDR((hp),ArrayOfData_info,CCC,DATA_VHS+MIN_MP_INT_SIZE,0);          \
-                                                                               \
-  if ((val) != 0)     { (sr) = 1; (hp)[DATA_HS] =  (val); }                    \
-  else /* val==0 */   { (sr) = 0; }                                            \
-  (ar) = 1;                                                                    \
-  (dr) = (B_)(hp);             /* dr is an StgByteArray */                     \
-}
-
-#define integer2WordZh(r, hp, aa,sa,da)                                                \
-{ MP_INT arg;                                                                  \
-  /* Does not allocate memory */                                               \
-                                                                               \
-  arg.alloc    = (aa);                                                         \
-  arg.size     = (sa);                                                         \
-  arg.d                = (unsigned long int *) (BYTE_ARR_CTS(da));                     \
-                                                                               \
-  (r) = SAFESTGCALL1(I_,(void *, MP_INT *),mpz_get_ui,&arg);                   \
-}
-
-#define integerToInt64Zh(r, hp, aa,sa,da)                                      \
-{ unsigned long int* d;                                                                \
-  StgInt64 res;                                                                        \
-  /* Allocates memory. Chummy with gmp rep. */                                 \
-                                                                               \
-  d            = (unsigned long int *) (BYTE_ARR_CTS(da));                     \
-                                                                               \
-  if ( (aa) == 0)      { (res)=(LI_)0; }                                       \
-  else if ( (aa) == 1) { (res)=(LI_)d[0]; }                                    \
-  else                { (res)=(LI_)d[0] + (LI_)d[1] * 0x100000000LL; }         \
-  (r)=(LI_)( (sa) < 0 ? -res : res);                                           \
-}
-
-#define integerToWord64Zh(r, hp, aa,sa,da)                                     \
-{ unsigned long int* d;                                                                \
-  StgWord64 res;                                                               \
-  /* Allocates memory. Chummy with gmp rep. */                                 \
-                                                                               \
-  d            = (unsigned long int *) (BYTE_ARR_CTS(da));                     \
-                                                                               \
-  if ( (aa) == 0)      { (res)=(LW_)0; }                                       \
-  else if ( (aa) == 1) { (res)=(LW_)d[0]; }                                    \
-  else                { (res)=(LW_)d[0] + (LW_)d[1] * 0x100000000ULL; }        \
-  (r) = (res);                                                                 \
-}
-
-#define int64ToIntegerZh(ar,sr,dr, hp, li)                                     \
-{ StgInt64 val; /* to snaffle arg to avoid aliasing */                         \
-  StgWord hi;                                                          \
-  int neg=0;                                                           \
-                                                                               \
-  val = (li);  /* snaffle... */                                                        \
-                                                                               \
-  SET_DATA_HDR((hp),ArrayOfData_info,CCC,DATA_VHS+MIN_MP_INT_SIZE,0);          \
-                                                                               \
-  if ( val < 0LL ) {                                                           \
-    neg = 1;                                                                   \
-    val = -val;                                                                        \
-  }                                                                            \
-  hi = (W_)((LW_)val / 0x100000000ULL);                                                \
-  if ((LW_)(val) >= 0x100000000ULL)  { (sr) = 2; (ar) = 2; (hp)[DATA_HS] =  ((W_)val); (hp)[DATA_HS+1] = (hi); } \
-  else if ((val) != 0) { (sr) =        1; (ar) = 1; (hp)[DATA_HS] =  ((W_)val);  }     \
-  else /* val==0 */    { (sr) =        0; (ar) = 1; }                                  \
-  (sr) = ( neg ? -(sr) : (sr) );                                               \
-  (dr) = (B_)(hp);             /* dr is an StgByteArray */                     \
-}
-
-#define word64ToIntegerZh(ar,sr,dr, hp, lw)                                    \
-{ StgWord64 val; /* to snaffle arg to avoid aliasing */                                \
-  StgWord hi;                                                                  \
-                                                                               \
-  val = (lw);  /* snaffle... */                                                        \
-                                                                               \
-  SET_DATA_HDR((hp),ArrayOfData_info,CCC,DATA_VHS+MIN_MP_INT_SIZE,0);          \
-                                                                               \
-  hi = (W_)((LW_)val / 0x100000000ULL);                                                \
-  if ((val) >= 0x100000000ULL ) { (sr) = 2; (ar) = 2; (hp)[DATA_HS] =  ((W_)val); (hp)[DATA_HS+1] = (hi); } \
-  else if ((val) != 0)          { (sr) = 1; (ar) = 1; (hp)[DATA_HS] =  ((W_)val); } \
-  else /* val==0 */             { (sr) = 0; (ar) = 1; }                                \
-  (dr) = (B_)(hp);             /* dr is an StgByteArray */                     \
-}
-
-
-
-\end{code}
-
-Then there are a few oddments to make life easier:
-\begin{code}
-/*
-   DIRE WARNING.
-   The "str" argument must be a literal C string.
-
-       addr2Integer( ..., "foo")   OK!
-
-       x = "foo";
-       addr2Integer( ..., x)       NO! NO!
-*/
-
-#define addr2IntegerZh(ar,sr,dr, liveness, str)                                        \
-{ MP_INT result;                                                               \
-  /* taking the number of bytes/8 as the number of words of lookahead          \
-     is plenty conservative */                                                 \
-  I_ space = GMP_SAME_SIZE(sizeof(str) / 8 + 1);                               \
-                                                                               \
-  GMP_HEAP_LOOKAHEAD(liveness, space);                                         \
-                                                                               \
-  /* Perform the operation */                                                  \
-  if (SAFESTGCALL3(I_,(void *, MP_INT *, char *, int), mpz_init_set_str,&result,(str),/*base*/10)) \
-      abort();                                                                 \
-                                                                               \
-  GMP_HEAP_HANDBACK();         /* restore Hp */                                \
-  (ar) = result.alloc;                                                         \
-  (sr) = result.size;                                                          \
-  (dr) = (B_) (result.d - DATA_HS);                                            \
-  /* pt to *beginning* of object (GMP has been monkeying around in the middle) */ \
-}
-\end{code}
-
-Encoding and decoding float-ish things is pretty Integer-ish.  We use
-these pretty magical support functions, essentially stolen from Lennart:
-\begin{code}
-StgFloat  __encodeFloat         PROTO((MP_INT *, I_));
-void      __decodeFloat  PROTO((MP_INT * /*result1*/,
-                               I_ * /*result2*/,
-                               StgFloat));
-
-StgDouble __encodeDouble PROTO((MP_INT *, I_));
-void      __decodeDouble PROTO((MP_INT * /*result1*/,
-                               I_ * /*result2*/,
-                               StgDouble));
-\end{code}
-
-Some floating-point format info, made with the \tr{enquire} program
-(version~4.3) [comes with gcc].
-\begin{code}
-/* this should be done by CPU architecture, insofar as possible [WDP] */
-
-#if sparc_TARGET_ARCH  \
- || alpha_TARGET_ARCH  \
- || hppa1_1_TARGET_ARCH        \
- || i386_TARGET_ARCH   \
- || m68k_TARGET_ARCH   \
- || mipsel_TARGET_ARCH \
- || mipseb_TARGET_ARCH \
- || powerpc_TARGET_ARCH \
- || rs6000_TARGET_ARCH
-
-/* yes, it is IEEE floating point */
-#include "ieee-flpt.h"
-
-#if alpha_TARGET_ARCH  \
- || i386_TARGET_ARCH           \
- || mipsel_TARGET_ARCH
-
-#undef BIGENDIAN /* little-endian weirdos... */
-#else
-#define BIGENDIAN 1
-#endif
-
-#else /* unknown floating-point format */
-
-******* ERROR *********** Any ideas about floating-point format?
-
-#endif /* unknown floating-point */
-\end{code}
-
-\begin{code}
-#if alpha_TARGET_ARCH
-#define encodeFloatZh(r, hp, aa,sa,da, expon)  encodeDoubleZh(r, hp, aa,sa,da, expon)
-#else
-#define encodeFloatZh(r, hp, aa,sa,da, expon)  \
-{ MP_INT arg;                                  \
-  /* Does not allocate memory */               \
-                                               \
-  arg.alloc    = aa;                           \
-  arg.size     = sa;                           \
-  arg.d                = (unsigned long int *) (BYTE_ARR_CTS(da)); \
-                                               \
-  r = SAFESTGCALL2(StgFloat,(void *, MP_INT *, I_), __encodeFloat,&arg,(expon));       \
-}
-#endif /* ! alpha */
-
-#define encodeDoubleZh(r, hp, aa,sa,da, expon) \
-{ MP_INT arg;                                  \
-  /* Does not allocate memory */               \
-                                               \
-  arg.alloc    = aa;                           \
-  arg.size     = sa;                           \
-  arg.d                = (unsigned long int *) (BYTE_ARR_CTS(da)); \
-                                               \
-  r = SAFESTGCALL2(StgDouble,(void *, MP_INT *, I_), __encodeDouble,&arg,(expon));\
-}
-
-#if alpha_TARGET_ARCH
-#define decodeFloatZh(exponr, ar,sr,dr, hp, f) decodeDoubleZh(exponr, ar,sr,dr, hp, f)
-#else
-#define decodeFloatZh(exponr, ar,sr,dr, hp, f)                         \
-{ MP_INT mantissa;                                                     \
-  I_ exponent;                                                         \
-  StgFloat arg = (f);                                                  \
-                                                                       \
-  /* Be prepared to tell Lennart-coded __decodeFloat   */              \
-  /* where mantissa.d can be put (it does not care about the rest) */  \
-  SET_DATA_HDR(hp,ArrayOfData_info,CCC,DATA_VHS+MIN_MP_INT_SIZE,0);    \
-  mantissa.d = (hp) + DATA_HS;                                         \
-                                                                       \
-  /* Perform the operation */                                          \
-  SAFESTGCALL3(void,(void *, MP_INT *, I_ *, StgFloat),__decodeFloat,&mantissa,&exponent,arg);         \
-  exponr= exponent;                                                    \
-  ar   = mantissa.alloc;                                               \
-  sr   = mantissa.size;                                                \
-  dr   = (B_)(hp);                                                     \
-}
-#endif /* !alpha */
-
-#define decodeDoubleZh(exponr, ar,sr,dr, hp, f)                                \
-{ MP_INT mantissa;                                                     \
-  I_ exponent;                                                         \
-  StgDouble arg = (f);                                                 \
-                                                                       \
-  /* Be prepared to tell Lennart-coded __decodeDouble  */              \
-  /* where mantissa.d can be put (it does not care about the rest) */  \
-  SET_DATA_HDR(hp,ArrayOfData_info,CCC,DATA_VHS+MIN_MP_INT_SIZE,0);    \
-  mantissa.d = (hp) + DATA_HS;                                         \
-                                                                       \
-  /* Perform the operation */                                          \
-  SAFESTGCALL3(void,(void *, MP_INT *, I_ *, StgDouble),__decodeDouble,&mantissa,&exponent,arg);               \
-  exponr= exponent;                                                    \
-  ar   = mantissa.alloc;                                               \
-  sr   = mantissa.size;                                                \
-  dr   = (B_)(hp);                                                     \
-}
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection[StgMacros-mv-floats]{Moving floats and doubles around (e.g., to/from stacks)}
-%*                                                                     *
-%************************************************************************
-
-With GCC, we use magic non-standard inlining; for other compilers, we
-just use functions (see also \tr{runtime/prims/PrimArith.lc}).
-
-(The @OMIT_...@ is only used in compiling some of the RTS, none of
-which uses these anyway.)
-
-\begin{code}
-#if alpha_TARGET_ARCH  \
- || i386_TARGET_ARCH   \
- || m68k_TARGET_ARCH
-
-#define ASSIGN_FLT(dst, src) *(StgFloat *)(dst) = (src);
-#define PK_FLT(src) (*(StgFloat *)(src))
-
-#define ASSIGN_DBL(dst, src) *(StgDouble *)(dst) = (src);
-#define PK_DBL(src) (*(StgDouble *)(src))
-
-#else  /* not m68k || alpha || i[34]86 */
-
-/* Special handling for machines with troublesome alignment constraints */
-
-#define FLOAT_ALIGNMENT_TROUBLES    TRUE
-
-#if ! defined(__GNUC__) || ! defined(__STG_GCC_REGS__)
-
-void       ASSIGN_DBL PROTO((W_ [], StgDouble));
-StgDouble   PK_DBL     PROTO((W_ []));
-void       ASSIGN_FLT PROTO((W_ [], StgFloat));
-StgFloat    PK_FLT     PROTO((W_ []));
-
-#else /* yes, its __GNUC__ && we really want them */
-
-#if sparc_TARGET_ARCH
-
-#define ASSIGN_FLT(dst, src) *(StgFloat *)(dst) = (src);
-#define PK_FLT(src) (*(StgFloat *)(src))
-
-#define ASSIGN_DBL(dst,src) \
-      __asm__("st %2,%0\n\tst %R2,%1" : "=m" (((P_)(dst))[0]), \
-       "=m" (((P_)(dst))[1]) : "f" (src));
-
-#define PK_DBL(src) \
-    ( { register double d; \
-      __asm__("ld %1,%0\n\tld %2,%R0" : "=f" (d) : \
-       "m" (((P_)(src))[0]), "m" (((P_)(src))[1])); d; \
-    } )
-
-#else /* ! sparc */
-
-/* (not very) forward prototype declarations */
-void       ASSIGN_DBL PROTO((W_ [], StgDouble));
-StgDouble   PK_DBL     PROTO((W_ []));
-void       ASSIGN_FLT PROTO((W_ [], StgFloat));
-StgFloat    PK_FLT     PROTO((W_ []));
-
-extern STG_INLINE
-void
-ASSIGN_DBL(W_ p_dest[], StgDouble src)
-{
-    double_thing y;
-    y.d = src;
-    p_dest[0] = y.du.dhi;
-    p_dest[1] = y.du.dlo;
-}
-
-/* GCC also works with this version, but it generates
-   the same code as the previous one, and is not ANSI
-
-#define ASSIGN_DBL( p_dest, src ) \
-       *p_dest = ((double_thing) src).du.dhi; \
-       *(p_dest+1) = ((double_thing) src).du.dlo \
-*/
-
-extern STG_INLINE
-StgDouble
-PK_DBL(W_ p_src[])
-{
-    double_thing y;
-    y.du.dhi = p_src[0];
-    y.du.dlo = p_src[1];
-    return(y.d);
-}
-
-extern STG_INLINE
-void
-ASSIGN_FLT(W_ p_dest[], StgFloat src)
-{
-    float_thing y;
-    y.f = src;
-    *p_dest = y.fu;
-}
-
-extern STG_INLINE
-StgFloat
-PK_FLT(W_ p_src[])
-{
-    float_thing y;
-    y.fu = *p_src;
-    return(y.f);
-}
-
-#endif /* ! sparc */
-
-#endif /* __GNUC__ */
-
-#endif /* not __m68k__ */
-
-#if HAVE_LONG_LONG
-extern STG_INLINE
-void
-ASSIGN_Word64(W_ p_dest[], StgWord64 src)
-{
-    word64_thing y;
-    y.w = src;
-    p_dest[0] = y.wu.dhi;
-    p_dest[1] = y.wu.dlo;
-}
-
-extern STG_INLINE
-StgWord64
-PK_Word64(W_ p_src[])
-{
-    word64_thing y;
-    y.wu.dhi = p_src[0];
-    y.wu.dlo = p_src[1];
-    return(y.w);
-}
-
-extern STG_INLINE
-void
-ASSIGN_Int64(W_ p_dest[], StgInt64 src)
-{
-    int64_thing y;
-    y.i = src;
-    p_dest[0] = y.iu.dhi;
-    p_dest[1] = y.iu.dlo;
-}
-
-extern STG_INLINE
-StgInt64
-PK_Int64(W_ p_src[])
-{
-    int64_thing y;
-    y.iu.dhi = p_src[0];
-    y.iu.dlo = p_src[1];
-    return(y.i);
-}
-#endif
-
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection[StgMacros-array-primops]{Primitive arrays}
-%*                                                                     *
-%************************************************************************
-
-We regularly use this macro to fish the ``contents'' part
-out of a DATA or TUPLE closure, which is what is used for
-non-ptr and ptr arrays (respectively).
-
-BYTE_ARR_CTS returns a @C_ *@!
-
-We {\em ASSUME} we can use the same macro for both!!
-\begin{code}
-
-#ifdef DEBUG
-#define BYTE_ARR_CTS(a)                                        \
- ({ ASSERT(INFO_PTR(a) == (W_) ArrayOfData_info);      \
-    ((C_ *) (((StgPtr) (a))+DATA_HS)); })
-#define PTRS_ARR_CTS(a)                                        \
- ({ ASSERT((INFO_PTR(a) == (W_) ArrayOfPtrs_info)      \
-       || (INFO_PTR(a) == (W_) ImMutArrayOfPtrs_info));\
-    ((a)+MUTUPLE_HS);} )
-#else
-#define BYTE_ARR_CTS(a)                ((char *) (((StgPtr) (a))+DATA_HS))
-#define PTRS_ARR_CTS(a)                ((a)+MUTUPLE_HS)
-#endif
-
-/* sigh */
-extern I_ genSymZh(STG_NO_ARGS);
-extern I_ resetGenSymZh(STG_NO_ARGS);
-extern I_ incSeqWorldZh(STG_NO_ARGS);
-
-extern I_ byteArrayHasNUL__ PROTO((const char *, I_));
-\end{code}
-
-OK, the easy ops first: (all except \tr{newArr*}:
-
-(OLD:) VERY IMPORTANT! The read/write/index primitive ops
-on @ByteArray#@s index the array using a {\em BYTE} offset, even
-if the thing begin gotten out is a multi-byte @Int#@, @Float#@ etc.
-This is because you might be trying to take apart a C struct, where
-the offset from the start of the struct isn't a multiple of the
-size of the thing you're getting.  Hence the @(char *)@ casts.
-
-EVEN MORE IMPORTANT! The above is a lie.  The offsets for BlahArrays
-are in Blahs.  WDP 95/08
-
-In the case of messing with @StgAddrs@ (@A_@), which are really \tr{void *},
-we cast to @P_@, because you can't index off an uncast \tr{void *}.
-
-In the case of @Array#@ (which contain pointers), the offset is in units
-of one ptr (not bytes).
-
-\begin{code}
-#define sameMutableArrayZh(r,a,b)      r=(I_)((a)==(b))
-#define sameMutableByteArrayZh(r,a,b)  r=(I_)((B_)(a)==(B_)(b))
-
-#define readArrayZh(r,a,i)      r=((PP_) PTRS_ARR_CTS(a))[(i)]
-
-#define readCharArrayZh(r,a,i)     indexCharOffAddrZh(r,BYTE_ARR_CTS(a),i)
-#define readIntArrayZh(r,a,i)      indexIntOffAddrZh(r,BYTE_ARR_CTS(a),i)
-#define readStablePtrArrayZh(r,a,i) indexStablePtrOffAddrZh(r,BYTE_ARR_CTS(a),i)
-#define readWordArrayZh(r,a,i)     indexWordOffAddrZh(r,BYTE_ARR_CTS(a),i)
-#define readInt64ArrayZh(r,a,i)            indexInt64OffAddrZh(r,BYTE_ARR_CTS(a),i)
-#define readWord64ArrayZh(r,a,i)    indexWord64OffAddrZh(r,BYTE_ARR_CTS(a),i)
-#define readAddrArrayZh(r,a,i)     indexAddrOffAddrZh(r,BYTE_ARR_CTS(a),i)
-#define readFloatArrayZh(r,a,i)            indexFloatOffAddrZh(r,BYTE_ARR_CTS(a),i)
-#define readDoubleArrayZh(r,a,i)    indexDoubleOffAddrZh(r,BYTE_ARR_CTS(a),i)
-
-/* result ("r") arg ignored in write macros! */
-#define writeArrayZh(a,i,v)    ((PP_) PTRS_ARR_CTS(a))[(i)]=(v)
-
-#define writeCharArrayZh(a,i,v)              ((C_ *)(BYTE_ARR_CTS(a)))[i] = (v)
-#define writeIntArrayZh(a,i,v)       ((I_ *)(BYTE_ARR_CTS(a)))[i] = (v)
-#define writeStablePtrArrayZh(a,i,v)  ((StgStablePtr *)(BYTE_ARR_CTS(a)))[i] = (v)
-#define writeWordArrayZh(a,i,v)              ((W_ *)(BYTE_ARR_CTS(a)))[i] = (v)
-#define writeInt64ArrayZh(a,i,v)      ((LI_ *)(BYTE_ARR_CTS(a)))[i] = (v)
-#define writeWord64ArrayZh(a,i,v)     ((LW_ *)(BYTE_ARR_CTS(a)))[i] = (v)
-#define writeAddrArrayZh(a,i,v)              ((PP_)(BYTE_ARR_CTS(a)))[i] = (v)
-#define writeFloatArrayZh(a,i,v)      ASSIGN_FLT((P_) (((StgFloat *)(BYTE_ARR_CTS(a))) + i),v)
-#define writeDoubleArrayZh(a,i,v)     ASSIGN_DBL((P_) (((StgDouble *)(BYTE_ARR_CTS(a))) + i),v)
-
-#define indexArrayZh(r,a,i)      r=((PP_) PTRS_ARR_CTS(a))[(i)]
-
-#define indexCharArrayZh(r,a,i)             indexCharOffAddrZh(r,BYTE_ARR_CTS(a),i)
-#define indexIntArrayZh(r,a,i)      indexIntOffAddrZh(r,BYTE_ARR_CTS(a),i)
-#define indexStablePtrArrayZh(r,a,i) indexStablePtrOffAddrZh(r,BYTE_ARR_CTS(a),i)
-#define indexWordArrayZh(r,a,i)             indexWordOffAddrZh(r,BYTE_ARR_CTS(a),i)
-#define indexAddrArrayZh(r,a,i)             indexAddrOffAddrZh(r,BYTE_ARR_CTS(a),i)
-#define indexFloatArrayZh(r,a,i)     indexFloatOffAddrZh(r,BYTE_ARR_CTS(a),i)
-#define indexDoubleArrayZh(r,a,i)    indexDoubleOffAddrZh(r,BYTE_ARR_CTS(a),i)
-#define indexInt64ArrayZh(r,a,i)     indexInt64OffAddrZh(r,BYTE_ARR_CTS(a),i)
-#define indexWord64ArrayZh(r,a,i)    indexWord64OffAddrZh(r,BYTE_ARR_CTS(a),i)
-
-#define indexCharOffForeignObjZh(r,fo,i)      indexCharOffAddrZh(r,ForeignObj_CLOSURE_DATA(fo),i)
-#define indexIntOffForeignObjZh(r,fo,i)       indexIntOffAddrZh(r,ForeignObj_CLOSURE_DATA(fo),i)
-#define indexStablePtrOffForeignObjZh(r,fo,i) indexStablePtrOffAddrZh(r,ForeignObj_CLOSURE_DATA(fo),i)
-#define indexWordOffForeignObjZh(r,fo,i)      indexWordOffAddrZh(r,ForeignObj_CLOSURE_DATA(fo),i)
-#define indexAddrOffForeignObjZh(r,fo,i)      indexAddrOffAddrZh(r,ForeignObj_CLOSURE_DATA(fo),i)
-#define indexFloatOffForeignObjZh(r,fo,i)     indexFloatOffAddrZh(r,ForeignObj_CLOSURE_DATA(fo),i)
-#define indexDoubleOffForeignObjZh(r,fo,i)    indexDoubleOffAddrZh(r,ForeignObj_CLOSURE_DATA(fo),i)
-#define indexInt64OffForeignObjZh(r,fo,i)     indexInt64OffAddrZh(r,ForeignObj_CLOSURE_DATA(fo),i)
-#define indexWord64OffForeignObjZh(r,fo,i)    indexWord64OffAddrZh(r,ForeignObj_CLOSURE_DATA(fo),i)
-
-#define indexCharOffAddrZh(r,a,i)       r= ((C_ *)(a))[i]
-#define indexIntOffAddrZh(r,a,i)        r= ((I_ *)(a))[i]
-#define indexStablePtrOffAddrZh(r,a,i)  r= ((StgStablePtr *)(a))[i]
-#define indexWordOffAddrZh(r,a,i)       r= ((W_ *)(a))[i]
-#define indexAddrOffAddrZh(r,a,i)       r= ((PP_)(a))[i]
-#define indexFloatOffAddrZh(r,a,i)      r= PK_FLT((P_) (((StgFloat *)(a)) + i))
-#define indexDoubleOffAddrZh(r,a,i)     r= PK_DBL((P_) (((StgDouble *)(a)) + i))
-#define indexInt64OffAddrZh(r,a,i)      r= ((LI_ *)(a))[i]
-#define indexWord64OffAddrZh(r,a,i) r= ((LW_ *)(a))[i]
-
-#define writeCharOffAddrZh(a,i,v)       ((C_ *)(a))[i] = (v)
-#define writeIntOffAddrZh(a,i,v)        ((I_ *)(a))[i] = (v)
-#define writeStablePtrOffAddrZh(a,i,v)  ((StgStablePtr *)(a))[i] = (v)
-#define writeWordOffAddrZh(a,i,v)       ((W_ *)(a))[i] = (v)
-#define writeAddrOffAddrZh(a,i,v)       ((PP_)(a))[i] = (v)
-#define writeForeignObjOffAddrZh(a,i,v) ((PP_)(a))[i] = ForeignObj_CLOSURE_DATA(v)
-#define writeFloatOffAddrZh(a,i,v)      ASSIGN_FLT((P_) (((StgFloat *)(a)) + i),v)
-#define writeDoubleOffAddrZh(a,i,v)     ASSIGN_DBL((P_) (((StgDouble *)(a)) + i),v)
-#define writeInt64OffAddrZh(a,i,v)      ((LI_ *)(a))[i] = (v)
-#define writeWord64OffAddrZh(a,i,v)     ((LW_ *)(a))[i] = (v)
-
-
-/* Freezing arrays-of-ptrs requires changing an info table, for the
-   benefit of the generational collector.  It needs to scavenge mutable
-   objects, even if they are in old space.  When they become immutable,
-   they can be removed from this scavenge list.         */
-#define unsafeFreezeArrayZh(r,a)                               \
-       do {                                            \
-       P_ result;                                      \
-       result=(P_) (a);                                \
-       FREEZE_MUT_HDR(result,ImMutArrayOfPtrs_info);   \
-       r = result;                                     \
-       }while(0)
-
-#define unsafeFreezeByteArrayZh(r,a)   r=(B_)(a)
-
-#define sizeofByteArrayZh(r,a)        r=(W_)sizeof(W_)*(W_)(DATA_CLOSURE_SIZE(a)-DATA_VHS)
-#define sizeofMutableByteArrayZh(r,a) r=(W_)sizeof(W_)*(W_)(DATA_CLOSURE_SIZE(a)-DATA_VHS)
-\end{code}
-
-Now the \tr{newArr*} ops:
-
-\begin{code}
-/*
---------------------
-Will: ToDo: we need to find suitable places to put this comment, and the
-"in-general" one which follows.
-
-************ Nota Bene.         The "n" in this macro is guaranteed to
-be a register, *not* (say) Node[1].  That means that it is guaranteed
-to survive GC, provided only that the register is kept unaltered.
-This is important, because "n" is used after the HEAP_CHK.
-
-In general, *all* parameters to these primitive-op macros are always
-registers.  (Will: For exactly *which* primitive-op macros is this guaranteed?
-Exactly those which can trigger GC?)
-------------------------
-
-NOTE: the above may now be OLD (WDP 94/02/10)
-*/
-\end{code}
-
-For char arrays, the size is in {\em BYTES}.
-
-\begin{code}
-#define newCharArrayZh(r,liveness,n)     newByteArray(r,liveness,(n) * sizeof(C_))
-#define newIntArrayZh(r,liveness,n)      newByteArray(r,liveness,(n) * sizeof(I_))
-#define newStablePtrArrayZh(r,liveness,n) newByteArray(r,liveness,(n) * sizeof(StgStablePtr))
-#define newWordArrayZh(r,liveness,n)     newByteArray(r,liveness,(n) * sizeof(W_))
-#define newInt64ArrayZh(r,liveness,n)    newByteArray(r,liveness,(n) * sizeof(LI_))
-#define newWord64ArrayZh(r,liveness,n)   newByteArray(r,liveness,(n) * sizeof(LW_))
-#define newAddrArrayZh(r,liveness,n)     newByteArray(r,liveness,(n) * sizeof(P_))
-#define newFloatArrayZh(r,liveness,n)    newByteArray(r,liveness,(n) * sizeof(StgFloat))
-#define newDoubleArrayZh(r,liveness,n)   newByteArray(r,liveness,(n) * sizeof(StgDouble))
-
-#define newByteArray(r,liveness,n)                             \
-{                                                              \
-  P_ result;                                                   \
-  I_ size;                                                     \
-                                                               \
-  HEAP_CHK(liveness,DATA_HS+BYTES_TO_STGWORDS(n),0);           \
-  size = BYTES_TO_STGWORDS(n);                                 \
-  ALLOC_PRIM(DATA_HS,size,0,DATA_HS+size) /* ticky ticky */;   \
-  CC_ALLOC(CCC,DATA_HS+size,ARR_K);                            \
-                                                               \
-  result = Hp-(DATA_HS+size)+1;                                        \
-  SET_DATA_HDR(result,ArrayOfData_info,CCC,DATA_VHS+size,0);   \
-  r = (B_) result;                                             \
-}
-\end{code}
-
-Arrays of pointers need to be initialised; uses \tr{TUPLES}!
-The initialisation value is guaranteed to be in a register,
-and will be indicated by the liveness mask, so it's ok to do
-a \tr{HEAP_CHK}, which may trigger GC.
-
-\begin{code}
-/* The new array initialization routine for the NCG */
-void newArrZh_init PROTO((P_ result, I_ n, P_ init));
-
-#define newArrayZh(r,liveness,n,init)                  \
-{                                                      \
-  P_ p;                                                        \
-  P_ result;                                           \
-                                                       \
-  HEAP_CHK(liveness, MUTUPLE_HS+(n),0);                        \
-  ALLOC_PRIM(MUTUPLE_HS,(n),0,MUTUPLE_HS+(n)) /* ticky ticky */; \
-  CC_ALLOC(CCC,MUTUPLE_HS+(n),ARR_K); /* cc prof */    \
-                                                       \
-  result = Hp + 1 - (MUTUPLE_HS+(n));                  \
-  SET_MUTUPLE_HDR(result,ArrayOfPtrs_info,CCC,MUTUPLE_VHS+(n),0) \
-  for (p = result+MUTUPLE_HS; p < (result+MUTUPLE_HS+(n)); p++) { \
-       *p = (W_) (init);                               \
-  }                                                    \
-                                                       \
-  r = result;                                          \
-}
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection[StgMacros-SynchVar-primops]{Synchronizing Variables PrimOps}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-ED_(PrelBase_Z91Z93_closure);
-
-#define sameMVarZh(r,a,b)      r=(I_)((a)==(b))
-
-#define newSynchVarZh(r, hp)                           \
-{                                                      \
-  ALLOC_PRIM(MUTUPLE_HS,3,0,MUTUPLE_HS+3) /* ticky ticky */; \
-  CC_ALLOC(CCC,MUTUPLE_HS+3,ARR_K); /* cc prof */      \
-  SET_SVAR_HDR(hp,EmptySVar_info,CCC);                 \
-  SVAR_HEAD(hp) = SVAR_TAIL(hp) = SVAR_VALUE(hp) = PrelBase_Z91Z93_closure;    \
-  r = hp;                                              \
-}
-\end{code}
-
-\begin{code}
-#ifdef CONCURRENT
-
-void Yield PROTO((W_));
-
-#define takeMVarZh(r, liveness, node)                  \
-{                                                      \
-  while (INFO_PTR(node) != (W_) FullSVar_info) {       \
-    if (SVAR_HEAD(node) == PrelBase_Z91Z93_closure)            \
-      SVAR_HEAD(node) = CurrentTSO;                    \
-    else                                               \
-      TSO_LINK(SVAR_TAIL(node)) = CurrentTSO;          \
-    TSO_LINK(CurrentTSO) = (P_) PrelBase_Z91Z93_closure;               \
-    SVAR_TAIL(node) = CurrentTSO;                      \
-    DO_YIELD(liveness << 1);                           \
-  }                                                    \
-  SET_INFO_PTR(node, EmptySVar_info);                  \
-  r = SVAR_VALUE(node);                                        \
-  SVAR_VALUE(node) = PrelBase_Z91Z93_closure;                          \
-}
-
-#else
-
-#define takeMVarZh(r, liveness, node)                  \
-{                                                      \
-  if (INFO_PTR(node) != (W_) FullSVar_info) {          \
-    /* Don't wrap the calls; we're done with STG land */\
-    fflush(stdout);                                    \
-    fprintf(stderr, "takeMVar#: MVar is empty.\n");            \
-    EXIT(EXIT_FAILURE);                                        \
-  }                                                    \
-  SET_INFO_PTR(node, EmptySVar_info);                  \
-  r = SVAR_VALUE(node);                                        \
-  SVAR_VALUE(node) = PrelBase_Z91Z93_closure;                          \
-}
-
-#endif
-\end{code}
-
-\begin{code}
-#ifdef CONCURRENT
-
-#ifdef GRAN
-
-/* Only difference to the !GRAN def: RunnableThreadsHd has been replaced by */
-/* ThreadQueueHd i.e. the tso is added at the end of the thread queue on */
-/* the CurrentProc. This means we have an implicit context switch after */
-/* putMVar even if unfair scheduling is used in GranSim (default)!  -- HWL */
-
-#define putMVarZh(node, value)                         \
-{                                                      \
-  P_ tso;                                              \
-  if (INFO_PTR(node) == (W_) FullSVar_info) {          \
-    /* Don't wrap the calls; we're done with STG land */\
-    fflush(stdout);                                    \
-    fprintf(stderr, "putMVar#: MVar already full.\n"); \
-    EXIT(EXIT_FAILURE);                                        \
-  }                                                    \
-  SET_INFO_PTR(node, FullSVar_info);                   \
-  SVAR_VALUE(node) = value;                            \
-  tso = SVAR_HEAD(node);                               \
-  if (tso != (P_) PrelBase_Z91Z93_closure) {                           \
-    if (DO_QP_PROF)                                    \
-      STGCALL3(void,(void *, char *, P_, P_),QP_Event2,do_qp_prof > 1 ? "RA" : "RG",tso,CurrentTSO);   \
-    if (ThreadQueueHd == PrelBase_Z91Z93_closure)              \
-      ThreadQueueHd = tso;                     \
-    else                                               \
-      TSO_LINK(ThreadQueueTl) = tso;           \
-    ThreadQueueTl = tso;                               \
-    SVAR_HEAD(node) = TSO_LINK(tso);                   \
-    TSO_LINK(tso) = (P_) PrelBase_Z91Z93_closure;                      \
-    if(SVAR_HEAD(node) == (P_) PrelBase_Z91Z93_closure)                \
-      SVAR_TAIL(node) = (P_) PrelBase_Z91Z93_closure;          \
-  }                                                    \
-}
-
-#else /* !GRAN */
-
-#define putMVarZh(node, value)                         \
-{                                                      \
-  P_ tso;                                              \
-  if (INFO_PTR(node) == (W_) FullSVar_info) {          \
-    /* Don't wrap the calls; we're done with STG land */\
-    fflush(stdout);                                    \
-    fprintf(stderr, "putMVar#: MVar already full.\n"); \
-    EXIT(EXIT_FAILURE);                                        \
-  }                                                    \
-  SET_INFO_PTR(node, FullSVar_info);                   \
-  SVAR_VALUE(node) = value;                            \
-  tso = SVAR_HEAD(node);                               \
-  if (tso != (P_) PrelBase_Z91Z93_closure) {                           \
-    if (DO_QP_PROF)                                    \
-      STGCALL3(void,(void *, char *, P_, P_),QP_Event2,do_qp_prof > 1 ? "RA" : "RG",tso,CurrentTSO);   \
-    if (RunnableThreadsHd == PrelBase_Z91Z93_closure)                  \
-      RunnableThreadsHd = tso;                         \
-    else                                               \
-      TSO_LINK(RunnableThreadsTl) = tso;               \
-    RunnableThreadsTl = tso;                           \
-    SVAR_HEAD(node) = TSO_LINK(tso);                   \
-    TSO_LINK(tso) = (P_) PrelBase_Z91Z93_closure;                      \
-    if(SVAR_HEAD(node) == (P_) PrelBase_Z91Z93_closure)                \
-      SVAR_TAIL(node) = (P_) PrelBase_Z91Z93_closure;          \
-  }                                                    \
-}
-
-#endif  /* GRAN */
-
-#else
-
-#define putMVarZh(node, value)                         \
-{                                                      \
-  P_ tso;                                              \
-  if (INFO_PTR(node) == (W_) FullSVar_info) {          \
-    /* Don't wrap the calls; we're done with STG land */\
-    fflush(stdout);                                    \
-    fprintf(stderr, "putMVar#: MVar already full.\n"); \
-    EXIT(EXIT_FAILURE);                                        \
-  }                                                    \
-  SET_INFO_PTR(node, FullSVar_info);                   \
-  SVAR_VALUE(node) = value;                            \
-}
-
-#endif
-\end{code}
-
-\begin{code}
-#ifdef CONCURRENT
-
-#define readIVarZh(r, liveness, node)                  \
-{                                                      \
-  if (INFO_PTR(node) != (W_) ImMutArrayOfPtrs_info) {  \
-    if (SVAR_HEAD(node) == PrelBase_Z91Z93_closure)            \
-      SVAR_HEAD(node) = CurrentTSO;                    \
-    else                                               \
-      TSO_LINK(SVAR_TAIL(node)) = CurrentTSO;          \
-    TSO_LINK(CurrentTSO) = (P_) PrelBase_Z91Z93_closure;               \
-    SVAR_TAIL(node) = CurrentTSO;                      \
-    DO_YIELD(liveness << 1);                           \
-  }                                                    \
-  r = SVAR_VALUE(node);                                        \
-}
-
-#else
-
-#define readIVarZh(r, liveness, node)                  \
-{                                                      \
-  if (INFO_PTR(node) != (W_) ImMutArrayOfPtrs_info) {  \
-    /* Don't wrap the calls; we're done with STG land */\
-    fflush(stdout);                                    \
-    fprintf(stderr, "readIVar#: IVar is empty.\n");            \
-    EXIT(EXIT_FAILURE);                                        \
-  }                                                    \
-  r = SVAR_VALUE(node);                                        \
-}
-
-#endif
-\end{code}
-
-\begin{code}
-#ifdef CONCURRENT
-
-#ifdef GRAN
-
-/* Only difference to the !GRAN def: RunnableThreadsHd has been replaced by */
-/* ThreadQueueHd i.e. the tso is added at the end of the thread queue on */
-/* the CurrentProc. This means we have an implicit context switch after */
-/* writeIVar even if unfair scheduling is used in GranSim (default)!  -- HWL */
-
-#define writeIVarZh(node, value)                       \
-{                                                      \
-  P_ tso;                                              \
-  if (INFO_PTR(node) == (W_) ImMutArrayOfPtrs_info) {  \
-    /* Don't wrap the calls; we're done with STG land */\
-    fflush(stdout);                                    \
-    fprintf(stderr, "writeIVar#: IVar already full.\n");\
-    EXIT(EXIT_FAILURE);                                        \
-  }                                                    \
-  tso = SVAR_HEAD(node);                               \
-  if (tso != (P_) PrelBase_Z91Z93_closure) {                           \
-    if (ThreadQueueHd == PrelBase_Z91Z93_closure)              \
-      ThreadQueueHd = tso;                     \
-    else                                               \
-      TSO_LINK(ThreadQueueTl) = tso;           \
-    while(TSO_LINK(tso) != PrelBase_Z91Z93_closure) {                  \
-      if (DO_QP_PROF)                                  \
-        STGCALL3(void,(void *, char *, P_, P_),QP_Event2,do_qp_prof > 1 ? "RA" : "RG",tso,CurrentTSO); \
-      tso = TSO_LINK(tso);                             \
-    }                                                  \
-    if (DO_QP_PROF)                                    \
-      STGCALL3(void,(void *, char *, P_, P_),QP_Event2,do_qp_prof > 1 ? "RA" : "RG",tso,CurrentTSO);   \
-    ThreadQueueTl = tso;                               \
-  }                                                    \
-  /* Don't use freeze, since it's conditional on GC */ \
-  SET_INFO_PTR(node, ImMutArrayOfPtrs_info);           \
-  MUTUPLE_CLOSURE_SIZE(node) = (MUTUPLE_VHS+1);        \
-  SVAR_VALUE(node) = value;                            \
-}
-
-#else /* !GRAN */
-
-#define writeIVarZh(node, value)                       \
-{                                                      \
-  P_ tso;                                              \
-  if (INFO_PTR(node) == (W_) ImMutArrayOfPtrs_info) {  \
-    /* Don't wrap the calls; we're done with STG land */\
-    fflush(stdout);                                    \
-    fprintf(stderr, "writeIVar#: IVar already full.\n");\
-    EXIT(EXIT_FAILURE);                                        \
-  }                                                    \
-  tso = SVAR_HEAD(node);                               \
-  if (tso != (P_) PrelBase_Z91Z93_closure) {                           \
-    if (RunnableThreadsHd == PrelBase_Z91Z93_closure)                  \
-      RunnableThreadsHd = tso;                         \
-    else                                               \
-      TSO_LINK(RunnableThreadsTl) = tso;               \
-    while(TSO_LINK(tso) != PrelBase_Z91Z93_closure) {                  \
-      if (DO_QP_PROF)                                  \
-        STGCALL3(void,(void *, char *, P_, P_),QP_Event2,do_qp_prof > 1 ? "RA" : "RG",tso,CurrentTSO); \
-      tso = TSO_LINK(tso);                             \
-    }                                                  \
-    if (DO_QP_PROF)                                    \
-      STGCALL3(void,(void *, char *, P_, P_),QP_Event2,do_qp_prof > 1 ? "RA" : "RG",tso,CurrentTSO);   \
-    RunnableThreadsTl = tso;                           \
-  }                                                    \
-  /* Don't use freeze, since it's conditional on GC */ \
-  SET_INFO_PTR(node, ImMutArrayOfPtrs_info);           \
-  MUTUPLE_CLOSURE_SIZE(node) = (MUTUPLE_VHS+1);        \
-  SVAR_VALUE(node) = value;                            \
-}
-
-#endif  /* GRAN */
-
-#else
-
-#define writeIVarZh(node, value)                       \
-{                                                      \
-  P_ tso;                                              \
-  if (INFO_PTR(node) == (W_) ImMutArrayOfPtrs_info) {  \
-    /* Don't wrap the calls; we're done with STG land */\
-    fflush(stdout);                                    \
-    fprintf(stderr, "writeIVar#: IVar already full.\n");\
-    EXIT(EXIT_FAILURE);                                        \
-  }                                                    \
-  /* Don't use freeze, since it's conditional on GC */ \
-  SET_INFO_PTR(node, ImMutArrayOfPtrs_info);           \
-  MUTUPLE_CLOSURE_SIZE(node) = (MUTUPLE_VHS+1);        \
-  SVAR_VALUE(node) = value;                            \
-}
-
-#endif
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection[StgMacros-Wait-primops]{Delay/Wait PrimOps}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-#ifdef CONCURRENT
-
-/* ToDo: for GRAN */
-
-#define delayZh(liveness, us)                          \
-  {                                                    \
-    if (WaitingThreadsTl == PrelBase_Z91Z93_closure)           \
-      WaitingThreadsHd = CurrentTSO;                   \
-    else                                               \
-      TSO_LINK(WaitingThreadsTl) = CurrentTSO;         \
-    WaitingThreadsTl = CurrentTSO;                     \
-    TSO_LINK(CurrentTSO) = PrelBase_Z91Z93_closure;                    \
-    TSO_EVENT(CurrentTSO) = (W_) ((us) < 1 ? 1 : (us)); \
-    DO_YIELD(liveness << 1);                           \
-  }
-
-#else
-
-#define delayZh(liveness, us)                          \
-  {                                                    \
-    fflush(stdout);                                    \
-    fprintf(stderr, "delay#: unthreaded build.\n");            \
-    EXIT(EXIT_FAILURE);                                        \
-  }
-
-#endif
-
-#ifdef CONCURRENT
-
-/* ToDo: something for GRAN */
-
-#define waitReadZh(liveness, fd)                       \
-  {                                                    \
-    if (WaitingThreadsTl == PrelBase_Z91Z93_closure)           \
-      WaitingThreadsHd = CurrentTSO;                   \
-    else                                               \
-      TSO_LINK(WaitingThreadsTl) = CurrentTSO;         \
-    WaitingThreadsTl = CurrentTSO;                     \
-    TSO_LINK(CurrentTSO) = PrelBase_Z91Z93_closure;                    \
-    TSO_EVENT(CurrentTSO) = (W_) (-(fd));              \
-    DO_YIELD(liveness << 1);                           \
-  }
-
-#else
-
-#define waitReadZh(liveness, fd)                       \
-  {                                                    \
-    fflush(stdout);                                    \
-    fprintf(stderr, "waitRead#: unthreaded build.\n");         \
-    EXIT(EXIT_FAILURE);                                        \
-  }
-
-#endif
-
-#ifdef CONCURRENT
-
-/* ToDo: something for GRAN */
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif  HAVE_SYS_TYPES_H */
-
-#define waitWriteZh(liveness, fd)                      \
-  {                                                    \
-    if (WaitingThreadsTl == PrelBase_Z91Z93_closure)           \
-      WaitingThreadsHd = CurrentTSO;                   \
-    else                                               \
-      TSO_LINK(WaitingThreadsTl) = CurrentTSO;         \
-    WaitingThreadsTl = CurrentTSO;                     \
-    TSO_LINK(CurrentTSO) = PrelBase_Z91Z93_closure;                    \
-    TSO_EVENT(CurrentTSO) = (W_) (-(fd+FD_SETSIZE));   \
-    DO_YIELD(liveness << 1);                           \
-  }
-
-#else
-
-#define waitWriteZh(liveness, fd)                      \
-  {                                                    \
-    fflush(stdout);                                    \
-    fprintf(stderr, "waitWrite#: unthreaded build.\n"); \
-    EXIT(EXIT_FAILURE);                                        \
-  }
-
-#endif
-
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection[StgMacros-IO-primops]{Primitive I/O, error-handling primops}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-extern P_ TopClosure;
-EXTFUN(ErrorIO_innards);
-EXTFUN(__std_entry_error__);
-
-#define errorIOZh(a)           \
-    do { TopClosure=(a);       \
-        (void) SAFESTGCALL1(I_,(void *, FILE *),fflush,stdout); \
-        (void) SAFESTGCALL1(I_,(void *, FILE *),fflush,stderr); \
-        JMP_(ErrorIO_innards); \
-    } while(0)
-
-/* These are now, I believe, unused. (8/98 SOF) */
-#if !defined(CALLER_SAVES_SYSTEM)
-/* can use the macros */
-#define stg_getc(stream)       getc((FILE *) (stream))
-#define stg_putc(c,stream)     putc((c),((FILE *) (stream)))
-#else
-/* must not use the macros (they contain embedded calls to _filbuf/whatnot) */
-#define stg_getc(stream)       SAFESTGCALL1(I_,(void *, FILE *),fgetc,(FILE *) (stream))
-#define stg_putc(c,stream)     SAFESTGCALL2(I_,(void *, char, FILE *),fputc,(c),((FILE *) (stream)))
-#endif
-
-int initialize_virtual_timer(int us);
-int install_segv_handler(STG_NO_ARGS);
-int install_vtalrm_handler(STG_NO_ARGS);
-void initUserSignals(STG_NO_ARGS);
-void blockUserSignals(STG_NO_ARGS);
-void unblockUserSignals(STG_NO_ARGS);
-IF_RTS(void blockVtAlrmSignal(STG_NO_ARGS);)
-IF_RTS(void unblockVtAlrmSignal(STG_NO_ARGS);)
-IF_RTS(void AwaitEvent(I_ delta);)
-
-#if  defined(_POSIX_SOURCE) && !defined(nextstep3_TARGET_OS)
-       /* For nextstep3_TARGET_OS comment see stgdefs.h. CaS */
-extern I_ sig_install PROTO((I_, I_, sigset_t *));
-#define stg_sig_ignore(s,m)    SAFESTGCALL3(I_,(void *, I_, I_),sig_install,s,STG_SIG_IGN,(sigset_t *)m)
-#define stg_sig_default(s,m)   SAFESTGCALL3(I_,(void *, I_, I_),sig_install,s,STG_SIG_DFL,(sigset_t *)m)
-#define stg_sig_catch(s,sp,m)  SAFESTGCALL3(I_,(void *, I_, I_),sig_install,s,sp,(sigset_t *)m)
-#else
-extern I_ sig_install PROTO((I_, I_));
-#define stg_sig_ignore(s,m)    SAFESTGCALL2(I_,(void *, I_, I_),sig_install,s,STG_SIG_IGN)
-#define stg_sig_default(s,m)   SAFESTGCALL2(I_,(void *, I_, I_),sig_install,s,STG_SIG_DFL)
-#define stg_sig_catch(s,sp,m)  SAFESTGCALL2(I_,(void *, I_, I_),sig_install,s,sp)
-#endif
-
-#define STG_SIG_DFL    (-1)
-#define STG_SIG_IGN    (-2)
-#define STG_SIG_ERR    (-3)
-
-StgInt getErrorHandler(STG_NO_ARGS);
-#ifndef PAR
-void   raiseError PROTO((StgStablePtr handler));
-StgInt catchError PROTO((StgStablePtr newErrorHandler));
-#endif
-void decrementErrorCount(STG_NO_ARGS);
-
-#define stg_catchError(sp)        SAFESTGCALL1(I_,(void *, StgStablePtr),catchError,sp)
-#define stg_decrementErrorCount() SAFESTGCALL0(void,(void *),decrementErrorCount)
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection[StgMacros-stable-ptr]{Primitive ops for manipulating stable pointers}
-%*                                                                     *
-%************************************************************************
-
-
-The type of these should be:
-
-\begin{verbatim}
-makeStablePointer#  :: a -> State# _RealWorld -> StateAndStablePtr# _RealWorld a
-deRefStablePointer# :: StablePtr# a -> State# _RealWorld -> StateAndPtr _RealWorld a
-\end{verbatim}
-
-Since world-tokens are no longer explicitly passed around, the
-implementations have a few less arguments/results.
-
-The simpler one is @deRefStablePointer#@ (which is only a primop
-because it is more polymorphic than is allowed of a ccall).
-
-\begin{code}
-#ifdef PAR
-
-#define deRefStablePtrZh(ri,sp)                                            \
-do {                                                               \
-    fflush(stdout);                                                \
-    fprintf(stderr, "deRefStablePtr#: no stable pointer support.\n");\
-    EXIT(EXIT_FAILURE);                                                    \
-} while(0)
-
-#else /* !PAR */
-
-extern StgPtr _deRefStablePointer PROTO((StgInt, StgPtr));
-
-#define deRefStablePtrZh(ri,sp) \
-   ri = SAFESTGCALL2(I_,(void *, I_, P_),_deRefStablePointer,sp,StorageMgrInfo.StablePointerTable);
-\end{code}
-
-Declarations for other stable pointer operations.
-
-\begin{code}
-void   freeStablePointer       PROTO((I_ stablePtr));
-
-void   enterStablePtr          PROTO((StgStablePtr, StgFunPtr));
-void   performIO               PROTO((StgStablePtr));
-I_     enterInt                PROTO((StgStablePtr));
-I_     enterFloat              PROTO((StgStablePtr));
-P_     deRefStablePointer      PROTO((StgStablePtr));
-IF_RTS(I_ catchSoftHeapOverflow        PROTO((StgStablePtr, I_));)
-IF_RTS(I_ getSoftHeapOverflowHandler(STG_NO_ARGS);)
-IF_RTS(extern StgStablePtr softHeapOverflowHandler;)
-IF_RTS(void shutdownHaskell(STG_NO_ARGS);)
-
-EXTFUN(stopPerformIODirectReturn);
-EXTFUN(startPerformIO);
-EXTFUN(stopEnterIntDirectReturn);
-EXTFUN(startEnterInt);
-EXTFUN(stopEnterFloatDirectReturn);
-EXTFUN(startEnterFloat);
-
-void enterStablePtr PROTO((StgStablePtr stableIndex, StgFunPtr startCode));
-
-char* createAdjustor PROTO((int cc,StgStablePtr hptr, StgFunPtr wptr));
-void freeAdjustor PROTO((void* ptr));
-
-#endif /* !PAR */
-
-IF_RTS(extern I_ ErrorIO_call_count;)
-\end{code}
-
-Somewhat harder is @makeStablePointer#@ --- it is usually simple but
-if we're unlucky, it will have to allocate a new table and copy the
-old bit over.  Since we might, very occasionally, have to call the
-garbage collector, this has to be a macro... sigh!
-
-NB @newSP@ is required because it is entirely possible that
-@stablePtr@ and @unstablePtr@ are aliases and so we can't do the
-assignment to @stablePtr@ until we've finished with @unstablePtr@.
-
-Another obscure piece of coding is the recalculation of the size of
-the table.  We do this just in case Jim's threads decide they want to
-context switch---in which case any stack-allocated variables may get
-trashed.  (If only there was a special heap check which didn't
-consider context switching...)
-
-\begin{code}
-#ifndef PAR
-
-/* Calculate SP Table size from number of pointers */
-#define SPTSizeFromNoPtrs( newNP ) (DYN_VHS + 1 + 2 * (newNP))
-
-/* Calculate number of pointers in new table from number in old table:
-   any strictly increasing expression will do here */
-#define CalcNewNoSPtrs( i ) ((i)*2 + 100)
-
-void enlargeSPTable PROTO((P_, P_));
-
-#define makeStablePtrZh(stablePtr,liveness,unstablePtr)                    \
-do {                                                               \
-  EXTDATA_RO(StablePointerTable_info);                             \
-  EXTDATA(UnusedSP);                                               \
-  StgStablePtr newSP;                                              \
-                                                                   \
-  if (SPT_EMPTY(StorageMgrInfo.StablePointerTable)) { /* free stack is empty */ \
-    { /* Variables used before the heap check */                   \
-      I_ OldNoPtrs = SPT_NoPTRS( StorageMgrInfo.StablePointerTable ); \
-      I_ NewNoPtrs = CalcNewNoSPtrs( OldNoPtrs );                  \
-      I_ NewSize = SPTSizeFromNoPtrs( NewNoPtrs );                 \
-      HEAP_CHK(liveness, _FHS+NewSize, 0);                         \
-    }                                                              \
-    { /* Variables used after the heap check - same values */      \
-      I_ OldNoPtrs = SPT_NoPTRS( StorageMgrInfo.StablePointerTable ); \
-      I_ NewNoPtrs = CalcNewNoSPtrs( OldNoPtrs );                  \
-      I_ NewSize = SPTSizeFromNoPtrs( NewNoPtrs );                 \
-      P_ SPTable = Hp + 1 - (_FHS + NewSize);                      \
-                                                                   \
-      CC_ALLOC(CCC, _FHS+NewSize, SPT_K); /* cc prof */                    \
-      SET_DYN_HDR(SPTable,StablePointerTable_info,CCC,NewSize,NewNoPtrs);\
-      SAFESTGCALL2(void, (void *, P_, P_), enlargeSPTable, SPTable, StorageMgrInfo.StablePointerTable);             \
-      StorageMgrInfo.StablePointerTable = SPTable;                 \
-    }                                                              \
-  }                                                                \
-                                                                   \
-  newSP = SPT_POP(StorageMgrInfo.StablePointerTable);              \
-  SPT_SPTR(StorageMgrInfo.StablePointerTable, newSP) = unstablePtr; \
-  CHECK_SPT_CLOSURE( StorageMgrInfo.StablePointerTable );           \
-  stablePtr = newSP;                                               \
-} while (0)
-
-#else
-
-#define makeStablePtrZh(stablePtr,liveness,unstablePtr)                    \
-do {                                                               \
-    fflush(stdout);                                                \
-    fprintf(stderr, "makeStablePtr#: no stable pointer support.\n");\
-    EXIT(EXIT_FAILURE);                                                    \
-} while(0)
-
-#endif /* !PAR */
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection[StgMacros-unsafePointerEquality]{Primitive `op' for breaking referential transparency}
-%*                                                                     *
-%************************************************************************
-
-The type of this is @reallyUnsafePtrEquality :: a -> a -> Int#@ so we
-can expect three parameters: the two arguments and a "register" to put
-the result into.
-
-Message to Will: This primop breaks referential transparency so badly
-you might want to leave it out.         On the other hand, if you hide it
-away in an appropriate monad, it's perfectly safe. [ADR]
-
-Note that this primop is non-deterministic: different results can be
-obtained depending on just what the garbage collector (and code
-optimiser??) has done. However, we can guarantee that if two objects
-are pointer-equal, they have the same denotation --- the converse most
-certainly doesn't hold.
-
-ToDo ADR: The degree of non-determinism could be greatly reduced by
-following indirections.
-
-\begin{code}
-#define reallyUnsafePtrEqualityZh(r,a,b) r=((StgPtr)(a) == (StgPtr)(b))
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection[StgMacros-parallel-primop]{Primitive `op' for sparking (etc)}
-%*                                                                     *
-%************************************************************************
-
-Assuming local sparking in some form, we can now inline the spark request.
-
-We build a doubly-linked list in the heap, so that we can handle FIFO
-or LIFO scheduling as we please.
-
-Anything with tag >= 0 is in WHNF, so we discard it.
-
-\begin{code}
-#ifdef CONCURRENT
-
-ED_(PrelBase_Z91Z93_closure);
-ED_(True_closure);
-
-#if defined(GRAN)
-#define parZh(r,node)                          \
-       PARZh(r,node,1,0,0,0,0,0)
-
-#define parAtZh(r,node,where,identifier,gran_info,size_info,par_info,rest) \
-       parATZh(r,node,where,identifier,gran_info,size_info,par_info,rest,1)
-
-#define parAtAbsZh(r,node,proc,identifier,gran_info,size_info,par_info,rest) \
-       parATZh(r,node,proc,identifier,gran_info,size_info,par_info,rest,2)
-
-#define parAtRelZh(r,node,proc,identifier,gran_info,size_info,par_info,rest) \
-       parATZh(r,node,proc,identifier,gran_info,size_info,par_info,rest,3)
-
-#define parAtForNowZh(r,node,where,identifier,gran_info,size_info,par_info,rest)       \
-       parATZh(r,node,where,identifier,gran_info,size_info,par_info,rest,0)
-
-#define parATZh(r,node,where,identifier,gran_info,size_info,par_info,rest,local)       \
-{                                                      \
-  sparkq result;                                               \
-  if (SHOULD_SPARK(node)) {                            \
-    SaveAllStgRegs();                                  \
-    { sparkq result;                                           \
-      result = NewSpark((P_)node,identifier,gran_info,size_info,par_info,local);       \
-      if (local==2) {         /* special case for parAtAbs */   \
-        GranSimSparkAtAbs(result,(I_)where,identifier);\
-      } else if (local==3) {  /* special case for parAtRel */   \
-        GranSimSparkAtAbs(result,(I_)(CurrentProc+where),identifier);  \
-      } else {       \
-        GranSimSparkAt(result,where,identifier);       \
-      }        \
-      context_switch = 1;                              \
-    }                                                   \
-    RestoreAllStgRegs();                               \
-  } else if (do_qp_prof) {                             \
-    I_ tid = threadId++;                               \
-    SAFESTGCALL2(void,(I_, P_),QP_Event0,tid,node);    \
-  }                                                    \
-  r = 1; /* return code for successful spark -- HWL */ \
-}
-
-#define parLocalZh(r,node,identifier,gran_info,size_info,par_info,rest)        \
-       PARZh(r,node,rest,identifier,gran_info,size_info,par_info,1)
-
-#define parGlobalZh(r,node,identifier,gran_info,size_info,par_info,rest) \
-       PARZh(r,node,rest,identifier,gran_info,size_info,par_info,0)
-
-#if 1
-
-#define PARZh(r,node,rest,identifier,gran_info,size_info,par_info,local) \
-{                                                      \
-  if (SHOULD_SPARK(node)) {                            \
-    SaveAllStgRegs();                                  \
-    { sparkq result;                                           \
-      result = NewSpark((P_)node,identifier,gran_info,size_info,par_info,local);\
-      add_to_spark_queue(result);                              \
-      GranSimSpark(local,(P_)node);                                    \
-      context_switch = 1;                              \
-    }                                                   \
-    RestoreAllStgRegs();                               \
-  } else if (do_qp_prof) {                             \
-    I_ tid = threadId++;                               \
-    SAFESTGCALL2(void,(I_, P_),QP_Event0,tid,node);    \
-  }                                                    \
-  r = 1; /* return code for successful spark -- HWL */ \
-}
-
-#else
-
-#define PARZh(r,node,rest,identifier,gran_info,size_info,par_info,local) \
-{                                                      \
-  sparkq result;                                               \
-  if (SHOULD_SPARK(node)) {                            \
-    result = NewSpark((P_)node,identifier,gran_info,size_info,par_info,local);\
-    ADD_TO_SPARK_QUEUE(result);                                \
-    SAFESTGCALL2(void,(W_),GranSimSpark,local,(P_)node);       \
-    /* context_switch = 1;  not needed any more -- HWL */      \
-  } else if (do_qp_prof) {                             \
-    I_ tid = threadId++;                               \
-    SAFESTGCALL2(void,(I_, P_),QP_Event0,tid,node);    \
-  }                                                    \
-  r = 1; /* return code for successful spark -- HWL */ \
-}
-
-#endif 
-
-#define copyableZh(r,node)                             \
-  /* copyable not yet implemented!! */
-
-#define noFollowZh(r,node)                             \
-  /* noFollow not yet implemented!! */
-
-#else  /* !GRAN */
-
-extern I_ required_thread_count;
-
-#ifdef PAR
-#define COUNT_SPARK     TSO_GLOBALSPARKS(CurrentTSO)++; sparksCreated++
-#else
-#define COUNT_SPARK
-#endif
-
-/* 
-   Note that we must bump the required thread count NOW, rather
-   than when the thread is actually created.  
- */
-
-#define forkZh(r,liveness,node)                                \
-{                                                      \
-  while (PendingSparksTl[REQUIRED_POOL] == PendingSparksLim[REQUIRED_POOL]) \
-    DO_YIELD((liveness << 1) | 1);                     \
-  COUNT_SPARK;                                         \
-  if (SHOULD_SPARK(node)) {                            \
-    *PendingSparksTl[REQUIRED_POOL]++ = (P_)(node);    \
-  } else if (DO_QP_PROF) {                             \
-    I_ tid = threadId++;                               \
-    SAFESTGCALL2(void,(I_, P_),QP_Event0,tid,node);    \
-  }                                                    \
-  required_thread_count++;                             \
-  context_switch = 1;                                  \
-  r = 1; /* Should not be necessary */                 \
-}
-
-#define parZh(r,node)                                  \
-{                                                      \
-  COUNT_SPARK;                                         \
-  if (SHOULD_SPARK(node) &&                            \
-   PendingSparksTl[ADVISORY_POOL] < PendingSparksLim[ADVISORY_POOL]) { \
-    *PendingSparksTl[ADVISORY_POOL]++ = (P_)(node);    \
-  } else {                                             \
-    sparksIgnored++;                                   \
-    if (DO_QP_PROF) {                                  \
-      I_ tid = threadId++;                             \
-      SAFESTGCALL2(void,(I_, P_),QP_Event0,tid,node);  \
-    }                                                  \
-  }                                                    \
-  r = 1; /* Should not be necessary */                 \
-}
-
-#endif  /* GRAN */ 
-
-#endif /* CONCURRENT */
-\end{code}
-
-The following seq# code should only be used in unoptimized code.
-Be warned: it's a potential bug-farm.
-[SOF 8/98: 
-  Yes, it completely fails to work for function values, since a PAP 
-  closure will be constructed when the arg satisfaction check fails.
-  This PAP closure will add the magic values that gets pushed on the B stack 
-  before entering the 'seqee' (new word!), as Jim is just about to tell
-  us about. Let's hear what he's got to say:
-]
-
-First we push two words on the B stack: the current value of RetReg 
-(which may or may not be live), and a continuation snatched largely out
-of thin air (it's a point within this code block).  Then we set RetReg
-to the special polymorphic return code for seq, load up Node with the
-closure to be evaluated, and we're off.  When the eval returns to the
-polymorphic seq return point, the two words are popped off the B stack,
-RetReg is restored, and we jump to the continuation, completing the
-primop and going on our merry way.
-
-[ To workaround the shortcoming of not being able to deal with partially
-  applied values, we explicitly prohibit this at the Haskell source level
-  (i.e., we don't define an Eval instance for (->) ). 
-]
-
-\begin{code}
-
-ED_RO_(vtbl_seq);
-
-#define seqZh(r,liveness,node)             \
-  ({                                       \
-    __label__ cont;                        \
-    /* STK_CHK(liveness,0,2,0,0,0,0); */    \
-    /* SpB -= BREL(2); */                  \
-    SpB[BREL(0)] = (W_) RetReg;                    \
-    SpB[BREL(1)] = (W_) &&cont;                    \
-    RetReg = (StgRetAddr) vtbl_seq;        \
-    Node = node;                           \
-    ENT_VIA_NODE();                        \
-    InfoPtr = (D_)(INFO_PTR(Node));        \
-    JMP_(ENTRY_CODE(InfoPtr));             \
-    cont:                                  \
-    r = 1; /* Should be unnecessary */     \
-  })
-
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection[StgMacros-foreign-objects]{Foreign Objects}
-%*                                                                     *
-%************************************************************************
-
-[Based on previous MallocPtr comments -- SOF]
-
-This macro is used to construct a ForeignObj on the heap.
-
-What this does is plug the pointer (which will be in a local
-variable) together with its finalising/free routine, into a fresh heap
-object and then sets a result (which will be a register) to point
-to the fresh heap object.
-
-To accommodate per-object finalisation, augment the macro with a
-finalisation routine argument. Nothing spectacular, just plug the
-pointer to the routine into the ForeignObj -- SOF 4/96
-
-Question: what's this "SET_ACTIVITY" stuff - should I be doing this
-too?  (It's if you want to use the SPAT profiling tools to
-characterize program behavior by ``activity'' -- tail-calling,
-heap-checking, etc. -- see Ticky.lh.  It is quite specialized.
-WDP 95/1)
-
-(Swapped first two arguments to make it come into line with what appears
-to be `standard' format, return register then liveness mask. -- SOF 4/96)
-
-\begin{code}
-#ifndef PAR
-
-StgInt eqForeignObj PROTO((StgForeignObj p1, StgForeignObj p2));
-StgInt eqStablePtr  PROTO((StgStablePtr  p1, StgStablePtr p2));
-
-#define makeForeignObjZh(r, liveness, mptr, finalise)    \
-do {                                                    \
-  P_ result;                                            \
-                                                        \
-  HEAP_CHK((W_)liveness, _FHS + ForeignObj_SIZE,0);             \
-  CC_ALLOC(CCC,_FHS + ForeignObj_SIZE,ForeignObj_K); /* cc prof */   \
-                                                                  \
-  result = Hp + 1 - (_FHS + ForeignObj_SIZE);                     \
-  SET_ForeignObj_HDR(result,ForeignObj_info,CCC,_FHS + ForeignObj_SIZE,0); \
-  ForeignObj_CLOSURE_DATA(result)      = (P_)mptr;                        \
-  ForeignObj_CLOSURE_FINALISER(result) = (P_)finalise;                    \
-  ForeignObj_CLOSURE_LINK(result) = StorageMgrInfo.ForeignObjList; \
-  StorageMgrInfo.ForeignObjList = result;                         \
-                                                       \
-                                                       \
- /*fprintf(stderr,"DEBUG: ForeignObj(0x%x) = <0x%x, 0x%x, 0x%x, 0x%x>\n",      \
-      result,                                          \
-      result[0],result[1],                             \
-      result[2],result[3]);*/                          \
-                                                       \
-  CHECK_ForeignObj_CLOSURE( result );                  \
-  VALIDATE_ForeignObjList( StorageMgrInfo.ForeignObjList ); \
-                                                       \
-  (r) = (P_) result;                                   \
-} while (0)
-
-#define writeForeignObjZh(res,datum)   ((PP_) ForeignObj_CLOSURE_DATA(res)) = ((P_)datum)
-
-#else
-#define makeForeignObjZh(r, liveness, mptr, finalise)              \
-do {                                                               \
-    fflush(stdout);                                                \
-    fprintf(stderr, "makeForeignObj#: no foreign object support.\n");\
-    EXIT(EXIT_FAILURE);                                                    \
-} while(0)
-
-#define writeForeignObjZh(res,datum)   \
-do {                                                               \
-    fflush(stdout);                                                \
-    fprintf(stderr, "writeForeignObj#: no foreign object support.\n");\
-    EXIT(EXIT_FAILURE);                                                    \
-} while(0)
-
-#endif /* !PAR */
-\end{code}
-
-
-End-of-file's multi-slurp protection:
-\begin{code}
-#endif /* ! STGMACROS_H */
-\end{code}