/* -----------------------------------------------------------------------------
- * $Id: StgMacros.h,v 1.2 1998/12/02 13:21:35 simonm Exp $
+ * $Id: StgMacros.h,v 1.9 1999/04/28 12:42:45 sewardj Exp $
+ *
+ * (c) The GHC Team, 1998-1999
*
* Macros used for writing STG-ish C code.
*
The macros can be used either to define the function itself, or to provide
prototypes (by following with a ';').
+
+ Note: the various I*_ shorthands in the second block below are used to
+ declare forward references to local symbols. These shorthands *have* to
+ use the 'extern' type specifier and not 'static'. The reason for this is
+ that 'static' declares a reference as being a static/local variable,
+ and *not* as a forward reference to a static variable.
+
+ This might seem obvious, but it had me stumped as to why my info tables
+ were suddenly all filled with 0s.
+
+ -- sof 1/99
+
--------------------------------------------------------------------------- */
#define STGFUN(f) StgFunPtr f(void)
-#define STATICFUN(f) static StgFunPtr f(void)
#define EXTFUN(f) extern StgFunPtr f(void)
-
+#define EXTFUN_RTS(f) extern DLL_IMPORT_RTS StgFunPtr f(void)
#define FN_(f) F_ f(void)
#define IFN_(f) static F_ f(void)
#define IF_(f) static F_ f(void)
#define EF_(f) extern F_ f(void)
+#define EDF_(f) extern DLLIMPORT F_ f(void)
+
#define ED_ extern
+#define EDD_ extern DLLIMPORT
#define ED_RO_ extern const
#define ID_ extern
#define ID_RO_ extern const
#define EI_ extern const StgInfoTable
+#define EDI_ extern DLLIMPORT const StgInfoTable
#define II_ extern const StgInfoTable
#define EC_ extern StgClosure
+#define EDC_ extern DLLIMPORT StgClosure
#define IC_ extern StgClosure
+#define ECP_(x) extern const StgClosure *(x)[]
+#define EDCP_(x) extern DLLIMPORT StgClosure *(x)[]
+#define ICP_(x) extern const StgClosure *(x)[]
/* -----------------------------------------------------------------------------
Stack Tagging.
/* -----------------------------------------------------------------------------
Argument checks.
- If (Sp + <n_args>) > Su { JMP_(stg_updatePAP); }
+ If (Sp + <n_args>) > Su { JMP_(stg_update_PAP); }
Sp points to the topmost used word on the stack, and Su points to
the most recently pushed update frame.
#define STK_CHK(headroom,ret,r,layout,tag_assts) \
if (Sp - headroom < SpLim) { \
- EXTFUN(stg_chk_##layout); \
+ EXTFUN_RTS(stg_chk_##layout); \
tag_assts \
(r) = (P_)ret; \
JMP_(stg_chk_##layout); \
#define HP_CHK(headroom,ret,r,layout,tag_assts) \
if ((Hp += headroom) > HpLim) { \
- EXTFUN(stg_chk_##layout); \
+ EXTFUN_RTS(stg_chk_##layout); \
tag_assts \
- (r) = (P_)ret; \
+ (r) = (P_)ret; \
JMP_(stg_chk_##layout); \
- }
+ } \
+ TICK_ALLOC_HEAP(headroom);
#define HP_STK_CHK(stk_headroom,hp_headroom,ret,r,layout,tag_assts) \
if (Sp - stk_headroom < SpLim || (Hp += hp_headroom) > HpLim) { \
- EXTFUN(stg_chk_##layout); \
+ EXTFUN_RTS(stg_chk_##layout); \
tag_assts \
- (r) = (P_)ret; \
+ (r) = (P_)ret; \
JMP_(stg_chk_##layout); \
- }
+ } \
+ TICK_ALLOC_HEAP(hp_headroom);
/* -----------------------------------------------------------------------------
A Heap Check in a case alternative are much simpler: everything is
#define STK_CHK_NP(headroom,ptrs,tag_assts) \
if ((Sp - (headroom)) < SpLim) { \
- EXTFUN(stg_gc_enter_##ptrs); \
+ EXTFUN_RTS(stg_gc_enter_##ptrs); \
tag_assts \
JMP_(stg_gc_enter_##ptrs); \
}
#define HP_CHK_NP(headroom,ptrs,tag_assts) \
if ((Hp += (headroom)) > HpLim) { \
- EXTFUN(stg_gc_enter_##ptrs); \
+ EXTFUN_RTS(stg_gc_enter_##ptrs); \
tag_assts \
JMP_(stg_gc_enter_##ptrs); \
- }
+ } \
+ TICK_ALLOC_HEAP(headroom);
#define HP_CHK_SEQ_NP(headroom,ptrs,tag_assts) \
if ((Hp += (headroom)) > HpLim) { \
- EXTFUN(stg_gc_seq_##ptrs); \
+ EXTFUN_RTS(stg_gc_seq_##ptrs); \
tag_assts \
JMP_(stg_gc_seq_##ptrs); \
- }
+ } \
+ TICK_ALLOC_HEAP(headroom);
#define HP_STK_CHK_NP(stk_headroom, hp_headroom, ptrs, tag_assts) \
if ((Sp - (stk_headroom)) < SpLim || (Hp += (hp_headroom)) > HpLim) { \
- EXTFUN(stg_gc_enter_##ptrs); \
+ EXTFUN_RTS(stg_gc_enter_##ptrs); \
tag_assts \
JMP_(stg_gc_enter_##ptrs); \
- }
+ } \
+ TICK_ALLOC_HEAP(hp_headroom);
/* Heap checks for branches of a primitive case / unboxed tuple return */
#define GEN_HP_CHK_ALT(headroom,lbl,tag_assts) \
if ((Hp += (headroom)) > HpLim) { \
- EXTFUN(lbl); \
+ EXTFUN_RTS(lbl); \
tag_assts \
JMP_(lbl); \
- }
+ } \
+ TICK_ALLOC_HEAP(headroom);
#define HP_CHK_NOREGS(headroom,tag_assts) \
GEN_HP_CHK_ALT(headroom,stg_gc_noregs,tag_assts);
#define R7_PTR 1<<6
#define R8_PTR 1<<7
-#define HP_CHK_GEN(headroom,liveness,reentry,tag_assts) \
- if ((Hp += (headroom)) > HpLim ) { \
- EF_(stg_gen_chk); \
- tag_assts \
- R9.w = (W_)LIVENESS_MASK(liveness); \
- R10.w = (W_)reentry; \
- JMP_(stg_gen_chk); \
- }
-
-#define STK_CHK_GEN(headroom,liveness,reentry,tag_assts) \
- if ((Sp - (headroom)) < SpLim) { \
- EF_(stg_gen_chk); \
- tag_assts \
- R9.w = (W_)LIVENESS_MASK(liveness); \
- R10.w = (W_)reentry; \
- JMP_(stg_gen_chk); \
+#define HP_CHK_GEN(headroom,liveness,reentry,tag_assts) \
+ if ((Hp += (headroom)) > HpLim ) { \
+ EF_(stg_gen_chk); \
+ tag_assts \
+ R9.w = (W_)LIVENESS_MASK(liveness); \
+ R10.w = (W_)reentry; \
+ JMP_(stg_gen_chk); \
+ } \
+ TICK_ALLOC_HEAP(headroom);
+
+#define STK_CHK_GEN(headroom,liveness,reentry,tag_assts) \
+ if ((Sp - (headroom)) < SpLim) { \
+ EF_(stg_gen_chk); \
+ tag_assts \
+ R9.w = (W_)LIVENESS_MASK(liveness); \
+ R10.w = (W_)reentry; \
+ JMP_(stg_gen_chk); \
}
-#define MAYBE_GC(liveness,reentry) \
- if (doYouWantToGC()) { \
- EF_(stg_gen_hp); \
- R9.w = (W_)LIVENESS_MASK(liveness); \
- R10.w = (W_)reentry; \
- JMP_(stg_gen_hp); \
+#define MAYBE_GC(liveness,reentry) \
+ if (doYouWantToGC()) { \
+ EF_(stg_gen_hp); \
+ R9.w = (W_)LIVENESS_MASK(liveness); \
+ R10.w = (W_)reentry; \
+ JMP_(stg_gen_hp); \
}
/* -----------------------------------------------------------------------------
out to be slowing us down we can make specialised ones.
-------------------------------------------------------------------------- */
+EF_(stg_gen_yield);
+EF_(stg_gen_block);
+
#define YIELD(liveness,reentry) \
{ \
- EF_(stg_gen_yield); \
R9.w = (W_)LIVENESS_MASK(liveness); \
R10.w = (W_)reentry; \
JMP_(stg_gen_yield); \
#define BLOCK(liveness,reentry) \
{ \
- EF_(stg_gen_block); \
R9.w = (W_)LIVENESS_MASK(liveness); \
R10.w = (W_)reentry; \
JMP_(stg_gen_block); \
#define BLOCK_NP(ptrs) \
{ \
- EF_(stg_bock_##ptrs); \
+ EF_(stg_block_##ptrs); \
JMP_(stg_block_##ptrs); \
}
We use a RET_DYN frame the same as for a dynamic heap check.
------------------------------------------------------------------------- */
+#if COMPILING_RTS
EI_(stg_gen_chk_info);
-
+#else
+EDI_(stg_gen_chk_info);
+#endif
/* -----------------------------------------------------------------------------
Vectored Returns
*/
#if sparc_TARGET_ARCH
-#define ASSIGN_DBL(dst,src) \
+#define ASSIGN_DBL(dst0,src) \
+ { StgPtr dst = (StgPtr)(dst0); \
__asm__("st %2,%0\n\tst %R2,%1" : "=m" (((P_)(dst))[0]), \
- "=m" (((P_)(dst))[1]) : "f" (src));
+ "=m" (((P_)(dst))[1]) : "f" (src)); \
+ }
-#define PK_DBL(src) \
- ( { register double d; \
+#define PK_DBL(src0) \
+ ( { StgPtr src = (StgPtr)(src0); \
+ register double d; \
__asm__("ld %1,%0\n\tld %2,%R0" : "=f" (d) : \
"m" (((P_)(src))[0]), "m" (((P_)(src))[1])); d; \
} )
} int64_thing;
typedef union
- { StgNat64 w;
+ { StgWord64 w;
unpacked_double_word wu;
} word64_thing;
-static inline void ASSIGN_Word64(W_ p_dest[], StgNat64 src)
+static inline void ASSIGN_Word64(W_ p_dest[], StgWord64 src)
{
word64_thing y;
y.w = src;
p_dest[1] = y.wu.dlo;
}
-static inline StgNat64 PK_Word64(W_ p_src[])
+static inline StgWord64 PK_Word64(W_ p_src[])
{
word64_thing y;
y.wu.dhi = p_src[0];
Catch frames
-------------------------------------------------------------------------- */
-extern const StgPolyInfoTable catch_frame_info;
+extern DLL_IMPORT_DATA const StgPolyInfoTable catch_frame_info;
/* -----------------------------------------------------------------------------
Seq frames
an update...
-------------------------------------------------------------------------- */
-extern const StgPolyInfoTable seq_frame_info;
+extern DLL_IMPORT_DATA const StgPolyInfoTable seq_frame_info;
#define PUSH_SEQ_FRAME(sp) \
{ \
LoadThreadState (void)
{
#ifdef REG_Base
- BaseReg = &MainRegTable;
+ BaseReg = (StgRegTable*)&MainRegTable;
#endif
Sp = CurrentTSO->sp;