Reorganisation of the source tree
[ghc-hetmet.git] / ghc / rts / HeapStackCheck.cmm
diff --git a/ghc/rts/HeapStackCheck.cmm b/ghc/rts/HeapStackCheck.cmm
deleted file mode 100644 (file)
index 4e5dd24..0000000
+++ /dev/null
@@ -1,964 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * (c) The GHC Team, 1998-2004
- *
- * Canned Heap-Check and Stack-Check sequences.
- *
- * This file is written in a subset of C--, extended with various
- * features specific to GHC.  It is compiled by GHC directly.  For the
- * syntax of .cmm files, see the parser in ghc/compiler/cmm/CmmParse.y.
- *
- * ---------------------------------------------------------------------------*/
-
-#include "Cmm.h"
-
-/* Stack/Heap Check Failure
- * ------------------------
- *
- * On discovering that a stack or heap check has failed, we do the following:
- *
- *    - If the context_switch flag is set, indicating that there are more
- *      threads waiting to run, we yield to the scheduler 
- *     (return ThreadYielding).
- *
- *    - If Hp > HpLim, we've had a heap check failure.  This means we've
- *     come to the end of the current heap block, so we try to chain
- *     another block on with ExtendNursery().  
- *
- *          - If this succeeds, we carry on without returning to the 
- *            scheduler.  
- *
- *          - If it fails, we return to the scheduler claiming HeapOverflow
- *            so that a garbage collection can be performed.
- *
- *    - If Hp <= HpLim, it must have been a stack check that failed.  In
- *     which case, we return to the scheduler claiming StackOverflow, the
- *     scheduler will either increase the size of our stack, or raise
- *     an exception if the stack is already too big.
- *
- * The effect of checking for context switch only in the heap/stack check
- * failure code is that we'll switch threads after the current thread has
- * reached the end of its heap block.  If a thread isn't allocating
- * at all, it won't yield.  Hopefully this won't be a problem in practice.
- */
-#define PRE_RETURN(why,what_next)                      \
-  StgTSO_what_next(CurrentTSO) = what_next::I16;       \
-  StgRegTable_rRet(BaseReg) = why;                     \
-  R1 = BaseReg;
-
-/* Remember that the return address is *removed* when returning to a
- * ThreadRunGHC thread.
- */
-
-#define GC_GENERIC                                             \
-    DEBUG_ONLY(foreign "C" heapCheckFail());                   \
-    if (Hp > HpLim) {                                          \
-        Hp = Hp - HpAlloc/*in bytes*/;                         \
-        if (HpAlloc <= BLOCK_SIZE                              \
-            && bdescr_link(CurrentNursery) != NULL) {          \
-            CLOSE_NURSERY();                                   \
-            CurrentNursery = bdescr_link(CurrentNursery);      \
-            OPEN_NURSERY();                                    \
-            if (CInt[context_switch] != 0 :: CInt) {           \
-                R1 = ThreadYielding;                           \
-                goto sched;                                    \
-            } else {                                           \
-                jump %ENTRY_CODE(Sp(0));                       \
-            }                                                  \
-       } else {                                                \
-            R1 = HeapOverflow;                                 \
-            goto sched;                                                \
-        }                                                      \
-    } else {                                                   \
-        R1 = StackOverflow;                                    \
-    }                                                          \
-  sched:                                                       \
-    PRE_RETURN(R1,ThreadRunGHC);                               \
-    jump stg_returnToSched;
-
-#define HP_GENERIC                             \
-   PRE_RETURN(HeapOverflow, ThreadRunGHC)      \
-  jump stg_returnToSched;
-
-#define BLOCK_GENERIC                          \
-   PRE_RETURN(ThreadBlocked,  ThreadRunGHC)    \
-  jump stg_returnToSched;
-
-#define YIELD_GENERIC                          \
-  PRE_RETURN(ThreadYielding, ThreadRunGHC)     \
-  jump stg_returnToSched;
-
-#define BLOCK_BUT_FIRST(c)                     \
-  PRE_RETURN(ThreadBlocked, ThreadRunGHC)      \
-  R2 = c;                                      \
-  jump stg_returnToSchedButFirst;
-
-#define YIELD_TO_INTERPRETER                   \
-  PRE_RETURN(ThreadYielding, ThreadInterpret)  \
-  jump stg_returnToSchedNotPaused;
-
-/* -----------------------------------------------------------------------------
-   Heap checks in thunks/functions.
-
-   In these cases, node always points to the function closure.  This gives
-   us an easy way to return to the function: just leave R1 on the top of
-   the stack, and have the scheduler enter it to return.
-
-   There are canned sequences for 'n' pointer values in registers.
-   -------------------------------------------------------------------------- */
-
-INFO_TABLE_RET( stg_enter, 1/*framesize*/, 0/*bitmap*/, RET_SMALL)
-{
-    R1 = Sp(1);
-    Sp_adj(2);
-    ENTER();
-}
-
-__stg_gc_enter_1
-{
-    Sp_adj(-2);
-    Sp(1) = R1;
-    Sp(0) = stg_enter_info;
-    GC_GENERIC
-}
-
-#if defined(GRAN)
-/*
-  ToDo: merge the block and yield macros, calling something like BLOCK(N)
-        at the end;
-*/
-
-/* 
-   Should we actually ever do a yield in such a case?? -- HWL
-*/
-gran_yield_0
-{
-    SAVE_THREAD_STATE();                                       
-    TSO_what_next(CurrentTSO) = ThreadRunGHC;          
-    R1 = ThreadYielding;
-    jump StgReturn;
-}
-
-gran_yield_1
-{
-    Sp_adj(-1);
-    Sp(0) = R1;
-    SAVE_THREAD_STATE();                                       
-    TSO_what_next(CurrentTSO) = ThreadRunGHC;          
-    R1 = ThreadYielding;
-    jump StgReturn;
-}
-
-/*- 2 Regs--------------------------------------------------------------------*/
-
-gran_yield_2
-{
-    Sp_adj(-2);
-    Sp(1) = R2;
-    Sp(0) = R1;
-    SAVE_THREAD_STATE();                                       
-    TSO_what_next(CurrentTSO) = ThreadRunGHC;          
-    R1 = ThreadYielding;
-    jump StgReturn;
-}
-
-/*- 3 Regs -------------------------------------------------------------------*/
-
-gran_yield_3
-{
-    Sp_adj(-3);
-    Sp(2) = R3;
-    Sp(1) = R2;
-    Sp(0) = R1;
-    SAVE_THREAD_STATE();                                       
-    TSO_what_next(CurrentTSO) = ThreadRunGHC;          
-    R1 = ThreadYielding;
-    jump StgReturn;
-}
-
-/*- 4 Regs -------------------------------------------------------------------*/
-
-gran_yield_4
-{
-    Sp_adj(-4);
-    Sp(3) = R4;
-    Sp(2) = R3;
-    Sp(1) = R2;
-    Sp(0) = R1;
-    SAVE_THREAD_STATE();                                       
-    TSO_what_next(CurrentTSO) = ThreadRunGHC;          
-    R1 = ThreadYielding;
-    jump StgReturn;
-}
-
-/*- 5 Regs -------------------------------------------------------------------*/
-
-gran_yield_5
-{
-    Sp_adj(-5);
-    Sp(4) = R5;
-    Sp(3) = R4;
-    Sp(2) = R3;
-    Sp(1) = R2;
-    Sp(0) = R1;
-    SAVE_THREAD_STATE();                                       
-    TSO_what_next(CurrentTSO) = ThreadRunGHC;          
-    R1 = ThreadYielding;
-    jump StgReturn;
-}
-
-/*- 6 Regs -------------------------------------------------------------------*/
-
-gran_yield_6
-{
-    Sp_adj(-6);
-    Sp(5) = R6;
-    Sp(4) = R5;
-    Sp(3) = R4;
-    Sp(2) = R3;
-    Sp(1) = R2;
-    Sp(0) = R1;
-    SAVE_THREAD_STATE();                                       
-    TSO_what_next(CurrentTSO) = ThreadRunGHC;          
-    R1 = ThreadYielding;
-    jump StgReturn;
-}
-
-/*- 7 Regs -------------------------------------------------------------------*/
-
-gran_yield_7
-{
-    Sp_adj(-7);
-    Sp(6) = R7;
-    Sp(5) = R6;
-    Sp(4) = R5;
-    Sp(3) = R4;
-    Sp(2) = R3;
-    Sp(1) = R2;
-    Sp(0) = R1;
-    SAVE_THREAD_STATE();                                       
-    TSO_what_next(CurrentTSO) = ThreadRunGHC;          
-    R1 = ThreadYielding;
-    jump StgReturn;
-}
-
-/*- 8 Regs -------------------------------------------------------------------*/
-
-gran_yield_8
-{
-    Sp_adj(-8);
-    Sp(7) = R8;
-    Sp(6) = R7;
-    Sp(5) = R6;
-    Sp(4) = R5;
-    Sp(3) = R4;
-    Sp(2) = R3;
-    Sp(1) = R2;
-    Sp(0) = R1;
-    SAVE_THREAD_STATE();                                       
-    TSO_what_next(CurrentTSO) = ThreadRunGHC;          
-    R1 = ThreadYielding;
-    jump StgReturn;
-}
-
-// the same routines but with a block rather than a yield
-
-gran_block_1
-{
-    Sp_adj(-1);
-    Sp(0) = R1;
-    SAVE_THREAD_STATE();                                       
-    TSO_what_next(CurrentTSO) = ThreadRunGHC;          
-    R1 = ThreadBlocked;
-    jump StgReturn;
-}
-
-/*- 2 Regs--------------------------------------------------------------------*/
-
-gran_block_2
-{
-    Sp_adj(-2);
-    Sp(1) = R2;
-    Sp(0) = R1;
-    SAVE_THREAD_STATE();                                       
-    TSO_what_next(CurrentTSO) = ThreadRunGHC;          
-    R1 = ThreadBlocked;
-    jump StgReturn;
-}
-
-/*- 3 Regs -------------------------------------------------------------------*/
-
-gran_block_3
-{
-    Sp_adj(-3);
-    Sp(2) = R3;
-    Sp(1) = R2;
-    Sp(0) = R1;
-    SAVE_THREAD_STATE();                                       
-    TSO_what_next(CurrentTSO) = ThreadRunGHC;          
-    R1 = ThreadBlocked;
-    jump StgReturn;
-}
-
-/*- 4 Regs -------------------------------------------------------------------*/
-
-gran_block_4
-{
-    Sp_adj(-4);
-    Sp(3) = R4;
-    Sp(2) = R3;
-    Sp(1) = R2;
-    Sp(0) = R1;
-    SAVE_THREAD_STATE();                                       
-    TSO_what_next(CurrentTSO) = ThreadRunGHC;          
-    R1 = ThreadBlocked;
-    jump StgReturn;
-}
-
-/*- 5 Regs -------------------------------------------------------------------*/
-
-gran_block_5
-{
-    Sp_adj(-5);
-    Sp(4) = R5;
-    Sp(3) = R4;
-    Sp(2) = R3;
-    Sp(1) = R2;
-    Sp(0) = R1;
-    SAVE_THREAD_STATE();                                       
-    TSO_what_next(CurrentTSO) = ThreadRunGHC;          
-    R1 = ThreadBlocked;
-    jump StgReturn;
-}
-
-/*- 6 Regs -------------------------------------------------------------------*/
-
-gran_block_6
-{
-    Sp_adj(-6);
-    Sp(5) = R6;
-    Sp(4) = R5;
-    Sp(3) = R4;
-    Sp(2) = R3;
-    Sp(1) = R2;
-    Sp(0) = R1;
-    SAVE_THREAD_STATE();                                       
-    TSO_what_next(CurrentTSO) = ThreadRunGHC;          
-    R1 = ThreadBlocked;
-    jump StgReturn;
-}
-
-/*- 7 Regs -------------------------------------------------------------------*/
-
-gran_block_7
-{
-    Sp_adj(-7);
-    Sp(6) = R7;
-    Sp(5) = R6;
-    Sp(4) = R5;
-    Sp(3) = R4;
-    Sp(2) = R3;
-    Sp(1) = R2;
-    Sp(0) = R1;
-    SAVE_THREAD_STATE();                                       
-    TSO_what_next(CurrentTSO) = ThreadRunGHC;          
-    R1 = ThreadBlocked;
-    jump StgReturn;
-}
-
-/*- 8 Regs -------------------------------------------------------------------*/
-
-gran_block_8
-{
-    Sp_adj(-8);
-    Sp(7) = R8;
-    Sp(6) = R7;
-    Sp(5) = R6;
-    Sp(4) = R5;
-    Sp(3) = R4;
-    Sp(2) = R3;
-    Sp(1) = R2;
-    Sp(0) = R1;
-    SAVE_THREAD_STATE();                                       
-    TSO_what_next(CurrentTSO) = ThreadRunGHC;          
-    R1 = ThreadBlocked;
-    jump StgReturn;
-}
-
-#endif
-
-#if 0 && defined(PAR)
-
-/*
-  Similar to stg_block_1 (called via StgMacro BLOCK_NP) but separates the
-  saving of the thread state from the actual jump via an StgReturn.
-  We need this separation because we call RTS routines in blocking entry codes
-  before jumping back into the RTS (see parallel/FetchMe.hc).
-*/
-
-par_block_1_no_jump
-{
-    Sp_adj(-1);
-    Sp(0) = R1;
-    SAVE_THREAD_STATE();                                       
-}
-
-par_jump
-{
-    TSO_what_next(CurrentTSO) = ThreadRunGHC;          
-    R1 = ThreadBlocked;
-    jump StgReturn;
-}
-
-#endif
-
-/* -----------------------------------------------------------------------------
-   Heap checks in Primitive case alternatives
-
-   A primitive case alternative is entered with a value either in 
-   R1, FloatReg1 or D1 depending on the return convention.  All the
-   cases are covered below.
-   -------------------------------------------------------------------------- */
-
-/*-- No Registers live ------------------------------------------------------ */
-
-stg_gc_noregs
-{
-    GC_GENERIC
-}
-
-/*-- void return ------------------------------------------------------------ */
-
-INFO_TABLE_RET( stg_gc_void, 0/*framesize*/, 0/*bitmap*/, RET_SMALL)
-{
-    Sp_adj(1);
-    jump %ENTRY_CODE(Sp(0));
-}
-
-/*-- R1 is boxed/unpointed -------------------------------------------------- */
-
-INFO_TABLE_RET( stg_gc_unpt_r1, 1/*framesize*/, 0/*bitmap*/, RET_SMALL)
-{
-    R1 = Sp(1);
-    Sp_adj(2);
-    jump %ENTRY_CODE(Sp(0));
-}
-
-stg_gc_unpt_r1
-{
-    Sp_adj(-2);
-    Sp(1) = R1;
-    Sp(0) = stg_gc_unpt_r1_info;
-    GC_GENERIC
-}
-
-/*-- R1 is unboxed -------------------------------------------------- */
-
-/* the 1 is a bitmap - i.e. 1 non-pointer word on the stack. */
-INFO_TABLE_RET(        stg_gc_unbx_r1, 1/*framesize*/, 1/*bitmap*/, RET_SMALL )
-{
-    R1 = Sp(1);
-    Sp_adj(2);
-    jump %ENTRY_CODE(Sp(0));
-}
-
-stg_gc_unbx_r1
-{
-    Sp_adj(-2);
-    Sp(1) = R1;
-    Sp(0) = stg_gc_unbx_r1_info;
-    GC_GENERIC
-}
-
-/*-- F1 contains a float ------------------------------------------------- */
-
-INFO_TABLE_RET(        stg_gc_f1, 1/*framesize*/, 1/*bitmap*/, RET_SMALL )
-{
-    F1 = F_[Sp+WDS(1)];
-    Sp_adj(2);
-    jump %ENTRY_CODE(Sp(0));
-}
-
-stg_gc_f1
-{
-    Sp_adj(-2);
-    F_[Sp + WDS(1)] = F1;
-    Sp(0) = stg_gc_f1_info;
-    GC_GENERIC
-}
-
-/*-- D1 contains a double ------------------------------------------------- */
-
-/* we support doubles of either 1 or 2 words in size */
-
-#if SIZEOF_DOUBLE == SIZEOF_VOID_P
-#  define DBL_BITMAP 1
-#  define DBL_WORDS  1
-#else
-#  define DBL_BITMAP 3
-#  define DBL_WORDS  2
-#endif 
-
-INFO_TABLE_RET(        stg_gc_d1, DBL_WORDS/*framesize*/, DBL_BITMAP/*bitmap*/, RET_SMALL )
-{
-    D1 = D_[Sp + WDS(1)];
-    Sp = Sp + WDS(1) + SIZEOF_StgDouble;
-    jump %ENTRY_CODE(Sp(0));
-}
-
-stg_gc_d1
-{
-    Sp = Sp - WDS(1) - SIZEOF_StgDouble;
-    D_[Sp + WDS(1)] = D1;
-    Sp(0) = stg_gc_d1_info;
-    GC_GENERIC
-}
-
-
-/*-- L1 contains an int64 ------------------------------------------------- */
-
-/* we support int64s of either 1 or 2 words in size */
-
-#if SIZEOF_VOID_P == 8
-#  define LLI_BITMAP 1
-#  define LLI_WORDS  1
-#else
-#  define LLI_BITMAP 3
-#  define LLI_WORDS  2
-#endif 
-
-INFO_TABLE_RET( stg_gc_l1, LLI_WORDS/*framesize*/, LLI_BITMAP/*bitmap*/, RET_SMALL )
-{
-    L1 = L_[Sp + WDS(1)];
-    Sp_adj(1) + SIZEOF_StgWord64;
-    jump %ENTRY_CODE(Sp(0));
-}
-
-stg_gc_l1
-{
-    Sp_adj(-1) - SIZEOF_StgWord64;
-    L_[Sp + WDS(1)] = L1;
-    Sp(0) = stg_gc_l1_info;
-    GC_GENERIC
-}
-
-/*-- Unboxed tuple return, one pointer (unregisterised build only) ---------- */
-
-INFO_TABLE_RET( stg_ut_1_0_unreg, 1/*size*/, 0/*BITMAP*/, RET_SMALL )
-{
-    Sp_adj(1);
-    // one ptr is on the stack (Sp(0))
-    jump %ENTRY_CODE(Sp(1));
-}
-
-/* -----------------------------------------------------------------------------
-   Generic function entry heap check code.
-
-   At a function entry point, the arguments are as per the calling convention,
-   i.e. some in regs and some on the stack.  There may or may not be 
-   a pointer to the function closure in R1 - if there isn't, then the heap
-   check failure code in the function will arrange to load it.
-
-   The function's argument types are described in its info table, so we
-   can just jump to this bit of generic code to save away all the
-   registers and return to the scheduler.
-
-   This code arranges the stack like this:
-        
-         |        ....         |
-         |        args         |
-        +---------------------+
-         |      f_closure      |
-        +---------------------+
-         |        size         |
-        +---------------------+
-         |   stg_gc_fun_info   |
-        +---------------------+
-
-   The size is the number of words of arguments on the stack, and is cached
-   in the frame in order to simplify stack walking: otherwise the size of
-   this stack frame would have to be calculated by looking at f's info table.
-
-   -------------------------------------------------------------------------- */
-
-__stg_gc_fun
-{
-    W_ size;
-    W_ info;
-    W_ type;
-
-    info = %GET_FUN_INFO(R1);
-
-    // cache the size
-    type = TO_W_(StgFunInfoExtra_fun_type(info));
-    if (type == ARG_GEN) {
-       size = BITMAP_SIZE(StgFunInfoExtra_bitmap(info));
-    } else { 
-       if (type == ARG_GEN_BIG) {
-#ifdef TABLES_NEXT_TO_CODE
-            // bitmap field holds an offset
-            size = StgLargeBitmap_size( StgFunInfoExtra_bitmap(info)
-                                        + %GET_ENTRY(R1) /* ### */ );
-#else
-           size = StgLargeBitmap_size( StgFunInfoExtra_bitmap(info) );
-#endif
-       } else {
-           size = BITMAP_SIZE(W_[stg_arg_bitmaps + WDS(type)]);
-       }
-    }
-    
-#ifdef NO_ARG_REGS
-    // we don't have to save any registers away
-    Sp_adj(-3);
-    Sp(2) = R1;
-    Sp(1) = size;
-    Sp(0) = stg_gc_fun_info;
-    GC_GENERIC
-#else
-    W_ type;
-    type = TO_W_(StgFunInfoExtra_fun_type(info));
-    // cache the size
-    if (type == ARG_GEN || type == ARG_GEN_BIG) {
-        // regs already saved by the heap check code
-        Sp_adj(-3);
-        Sp(2) = R1;
-        Sp(1) = size;
-        Sp(0) = stg_gc_fun_info;
-        // DEBUG_ONLY(foreign "C" debugBelch("stg_fun_gc_gen(ARG_GEN)"););
-        GC_GENERIC
-    } else { 
-       jump W_[stg_stack_save_entries + WDS(type)];
-           // jumps to stg_gc_noregs after saving stuff
-    }
-#endif /* !NO_ARG_REGS */
-}
-
-/* -----------------------------------------------------------------------------
-   Generic Apply (return point)
-
-   The dual to stg_fun_gc_gen (above): this fragment returns to the
-   function, passing arguments in the stack and in registers
-   appropriately.  The stack layout is given above.
-   -------------------------------------------------------------------------- */
-
-INFO_TABLE_RET( stg_gc_fun, 0/*framesize*/, 0/*bitmap*/, RET_FUN )
-{
-    R1 = Sp(2);
-    Sp_adj(3);
-#ifdef NO_ARG_REGS
-    // Minor optimisation: there are no argument registers to load up,
-    // so we can just jump straight to the function's entry point.
-    jump %GET_ENTRY(R1);
-#else
-    W_ info;
-    W_ type;
-    
-    info = %GET_FUN_INFO(R1);
-    type = TO_W_(StgFunInfoExtra_fun_type(info));
-    if (type == ARG_GEN || type == ARG_GEN_BIG) {
-       jump StgFunInfoExtra_slow_apply(info);
-    } else { 
-       if (type == ARG_BCO) {
-           // cover this case just to be on the safe side
-           Sp_adj(-2);
-           Sp(1) = R1;
-           Sp(0) = stg_apply_interp_info;
-           jump stg_yield_to_interpreter;
-       } else {
-           jump W_[stg_ap_stack_entries + WDS(type)];
-       }
-    }
-#endif
-}
-
-/* -----------------------------------------------------------------------------
-   Generic Heap Check Code.
-
-   Called with Liveness mask in R9,  Return address in R10.
-   Stack must be consistent (containing all necessary info pointers
-   to relevant SRTs).
-
-   See StgMacros.h for a description of the RET_DYN stack frame.
-
-   We also define an stg_gen_yield here, because it's very similar.
-   -------------------------------------------------------------------------- */
-
-// For simplicity, we assume that SIZEOF_DOUBLE == 2*SIZEOF_VOID_P
-// on a 64-bit machine, we'll end up wasting a couple of words, but
-// it's not a big deal.
-
-#define RESTORE_EVERYTHING                     \
-    L1   = L_[Sp + WDS(19)];                   \
-    D2   = D_[Sp + WDS(17)];                   \
-    D1   = D_[Sp + WDS(15)];                   \
-    F4   = F_[Sp + WDS(14)];                   \
-    F3   = F_[Sp + WDS(13)];                   \
-    F2   = F_[Sp + WDS(12)];                   \
-    F1   = F_[Sp + WDS(11)];                   \
-    R8 = Sp(10);                               \
-    R7 = Sp(9);                                        \
-    R6 = Sp(8);                                        \
-    R5 = Sp(7);                                        \
-    R4 = Sp(6);                                        \
-    R3 = Sp(5);                                        \
-    R2 = Sp(4);                                        \
-    R1 = Sp(3);                                        \
-    Sp_adj(21);
-
-#define RET_OFFSET (-19)
-
-#define SAVE_EVERYTHING                                \
-    Sp_adj(-21);                               \
-    L_[Sp + WDS(19)] = L1;                     \
-    D_[Sp + WDS(17)] = D2;                     \
-    D_[Sp + WDS(15)] = D1;                     \
-    F_[Sp + WDS(14)] = F4;                     \
-    F_[Sp + WDS(13)] = F3;                     \
-    F_[Sp + WDS(12)] = F2;                     \
-    F_[Sp + WDS(11)] = F1;                     \
-    Sp(10) = R8;                               \
-    Sp(9) = R7;                                        \
-    Sp(8) = R6;                                        \
-    Sp(7) = R5;                                        \
-    Sp(6) = R4;                                        \
-    Sp(5) = R3;                                        \
-    Sp(4) = R2;                                        \
-    Sp(3) = R1;                                        \
-    Sp(2) = R10;    /* return address */       \
-    Sp(1) = R9;     /* liveness mask  */       \
-    Sp(0) = stg_gc_gen_info;
-
-INFO_TABLE_RET( stg_gc_gen, 0/*framesize*/, 0/*bitmap*/, RET_DYN )
-/* bitmap in the above info table is unused, the real one is on the stack. */
-{
-    RESTORE_EVERYTHING;
-    jump Sp(RET_OFFSET); /* No %ENTRY_CODE( - this is an actual code ptr */
-}
-
-stg_gc_gen
-{
-    SAVE_EVERYTHING;
-    GC_GENERIC
-}        
-
-// A heap check at an unboxed tuple return point.  The return address
-// is on the stack, and we can find it by using the offsets given
-// to us in the liveness mask.
-stg_gc_ut
-{
-    R10 = %ENTRY_CODE(Sp(RET_DYN_NONPTRS(R9) + RET_DYN_PTRS(R9)));
-    SAVE_EVERYTHING;
-    GC_GENERIC
-}
-
-/*
- * stg_gen_hp is used by MAYBE_GC, where we can't use GC_GENERIC
- * because we've just failed doYouWantToGC(), not a standard heap
- * check.  GC_GENERIC would end up returning StackOverflow.
- */
-stg_gc_gen_hp
-{
-    SAVE_EVERYTHING;
-    HP_GENERIC
-}        
-
-/* -----------------------------------------------------------------------------
-   Yields
-   -------------------------------------------------------------------------- */
-
-stg_gen_yield
-{
-    SAVE_EVERYTHING;
-    YIELD_GENERIC
-}
-
-stg_yield_noregs
-{
-    YIELD_GENERIC;
-}
-
-/* -----------------------------------------------------------------------------
-   Yielding to the interpreter... top of stack says what to do next.
-   -------------------------------------------------------------------------- */
-
-stg_yield_to_interpreter
-{
-    YIELD_TO_INTERPRETER;
-}
-
-/* -----------------------------------------------------------------------------
-   Blocks
-   -------------------------------------------------------------------------- */
-
-stg_gen_block
-{
-    SAVE_EVERYTHING;
-    BLOCK_GENERIC;
-}
-
-stg_block_noregs
-{
-    BLOCK_GENERIC;
-}
-
-stg_block_1
-{
-    Sp_adj(-2);
-    Sp(1) = R1;
-    Sp(0) = stg_enter_info;
-    BLOCK_GENERIC;
-}
-
-/* -----------------------------------------------------------------------------
- * takeMVar/putMVar-specific blocks
- *
- * Stack layout for a thread blocked in takeMVar:
- *      
- *       ret. addr
- *       ptr to MVar   (R1)
- *       stg_block_takemvar_info
- *
- * Stack layout for a thread blocked in putMVar:
- *      
- *       ret. addr
- *       ptr to Value  (R2)
- *       ptr to MVar   (R1)
- *       stg_block_putmvar_info
- *
- * See PrimOps.hc for a description of the workings of take/putMVar.
- * 
- * -------------------------------------------------------------------------- */
-
-INFO_TABLE_RET( stg_block_takemvar, 1/*framesize*/, 0/*bitmap*/, RET_SMALL )
-{
-    R1 = Sp(1);
-    Sp_adj(2);
-    jump takeMVarzh_fast;
-}
-
-// code fragment executed just before we return to the scheduler
-stg_block_takemvar_finally
-{
-#ifdef THREADED_RTS
-    foreign "C" unlockClosure(R3 "ptr", stg_EMPTY_MVAR_info);
-#endif
-    jump StgReturn;
-}
-
-stg_block_takemvar
-{
-    Sp_adj(-2);
-    Sp(1) = R1;
-    Sp(0) = stg_block_takemvar_info;
-    R3 = R1;
-    BLOCK_BUT_FIRST(stg_block_takemvar_finally);
-}
-
-INFO_TABLE_RET( stg_block_putmvar, 2/*framesize*/, 0/*bitmap*/, RET_SMALL )
-{
-    R2 = Sp(2);
-    R1 = Sp(1);
-    Sp_adj(3);
-    jump putMVarzh_fast;
-}
-
-// code fragment executed just before we return to the scheduler
-stg_block_putmvar_finally
-{
-#ifdef THREADED_RTS
-    foreign "C" unlockClosure(R3 "ptr", stg_FULL_MVAR_info);
-#endif
-    jump StgReturn;
-}
-
-stg_block_putmvar
-{
-    Sp_adj(-3);
-    Sp(2) = R2;
-    Sp(1) = R1;
-    Sp(0) = stg_block_putmvar_info;
-    R3 = R1;
-    BLOCK_BUT_FIRST(stg_block_putmvar_finally);
-}
-
-// code fragment executed just before we return to the scheduler
-stg_block_blackhole_finally
-{
-#if defined(THREADED_RTS)
-    // The last thing we do is release sched_lock, which is
-    // preventing other threads from accessing blackhole_queue and
-    // picking up this thread before we are finished with it.
-    foreign "C" RELEASE_LOCK(sched_mutex "ptr");
-#endif
-    jump StgReturn;
-}
-
-stg_block_blackhole
-{
-    Sp_adj(-2);
-    Sp(1) = R1;
-    Sp(0) = stg_enter_info;
-    BLOCK_BUT_FIRST(stg_block_blackhole_finally);
-}
-
-#ifdef mingw32_HOST_OS
-INFO_TABLE_RET( stg_block_async, 0/*framesize*/, 0/*bitmap*/, RET_SMALL )
-{
-    W_ ares;
-    W_ len, errC;
-
-    ares = StgTSO_block_info(CurrentTSO);
-    len = StgAsyncIOResult_len(ares);
-    errC = StgAsyncIOResult_errCode(ares);
-    StgTSO_block_info(CurrentTSO) = NULL;
-    foreign "C" free(ares "ptr");
-    R1 = len;
-    Sp(0) = errC;
-    jump %ENTRY_CODE(Sp(1));
-}
-
-stg_block_async
-{
-    Sp_adj(-1);
-    Sp(0) = stg_block_async_info;
-    BLOCK_GENERIC;
-}
-
-/* Used by threadDelay implementation; it would be desirable to get rid of
- * this free()'ing void return continuation.
- */
-INFO_TABLE_RET( stg_block_async_void, 0/*framesize*/, 0/*bitmap*/, RET_SMALL )
-{
-    W_ ares;
-
-    ares = StgTSO_block_info(CurrentTSO);
-    StgTSO_block_info(CurrentTSO) = NULL;
-    foreign "C" free(ares "ptr");
-    Sp_adj(1);
-    jump %ENTRY_CODE(Sp(0));
-}
-
-stg_block_async_void
-{
-    Sp_adj(-1);
-    Sp(0) = stg_block_async_void_info;
-    BLOCK_GENERIC;
-}
-
-#endif
-
-/* -----------------------------------------------------------------------------
-   STM-specific waiting
-   -------------------------------------------------------------------------- */
-
-stg_block_stmwait_finally
-{
-    foreign "C" stmWaitUnlock(MyCapability() "ptr", R3 "ptr");
-    jump StgReturn;
-}
-
-stg_block_stmwait
-{
-    BLOCK_BUT_FIRST(stg_block_stmwait_finally);
-}