[project @ 1998-12-02 13:17:09 by simonm]
[ghc-hetmet.git] / ghc / includes / SMInfoTables.lh
diff --git a/ghc/includes/SMInfoTables.lh b/ghc/includes/SMInfoTables.lh
deleted file mode 100644 (file)
index 5798bec..0000000
+++ /dev/null
@@ -1,1761 +0,0 @@
-%
-% (c) The OBFUSCATION-THROUGH-GRATUITOUS-PREPROCESSOR-ABUSE Project,
-%     Glasgow University, 1990-1994
-%
-%************************************************************************
-%*                                                                     *
-\section[info-table-macros]{Info-table macros}
-%*                                                                     *
-%************************************************************************
-
-We define {\em info tables} here.  First, all the different pieces of
-an info table (entry code, evac code, etc.); then all the different
-kinds of info tables (SPEC, DYN, etc).  NB: some of the parallel-only
-kinds are defined in \tr{Parallel.lh}, not here.
-
-An info-table contains several fields. The first field is
-the label of the closure's {\em standard-entry code}. This is used by
-the reducer to ``evaluate'' the closure. The remaining fields are used
-by the garbage collector and other parts of the runtime
-system. Info-tables are declared using the C macros defined below.
-The details of the contents are determined by the storage manager and
-are not of interest outside it.
-
-Info tables may either be {\em reversed} or not.  Reversed is normal
-and preferred, but it requires ``assembler mangling'' of the C
-compiler output.  (The native-code generator does reversed info-tables
-automagically.) With reversed info tables, (a)~the words are reversed
-[obviously], (b)~the info-table's C label addresses the word {\em just
-after} the info table (where its associated entry code ``happens to be''),
-and (c)~the entry-code word in the info table is omitted (it's
-vestigial).
-
-Info-table reversal is hidden behind the @IREL@ macro.
-
-The following fields are used when defining particular info-tables.
-Some sorts of info-table (e.g. @FETCHME_ITBL@) don't need all these
-fields to be specified.
-
-\begin{description}
-\item[@infolbl@]
-The name used to create labels for the info-table, profiling
-information, etc.
-
-\item[\tr{entry_code}:]
-The function which is called when entering the closure.
-
-\item[\tr{update_code}:]
-The function which is called when updating the closure (constructors only).
-
-\item[\tr{tag}:]
-(So much for the Spineless {\em Tagless} G-Machine...)  Used for
-semi-tagging checks.
-
-\item[\tr{type}:]
-Similar-but-different info to the \tr{tag} stuff; the
-parallel world needs more elaborate info.
-
-\item[\tr{size}:]
-The size of the closure (see \tr{SMClosures.lh} for a precise
-definition of ``size'').  Used by the garbage-collector, not the
-Haskell reducer.
-
-\item[\tr{ptrs}:]
-The number of pointers in the closure.  Used by the garbage-collector,
-not the Haskell reducer.
-
-\item[@localness@]
-Whether the info-table is local to this module or not.
-The field is set to @static@ if the info-table is
-local, and is empty otherwise.
-
-\item[@entry_localness@]
-Whether the @entry_code@ routine is local to this module or not.
-This field can have the following values:
-  \begin{description}
-  \item [@EXTFUN@]
-  The entry code is global.
-  \item [@INTFUN@]
-  The entry code is local.
-  \end{description}
-
-\item[@kind@]
-This identifies the general sort of the closure for profiling purposes.
-It can have the following values (defined in CostCentre.lh):
-
-  \begin{description}
-  \item[@CON_K@]
-  A constructor.
-  \item[@FN_K@]
-  A literal function.
-  \item[@PAP_K@]
-  A partial application.
-  \item[@THK_K@]
-  A thunk, or suspension.
-  \item[@BH_K@]
-  A black hole.
-  \item[@ARR_K@]
-  An array.
-  \item[@ForeignObj_K@]
-  A Foreign object (non-Haskell heap resident).
-  \item[@SPT_K@]
-  The Stable Pointer table.  (There should only be one of these but it
-  represents a form of weak space leak since it can't shrink to meet
-  non-demand so it may be worth watching separately? ADR)
-  \item[@INTERNAL_KIND@]
-  Something internal to the runtime system.
-  \end{description}
-
-\item[@descr@]
-This is a string used to identify the closure for profiling purposes.
-\end{description}
-
-So, for example:
-\begin{pseudocode}
-SPEC_N_ITBL(RBH_Save_0_info,RBH_Save_0_entry,UpdErr,0,INFO_OTHER_TAG,2,0,,IF_,INTERNAL_KIND,"RBH-SAVE","RBH_Save_0");
-\end{pseudocode}
-
-%************************************************************************
-%*                                                                     *
-\subsection[info-table-common-up]{The commoned-up info-table world}
-%*                                                                     *
-%************************************************************************
-
-Since lots of info-tables share the same information (which doesn't
-change at run time) needlessly, we gather this common information
-together into a rep-table.
-
-Conditionally present data (concerning the parallel world, and also
-information for the collectors) are gathered into unique rep-tables,
-which are pointed to from info-tables.  This saves several words for
-each closure we build, at the cost of making garbage collection and
-fetching of data from info-tables a little more hairy.
-
-Size and pointers fields go away altogether, save for @GEN@ closures
-where they are tacked on to the end of info-tables.
-
-%************************************************************************
-%*                                                                     *
-\subsection[info-table-common]{Bits common to all info-tables}
-%*                                                                     *
-%************************************************************************
-
-The entry code for a closure, its type, its ``size'', and the number
-of pointer-words it contains are the same in every info table.  For
-the parallel system, two flush code-entries are also standard.
-
-Multi-slurp protection:
-\begin{code}
-#ifndef SMInfoTables_H
-#define SMInfoTables_H
-\end{code}
-
-\begin{code}
-#ifdef __STG_REV_TBLS__
-
-# define IREL(offset)  (-(offset))
-
-/* NB: the ENT_ macro (StgMacros.lh) must also be changed */
-
-# define ENTRY_CODE(infoptr)     ((F_)(infoptr))
-
-#else /* boring non-reversed info tables */
-
-# define IREL(offset)  (offset)
-
-# define ENTRY_CODE(infoptr)     (((FP_)(infoptr))[IREL(0)])
-
-#endif /* non-fixed size info tables */
-\end{code}
-
-\begin{code}
-#define INFO_TAG(infoptr)      ((I_) ((P_)(infoptr))[IREL(1)])
-#define EVAL_TAG(infoptr)      (INFO_TAG(infoptr) >= 0)
-\end{code}
-
-\begin{code}
-
-#define INFO_INTERNAL          (~0L)   /* Should never see this */
-
-#define INFO_UNUSED            (~0L)
-/* We'd like to see this go away in code pointer fields, with specialized code
-   to print out an appropriate error message instead.
-   WDP 94/11: At least make it an Obviously Weird Value?
- */
-
-\end{code}
-
-
-%************************************************************************
-%*                                                                     *
-\subsection[info-table-rtbl]{Rep tables in an info table}
-%*                                                                     *
-%************************************************************************
-
-Common information is pointed to by the rep table pointer.  We want to
-use extern declarations almost everywhere except for the single module
-(\tr{Rep.lc}) in which the rep tables are declared locally.
-
-\begin{code}
-#if defined(COMPILING_REP_LC) || defined(COMPILING_NCG)
-# define MAYBE_DECLARE_RTBL(l,s,p)
-#else
-# define MAYBE_DECLARE_RTBL(l,s,p)     EXTDATA_RO(MK_REP_REF(l,s,p));
-#endif
-
-#define INFO_RTBL(infoptr)     (((PP_)(infoptr))[IREL(2)])
-\end{code}
-  
-%************************************************************************
-%*                                                                     *
-\subsection{Maybe-there-maybe-not fields in an info table}
-%*                                                                     *
-%************************************************************************
-
-That's about it for the fixed stuff...entry code, a tag and an RTBL pointer.
-
-\begin{code}
-#define FIXED_INFO_WORDS               3
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection{Profiling-only fields in an info table}
-%*                                                                     *
-%************************************************************************
-
-These macros result in the profiling kind and description string being
-included only if required.
-\begin{code}
-#define PROFILING_INFO_OFFSET  (FIXED_INFO_WORDS)
-
-#if !defined(PROFILING)
-# define PROFILING_INFO_WORDS  0
-# define INCLUDE_PROFILING_INFO(base_name)
-# define INREGS_PROFILING_INFO    
-
-#else
-# define PROFILING_INFO_WORDS  1
-
-# define INCLUDE_PROFILING_INFO(base_name) , (W_)REF_CAT_IDENT(base_name)
-# define INREGS_PROFILING_INFO ,INFO_UNUSED
-
-# define INFO_CAT(infoptr)  (((ClCategory *)(infoptr))[IREL(PROFILING_INFO_OFFSET)])
-
-#endif
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection{Non-standard fields in an info table: where they'll be}
-%*                                                                     *
-%************************************************************************
-
-The @UPDATE_CODE@ field is a pointer to the update code for a constructor.
-I believe that constructors are always of the following types:
-
-\begin{itemize}
-\item @CHARLIKE@
-\item @CONST@
-\item @GEN_N@
-\item @INTLIKE@
-\item @SPEC_N@
-\item @STATIC@
-\end{itemize}
-
-Info tables for these types have non-standard update code fields.  In addition,
-because @GEN@ closures have further non-standard fields (size, ptrs), the
-info tables for @GEN_U@ closures also have a non-standard update code field 
-(which is filled in with @StdErrorCode@).
-
-When we're in the parallel world, we also have to know which registers are
-live when we're returning a constructor in registers, so we have a second 
-word for that as well.
-
-\begin{code}
-
-#define UPDATE_INFO_OFFSET  (PROFILING_INFO_OFFSET+PROFILING_INFO_WORDS)
-
-#ifndef PAR
-# define UPDATE_INFO_WORDS    1
-# define INCLUDE_UPDATE_INFO(upd,live) ,(W_)upd
-#else
-# define UPDATE_INFO_WORDS    2
-# define INCLUDE_UPDATE_INFO(upd,live) ,(W_)upd,(W_)live
-#endif
-
-#define UPDATE_CODE(infoptr)   (((FP_)(infoptr))[IREL(UPDATE_INFO_OFFSET)])
-#define INFO_LIVENESS(infoptr) (((P_)(infoptr))[IREL(UPDATE_INFO_OFFSET+1)])
-\end{code}
-
-@GEN@ closures have the size and number of pointers in the info table
-rather than the rep table.  These non-standard fields follow the update
-code field (which is only required for @GEN_N@ closures, but which we
-include in @GEN_U@ closures just to keep this other stuff at a consistent
-offset).
-
-\begin{code}
-#define GEN_INFO_OFFSET            (UPDATE_INFO_OFFSET+UPDATE_INFO_WORDS)
-#define GEN_INFO_WORDS    2
-#define INCLUDE_GEN_INFO(size,ptrs)    ,(W_)size,(W_)ptrs
-
-#define GEN_INFO_SIZE(infoptr)  ((I_)((P_)(infoptr))[IREL(GEN_INFO_OFFSET)])
-#define GEN_INFO_NoPTRS(infoptr) ((I_)((P_)(infoptr))[IREL(GEN_INFO_OFFSET+1)])
-\end{code}
-
-@CONST@ closures have a pointer to a static version of the closure in their
-info tables.  This non-standard field follows their update code field.
-
-\begin{code}
-#define CONST_INFO_OFFSET          (UPDATE_INFO_OFFSET+UPDATE_INFO_WORDS)
-#define CONST_INFO_WORDS    1
-#define INCLUDE_CONST_INFO(closure)    ,(W_)closure
-
-#define CONST_STATIC_CLOSURE(infoptr)  (((PP_)(infoptr))[IREL(CONST_INFO_OFFSET)])
-\end{code}
-
-@STATIC@ closures are like @GEN@ closures in that they also have the
-size and number of pointers in the info table rather than the rep
-table.  Again, these non-standard fields follow the update code field
-(which I believe is not actually needed for STATIC closures).
-
-\begin{code}
-#define STATIC_INFO_OFFSET         (UPDATE_INFO_OFFSET+UPDATE_INFO_WORDS)
-#define STATIC_INFO_WORDS    2
-#define INCLUDE_STATIC_INFO(size,ptrs) ,(W_)size,(W_)ptrs
-
-#define STATIC_INFO_SIZE(infoptr)   ((I_)((P_)(infoptr))[IREL(STATIC_INFO_OFFSET)])
-#define STATIC_INFO_NoPTRS(infoptr) ((I_)((P_)(infoptr))[IREL(STATIC_INFO_OFFSET+1)])
-\end{code}
-
-In the parallel system, all updatable closures have corresponding
-revertible black holes.  When we are assembly-mangling, we guarantee that
-the revertible black hole code precedes the normal entry code, so that
-the RBH info table resides at a fixed offset from the normal info table.
-Otherwise, we add the RBH info table pointer to the end of the normal
-info table and vice versa.
-
-\begin{code}
-#if defined(PAR) || defined(GRAN)
-# define RBH_INFO_OFFSET           (GEN_INFO_OFFSET+GEN_INFO_WORDS)
-
-# define INCLUDE_SPEC_PADDING                          \
-       INCLUDE_UPDATE_INFO(INFO_UNUSED,INFO_UNUSED)    \
-       INCLUDE_GEN_INFO(INFO_UNUSED,INFO_UNUSED)
-
-# ifdef RBH_MAGIC_OFFSET
-
-#  define RBH_INFO_WORDS    0
-#  define INCLUDE_RBH_INFO(infoptr)
-
-#  define RBH_INFOPTR(infoptr)     (((P_)infoptr) - RBH_MAGIC_OFFSET)
-#  define REVERT_INFOPTR(infoptr)   (((P_)infoptr) + RBH_MAGIC_OFFSET)
-
-# else
-
-#  define RBH_INFO_WORDS    1
-#  define INCLUDE_RBH_INFO(infoptr) ,(W_)infoptr
-
-#  define RBH_INFOPTR(infoptr)     (((PP_)(infoptr))[IREL(RBH_INFO_OFFSET)])
-#  define REVERT_INFOPTR(infoptr)   (((PP_)(infoptr))[IREL(RBH_INFO_OFFSET)])
-
-# endif
-
-EXTFUN(RBH_entry);
-P_ convertToRBH PROTO((P_ closure));
-#if defined(GRAN)
-void convertFromRBH PROTO((P_ closure));
-#elif defined(PAR)
-void convertToFetchMe PROTO((P_ closure, globalAddr *ga));
-#endif
-
-#endif
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection{Maybe-there-maybe-not fields in a rep table}
-%*                                                                     *
-%************************************************************************
-
-%************************************************************************
-%*                                                                     *
-\subsubsection{Type field in a rep table}
-%*                                                                     *
-%************************************************************************
-
-The @INFO_TYPE@ field in the rep table tells what sort of animal
-the closure is.  
-
-\begin{code}
-#define TYPE_INFO_OFFSET  0
-#define TYPE_INFO_WORDS    1
-#define INCLUDE_TYPE_INFO(kind) (W_)CAT3(INFO_,kind,_TYPE)
-
-#define INFO_TYPE(infoptr)     (((P_)(INFO_RTBL(infoptr)))[TYPE_INFO_OFFSET])
-\end{code}
-
-The least significant 9 bits of the info-type are used as follows:
-
-\begin{tabular}{||l|l||}                                                  \hline
-Bit & Interpretation                                                   \\ \hline
-0   & 1 $\Rightarrow$ Head normal form                                 \\
-1   & 1 $\Rightarrow$ Don't spark me  (Any HNF will have this set to 1)        \\
-2   & 1 $\Rightarrow$ This is a static closure                         \\
-3   & 1 $\Rightarrow$ Has mutable pointer fields \\ 
-4   & 1 $\Rightarrow$ May be updated (inconsistent with being a HNF) \\ 
-5   & 1 $\Rightarrow$ Is a "primitive" array (a BIG structure) \\
-6   & 1 $\Rightarrow$ Is a black hole                                  \\
-7   & 1 $\Rightarrow$ Is an indirection                                        \\
-8   & 1 $\Rightarrow$ Is a thunk                                       \\
-\hline
-\end{tabular}
-
-Updatable structures (@_UP@) are thunks that may be shared.  Primitive
-arrays (@_BM@ -- Big Mothers) are structures that are always held
-in-memory (basically extensions of a closure).  Because there may be
-offsets into these arrays, a primitive array cannot be handled as a
-FetchMe in the parallel system, but must be shipped in its entirety if
-its parent closure is shipped.
-
-\begin{code}
-#define        IP_TAG_BITS             9
-
-#define _NF                    0x0001  /* Normal form  */
-#define _NS                    0x0002  /* Don't spark  */
-#define _ST                    0x0004  /* Is static    */
-#define _MU                    0x0008  /* Is mutable   */
-#define _UP                    0x0010  /* Is updatable (but not mutable) */
-#define _BM                    0x0020  /* Is a "primitive" array */
-#define _BH                    0x0040  /* Is a black hole */
-#define _IN                    0x0080  /* Is an indirection */
-#define _TH                    0x0100  /* Is a thunk */
-
-#define        IS_NF(infoptr)          ((INFO_TYPE(infoptr)&_NF) != 0)
-#define        IS_MUTABLE(infoptr)     ((INFO_TYPE(infoptr)&_MU) != 0)
-#define        IS_STATIC(infoptr)      ((INFO_TYPE(infoptr)&_ST) != 0)
-#define        IS_UPDATABLE(infoptr)   ((INFO_TYPE(infoptr)&_UP) != 0)
-#define        IS_BIG_MOTHER(infoptr)  ((INFO_TYPE(infoptr)&_BM) != 0)
-#define IS_BLACK_HOLE(infoptr) ((INFO_TYPE(infoptr)&_BH) != 0)
-#define IS_INDIRECTION(infoptr)        ((INFO_TYPE(infoptr)&_IN) != 0)
-#define IS_THUNK(infoptr)      ((INFO_TYPE(infoptr)&_TH) != 0)
-
-#define        SHOULD_SPARK(closure)   ((INFO_TYPE(INFO_PTR(closure))&_NS) == 0)
-\end{code}
-
-The other bits in the info-type field simply give a unique bit-pattern
-to identify the closure type.
-
-\begin{code}
-#define        IP_TAG_BIT_MASK         ((1L<<IP_TAG_BITS)-1)
-
-#define BASE_INFO_TYPE(infoptr)        (INFO_TYPE(infoptr) & (~IP_TAG_BIT_MASK)) /* Strips out the tag bits */
-
-#define MAKE_BASE_INFO_TYPE(x) ((x) << IP_TAG_BITS)
-
-#define INFO_SPEC_TYPE         (MAKE_BASE_INFO_TYPE(1L))
-#define INFO_GEN_TYPE          (MAKE_BASE_INFO_TYPE(2L))
-#define INFO_DYN_TYPE          (MAKE_BASE_INFO_TYPE(3L) | _NF | _NS)
-#define INFO_TUPLE_TYPE                (MAKE_BASE_INFO_TYPE(4L) | _NF | _NS | _BM)
-#define INFO_DATA_TYPE         (MAKE_BASE_INFO_TYPE(5L) | _NF | _NS | _BM)
-#define INFO_MUTUPLE_TYPE      (MAKE_BASE_INFO_TYPE(6L) | _NF | _NS | _MU | _BM)
-#define INFO_IMMUTUPLE_TYPE    (MAKE_BASE_INFO_TYPE(7L) | _NF | _NS | _BM)
-#define INFO_STATIC_TYPE       (MAKE_BASE_INFO_TYPE(8L) | _NS | _ST)
-#define INFO_CONST_TYPE                (MAKE_BASE_INFO_TYPE(9L) | _NF | _NS)
-#define INFO_CHARLIKE_TYPE     (MAKE_BASE_INFO_TYPE(10L) | _NF | _NS)
-#define INFO_INTLIKE_TYPE      (MAKE_BASE_INFO_TYPE(11L) | _NF | _NS)
-#define INFO_BH_TYPE           (MAKE_BASE_INFO_TYPE(12L) | _NS | _BH)
-#define INFO_BQ_TYPE           (MAKE_BASE_INFO_TYPE(13L) | _NS | _MU | _BH)
-#define INFO_IND_TYPE          (MAKE_BASE_INFO_TYPE(14L) | _NS | _IN)
-#define INFO_CAF_TYPE          (MAKE_BASE_INFO_TYPE(15L) | _NF | _NS | _ST | _IN)
-#define INFO_FM_TYPE           (MAKE_BASE_INFO_TYPE(16L))
-#define INFO_TSO_TYPE          (MAKE_BASE_INFO_TYPE(17L) | _MU)
-#define INFO_STKO_TYPE         (MAKE_BASE_INFO_TYPE(18L))
-#define INFO_SPEC_RBH_TYPE     (MAKE_BASE_INFO_TYPE(19L) | _NS | _MU | _BH)
-#define INFO_GEN_RBH_TYPE      (MAKE_BASE_INFO_TYPE(20L) | _NS | _MU | _BH)
-#define INFO_BF_TYPE           (MAKE_BASE_INFO_TYPE(21L) | _NS | _MU | _BH)
-#define INFO_INTERNAL_TYPE     (MAKE_BASE_INFO_TYPE(22L))
-
-/* S = single-entry thunk
-   U = updatable thunk
-   N = head normal form */
-
-#define INFO_SPEC_N_TYPE       (INFO_SPEC_TYPE | _NF | _NS)
-#define INFO_SPEC_S_TYPE       (INFO_SPEC_TYPE | _TH)
-#define INFO_SPEC_U_TYPE       (INFO_SPEC_TYPE | _UP | _TH)
-
-#define INFO_GEN_N_TYPE                (INFO_GEN_TYPE | _NF | _NS)
-#define INFO_GEN_S_TYPE                (INFO_GEN_TYPE | _TH)
-#define INFO_GEN_U_TYPE                (INFO_GEN_TYPE | _UP | _TH)
-
-#define INFO_BH_N_TYPE         (INFO_BH_TYPE)
-#define INFO_BH_U_TYPE         (INFO_BH_TYPE | _UP)
-
-#define INFO_STKO_DYNAMIC_TYPE (INFO_STKO_TYPE | _MU)
-#define INFO_STKO_STATIC_TYPE  (INFO_STKO_TYPE | _ST)
-
-#define INFO_FETCHME_TYPE      (INFO_FM_TYPE | _MU)
-#define INFO_FMBQ_TYPE         (INFO_FM_TYPE | _MU | _BH)
-
-#define MIN_INFO_TYPE          0
-#define MAX_INFO_TYPE          INFO_INTERNAL_TYPE
-
-\end{code}
-
-Notes:
-
-An indirection either points to HNF (post update); or is result of
-overwriting a FetchMe, in which case the thing fetched is either
-under evaluation (BH), or by now an HNF.  Thus, indirections get @_NS@.
-
-%************************************************************************
-%*                                                                     *
-\subsubsection{Size/no-of-pointers fields in a rep table}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-#define SIZE_INFO_OFFSET  (TYPE_INFO_OFFSET+TYPE_INFO_WORDS)
-#define SIZE_INFO_WORDS          2
-#define INCLUDE_SIZE_INFO(size,ptrs) ,(W_)size, (W_)ptrs
-
-#define INFO_SIZE(infoptr)   ((I_)((FP_)(INFO_RTBL(infoptr)))[SIZE_INFO_OFFSET])
-#define INFO_NoPTRS(infoptr) ((I_)((FP_)(INFO_RTBL(infoptr)))[SIZE_INFO_OFFSET+1])
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection{Parallel-only fields in a rep table}
-%*                                                                     *
-%************************************************************************
-
-There is now nothing that is specific to the parallel world (GUM), but
-this could change so don't go deleting this little lot!  KH
-
-\begin{code}
-# define PAR_INFO_OFFSET               (SIZE_INFO_OFFSET+SIZE_INFO_WORDS)
-
-/* now the bits that are either on or off: */
-
-# define PAR_INFO_WORDS                0
-# define INCLUDE_PAR_INFO
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection{Copying-only fields in a rep table}
-%*                                                                     *
-%************************************************************************
-
-These macros result in the copying garbage collection code being
-included only if required.
-\begin{code}
-#if defined(_INFO_COPYING)
-# include "SMcopying.h" /* Copying Code Labels */
-# define COPY_INFO_OFFSET  (PAR_INFO_OFFSET+PAR_INFO_WORDS)
-# define COPY_INFO_WORDS 2
-# define INCLUDE_COPYING_INFO(evac, scav) ,(W_)evac,(W_)scav
-
-/* 
- * use these if you have an unquenchable urge to dig around in
- *  info tables (e.g., runtime/.../StgDebug.lc)
- */
-
-# define INFO_EVAC_2S(infoptr)  (((FP_)(INFO_RTBL(infoptr)))[COPY_INFO_OFFSET])
-# define INFO_SCAV_2S(infoptr)  (((FP_)(INFO_RTBL(infoptr)))[COPY_INFO_OFFSET + 1])
-
-#else  /* ! _INFO_COPYING */
-
-# define COPY_INFO_WORDS 0
-# define INCLUDE_COPYING_INFO(evac, scav)
-
-#endif /* ! _INFO_COPYING */
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection{Compacting-only fields in a rep table}
-%*                                                                     *
-%************************************************************************
-
-These macros result in the compacting garbage collection code being
-included only if required. This includes the variable length
-specialised marking code.
-
-\begin{code}
-#if !defined(_INFO_COMPACTING)
-
-# define INCLUDE_COMPACTING_INFO(scanlink,prmark,scanmove,marking)
-# define SPEC_COMPACTING_INFO(scanlink,prmark,scanmove,marking)
-
-#else /* defined(_INFO_COMPACTING) */
-
-# include "SMcompact.h"        /* Single Space Compacting Code */
-# include "SMmark.h"           /* Pointer Reversal Marking Code Labels */
-
-/* For SPEC closures compacting info is variable length -> must come last */
-
-# define COMPACTING_INFO_OFFSET  (COPY_INFO_OFFSET+COPY_INFO_WORDS)
-
-# define INCLUDE_COMPACTING_INFO(scanlink,prmark,scanmove,marking) \
-       ,(W_)scanlink,(W_)prmark \
-       ,(W_)scanmove,(W_)marking
-
-# define SPEC_COMPACTING_INFO(scanlink,prmark,scanmove,prreturn) \
-       ,(W_)scanlink,(W_)prmark \
-       ,(W_)scanmove, \
-        (W_)prreturn
-
-
-# define INFO_SCAN_LINK_1S(infoptr)    (((FP_)(INFO_RTBL(infoptr)))[COMPACTING_INFO_OFFSET])
-# define INFO_MARK_1S(infoptr)         (((FP_)(INFO_RTBL(infoptr)))[COMPACTING_INFO_OFFSET+1])
-# define INFO_SCAN_MOVE_1S(infoptr)    (((FP_)(INFO_RTBL(infoptr)))[COMPACTING_INFO_OFFSET+2])
-# define INFO_MARKED_1S(infoptr)       (((FP_)(INFO_RTBL(infoptr)))[COMPACTING_INFO_OFFSET+3])
-# define INFO_MARKING_1S(infoptr)      (((FP_)(INFO_RTBL(infoptr)))[COMPACTING_INFO_OFFSET+4])
-
-#ifndef COMPILING_NCG
-extern F_ _Dummy_Static_entry(STG_NO_ARGS);
-extern F_ _Dummy_Ind_entry(STG_NO_ARGS);
-extern F_ _Dummy_Caf_entry(STG_NO_ARGS);
-extern F_ _Dummy_Const_entry(STG_NO_ARGS);
-extern F_ _Dummy_CharLike_entry(STG_NO_ARGS);
-#endif
-
-#endif /* _INFO_COMPACTING */
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[SPEC_ITBL]{@SPEC_x_ITBL@: @SPEC@ info-tables}
-%*                                                                     *
-%************************************************************************
-
-Normal-form and updatable (non-normal-form) variants.
-
-\begin{code}
-
-#define SPEC_N_ITBL(infolbl,entry_code,upd_code,liveness,tag,size,ptrs,localness,entry_localness,kind,descr,type) \
-    CAT_DECLARE(infolbl,kind,descr,type)       \
-    entry_localness(entry_code);               \
-    localness W_ infolbl[] = {                 \
-        (W_) entry_code                                \
-       ,(W_) tag                               \
-       ,(W_) MK_REP_REF(Spec_N,size,ptrs)      \
-       INCLUDE_PROFILING_INFO(infolbl)         \
-       INCLUDE_UPDATE_INFO(upd_code,liveness)  \
-       }
-
-MAYBE_DECLARE_RTBL(Spec_N,1,0)
-MAYBE_DECLARE_RTBL(Spec_N,1,1)
-MAYBE_DECLARE_RTBL(Spec_N,2,0)
-MAYBE_DECLARE_RTBL(Spec_N,2,1)
-MAYBE_DECLARE_RTBL(Spec_N,2,2)
-MAYBE_DECLARE_RTBL(Spec_N,3,0)
-MAYBE_DECLARE_RTBL(Spec_N,3,1)
-MAYBE_DECLARE_RTBL(Spec_N,3,2)
-MAYBE_DECLARE_RTBL(Spec_N,3,3)
-MAYBE_DECLARE_RTBL(Spec_N,4,0)
-MAYBE_DECLARE_RTBL(Spec_N,4,4)
-MAYBE_DECLARE_RTBL(Spec_N,5,0)
-MAYBE_DECLARE_RTBL(Spec_N,5,5)
-MAYBE_DECLARE_RTBL(Spec_N,6,6)
-MAYBE_DECLARE_RTBL(Spec_N,7,7)
-MAYBE_DECLARE_RTBL(Spec_N,8,8)
-MAYBE_DECLARE_RTBL(Spec_N,9,9)
-MAYBE_DECLARE_RTBL(Spec_N,10,10)
-MAYBE_DECLARE_RTBL(Spec_N,11,11)
-MAYBE_DECLARE_RTBL(Spec_N,12,12)
-
-#define SPEC_N_RTBL(size,ptrs)                                                         \
-    const W_ MK_REP_LBL(Spec_N,size,ptrs)[] = {                                        \
-       INCLUDE_TYPE_INFO(SPEC_N)                                               \
-       INCLUDE_SIZE_INFO(size,ptrs)                                            \
-       INCLUDE_PAR_INFO                                                        \
-       INCLUDE_COPYING_INFO(CAT2(_Evacuate_,size),CAT4(_Scavenge_,size,_,ptrs)) \
-       SPEC_COMPACTING_INFO(CAT4(_ScanLink_,size,_,ptrs),                      \
-                            CAT2(_PRStart_,ptrs),                              \
-                            CAT2(_ScanMove_,size),CAT2(_PRIn_,ptrs))           \
-       }
-
-#define SPEC_S_ITBL(infolbl,entry_code,upd_code,liveness,tag,size,ptrs,localness,entry_localness,kind,descr,type) \
-    CAT_DECLARE(infolbl,kind,descr,type)       \
-    entry_localness(entry_code);               \
-    localness W_ infolbl[] = {                 \
-        (W_) entry_code                                \
-       ,(W_) tag                               \
-       ,(W_) MK_REP_REF(Spec_S,size,ptrs)      \
-       INCLUDE_PROFILING_INFO(infolbl)         \
-       INCLUDE_UPDATE_INFO(upd_code,liveness)  \
-       }
-
-MAYBE_DECLARE_RTBL(Spec_S,1,0)
-MAYBE_DECLARE_RTBL(Spec_S,1,1)
-MAYBE_DECLARE_RTBL(Spec_S,2,0)
-MAYBE_DECLARE_RTBL(Spec_S,2,1)
-MAYBE_DECLARE_RTBL(Spec_S,2,2)
-MAYBE_DECLARE_RTBL(Spec_S,3,0)
-MAYBE_DECLARE_RTBL(Spec_S,3,1)
-MAYBE_DECLARE_RTBL(Spec_S,3,2)
-MAYBE_DECLARE_RTBL(Spec_S,3,3)
-MAYBE_DECLARE_RTBL(Spec_S,4,0)
-MAYBE_DECLARE_RTBL(Spec_S,4,4)
-MAYBE_DECLARE_RTBL(Spec_S,5,0)
-MAYBE_DECLARE_RTBL(Spec_S,5,5)
-MAYBE_DECLARE_RTBL(Spec_S,6,6)
-MAYBE_DECLARE_RTBL(Spec_S,7,7)
-MAYBE_DECLARE_RTBL(Spec_S,8,8)
-MAYBE_DECLARE_RTBL(Spec_S,9,9)
-MAYBE_DECLARE_RTBL(Spec_S,10,10)
-MAYBE_DECLARE_RTBL(Spec_S,11,11)
-MAYBE_DECLARE_RTBL(Spec_S,12,12)
-
-#define SPEC_S_RTBL(size,ptrs)                                                         \
-    const W_ MK_REP_LBL(Spec_S,size,ptrs)[] = {                                        \
-       INCLUDE_TYPE_INFO(SPEC_S)                                               \
-       INCLUDE_SIZE_INFO(size,ptrs)                                            \
-       INCLUDE_PAR_INFO                                                        \
-       INCLUDE_COPYING_INFO(CAT2(_Evacuate_,size),CAT4(_Scavenge_,size,_,ptrs)) \
-       SPEC_COMPACTING_INFO(CAT4(_ScanLink_,size,_,ptrs),                      \
-                            CAT2(_PRStart_,ptrs),                              \
-                            CAT2(_ScanMove_,size),CAT2(_PRIn_,ptrs))           \
-       }
-
-#if defined(PAR) || defined(GRAN)
-# define SPEC_U_ITBL(infolbl,entry_code,upd_code,liveness,tag,size,ptrs,localness,entry_localness,kind,descr,type) \
-    entry_localness(CAT2(RBH_,entry_code));            \
-    localness W_ infolbl[];                    \
-     localness W_ CAT2(RBH_,infolbl)[] = {     \
-        (W_) CAT2(RBH_,entry_code)             \
-       ,(W_) INFO_OTHER_TAG                    \
-       ,(W_) MK_REP_REF(Spec_RBH,size,ptrs)    \
-       INCLUDE_PROFILING_INFO(RBH)             \
-       INCLUDE_SPEC_PADDING                    \
-       INCLUDE_RBH_INFO(infolbl)               \
-       };                                      \
-    STGFUN(CAT2(RBH_,entry_code)) { JMP_(RBH_entry); }\
-    CAT_DECLARE(infolbl,kind,descr,type)       \
-    entry_localness(entry_code);               \
-    localness W_ infolbl[] = {                 \
-        (W_) entry_code                                \
-       ,(W_) tag                               \
-       ,(W_) MK_REP_REF(Spec_U,size,ptrs)      \
-       INCLUDE_PROFILING_INFO(infolbl)         \
-       INCLUDE_SPEC_PADDING                    \
-       INCLUDE_RBH_INFO(CAT2(RBH_,infolbl))    \
-       }
-
-MAYBE_DECLARE_RTBL(Spec_RBH,1,0)
-MAYBE_DECLARE_RTBL(Spec_RBH,1,1)
-MAYBE_DECLARE_RTBL(Spec_RBH,2,0)
-MAYBE_DECLARE_RTBL(Spec_RBH,2,1)
-MAYBE_DECLARE_RTBL(Spec_RBH,2,2)
-MAYBE_DECLARE_RTBL(Spec_RBH,3,0)
-MAYBE_DECLARE_RTBL(Spec_RBH,3,1)
-MAYBE_DECLARE_RTBL(Spec_RBH,3,2)
-MAYBE_DECLARE_RTBL(Spec_RBH,3,3)
-MAYBE_DECLARE_RTBL(Spec_RBH,4,0)
-MAYBE_DECLARE_RTBL(Spec_RBH,4,4)
-MAYBE_DECLARE_RTBL(Spec_RBH,5,0)
-MAYBE_DECLARE_RTBL(Spec_RBH,5,5)
-MAYBE_DECLARE_RTBL(Spec_RBH,6,6)
-MAYBE_DECLARE_RTBL(Spec_RBH,7,7)
-MAYBE_DECLARE_RTBL(Spec_RBH,8,8)
-MAYBE_DECLARE_RTBL(Spec_RBH,9,9)
-MAYBE_DECLARE_RTBL(Spec_RBH,10,10)
-MAYBE_DECLARE_RTBL(Spec_RBH,11,11)
-MAYBE_DECLARE_RTBL(Spec_RBH,12,12)
-
-#define SPEC_RBH_RTBL(size,ptrs)                                               \
-    const W_ MK_REP_LBL(Spec_RBH,size,ptrs)[] = {                              \
-       INCLUDE_TYPE_INFO(SPEC_RBH)                                             \
-       INCLUDE_SIZE_INFO(size,ptrs)                                            \
-       INCLUDE_PAR_INFO                                                        \
-       INCLUDE_COPYING_INFO(CAT2(_Evacuate_RBH_,size),CAT4(_Scavenge_RBH_,size,_,ptrs)) \
-       SPEC_COMPACTING_INFO(CAT4(_ScanLink_RBH_,size,_,ptrs),                  \
-                            CAT2(_PRStart_RBH_,ptrs),                          \
-                            CAT2(_ScanMove_RBH_,size),CAT2(_PRIn_RBH_,ptrs))   \
-       }
-
-#define _Scavenge_RBH_2_0   _Scavenge_RBH_2_1
-#define _Scavenge_RBH_2_2   _Scavenge_RBH_2_1
-
-#define _Scavenge_RBH_3_0   _Scavenge_RBH_3_1
-#define _Scavenge_RBH_3_2   _Scavenge_RBH_3_1
-
-#define _Scavenge_RBH_4_0   _Scavenge_RBH_4_1
-#define _Scavenge_RBH_5_0   _Scavenge_RBH_5_1
-#define _Scavenge_RBH_6_0   _Scavenge_RBH_6_1
-#define _Scavenge_RBH_7_0   _Scavenge_RBH_7_1
-#define _Scavenge_RBH_8_0   _Scavenge_RBH_8_1
-#define _Scavenge_RBH_9_0   _Scavenge_RBH_9_1
-#define _Scavenge_RBH_10_0   _Scavenge_RBH_10_1
-#define _Scavenge_RBH_11_0   _Scavenge_RBH_11_1
-#define _Scavenge_RBH_12_0   _Scavenge_RBH_12_1
-
-#define _ScanLink_RBH_2_0   _ScanLink_RBH_2_1
-#define _ScanLink_RBH_2_2   _ScanLink_RBH_2_1
-
-#define _ScanLink_RBH_3_0   _ScanLink_RBH_3_1
-#define _ScanLink_RBH_3_2   _ScanLink_RBH_3_1
-
-#define _ScanLink_RBH_4_0   _ScanLink_RBH_4_1
-#define _ScanLink_RBH_5_0   _ScanLink_RBH_5_1
-#define _ScanLink_RBH_6_0   _ScanLink_RBH_6_1
-#define _ScanLink_RBH_7_0   _ScanLink_RBH_7_1
-#define _ScanLink_RBH_8_0   _ScanLink_RBH_8_1
-#define _ScanLink_RBH_9_0   _ScanLink_RBH_9_1
-#define _ScanLink_RBH_10_0   _ScanLink_RBH_10_1
-#define _ScanLink_RBH_11_0   _ScanLink_RBH_11_1
-#define _ScanLink_RBH_12_0   _ScanLink_RBH_12_1
-
-#define _PRStart_RBH_0 _PRStart_RBH_2
-#define _PRStart_RBH_1 _PRStart_RBH_2
-
-#define _PRIn_RBH_0    _PRIn_RBH_2
-#define _PRIn_RBH_1    _PRIn_RBH_2
-
-#else
-
-# define SPEC_U_ITBL(infolbl,entry_code,upd_code,liveness,tag,size,ptrs,localness,entry_localness,kind,descr,type) \
-    CAT_DECLARE(infolbl,kind,descr,type)       \
-    entry_localness(entry_code);               \
-    localness W_ infolbl[] = {                 \
-        (W_) entry_code                                \
-       ,(W_) tag                               \
-       ,(W_) MK_REP_REF(Spec_U,size,ptrs)      \
-       INCLUDE_PROFILING_INFO(infolbl)         \
-       }
-#endif
-
-MAYBE_DECLARE_RTBL(Spec_U,1,0)
-MAYBE_DECLARE_RTBL(Spec_U,1,1)
-MAYBE_DECLARE_RTBL(Spec_U,2,0)
-MAYBE_DECLARE_RTBL(Spec_U,2,1)
-MAYBE_DECLARE_RTBL(Spec_U,2,2)
-MAYBE_DECLARE_RTBL(Spec_U,3,0)
-MAYBE_DECLARE_RTBL(Spec_U,3,1)
-MAYBE_DECLARE_RTBL(Spec_U,3,2)
-MAYBE_DECLARE_RTBL(Spec_U,3,3)
-MAYBE_DECLARE_RTBL(Spec_U,4,0)
-MAYBE_DECLARE_RTBL(Spec_U,4,4)
-MAYBE_DECLARE_RTBL(Spec_U,5,0)
-MAYBE_DECLARE_RTBL(Spec_U,5,5)
-MAYBE_DECLARE_RTBL(Spec_U,6,6)
-MAYBE_DECLARE_RTBL(Spec_U,7,7)
-MAYBE_DECLARE_RTBL(Spec_U,8,8)
-MAYBE_DECLARE_RTBL(Spec_U,9,9)
-MAYBE_DECLARE_RTBL(Spec_U,10,10)
-MAYBE_DECLARE_RTBL(Spec_U,11,11)
-MAYBE_DECLARE_RTBL(Spec_U,12,12)
-
-#define SPEC_U_RTBL(size,ptrs)                                                 \
-    const W_ MK_REP_LBL(Spec_U,size,ptrs)[] = {                                        \
-       INCLUDE_TYPE_INFO(SPEC_U)                                               \
-       INCLUDE_SIZE_INFO(size,ptrs)                                            \
-       INCLUDE_PAR_INFO                                                        \
-       INCLUDE_COPYING_INFO(CAT2(_Evacuate_,size),CAT4(_Scavenge_,size,_,ptrs)) \
-       SPEC_COMPACTING_INFO(CAT4(_ScanLink_,size,_,ptrs),                      \
-                            CAT2(_PRStart_,ptrs),                              \
-                            CAT2(_ScanMove_,size),CAT2(_PRIn_,ptrs))           \
-       }
-
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[SELECT_ITBL]{@SELECT_ITBL@: Special @SPEC_U@ info-table for selectors}
-%*                                                                     *
-%************************************************************************
-
-These are different only in having slightly-magic GC code.  The idea
-is: it is a @MIN_UPD_SIZE@ (==2) thunk with one pointer, which, when
-entered, will select word $i$ from its pointee.
-
-When garbage-collecting such a closure, we ``peek'' at the pointee's
-tag (in its info table).  If it is evaluated, then we go ahead and do
-the selection---which is {\em just like an indirection}.  If it is not
-evaluated, we carry on {\em exactly as if it is a size-2/1-ptr thunk}.
-
-Copying: only the evacuate routine needs to be special.
-
-Compacting: only the PRStart (marking) routine needs to be special.
-
-\begin{code}
-
-#if defined(PAR) || defined(GRAN)
-# define SELECT_ITBL(infolbl,entry_code,upd_code,liveness,tag,size,ptrs,localness,entry_localness,select_word_i,kind,descr,type) \
-    entry_localness(CAT2(RBH_,entry_code));            \
-    localness W_ infolbl[];                    \
-    localness W_ CAT2(RBH_,infolbl)[] = {      \
-        (W_) CAT2(RBH_,entry_code)             \
-       ,(W_) INFO_OTHER_TAG                    \
-       ,(W_) MK_REP_REF(Spec_RBH,size,ptrs)    \
-       INCLUDE_PROFILING_INFO(RBH)             \
-       INCLUDE_SPEC_PADDING                    \
-       INCLUDE_RBH_INFO(infolbl)               \
-       };                                      \
-    STGFUN(CAT2(RBH_,entry_code)) { JMP_(RBH_entry); }\
-    CAT_DECLARE(infolbl,kind,descr,type)       \
-    entry_localness(entry_code);               \
-    localness W_ infolbl[] = {                 \
-        (W_) entry_code                                \
-       ,(W_) tag                               \
-       ,(W_) MK_REP_REF(Select,,select_word_i) \
-       INCLUDE_PROFILING_INFO(infolbl)         \
-       INCLUDE_SPEC_PADDING                    \
-       INCLUDE_RBH_INFO(CAT2(RBH_,infolbl))    \
-       }                                       \
-
-#else
-
-# define SELECT_ITBL(infolbl,entry_code,upd_code,liveness,tag,size,ptrs,localness,entry_localness,select_word_i,kind,descr,type) \
-    CAT_DECLARE(infolbl,kind,descr,type)       \
-    entry_localness(entry_code);               \
-    localness W_ infolbl[] = {                 \
-        (W_) entry_code                                \
-       ,(W_) tag                               \
-       ,(W_) MK_REP_REF(Select,,select_word_i) \
-       INCLUDE_PROFILING_INFO(infolbl)         \
-       }
-
-#endif
-
-MAYBE_DECLARE_RTBL(Select,,0)
-MAYBE_DECLARE_RTBL(Select,,1)
-MAYBE_DECLARE_RTBL(Select,,2)
-MAYBE_DECLARE_RTBL(Select,,3)
-MAYBE_DECLARE_RTBL(Select,,4)
-MAYBE_DECLARE_RTBL(Select,,5)
-MAYBE_DECLARE_RTBL(Select,,6)
-MAYBE_DECLARE_RTBL(Select,,7)
-MAYBE_DECLARE_RTBL(Select,,8)
-MAYBE_DECLARE_RTBL(Select,,9)
-MAYBE_DECLARE_RTBL(Select,,10)
-MAYBE_DECLARE_RTBL(Select,,11)
-MAYBE_DECLARE_RTBL(Select,,12)
-
-#define SELECT_RTBL(size,ptrs,select_word_i)                                   \
-    const W_ MK_REP_LBL(Select,,select_word_i)[] = {                           \
-       INCLUDE_TYPE_INFO(SPEC_U)                                               \
-       INCLUDE_SIZE_INFO(size,ptrs)                                            \
-       INCLUDE_PAR_INFO                                                        \
-       INCLUDE_COPYING_INFO(CAT2(_EvacuateSelector_,select_word_i),            \
-                            CAT4(_Scavenge_,size,_,ptrs))                      \
-       SPEC_COMPACTING_INFO(CAT4(_ScanLink_,size,_,ptrs),                      \
-                            CAT2(_PRStartSelector_,select_word_i),             \
-                             CAT2(_ScanMove_,size),                            \
-                            CAT2(_PRIn_,ptrs))                                 \
-       }
-
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[GEN_ITBL]{@GEN_x_ITBL@: Generic/general? info-tables}
-%*                                                                     *
-%************************************************************************
-
-@GEN@ info-table for non-updatable nodes (normal and non-normal forms).
-
-Size/no-of-ptrs are known at compile time, but we don't have GC
-routines wired in for those specific sizes.  Hence the size/no-of-ptrs
-is stored in the info-table.
-
-\begin{code}
-
-#define GEN_N_ITBL(infolbl,entry_code,upd_code,liveness,tag,size,ptrs,localness,entry_localness,kind,descr,type) \
-    CAT_DECLARE(infolbl,kind,descr,type)       \
-    entry_localness(entry_code);               \
-    localness W_ infolbl[] = {                 \
-        (W_) entry_code                                \
-       ,(W_) tag                               \
-       ,(W_) MK_REP_REF(Gen_N,,)               \
-       INCLUDE_PROFILING_INFO(infolbl)         \
-       INCLUDE_UPDATE_INFO(upd_code,liveness)  \
-       INCLUDE_GEN_INFO(size,ptrs)             \
-       }
-
-MAYBE_DECLARE_RTBL(Gen_N,,)
-
-#define GEN_N_RTBL()                                                           \
-    const W_ MK_REP_LBL(Gen_N,,)[] = {                                         \
-       INCLUDE_TYPE_INFO(GEN_N)                                                \
-       INCLUDE_SIZE_INFO(INFO_UNUSED,INFO_UNUSED) /* NB: in info table */      \
-       INCLUDE_PAR_INFO                                                        \
-       INCLUDE_COPYING_INFO(_Evacuate_S,_Scavenge_S_N)                         \
-       INCLUDE_COMPACTING_INFO(_ScanLink_S_N,_PRStart_N,_ScanMove_S,_PRIn_I)   \
-       }
-
-#define GEN_S_ITBL(infolbl,entry_code,upd_code,liveness,tag,size,ptrs,localness,entry_localness,kind,descr,type) \
-    CAT_DECLARE(infolbl,kind,descr,type)       \
-    entry_localness(entry_code);               \
-    localness W_ infolbl[] = {                 \
-        (W_) entry_code                                \
-       ,(W_) tag                               \
-       ,(W_) MK_REP_REF(Gen_S,,)               \
-       INCLUDE_PROFILING_INFO(infolbl)         \
-       INCLUDE_UPDATE_INFO(upd_code,liveness)  \
-       INCLUDE_GEN_INFO(size,ptrs)             \
-       }
-
-MAYBE_DECLARE_RTBL(Gen_S,,)
-
-#define GEN_S_RTBL()                                                           \
-    const W_ MK_REP_LBL(Gen_S,,)[] = {                                         \
-       INCLUDE_TYPE_INFO(GEN_S)                                                \
-       INCLUDE_SIZE_INFO(INFO_UNUSED,INFO_UNUSED) /* NB: in info table */      \
-       INCLUDE_PAR_INFO                                                        \
-       INCLUDE_COPYING_INFO(_Evacuate_S,_Scavenge_S_N)                         \
-       INCLUDE_COMPACTING_INFO(_ScanLink_S_N,_PRStart_N,_ScanMove_S,_PRIn_I)   \
-       }
-
-#if defined(PAR) || defined(GRAN)
-# define GEN_U_ITBL(infolbl,entry_code,upd_code,liveness,tag,size,ptrs,localness,entry_localness,kind,descr,type) \
-    entry_localness(CAT2(RBH_,entry_code));            \
-    localness W_ infolbl[];                    \
-    localness W_ CAT2(RBH_,infolbl)[] = {      \
-        (W_) CAT2(RBH_,entry_code)             \
-       ,(W_) INFO_OTHER_TAG                    \
-       ,(W_) MK_REP_REF(Gen_RBH,,)             \
-       INCLUDE_PROFILING_INFO(RBH)             \
-       INCLUDE_UPDATE_INFO(INFO_UNUSED,INFO_UNUSED)    \
-       INCLUDE_GEN_INFO(size,ptrs)             \
-       INCLUDE_RBH_INFO(infolbl)               \
-       };                                      \
-    STGFUN(CAT2(RBH_,entry_code)) { JMP_(RBH_entry); }\
-    CAT_DECLARE(infolbl,kind,descr,type)       \
-    entry_localness(entry_code);               \
-    localness W_ infolbl[] = {                 \
-        (W_) entry_code                                \
-       ,(W_) tag                               \
-       ,(W_) MK_REP_REF(Gen_U,,)               \
-       INCLUDE_PROFILING_INFO(infolbl)         \
-       INCLUDE_UPDATE_INFO(INFO_UNUSED,INFO_UNUSED)    \
-       INCLUDE_GEN_INFO(size,ptrs)             \
-       INCLUDE_RBH_INFO(CAT2(RBH_,infolbl))    \
-       }
-
-MAYBE_DECLARE_RTBL(Gen_RBH,,)
-
-# define GEN_RBH_RTBL()                                                                \
-    const W_ MK_REP_LBL(Gen_RBH,,)[] = {                                       \
-       INCLUDE_TYPE_INFO(GEN_RBH)                                              \
-       INCLUDE_SIZE_INFO(INFO_UNUSED,INFO_UNUSED) /* NB: no size/no-ptrs! */   \
-       INCLUDE_PAR_INFO                                                        \
-       INCLUDE_COPYING_INFO(_Evacuate_RBH_S,_Scavenge_RBH_N)                   \
-       INCLUDE_COMPACTING_INFO(_ScanLink_RBH_N,_PRStart_RBH_N,_ScanMove_RBH_S,_PRIn_RBH_I)     \
-       }
-
-#else
-
-# define GEN_U_ITBL(infolbl,entry_code,upd_code,liveness,tag,size,ptrs,localness,entry_localness,kind,descr,type) \
-    CAT_DECLARE(infolbl,kind,descr,type)       \
-    entry_localness(entry_code);               \
-    localness W_ infolbl[] = {                 \
-        (W_) entry_code                                \
-       ,(W_) tag                               \
-       ,(W_) MK_REP_REF(Gen_U,,)               \
-       INCLUDE_PROFILING_INFO(infolbl)         \
-       INCLUDE_UPDATE_INFO(INFO_UNUSED,INFO_UNUSED)    \
-       INCLUDE_GEN_INFO(size,ptrs)             \
-       }
-#endif
-
-MAYBE_DECLARE_RTBL(Gen_U,,)
-
-#define GEN_U_RTBL()                                                           \
-    const W_ MK_REP_LBL(Gen_U,,)[] = {                                         \
-       INCLUDE_TYPE_INFO(GEN_U)                                                \
-       INCLUDE_SIZE_INFO(INFO_UNUSED,INFO_UNUSED) /* NB: no size/no-ptrs! */   \
-       INCLUDE_PAR_INFO                                                        \
-       INCLUDE_COPYING_INFO(_Evacuate_S,_Scavenge_S_N)                         \
-       INCLUDE_COMPACTING_INFO(_ScanLink_S_N,_PRStart_N,_ScanMove_S,_PRIn_I)   \
-       }
-
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[DYN_ITBL]{Dynamic-object info tables}
-%*                                                                     *
-%************************************************************************
-
-For these, the size/no-of-pointers is not known until runtime.  E.g.,
-arrays.  Those fields are, therefore, in the closure itself, and not
-in the info table.
-
-All @DYN@ closures are @PAP@s, so they are not updatable.
-
-\begin{code}
-
-#define DYN_ITBL(infolbl,entry_code,upd_code,liveness,tag,size,ptrs,localness,entry_localness,kind,descr,type) /*size,ptrs unused*/ \
-    CAT_DECLARE(infolbl,kind,descr,type)       \
-    entry_localness(entry_code);               \
-    localness W_ infolbl[] = {                 \
-        (W_) entry_code                                \
-       ,(W_) tag                               \
-       ,(W_) MK_REP_LBL(Dyn,,)                 \
-       INCLUDE_PROFILING_INFO(infolbl)         \
-       }
-
-MAYBE_DECLARE_RTBL(Dyn,,)
-
-#define DYN_RTBL()                                                     \
-    const W_ MK_REP_LBL(Dyn,,)[] = {                                   \
-       INCLUDE_TYPE_INFO(DYN)                                          \
-       INCLUDE_SIZE_INFO(INFO_UNUSED,INFO_UNUSED) /* in closure! */    \
-       INCLUDE_PAR_INFO                                                \
-       INCLUDE_COPYING_INFO(_Evacuate_Dyn,_Scavenge_Dyn)               \
-       INCLUDE_COMPACTING_INFO(_ScanLink_Dyn,_PRStart_Dyn,_ScanMove_Dyn,_PRIn_I_Dyn) \
-       }
-
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[TUPLE_ITBL]{``Tuple'' and ``Data'' info-tables}
-%*                                                                     *
-%************************************************************************
-
-``Tuples'' are essentially DYNs with all pointers (no non-pointers).
-``Data things'' are DYNs with all non-pointers.
-
-\begin{code}
-
-#define TUPLE_ITBL(infolbl,entry_code,upd_code,liveness,tag,size,ptrs,localness,entry_localness,kind,descr,type) /*size,ptrs unused*/ \
-    CAT_DECLARE(infolbl,kind,descr,type)       \
-    entry_localness(entry_code);               \
-    localness W_ infolbl[] = {                 \
-        (W_) entry_code                                \
-       ,(W_) tag                               \
-       ,(W_) MK_REP_REF(Tuple,,)               \
-       INCLUDE_PROFILING_INFO(infolbl)         \
-       }
-
-MAYBE_DECLARE_RTBL(Tuple,,)
-
-#define TUPLE_RTBL() \
-    const W_ MK_REP_LBL(Tuple,,)[] = { \
-       INCLUDE_TYPE_INFO(TUPLE)                                        \
-       INCLUDE_SIZE_INFO(INFO_UNUSED,INFO_UNUSED) /* NB: in closure */ \
-       INCLUDE_PAR_INFO                                                \
-       INCLUDE_COPYING_INFO(_Evacuate_Tuple,_Scavenge_Tuple) \
-       INCLUDE_COMPACTING_INFO(_ScanLink_Tuple,_PRStart_Tuple,_ScanMove_Tuple,_PRIn_I_Tuple) \
-       }
-
-#define DATA_ITBL(infolbl,entry_code,upd_code,liveness,tag,size,ptrs,localness,entry_localness,kind,descr,type) /*size,ptrs unused*/ \
-    CAT_DECLARE(infolbl,kind,descr,type)       \
-    entry_localness(entry_code);               \
-    localness W_ infolbl[] = {                 \
-        (W_) entry_code                                \
-       ,(W_) tag                               \
-       ,(W_) MK_REP_REF(Data,,)                \
-       INCLUDE_PROFILING_INFO(infolbl)         \
-       }
-
-MAYBE_DECLARE_RTBL(Data,,)
-
-#define DATA_RTBL()                    \
-    const W_ MK_REP_LBL(Data,,)[] = {  \
-       INCLUDE_TYPE_INFO(DATA)         \
-       INCLUDE_SIZE_INFO(INFO_UNUSED,INFO_UNUSED) /* NB: in closure */ \
-       INCLUDE_PAR_INFO                 \
-       INCLUDE_COPYING_INFO(_Evacuate_Data,_Scavenge_Data) \
-       INCLUDE_COMPACTING_INFO(_ScanLink_Data,_PRStart_Data,_ScanMove_Data,_PRIn_Error) \
-    }
-
-/* Here is the decl for the only DATA info table used! */
-#ifndef COMPILING_NCG
-EXTDATA_RO(ArrayOfData_info);
-#endif
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[MUTUPLE_ITBL]{Info-table for (im)mutable [array-ish] objects}
-%*                                                                     *
-%************************************************************************
-
-ToDo: Integrate with PAR stuff (Kevin) !!
-If someone bothers to document this I'll see what I can do! KH
-
-\begin{code}
-
-#if defined(GC_MUT_REQUIRED)
-
-# define MUTUPLE_ITBL(infolbl,entry_code,upd_code,liveness,tag,size,ptrs,localness,entry_localness,kind,descr,type) /*size,ptrs unused*/ \
-    CAT_DECLARE(infolbl,kind,descr,type)       \
-    entry_localness(entry_code);               \
-    localness W_ infolbl[] = {                 \
-        (W_) entry_code                                \
-       ,(W_) tag                               \
-       ,(W_) MK_REP_REF(MuTuple,,)             \
-       INCLUDE_PROFILING_INFO(infolbl)         \
-       }
-
-MAYBE_DECLARE_RTBL(MuTuple,,)
-
-# define MUTUPLE_RTBL()                                \
-    const W_ MK_REP_LBL(MuTuple,,)[] = {       \
-       INCLUDE_TYPE_INFO(MUTUPLE)              \
-       INCLUDE_SIZE_INFO(INFO_UNUSED,INFO_UNUSED) /* NB: in closure! */ \
-       INCLUDE_PAR_INFO                         \
-       INCLUDE_COPYING_INFO(_Evacuate_MuTuple,_Scavenge_MuTuple) \
-       INCLUDE_COMPACTING_INFO(_ScanLink_MuTuple,_PRStart_MuTuple,_ScanMove_MuTuple,_PRIn_I_MuTuple) \
-       }
-
-# define IMMUTUPLE_ITBL(infolbl,entry_code,upd_code,liveness,tag,size,ptrs,localness,entry_localness,kind,descr,type) /*size,ptrs unused*/ \
-    CAT_DECLARE(infolbl,kind,descr,type)       \
-    entry_localness(entry_code);               \
-    localness W_ infolbl[] = {                 \
-        (W_) entry_code                                \
-       ,(W_) tag                               \
-       ,(W_) MK_REP_REF(ImmuTuple,,)           \
-       INCLUDE_PROFILING_INFO(infolbl)         \
-       }
-
-MAYBE_DECLARE_RTBL(ImmuTuple,,)
-
-# define IMMUTUPLE_RTBL() \
-    const W_ MK_REP_LBL(ImmuTuple,,)[] = {  \
-       INCLUDE_TYPE_INFO(IMMUTUPLE)        \
-       INCLUDE_SIZE_INFO(INFO_UNUSED,INFO_UNUSED) /* NB: in closure! */ \
-       INCLUDE_PAR_INFO                         \
-       INCLUDE_COPYING_INFO(_Evacuate_MuTuple,_Scavenge_MuTuple) \
-       INCLUDE_COMPACTING_INFO(_ScanLink_MuTuple,_PRStart_MuTuple,_ScanMove_ImmuTuple,_PRIn_I_MuTuple) \
-    }
-  
-#else   /* ! GC_MUT_REQUIRED --- define as TUPLE closure */
-
-# define MUTUPLE_ITBL(infolbl,entry_code,upd_code,liveness,tag,size,ptrs,localness,entry_localness,kind,descr,type) \
-       TUPLE_ITBL(infolbl,entry_code,upd_code,liveness,tag,size,ptrs,localness,entry_localness,kind,descr,type)
-# define IMMUTUPLE_ITBL(infolbl,entry_code,upd_code,liveness,tag,size,ptrs,localness,entry_localness,kind,descr,type) \
-       TUPLE_ITBL(infolbl,entry_code,upd_code,liveness,tag,size,ptrs,localness,entry_localness,kind,descr,type)
-
-# define MUTUPLE_RTBL()
-# define IMMUTUPLE_RTBL()
-#endif
-
-/* Here are the decls for the only MUTUPLE info tables used. */
-#ifndef COMPILING_NCG
-EXTDATA_RO(ArrayOfPtrs_info);
-EXTDATA_RO(ImMutArrayOfPtrs_info);
-EXTDATA_RO(EmptySVar_info);
-EXTDATA_RO(FullSVar_info);
-#endif
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[STATIC_ITBL]{Info tables for static objects (outside the heap)}
-%*                                                                     *
-%************************************************************************
-
-Size and ptrs fields are used by interpretive code, such as @ghci@,
-the parallel Pack code (@Pack.lc@) and possibly to-be-written debug
-code.
-
-\begin{code}
-#define STATIC_ITBL(infolbl,entry_code,upd_code,liveness,tag,size,ptrs,localness,entry_localness,kind,descr,type) \
-    CAT_DECLARE(infolbl,kind,descr,type)       \
-    entry_localness(entry_code);               \
-    localness W_ infolbl[] = {                 \
-        (W_) entry_code                                \
-       ,(W_) tag                               \
-       ,(W_) MK_REP_REF(Static,,)              \
-       INCLUDE_PROFILING_INFO(infolbl)         \
-       INCLUDE_UPDATE_INFO(upd_code,liveness)  \
-       INCLUDE_STATIC_INFO(size,ptrs)          \
-       }
-
-MAYBE_DECLARE_RTBL(Static,,)
-
-#define STATIC_RTBL() \
-    const W_ MK_REP_LBL(Static,,)[] = { \
-       INCLUDE_TYPE_INFO(STATIC)       \
-       INCLUDE_SIZE_INFO(INFO_UNUSED,INFO_UNUSED) /* NB: in info table! */ \
-       INCLUDE_PAR_INFO                 \
-       INCLUDE_COPYING_INFO(_Evacuate_Static,_Dummy_Static_entry) \
-       INCLUDE_COMPACTING_INFO(_Dummy_Static_entry,_PRStart_Static, \
-                               _Dummy_Static_entry,_Dummy_Static_entry) \
-       }
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[ForeignObj_ITBL]{@ForeignObj_TBL@: @ForeignObj@ info-table}
-%*                                                                     *
-%************************************************************************
-
-The following table is a bit like that for @SPEC@ with 0 pointers and
-a small number of non-ptrs.  However, the garbage collection routines
-are a bit special.
-
-I'm assuming @SPEC_N@, so that we don't need to pad out the info table. (JSM)
-
-\begin{code}
-#if !defined(PAR)
-
-# define ForeignObj_ITBL(infolbl,entry_code,upd_code,liveness,tag,size,ptrs,localness,entry_localness,kind,descr,type) /*size,ptrs unused*/ \
-    CAT_DECLARE(infolbl,kind,descr,type)       \
-    entry_localness(entry_code);               \
-    localness W_ infolbl[] = {                 \
-        (W_) entry_code                                \
-       ,(W_) tag                               \
-       ,(W_) MK_REP_REF(ForeignObj,,)          \
-       INCLUDE_PROFILING_INFO(infolbl)         \
-    }
-
-MAYBE_DECLARE_RTBL(ForeignObj,,)
-
-# define ForeignObj_RTBL() \
-    const W_ MK_REP_LBL(ForeignObj,,)[] = { \
-       INCLUDE_TYPE_INFO(INTERNAL)                             \
-       INCLUDE_SIZE_INFO(ForeignObj_SIZE, 0L)                  \
-       INCLUDE_PAR_INFO                                        \
-       INCLUDE_COPYING_INFO(_Evacuate_ForeignObj,_Scavenge_ForeignObj)         \
-       SPEC_COMPACTING_INFO(_ScanLink_ForeignObj,_PRStart_ForeignObj,_ScanMove_ForeignObj,_PRIn_0) \
-       }
-
-#endif /* !PAR */
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[BH_ITBL]{Info tables for ``black holes''}
-%*                                                                     *
-%************************************************************************
-
-Special info-table for black holes. It is possible to describe these
-using @SPEC@ closures but this requires explicit use of the value of
-@MIN_UPD_SIZE@. For now we have a special macro and code.
-
-\begin{code}
-
-#define BH_ITBL(infolbl,bh_code,kind,localness,entry_localness) \
-    entry_localness(bh_code);                  \
-    localness W_ infolbl[] = {                 \
-        (W_) bh_code                           \
-       ,(W_) INFO_OTHER_TAG                    \
-       ,(W_) MK_REP_REF(BH,kind,)              \
-       INCLUDE_PROFILING_INFO(BH)              \
-    }
-
-MAYBE_DECLARE_RTBL(BH,U,)
-MAYBE_DECLARE_RTBL(BH,N,)
-
-#define BH_RTBL(kind)                                                          \
-    const W_ MK_REP_LBL(BH,kind,)[] = {                                                \
-       INCLUDE_TYPE_INFO(BH)                                                   \
-       INCLUDE_SIZE_INFO(CAT3(BH_,kind,_SIZE),0L)                              \
-       INCLUDE_PAR_INFO                                                        \
-       INCLUDE_COPYING_INFO(CAT2(_Evacuate_BH_,kind),CAT2(_Scavenge_BH_,kind)) \
-       INCLUDE_COMPACTING_INFO(CAT2(_ScanLink_BH_,kind),_PRStart_BH,           \
-                               CAT2(_ScanMove_BH_,kind),_PRIn_Error)           \
-    }
-
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[IND_ITBL]{Info table for indirections}
-%*                                                                     *
-%************************************************************************
-
-An indirection simply extracts the pointer from the
-@IND_CLOSURE_PTR(closure)@ field. The garbage collection routines will
-short out the indirection (normally).
-\begin{code}
-
-#define IND_ITBL(infolbl,ind_code,localness,entry_localness) \
-    CAT_DECLARE(infolbl,INTERNAL_KIND,"IND","IND")     \
-    entry_localness(ind_code);                         \
-    localness W_ infolbl[] = {                         \
-        (W_) ind_code                                  \
-       ,(W_) INFO_IND_TAG                              \
-       ,(W_) MK_REP_REF(Ind,,)                         \
-       INCLUDE_PROFILING_INFO(infolbl)                 \
-       }
-
-MAYBE_DECLARE_RTBL(Ind,,)
-
-#define IND_RTBL()                                                             \
-    const W_ MK_REP_LBL(Ind,,)[] = {                                           \
-       INCLUDE_TYPE_INFO(IND)                                                  \
-       INCLUDE_SIZE_INFO(MIN_UPD_SIZE,INFO_UNUSED) /* #ptrs not here! */       \
-       INCLUDE_PAR_INFO                                                        \
-       INCLUDE_COPYING_INFO(_Evacuate_Ind,_Scavenge_Ind)                       \
-       INCLUDE_COMPACTING_INFO(_Dummy_Ind_entry,_PRStart_Ind,                  \
-                               _Dummy_Ind_entry,_Dummy_Ind_entry)              \
-    }
-
-\end{code}
-
-Lexical-scoped profiling (now more-or-less the default... 94/06)
-requires a special permanent indirection for PAP closures.  These 
-look exactly like regular indirections, but they are not short-circuited
-on garbage collection.
-
-\begin{code}
-#if defined(PROFILING) || defined(TICKY_TICKY)
-
-# define PERM_IND_ITBL(infolbl,ind_code,localness,entry_localness) \
-    entry_localness(ind_code);                         \
-    CAT_DECLARE(infolbl,INTERNAL_KIND,"IND","IND")     \
-    localness W_ infolbl[] = {                         \
-        (W_) ind_code                                  \
-       ,(W_) INFO_IND_TAG                              \
-       ,(W_) MK_REP_REF(Perm_Ind,,)                    \
-       INCLUDE_PROFILING_INFO(infolbl)                 \
-    }
-
-MAYBE_DECLARE_RTBL(Perm_Ind,,)
-
-# define PERM_IND_RTBL()                                                       \
-    const W_ MK_REP_LBL(Perm_Ind,,)[] = {                                      \
-       INCLUDE_TYPE_INFO(IND)                                                  \
-       INCLUDE_SIZE_INFO(MIN_UPD_SIZE,INFO_UNUSED) /* #ptrs not here! */       \
-       INCLUDE_PAR_INFO                                                        \
-       INCLUDE_COPYING_INFO(_Evacuate_PI,_Scavenge_PI)                         \
-       SPEC_COMPACTING_INFO(_ScanLink_PI,_PRStart_PI,                          \
-                            _ScanMove_PI,_PRIn_PI)                             \
-       }
-
-#else
-# define PERM_IND_RTBL()
-#endif
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[CAF_ITBL]{Info table for updated @CAF@s}
-%*                                                                     *
-%************************************************************************
-
-Garbage collection of @CAF@s is tricky.  We have to cope with explicit
-collection from the @CAFlist@ as well as potential references from the
-stack and heap which will cause the @CAF@ evacuation code to be
-called.  They are treated like indirections which are shorted out.
-However they must also be updated to point to the new location of the
-new closure as the @CAF@ may still be used by references which
-reside in the code.
-
-\subsubsection{Copying Collection}
-
-A first scheme might use evacuation code which evacuates the reference
-and updates the indirection. This is no good as subsequent evacuations
-will result in an already evacuated closure being evacuated. This will
-leave a forward reference in to-space!
-
-An alternative scheme evacuates the @CAFlist@ first. The closures
-referenced are evacuated and the @CAF@ indirection updated to point to
-the evacuated closure. The @CAF@ evacuation code simply returns the
-updated indirection pointer --- the pointer to the evacuated closure.
-Unfortunately the closure the @CAF@ references may be a static
-closure, in fact, it may be another @CAF@. This will cause the second
-@CAF@'s evacuation code to be called before the @CAF@ has been
-evacuated, returning an unevacuated pointer.
-
-Another scheme leaves updating the @CAF@ indirections to the end of
-the garbage collection.  All the references are evacuated and
-scavenged as usual (including the @CAFlist@). Once collection is
-complete the @CAFlist@ is traversed updating the @CAF@ references with
-the result of evacuating the referenced closure again. This will
-immediately return as it must be a forward reference, a static
-closure, or a @CAF@ which will indirect by evacuating its reference.
-
-The crux of the problem is that the @CAF@ evacuation code needs to
-know if its reference has already been evacuated and updated. If not,
-then the reference can be evacuated, updated and returned safely
-(possibly evacuating another @CAF@). If it has, then the updated
-reference can be returned. This can be done using two @CAF@
-info-tables. At the start of a collection the @CAFlist@ is traversed
-and set to an internal {\em evacuate and update} info-table. During
-collection, evacution of such a @CAF@ also results in the info-table
-being reset back to the standard @CAF@ info-table. Thus subsequent
-evacuations will simply return the updated reference. On completion of
-the collection all @CAF@s will have {\em return reference} info-tables
-again.
-
-This is the scheme we adopt. A @CAF@ indirection has evacuation code
-which returns the evacuated and updated reference. During garbage
-collection, all the @CAF@s are overwritten with an internal @CAF@ info
-table which has evacuation code which performs this evacuate and
-update and restores the original @CAF@ code. At some point during the
-collection we must ensure that all the @CAF@s are indeed evacuated.
-
-The only potential problem with this scheme is a cyclic list of @CAF@s
-all directly referencing (possibly via indirections) another @CAF@!
-Evacuation of the first @CAF@ will fail in an infinite loop of @CAF@
-evacuations. This is solved by ensuring that the @CAF@ info-table is
-updated to a {\em return reference} info-table before performing the
-evacuate and update. If this {\em return reference} evacuation code is
-called before the actual evacuation is complete it must be because
-such a cycle of references exists. Returning the still unevacuated
-reference is OK --- all the @CAF@s will now reference the same
-@CAF@ which will reference itself! Construction of such a structure
-indicates the program must be in an infinite loop.
-
-\subsubsection{Compacting Collector}
-
-When shorting out a @CAF@, its reference must be marked. A first
-attempt might explicitly mark the @CAF@s, updating the reference with
-the marked reference (possibly short circuting indirections). The
-actual @CAF@ marking code can indicate that they have already been
-marked (though this might not have actually been done yet) and return
-the indirection pointer so it is shorted out. Unfortunately the @CAF@
-reference might point to an indirection which will be subsequently
-shorted out. Rather than returning the @CAF@ reference we treat the
-@CAF@ as an indirection, calling the mark code of the reference, which
-will return the appropriately shorted reference.
-
-Problem: Cyclic list of @CAF@s all directly referencing (possibly via
-indirections) another @CAF@!
-
-Before compacting, the locations of the @CAF@ references are
-explicitly linked to the closures they reference (if they reference
-heap allocated closures) so that the compacting process will update
-them to the closure's new location. Unfortunately these locations'
-@CAF@ indirections are static.  This causes premature termination
-since the test to find the info pointer at the end of the location
-list will match more than one value.  This can be solved by using an
-auxiliary dynamic array (on the top of the A stack).  One location for
-each @CAF@ indirection is linked to the closure that the @CAF@
-references. Once collection is complete this array is traversed and
-the corresponding @CAF@ is then updated with the updated pointer from
-the auxiliary array.
-
-\begin{code}
-
-#define CAF_ITBL(infolbl,ind_code,localness,entry_localness) \
-    CAT_DECLARE(infolbl,INTERNAL_KIND,"CAF","CAF")     \
-    entry_localness(ind_code);                         \
-    localness W_ infolbl[] = {                         \
-        (W_) ind_code                                  \
-       ,(W_) INFO_IND_TAG                              \
-       ,(W_) MK_REP_REF(Caf,,)                         \
-       INCLUDE_PROFILING_INFO(infolbl)                 \
-    }
-
-MAYBE_DECLARE_RTBL(Caf,,)
-
-#define CAF_RTBL()                                                             \
-    const W_ MK_REP_LBL(Caf,,)[] = {                                           \
-       INCLUDE_TYPE_INFO(CAF)                                                  \
-       INCLUDE_SIZE_INFO(MIN_UPD_SIZE,INFO_UNUSED) /* #ptrs not here! */       \
-       INCLUDE_PAR_INFO                                                        \
-       INCLUDE_COPYING_INFO(_Evacuate_Caf,_Scavenge_Caf)                       \
-       INCLUDE_COMPACTING_INFO(_Dummy_Caf_entry,_PRStart_Caf,                  \
-                               _Dummy_Caf_entry,_Dummy_Caf_entry)              \
-       }
-\end{code}
-
-
-It is possible to use an alternative marking scheme, using a similar
-idea to the copying solution. This scheme avoids the need to update
-the @CAF@ references explicitly. We introduce an auxillary {\em mark
-and update} @CAF@ info-table which is used to update all @CAF@s at the
-start of a collection. The new code marks the @CAF@ reference,
-updating it with the returned reference.  The returned reference is
-itself returned so the @CAF@ is shorted out.  The code also modifies the
-@CAF@ info-table to be a {\em return reference}.  Subsequent attempts to
-mark the @CAF@ simply return the updated reference.
-
-A cyclic @CAF@ reference will result in an attempt to mark the @CAF@
-before the marking has been completed and the reference updated. We
-cannot start marking the @CAF@ as it is already being marked. Nor can
-we return the reference as it has not yet been updated. Neither can we
-treat the CAF as an indirection since the @CAF@ reference has been
-obscured by the pointer reversal stack. All we can do is return the
-@CAF@ itself. This will result in some @CAF@ references not being
-shorted out.
-
-This scheme has not been adopted but has been implemented. The code is
-commented out with @#if 0@.
-
-%************************************************************************
-%*                                                                     *
-\subsection[CONST_ITBL]{@CONST_ITBL@}
-%*                                                                     *
-%************************************************************************
-
-This declares an info table for @CONST@ closures (size 0).  It is the
-info table for a dynamicaly-allocated closure which will redirect
-references to the corresponding static closure @<infolbl>_closure@
-during garbage collection.  A pointer to the static closure is kept in
-the info table.  (It is assumed that this closure is declared
-elsewhere.)
-
-Why do such @CONST@ objects ever exist?  Why don't we just use the
-static object in the first place?  @CONST@ objects are used only for
-updating existing objects.  We could use an indirection, but that
-risks costing extra run-time indirections until the next GC shorts it
-out.  So we update with a @CONST@, and the next GC gets rid of it.
-
-\begin{code}
-#define CONST_ITBL(infolbl,closurelbl,entry_code,upd_code,liveness,tag,size,ptrs,localness,entry_localness,kind,descr,type) /*size,ptrs unused*/ \
-    CAT_DECLARE(infolbl,kind,descr,type)       \
-    entry_localness(entry_code);               \
-    EXTDATA(closurelbl);                       \
-    localness W_ infolbl[] = {                 \
-        (W_) entry_code                                \
-       ,(W_) tag                               \
-       ,(W_) MK_REP_REF(Const,,)               \
-       INCLUDE_PROFILING_INFO(infolbl)         \
-       INCLUDE_UPDATE_INFO(upd_code,liveness)  \
-       INCLUDE_CONST_INFO(closurelbl)          \
-       }
-
-MAYBE_DECLARE_RTBL(Const,,)
-
-#ifdef TICKY_TICKY
-    /* we need real routines if we may not be commoning up */
-#define CONST_Scav _Scavenge_0_0
-#define CONST_Link _ScanLink_0_0
-#define CONST_Move _ScanMove_0
-#else
-#define CONST_Scav _Dummy_Const_entry
-#define CONST_Link _Dummy_Const_entry
-#define CONST_Move _Dummy_Const_entry
-#endif
-
-#define CONST_RTBL()                                           \
-    const W_ MK_REP_LBL(Const,,)[] = {                         \
-       INCLUDE_TYPE_INFO(CONST)                                \
-       INCLUDE_SIZE_INFO(INFO_UNUSED,INFO_UNUSED)              \
-       INCLUDE_PAR_INFO                                        \
-       INCLUDE_COPYING_INFO(_Evacuate_Const,CONST_Scav)        \
-       INCLUDE_COMPACTING_INFO(CONST_Link,_PRStart_Const,      \
-                               CONST_Move,_Dummy_Const_entry)  \
-    }
-\end{code}
-
-This builds an info-table which will have pointers to the closure
-replaced with @closure_lbl@ during garbage collection. @closure_lbl@
-must be the label of a static closure, whose entry code has identical
-behaviour to that in the corresponding @CONST_ITBL@.  Usually
-the info pointer of this closure will be the very one defined by this
-macro!
-
-These closures always consist only of an info pointer; that is, its
-size is zero.
-
-A copying collection implements this with evacuation code which
-returns @closure_lbl@, without actually evacuating the object at all.
-A compacting collector uses marking code which returns
-@closure_lbl@, without marking the closure.
-
-%************************************************************************
-%*                                                                     *
-\subsection[FOOLIKE_ITBL]{``Char-like'' and ``Int-like'' info-tables}
-%*                                                                     *
-%************************************************************************
-
-Char-like: This builds an info-table which, when GC happens, will have
-pointers to the closure replaced with the appropriate element of the
-@CHARLIKE_closures@ array.
-
-\begin{code}
-#define CHARLIKE_ITBL(infolbl,entry_code,upd_code,liveness,tag,size,ptrs,localness,entry_localness,kind,descr,type) /*tag,size,ptrs unused*/ \
-    CAT_DECLARE(infolbl,kind,descr,type)       \
-    entry_localness(entry_code);               \
-    localness W_ infolbl[] = {                 \
-        (W_) entry_code                                \
-       ,(W_) INFO_FIRST_TAG                    \
-       ,(W_) MK_REP_REF(CharLike,,)            \
-       INCLUDE_PROFILING_INFO(infolbl)         \
-       INCLUDE_UPDATE_INFO(upd_code,liveness)  \
-       }
-
-MAYBE_DECLARE_RTBL(CharLike,,)
-
-#ifdef TICKY_TICKY
-    /* we need real routines if we may not be commoning up */
-#define CHARLIKE_Scav _Scavenge_1_0
-#define CHARLIKE_Link _ScanLink_1_0
-#define CHARLIKE_Move _ScanMove_1
-#else
-#define CHARLIKE_Scav _Dummy_CharLike_entry
-#define CHARLIKE_Link _Dummy_CharLike_entry
-#define CHARLIKE_Move _Dummy_CharLike_entry
-#endif
-
-#define CHARLIKE_RTBL()                                                        \
-    const W_ MK_REP_LBL(CharLike,,)[] = {                              \
-       INCLUDE_TYPE_INFO(CHARLIKE)                                     \
-       INCLUDE_SIZE_INFO(INFO_UNUSED,INFO_UNUSED)                      \
-       INCLUDE_PAR_INFO                                                \
-       INCLUDE_COPYING_INFO(_Evacuate_CharLike,CHARLIKE_Scav)          \
-       INCLUDE_COMPACTING_INFO(CHARLIKE_Link,_PRStart_CharLike,        \
-                               CHARLIKE_Move,_PRIn_Error)              \
-       }
-\end{code}
-
-Int-like: this builds the info-table required for intlike closures.
-The normal heap-allocated info-table for fixed-size integers (size
-@1@); it is used for updates too.  At GC, this is redirected to a
-static intlike closure if one is available.
-
-\begin{code}
-#define INTLIKE_ITBL(infolbl,entry_code,upd_code,liveness,tag,size,ptrs,localness,entry_localness,kind,descr,type) /*tag,size,ptrs unused*/ \
-    CAT_DECLARE(infolbl,kind,descr,type)       \
-    entry_localness(entry_code);               \
-    localness W_ infolbl[] = {                 \
-        (W_) entry_code                                \
-       ,(W_) INFO_FIRST_TAG                    \
-       ,(W_) MK_REP_REF(IntLike,,)             \
-       INCLUDE_PROFILING_INFO(infolbl)         \
-       INCLUDE_UPDATE_INFO(upd_code,liveness)  \
-    }
-
-MAYBE_DECLARE_RTBL(IntLike,,)
-
-#define INTLIKE_RTBL()                                                 \
-    const W_ MK_REP_LBL(IntLike,,)[] = {                               \
-       INCLUDE_TYPE_INFO(INTLIKE)                                      \
-       INCLUDE_SIZE_INFO(INFO_UNUSED,INFO_UNUSED)                      \
-       INCLUDE_PAR_INFO                                                \
-       INCLUDE_COPYING_INFO(_Evacuate_IntLike,_Scavenge_1_0)           \
-       INCLUDE_COMPACTING_INFO(_ScanLink_1_0,_PRStart_IntLike,         \
-                               _ScanMove_1,_PRIn_Error)                \
-    }
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[INREGS_ITBL]{@INREGS_ITBL@s}
-%*                                                                     *
-%************************************************************************
-
-The emaciated info table for a phantom closure that lives only in regs.
-We don't need any GC information, because these closures never make it into
-the heap (not with this info table, anyway).  Similarly, we don't need an
-entry address, because these closures are never entered...they only exist
-during a return.
-
-\begin{code}
-
-#define INREGS_ITBL(infolbl,entry_code,upd_code,liveness,tag,size,ptrs,localness,entry_localness,kind,descr,type) /*mostly unused*/ \
-    localness W_ infolbl[] = {                 \
-        (W_) INFO_UNUSED                       \
-       ,(W_) tag                               \
-       ,(W_) INFO_UNUSED                       \
-       INREGS_PROFILING_INFO                   \
-       INCLUDE_UPDATE_INFO(upd_code,liveness)  \
-    }
-
-/* Declare the phantom info table vectors (just Bool at the moment) */
-#ifndef COMPILING_NCG
-#ifndef aix_TARGET_OS /* AIX gives link errors with this as a const (RO assembler section) */
-EXTDATA_RO(PrelBase_Bool_itblvtbl);
-#else
-extern W_ PrelBase_Bool_itblvtbl[];
-#endif
-#endif
-
-\end{code}
-
-End multi-slurp protection:
-\begin{code}
-#endif /* SMInfoTables_H */
-\end{code}