1 /* -----------------------------------------------------------------------------
2 * $Id: StgMacros.h,v 1.16 1999/11/05 12:28:05 simonmar Exp $
4 * (c) The GHC Team, 1998-1999
6 * Macros used for writing STG-ish C code.
8 * ---------------------------------------------------------------------------*/
13 /* -----------------------------------------------------------------------------
14 The following macros create function headers.
16 Each basic block is represented by a C function with no arguments.
17 We therefore always begin with either
25 The macros can be used either to define the function itself, or to provide
26 prototypes (by following with a ';').
28 Note: the various I*_ shorthands in the second block below are used to
29 declare forward references to local symbols. These shorthands *have* to
30 use the 'extern' type specifier and not 'static'. The reason for this is
31 that 'static' declares a reference as being a static/local variable,
32 and *not* as a forward reference to a static variable.
34 This might seem obvious, but it had me stumped as to why my info tables
35 were suddenly all filled with 0s.
39 --------------------------------------------------------------------------- */
41 #define STGFUN(f) StgFunPtr f(void)
42 #define EXTFUN(f) extern StgFunPtr f(void)
43 #define EXTFUN_RTS(f) extern DLL_IMPORT_RTS StgFunPtr f(void)
44 #define FN_(f) F_ f(void)
45 #define IFN_(f) static F_ f(void)
46 #define IF_(f) static F_ f(void)
47 #define EF_(f) extern F_ f(void)
48 #define EDF_(f) extern DLLIMPORT F_ f(void)
51 #define EDD_ extern DLLIMPORT
52 #define ED_RO_ extern const
54 #define ID_RO_ extern const
55 #define EI_ extern INFO_TBL_CONST StgInfoTable
56 #define EDI_ extern DLLIMPORT INFO_TBL_CONST StgInfoTable
57 #define II_ extern INFO_TBL_CONST StgInfoTable
58 #define EC_ extern StgClosure
59 #define EDC_ extern DLLIMPORT StgClosure
60 #define IC_ extern StgClosure
61 #define ECP_(x) extern const StgClosure *(x)[]
62 #define EDCP_(x) extern DLLIMPORT StgClosure *(x)[]
63 #define ICP_(x) extern const StgClosure *(x)[]
65 /* -----------------------------------------------------------------------------
68 For a block of non-pointer words on the stack, we precede the
69 block with a small-integer tag giving the number of non-pointer
71 -------------------------------------------------------------------------- */
74 #define ARGTAG_MAX 16 /* probably arbitrary */
75 #define ARG_TAG(n) (n)
76 #define ARG_SIZE(n) stgCast(StgWord,n)
80 INT_TAG = sizeofW(StgInt),
81 INT64_TAG = sizeofW(StgInt64),
82 WORD_TAG = sizeofW(StgWord),
83 ADDR_TAG = sizeofW(StgAddr),
84 CHAR_TAG = sizeofW(StgChar),
85 FLOAT_TAG = sizeofW(StgFloat),
86 DOUBLE_TAG = sizeofW(StgDouble),
87 STABLE_TAG = sizeofW(StgWord),
90 #else /* DEBUG_EXTRA */
103 ARGTAG_MAX = DOUBLE_TAG
106 /* putting this in a .h file generates many copies - but its only a
109 static StgWord stg_arg_size[] = {
111 [INT_TAG ] = sizeofW(StgInt),
112 [INT64_TAG ] = sizeofW(StgInt64),
113 [WORD_TAG ] = sizeofW(StgWord),
114 [ADDR_TAG ] = sizeofW(StgAddr),
115 [CHAR_TAG ] = sizeofW(StgChar),
116 [FLOAT_TAG ] = sizeofW(StgFloat),
117 [DOUBLE_TAG] = sizeofW(StgDouble),
118 [STABLE_TAG] = sizeofW(StgWord)
121 #define ARG_SIZE(tag) stg_arg_size[stgCast(StgWord,tag)]
123 #endif /* DEBUG_EXTRA */
125 static inline int IS_ARG_TAG( StgWord p );
126 static inline int IS_ARG_TAG( StgWord p ) { return p <= ARGTAG_MAX; }
128 /* -----------------------------------------------------------------------------
131 If (Sp + <n_args>) > Su { JMP_(stg_update_PAP); }
133 Sp points to the topmost used word on the stack, and Su points to
134 the most recently pushed update frame.
136 Remember that <n_args> must include any tagging of unboxed values.
138 ARGS_CHK_LOAD_NODE is for top-level functions, whose entry
139 convention doesn't require that Node is loaded with a pointer to
140 the closure. Thus we must load node before calling stg_updatePAP if
141 the argument check fails.
142 -------------------------------------------------------------------------- */
144 #define ARGS_CHK(n) \
145 if ((P_)(Sp + (n)) > (P_)Su) { \
146 JMP_(stg_update_PAP); \
149 #define ARGS_CHK_LOAD_NODE(n,closure) \
150 if ((P_)(Sp + (n)) > (P_)Su) { \
151 R1.p = (P_)closure; \
152 JMP_(stg_update_PAP); \
155 /* -----------------------------------------------------------------------------
158 When failing a check, we save a return address on the stack and
159 jump to a pre-compiled code fragment that saves the live registers
160 and returns to the scheduler.
162 The return address in most cases will be the beginning of the basic
163 block in which the check resides, since we need to perform the check
164 again on re-entry because someone else might have stolen the resource
166 ------------------------------------------------------------------------- */
168 #define STK_CHK(headroom,ret,r,layout,tag_assts) \
169 if (Sp - headroom < SpLim) { \
170 EXTFUN_RTS(stg_chk_##layout); \
173 JMP_(stg_chk_##layout); \
176 #define HP_CHK(headroom,ret,r,layout,tag_assts) \
177 if ((Hp += headroom) > HpLim) { \
178 EXTFUN_RTS(stg_chk_##layout); \
181 JMP_(stg_chk_##layout); \
184 #define HP_STK_CHK(stk_headroom,hp_headroom,ret,r,layout,tag_assts) \
185 if (Sp - stk_headroom < SpLim || (Hp += hp_headroom) > HpLim) { \
186 EXTFUN_RTS(stg_chk_##layout); \
189 JMP_(stg_chk_##layout); \
192 /* -----------------------------------------------------------------------------
193 A Heap Check in a case alternative are much simpler: everything is
194 on the stack and covered by a liveness mask already, and there is
195 even a return address with an SRT info table there as well.
197 Just push R1 and return to the scheduler saying 'EnterGHC'
199 {STK,HP,HP_STK}_CHK_NP are the various checking macros for
200 bog-standard case alternatives, thunks, and non-top-level
201 functions. In all these cases, node points to a closure that we
202 can just enter to restart the heap check (the NP stands for 'node points').
204 HpLim points to the LAST WORD of valid allocation space.
205 -------------------------------------------------------------------------- */
207 #define STK_CHK_NP(headroom,ptrs,tag_assts) \
208 if ((Sp - (headroom)) < SpLim) { \
209 EXTFUN_RTS(stg_gc_enter_##ptrs); \
211 JMP_(stg_gc_enter_##ptrs); \
214 #define HP_CHK_NP(headroom,ptrs,tag_assts) \
215 if ((Hp += (headroom)) > HpLim) { \
216 EXTFUN_RTS(stg_gc_enter_##ptrs); \
218 JMP_(stg_gc_enter_##ptrs); \
221 #define HP_CHK_SEQ_NP(headroom,ptrs,tag_assts) \
222 if ((Hp += (headroom)) > HpLim) { \
223 EXTFUN_RTS(stg_gc_seq_##ptrs); \
225 JMP_(stg_gc_seq_##ptrs); \
228 #define HP_STK_CHK_NP(stk_headroom, hp_headroom, ptrs, tag_assts) \
229 if ((Sp - (stk_headroom)) < SpLim || (Hp += (hp_headroom)) > HpLim) { \
230 EXTFUN_RTS(stg_gc_enter_##ptrs); \
232 JMP_(stg_gc_enter_##ptrs); \
236 /* Heap checks for branches of a primitive case / unboxed tuple return */
238 #define GEN_HP_CHK_ALT(headroom,lbl,tag_assts) \
239 if ((Hp += (headroom)) > HpLim) { \
245 #define HP_CHK_NOREGS(headroom,tag_assts) \
246 GEN_HP_CHK_ALT(headroom,stg_gc_noregs,tag_assts);
247 #define HP_CHK_UNPT_R1(headroom,tag_assts) \
248 GEN_HP_CHK_ALT(headroom,stg_gc_unpt_r1,tag_assts);
249 #define HP_CHK_UNBX_R1(headroom,tag_assts) \
250 GEN_HP_CHK_ALT(headroom,stg_gc_unbx_r1,tag_assts);
251 #define HP_CHK_F1(headroom,tag_assts) \
252 GEN_HP_CHK_ALT(headroom,stg_gc_f1,tag_assts);
253 #define HP_CHK_D1(headroom,tag_assts) \
254 GEN_HP_CHK_ALT(headroom,stg_gc_d1,tag_assts);
256 #define HP_CHK_L1(headroom,tag_assts) \
257 GEN_HP_CHK_ALT(headroom,stg_gc_d1,tag_assts);
259 #define HP_CHK_UT_ALT(headroom, ptrs, nptrs, r, ret, tag_assts) \
260 GEN_HP_CHK_ALT(headroom, stg_gc_ut_##ptrs##_##nptrs, \
261 tag_assts r = (P_)ret;)
263 /* -----------------------------------------------------------------------------
266 These are slow, but have the advantage of being usable in a variety
269 The one restriction is that any relevant SRTs must already be pointed
270 to from the stack. The return address doesn't need to have an info
271 table attached: hence it can be any old code pointer.
273 The liveness mask is a logical 'XOR' of NO_PTRS and zero or more
274 Rn_PTR constants defined below. All registers will be saved, but
275 the garbage collector needs to know which ones contain pointers.
277 Good places to use a generic heap check:
279 - case alternatives (the return address with an SRT is already
282 - primitives (no SRT required).
284 The stack layout is like this:
293 so the liveness mask depends on the size of an StgDouble (FltRegs
294 and R<n> are guaranteed to be 1 word in size).
296 -------------------------------------------------------------------------- */
298 /* VERY MAGIC CONSTANTS!
299 * must agree with code in HeapStackCheck.c, stg_gen_chk
302 #if SIZEOF_DOUBLE > SIZEOF_VOID_P
303 #define ALL_NON_PTRS 0xffff
304 #else /* SIZEOF_DOUBLE == SIZEOF_VOID_P */
305 #define ALL_NON_PTRS 0x3fff
308 #define LIVENESS_MASK(ptr_regs) (ALL_NON_PTRS ^ (ptr_regs))
320 #define HP_CHK_GEN(headroom,liveness,reentry,tag_assts) \
321 if ((Hp += (headroom)) > HpLim ) { \
324 R9.w = (W_)LIVENESS_MASK(liveness); \
325 R10.w = (W_)reentry; \
329 #define HP_CHK_GEN_TICKY(headroom,liveness,reentry,tag_assts) \
330 HP_CHK_GEN(headroom,liveness,reentry,tag_assts); \
331 TICK_ALLOC_HEAP_NOCTR(headroom)
333 #define STK_CHK_GEN(headroom,liveness,reentry,tag_assts) \
334 if ((Sp - (headroom)) < SpLim) { \
337 R9.w = (W_)LIVENESS_MASK(liveness); \
338 R10.w = (W_)reentry; \
342 #define MAYBE_GC(liveness,reentry) \
343 if (doYouWantToGC()) { \
345 R9.w = (W_)LIVENESS_MASK(liveness); \
346 R10.w = (W_)reentry; \
350 /* -----------------------------------------------------------------------------
351 Voluntary Yields/Blocks
353 We only have a generic version of this at the moment - if it turns
354 out to be slowing us down we can make specialised ones.
355 -------------------------------------------------------------------------- */
360 #define YIELD(liveness,reentry) \
362 R9.w = (W_)LIVENESS_MASK(liveness); \
363 R10.w = (W_)reentry; \
364 JMP_(stg_gen_yield); \
367 #define BLOCK(liveness,reentry) \
369 R9.w = (W_)LIVENESS_MASK(liveness); \
370 R10.w = (W_)reentry; \
371 JMP_(stg_gen_block); \
374 #define BLOCK_NP(ptrs) \
376 EF_(stg_block_##ptrs); \
377 JMP_(stg_block_##ptrs); \
380 /* -----------------------------------------------------------------------------
381 CCall_GC needs to push a dummy stack frame containing the contents
382 of volatile registers and variables.
384 We use a RET_DYN frame the same as for a dynamic heap check.
385 ------------------------------------------------------------------------- */
388 EI_(stg_gen_chk_info);
390 EDI_(stg_gen_chk_info);
392 /* -----------------------------------------------------------------------------
395 RETVEC(p,t) where 'p' is a pointer to the info table for a
396 vectored return address, returns the address of the return code for
399 Return vectors are placed in *reverse order* immediately before the info
400 table for the return address. Hence the formula for computing the
401 actual return address is (addr - sizeof(InfoTable) - tag - 1).
402 The extra subtraction of one word is because tags start at zero.
403 -------------------------------------------------------------------------- */
405 #ifdef TABLES_NEXT_TO_CODE
406 #define RET_VEC(p,t) (*((P_)(p) - sizeofW(StgInfoTable) - t - 1))
408 #define RET_VEC(p,t) (((StgInfoTable *)p)->vector[t])
411 /* -----------------------------------------------------------------------------
413 -------------------------------------------------------------------------- */
416 /* set the tag register (if we have one) */
417 #define SET_TAG(t) /* nothing */
419 #ifdef EAGER_BLACKHOLING
421 # define UPD_BH_UPDATABLE(info) \
422 TICK_UPD_BH_UPDATABLE(); \
424 SET_INFO(R1.cl,&BLACKHOLE_info)
425 # define UPD_BH_SINGLE_ENTRY(info) \
426 TICK_UPD_BH_SINGLE_ENTRY(); \
428 SET_INFO(R1.cl,&BLACKHOLE_info)
430 # define UPD_BH_UPDATABLE(info) \
431 TICK_UPD_BH_UPDATABLE(); \
432 SET_INFO(R1.cl,&BLACKHOLE_info)
433 # define UPD_BH_SINGLE_ENTRY(info) \
434 TICK_UPD_BH_SINGLE_ENTRY(); \
435 SET_INFO(R1.cl,&SE_BLACKHOLE_info)
437 #else /* !EAGER_BLACKHOLING */
438 # define UPD_BH_UPDATABLE(thunk) /* nothing */
439 # define UPD_BH_SINGLE_ENTRY(thunk) /* nothing */
440 #endif /* EAGER_BLACKHOLING */
442 #define UPD_FRAME_UPDATEE(p) (((StgUpdateFrame *)(p))->updatee)
443 #define UPDATE_SU_FROM_UPD_FRAME(p) (Su=((StgUpdateFrame *)(p))->link)
445 /* -----------------------------------------------------------------------------
446 Moving Floats and Doubles
448 ASSIGN_FLT is for assigning a float to memory (usually the
449 stack/heap). The memory address is guaranteed to be
450 StgWord aligned (currently == sizeof(long)).
452 PK_FLT is for pulling a float out of memory. The memory is
453 guaranteed to be StgWord aligned.
454 -------------------------------------------------------------------------- */
456 static inline void ASSIGN_FLT (W_ [], StgFloat);
457 static inline StgFloat PK_FLT (W_ []);
459 #if ALIGNMENT_FLOAT <= ALIGNMENT_LONG
461 static inline void ASSIGN_FLT(W_ p_dest[], StgFloat src) { *(StgFloat *)p_dest = src; }
462 static inline StgFloat PK_FLT (W_ p_src[]) { return *(StgFloat *)p_src; }
464 #else /* ALIGNMENT_FLOAT > ALIGNMENT_UNSIGNED_INT */
466 static inline void ASSIGN_FLT(W_ p_dest[], StgFloat src)
473 static inline StgFloat PK_FLT(W_ p_src[])
480 #endif /* ALIGNMENT_FLOAT > ALIGNMENT_LONG */
482 #if ALIGNMENT_DOUBLE <= ALIGNMENT_LONG
484 static inline void ASSIGN_DBL (W_ [], StgDouble);
485 static inline StgDouble PK_DBL (W_ []);
487 static inline void ASSIGN_DBL(W_ p_dest[], StgDouble src) { *(StgDouble *)p_dest = src; }
488 static inline StgDouble PK_DBL (W_ p_src[]) { return *(StgDouble *)p_src; }
490 #else /* ALIGNMENT_DOUBLE > ALIGNMENT_LONG */
492 /* Sparc uses two floating point registers to hold a double. We can
493 * write ASSIGN_DBL and PK_DBL by directly accessing the registers
494 * independently - unfortunately this code isn't writable in C, we
495 * have to use inline assembler.
497 #if sparc_TARGET_ARCH
499 #define ASSIGN_DBL(dst0,src) \
500 { StgPtr dst = (StgPtr)(dst0); \
501 __asm__("st %2,%0\n\tst %R2,%1" : "=m" (((P_)(dst))[0]), \
502 "=m" (((P_)(dst))[1]) : "f" (src)); \
505 #define PK_DBL(src0) \
506 ( { StgPtr src = (StgPtr)(src0); \
508 __asm__("ld %1,%0\n\tld %2,%R0" : "=f" (d) : \
509 "m" (((P_)(src))[0]), "m" (((P_)(src))[1])); d; \
512 #else /* ! sparc_TARGET_ARCH */
514 static inline void ASSIGN_DBL (W_ [], StgDouble);
515 static inline StgDouble PK_DBL (W_ []);
527 static inline void ASSIGN_DBL(W_ p_dest[], StgDouble src)
531 p_dest[0] = y.du.dhi;
532 p_dest[1] = y.du.dlo;
535 /* GCC also works with this version, but it generates
536 the same code as the previous one, and is not ANSI
538 #define ASSIGN_DBL( p_dest, src ) \
539 *p_dest = ((double_thing) src).du.dhi; \
540 *(p_dest+1) = ((double_thing) src).du.dlo \
543 static inline StgDouble PK_DBL(W_ p_src[])
551 #endif /* ! sparc_TARGET_ARCH */
553 #endif /* ALIGNMENT_DOUBLE > ALIGNMENT_UNSIGNED_INT */
555 #ifdef SUPPORT_LONG_LONGS
560 } unpacked_double_word;
564 unpacked_double_word iu;
569 unpacked_double_word wu;
572 static inline void ASSIGN_Word64(W_ p_dest[], StgWord64 src)
576 p_dest[0] = y.wu.dhi;
577 p_dest[1] = y.wu.dlo;
580 static inline StgWord64 PK_Word64(W_ p_src[])
588 static inline void ASSIGN_Int64(W_ p_dest[], StgInt64 src)
592 p_dest[0] = y.iu.dhi;
593 p_dest[1] = y.iu.dlo;
596 static inline StgInt64 PK_Int64(W_ p_src[])
605 /* -----------------------------------------------------------------------------
607 -------------------------------------------------------------------------- */
609 extern DLL_IMPORT_DATA const StgPolyInfoTable catch_frame_info;
611 /* -----------------------------------------------------------------------------
614 A seq frame is very like an update frame, except that it doesn't do
616 -------------------------------------------------------------------------- */
618 extern DLL_IMPORT_DATA const StgPolyInfoTable seq_frame_info;
620 #define PUSH_SEQ_FRAME(sp) \
622 StgSeqFrame *__frame; \
623 TICK_SEQF_PUSHED(); \
624 __frame = (StgSeqFrame *)(sp); \
625 SET_HDR_(__frame,&seq_frame_info,CCCS); \
626 __frame->link = Su; \
627 Su = (StgUpdateFrame *)__frame; \
630 /* -----------------------------------------------------------------------------
632 -------------------------------------------------------------------------- */
634 #if defined(USE_SPLIT_MARKERS)
635 #define __STG_SPLIT_MARKER(n) FN_(__stg_split_marker##n) { }
637 #define __STG_SPLIT_MARKER(n) /* nothing */
640 /* -----------------------------------------------------------------------------
641 Closure and Info Macros with casting.
643 We don't want to mess around with casts in the generated C code, so
644 we use these casting versions of the closure/info tables macros.
645 -------------------------------------------------------------------------- */
647 #define SET_HDR_(c,info,ccs) \
648 SET_HDR((StgClosure *)(c),(StgInfoTable *)(info),ccs)
650 /* -----------------------------------------------------------------------------
651 Saving context for exit from the STG world, and loading up context
652 on entry to STG code.
654 We save all the STG registers (that is, the ones that are mapped to
655 machine registers) in their places in the TSO.
657 The stack registers go into the current stack object, and the
658 current nursery is updated from the heap pointer.
660 These functions assume that BaseReg is loaded appropriately (if
662 -------------------------------------------------------------------------- */
666 static __inline__ void
667 SaveThreadState(void)
669 /* Don't need to save REG_Base, it won't have changed. */
673 CurrentTSO->splim = SpLim;
676 #ifdef REG_CurrentTSO
677 SAVE_CurrentTSO = CurrentTSO;
679 #ifdef REG_CurrentNursery
680 SAVE_CurrentNursery = CurrentNursery;
682 #if defined(PROFILING)
683 CurrentTSO->prof.CCCS = CCCS;
687 static __inline__ void
688 LoadThreadState (void)
692 SpLim = CurrentTSO->splim;
693 OpenNursery(Hp,HpLim);
695 #ifdef REG_CurrentTSO
696 CurrentTSO = SAVE_CurrentTSO;
698 #ifdef REG_CurrentNursery
699 CurrentNursery = SAVE_CurrentNursery;
701 # if defined(PROFILING)
702 CCCS = CurrentTSO->prof.CCCS;
708 /* -----------------------------------------------------------------------------
709 Support for _ccall_GC_ and _casm_GC.
710 -------------------------------------------------------------------------- */
713 * Suspending/resuming threads for doing external C-calls (_ccall_GC).
714 * These functions are defined in rts/Schedule.c.
716 StgInt suspendThread ( StgRegTable *cap );
717 StgRegTable * resumeThread ( StgInt );
719 #define SUSPEND_THREAD(token) \
721 token = suspendThread(BaseReg);
724 #define RESUME_THREAD(token) \
725 BaseReg = resumeThread(token); \
728 #define RESUME_THREAD(token) \
729 (void)resumeThread(token); \
733 #endif /* STGMACROS_H */