/* -----------------------------------------------------------------------------
- * $Id: StgStartup.hc,v 1.21 2003/05/14 09:14:00 simonmar Exp $
*
- * (c) The GHC Team, 1998-2002
+ * (c) The GHC Team, 1998-2004
*
* Code for starting, stopping and restarting threads.
*
+ * 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 "Stg.h"
-#include "Rts.h"
-#include "StgRun.h" /* StgReturn */
-#include "StgStartup.h"
+#include "Cmm.h"
/*
* This module contains the two entry points and the final exit point
*/
#define CHECK_SENSIBLE_REGS() \
- ASSERT(Hp != (P_)0); \
- ASSERT(Sp != (P_)0); \
- ASSERT(SpLim != (P_)0); \
- ASSERT(HpLim != (P_)0); \
+ ASSERT(Hp != 0); \
+ ASSERT(Sp != 0); \
+ ASSERT(SpLim != 0); \
+ ASSERT(HpLim != 0); \
ASSERT(SpLim - RESERVED_STACK_WORDS <= Sp); \
ASSERT(HpLim >= Hp);
slot 0).
-------------------------------------------------------------------------- */
-EXTFUN(stg_stop_thread_ret);
-
#if defined(PROFILING)
#define STOP_THREAD_BITMAP 3
#define STOP_THREAD_WORDS 2
#define STOP_THREAD_WORDS 0
#endif
-/* VEC_POLY_INFO expects to see these names - but they should all be the same. */
-#define stg_stop_thread_0_ret stg_stop_thread_ret
-#define stg_stop_thread_1_ret stg_stop_thread_ret
-#define stg_stop_thread_2_ret stg_stop_thread_ret
-#define stg_stop_thread_3_ret stg_stop_thread_ret
-#define stg_stop_thread_4_ret stg_stop_thread_ret
-#define stg_stop_thread_5_ret stg_stop_thread_ret
-#define stg_stop_thread_6_ret stg_stop_thread_ret
-#define stg_stop_thread_7_ret stg_stop_thread_ret
-
-VEC_POLY_INFO_TABLE( stg_stop_thread,
- MK_SMALL_BITMAP(STOP_THREAD_WORDS, STOP_THREAD_BITMAP),
- 0,0,0,STOP_FRAME,,EF_);
-
-STGFUN(stg_stop_thread_ret)
+/* A polymorhpic return address, where all the vector slots point to the
+ direct entry point. */
+INFO_TABLE_RET( stg_stop_thread, STOP_THREAD_WORDS, STOP_THREAD_BITMAP,
+ STOP_FRAME,
+ RET_LBL(stg_stop_thread),
+ RET_LBL(stg_stop_thread),
+ RET_LBL(stg_stop_thread),
+ RET_LBL(stg_stop_thread),
+ RET_LBL(stg_stop_thread),
+ RET_LBL(stg_stop_thread),
+ RET_LBL(stg_stop_thread),
+ RET_LBL(stg_stop_thread) )
{
- FB_
- //
- // The final exit.
- //
- // The top-top-level closures (e.g., "main") are of type "IO a".
- // When entered, they perform an IO action and return an 'a' in R1.
- //
- // We save R1 on top of the stack where the scheduler can find it,
- // tidy up the registers and return to the scheduler.
- //
- // We Leave the stack looking like this:
- //
- // +----------------+
- // | -------------------> return value
- // +----------------+
- // | stg_enter_info |
- // +----------------+
- //
- // The stg_enter_info is just a dummy info table so that the
- // garbage collector can understand the stack (there must always
- // be an info table on top of the stack).
- //
-
- Sp += sizeofW(StgStopFrame) - 2;
- Sp[1] = R1.w;
- Sp[0] = (W_)&stg_enter_info;
-
- CurrentTSO->what_next = ThreadComplete;
-
- SaveThreadState(); // inline!
-
- // R1 contains the return value of the thread
- R1.i = ThreadFinished;
-
- JMP_(StgReturn);
- FE_
+ /*
+ The final exit.
+
+ The top-top-level closures (e.g., "main") are of type "IO a".
+ When entered, they perform an IO action and return an 'a' in R1.
+
+ We save R1 on top of the stack where the scheduler can find it,
+ tidy up the registers and return to the scheduler.
+
+ We Leave the stack looking like this:
+
+ +----------------+
+ | -------------------> return value
+ +----------------+
+ | stg_enter_info |
+ +----------------+
+
+ The stg_enter_info is just a dummy info table so that the
+ garbage collector can understand the stack (there must always
+ be an info table on top of the stack).
+ */
+
+ Sp = Sp + SIZEOF_StgStopFrame - WDS(2);
+ Sp(1) = R1;
+ Sp(0) = stg_enter_info;
+
+ StgTSO_what_next(CurrentTSO) = ThreadComplete::I16;
+
+ SAVE_THREAD_STATE();
+
+ /* R1 contains the return value of the thread */
+ R1 = ThreadFinished;
+
+ jump StgReturn;
}
/* -----------------------------------------------------------------------------
from C land.
-------------------------------------------------------------------------- */
-STGFUN(stg_returnToStackTop)
+stg_returnToStackTop
{
- FB_
- LoadThreadState();
+ LOAD_THREAD_STATE();
CHECK_SENSIBLE_REGS();
- JMP_(ENTRY_CODE(Sp[0]));
- FE_
+ jump %ENTRY_CODE(Sp(0));
}
/* -----------------------------------------------------------------------------
results that comes back.
------------------------------------------------------------------------- */
-INFO_TABLE_RET( stg_forceIO_info,stg_forceIO_ret,
- MK_SMALL_BITMAP(0/*size*/, 0/*BITMAP*/),
- 0/*SRT*/, 0/*SRT_OFF*/, 0/*SRT_BITMAP*/,
- RET_SMALL,, EF_, 0, 0);
+INFO_TABLE_RET( stg_forceIO, 0/*size*/, 0/*bitmap*/, RET_SMALL)
#ifdef REG_R1
-STGFUN(stg_forceIO_ret)
{
- FB_
- Sp++;
+ Sp_adj(1);
ENTER();
- FE_
}
#else
-STGFUN(stg_forceIO_ret)
{
- FB_
- R1.w = Sp[0];
- Sp += 2;
+ R1 = Sp(0);
+ Sp_adj(2);
ENTER();
- FE_
}
#endif
is a register or not.
------------------------------------------------------------------------- */
-INFO_TABLE_RET( stg_noforceIO_info,stg_noforceIO_ret,
- MK_SMALL_BITMAP(0/*size*/, 0/*BITMAP*/),
- 0/*SRT*/, 0/*SRT_OFF*/, 0/*SRT_BITMAP*/,
- RET_SMALL,, EF_, 0, 0);
+INFO_TABLE_RET( stg_noforceIO, 0/*size*/, 0/*bitmap*/, RET_SMALL )
#ifdef REG_R1
-STGFUN(stg_noforceIO_ret)
{
- FB_
- Sp++;
- JMP_(ENTRY_CODE(Sp[0]));
- FE_
+ Sp_adj(1);
+ jump %ENTRY_CODE(Sp(0));
}
#else
-STGFUN(stg_noforceIO_ret)
{
- FB_
- R1.w = Sp[0];
- Sp += 2;
- JMP_(ENTRY_CODE(Sp[0]));
- FE_
+ R1 = Sp(0);
+ Sp_adj(2);
+ jump %ENTRY_CODE(Sp(0));
}
#endif
Special STG entry points for module registration.
-------------------------------------------------------------------------- */
-extern F_ *init_stack;
-
-STGFUN(stg_init_ret)
+stg_init_finish
{
- FB_
- JMP_(StgReturn);
- FE_
+ jump StgReturn;
}
/* On entry to stg_init:
* init_stack[0] = &stg_init_ret;
* init_stack[1] = __stginit_Something;
*/
-STGFUN(stg_init)
+stg_init
{
- FB_
- Sp = BaseReg->rSp;
- JMP_(POP_INIT_STACK());
- FE_
+ W_ next;
+ Sp = W_[MainCapability + OFFSET_Capability_r + OFFSET_StgRegTable_rSp];
+ next = W_[Sp];
+ Sp_adj(1);
+ jump next;
}