1 /* -----------------------------------------------------------------------------
2 * $Id: StgMacros.h,v 1.7 1999/03/02 19:44:18 sof 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 const StgInfoTable
56 #define EDI_ extern DLLIMPORT const StgInfoTable
57 #define II_ extern const StgInfoTable
58 #define EC_ extern StgClosure
59 #define EDC_ extern DLLIMPORT StgClosure
60 #define IC_ extern StgClosure
62 /* -----------------------------------------------------------------------------
65 For a block of non-pointer words on the stack, we precede the
66 block with a small-integer tag giving the number of non-pointer
68 -------------------------------------------------------------------------- */
71 #define ARGTAG_MAX 16 /* probably arbitrary */
72 #define ARG_TAG(n) (n)
73 #define ARG_SIZE(n) stgCast(StgWord,n)
77 INT_TAG = sizeofW(StgInt),
78 INT64_TAG = sizeofW(StgInt64),
79 WORD_TAG = sizeofW(StgWord),
80 ADDR_TAG = sizeofW(StgAddr),
81 CHAR_TAG = sizeofW(StgChar),
82 FLOAT_TAG = sizeofW(StgFloat),
83 DOUBLE_TAG = sizeofW(StgDouble),
84 STABLE_TAG = sizeofW(StgWord),
87 #else /* DEBUG_EXTRA */
100 ARGTAG_MAX = DOUBLE_TAG
103 /* putting this in a .h file generates many copies - but its only a
106 static StgWord stg_arg_size[] = {
108 [INT_TAG ] = sizeofW(StgInt),
109 [INT64_TAG ] = sizeofW(StgInt64),
110 [WORD_TAG ] = sizeofW(StgWord),
111 [ADDR_TAG ] = sizeofW(StgAddr),
112 [CHAR_TAG ] = sizeofW(StgChar),
113 [FLOAT_TAG ] = sizeofW(StgFloat),
114 [DOUBLE_TAG] = sizeofW(StgDouble),
115 [STABLE_TAG] = sizeofW(StgWord)
118 #define ARG_SIZE(tag) stg_arg_size[stgCast(StgWord,tag)]
120 #endif /* DEBUG_EXTRA */
122 static inline int IS_ARG_TAG( StgWord p );
123 static inline int IS_ARG_TAG( StgWord p ) { return p <= ARGTAG_MAX; }
125 /* -----------------------------------------------------------------------------
128 If (Sp + <n_args>) > Su { JMP_(stg_update_PAP); }
130 Sp points to the topmost used word on the stack, and Su points to
131 the most recently pushed update frame.
133 Remember that <n_args> must include any tagging of unboxed values.
135 ARGS_CHK_LOAD_NODE is for top-level functions, whose entry
136 convention doesn't require that Node is loaded with a pointer to
137 the closure. Thus we must load node before calling stg_updatePAP if
138 the argument check fails.
139 -------------------------------------------------------------------------- */
141 #define ARGS_CHK(n) \
142 if ((P_)(Sp + (n)) > (P_)Su) { \
143 JMP_(stg_update_PAP); \
146 #define ARGS_CHK_LOAD_NODE(n,closure) \
147 if ((P_)(Sp + (n)) > (P_)Su) { \
148 R1.p = (P_)closure; \
149 JMP_(stg_update_PAP); \
152 /* -----------------------------------------------------------------------------
155 When failing a check, we save a return address on the stack and
156 jump to a pre-compiled code fragment that saves the live registers
157 and returns to the scheduler.
159 The return address in most cases will be the beginning of the basic
160 block in which the check resides, since we need to perform the check
161 again on re-entry because someone else might have stolen the resource
163 ------------------------------------------------------------------------- */
165 #define STK_CHK(headroom,ret,r,layout,tag_assts) \
166 if (Sp - headroom < SpLim) { \
167 EXTFUN_RTS(stg_chk_##layout); \
170 JMP_(stg_chk_##layout); \
173 #define HP_CHK(headroom,ret,r,layout,tag_assts) \
174 if ((Hp += headroom) > HpLim) { \
175 EXTFUN_RTS(stg_chk_##layout); \
178 JMP_(stg_chk_##layout); \
180 TICK_ALLOC_HEAP(headroom);
182 #define HP_STK_CHK(stk_headroom,hp_headroom,ret,r,layout,tag_assts) \
183 if (Sp - stk_headroom < SpLim || (Hp += hp_headroom) > HpLim) { \
184 EXTFUN_RTS(stg_chk_##layout); \
187 JMP_(stg_chk_##layout); \
189 TICK_ALLOC_HEAP(hp_headroom);
191 /* -----------------------------------------------------------------------------
192 A Heap Check in a case alternative are much simpler: everything is
193 on the stack and covered by a liveness mask already, and there is
194 even a return address with an SRT info table there as well.
196 Just push R1 and return to the scheduler saying 'EnterGHC'
198 {STK,HP,HP_STK}_CHK_NP are the various checking macros for
199 bog-standard case alternatives, thunks, and non-top-level
200 functions. In all these cases, node points to a closure that we
201 can just enter to restart the heap check (the NP stands for 'node points').
203 HpLim points to the LAST WORD of valid allocation space.
204 -------------------------------------------------------------------------- */
206 #define STK_CHK_NP(headroom,ptrs,tag_assts) \
207 if ((Sp - (headroom)) < SpLim) { \
208 EXTFUN_RTS(stg_gc_enter_##ptrs); \
210 JMP_(stg_gc_enter_##ptrs); \
213 #define HP_CHK_NP(headroom,ptrs,tag_assts) \
214 if ((Hp += (headroom)) > HpLim) { \
215 EXTFUN_RTS(stg_gc_enter_##ptrs); \
217 JMP_(stg_gc_enter_##ptrs); \
219 TICK_ALLOC_HEAP(headroom);
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); \
227 TICK_ALLOC_HEAP(headroom);
229 #define HP_STK_CHK_NP(stk_headroom, hp_headroom, ptrs, tag_assts) \
230 if ((Sp - (stk_headroom)) < SpLim || (Hp += (hp_headroom)) > HpLim) { \
231 EXTFUN_RTS(stg_gc_enter_##ptrs); \
233 JMP_(stg_gc_enter_##ptrs); \
235 TICK_ALLOC_HEAP(hp_headroom);
237 /* Heap checks for branches of a primitive case / unboxed tuple return */
239 #define GEN_HP_CHK_ALT(headroom,lbl,tag_assts) \
240 if ((Hp += (headroom)) > HpLim) { \
245 TICK_ALLOC_HEAP(headroom);
247 #define HP_CHK_NOREGS(headroom,tag_assts) \
248 GEN_HP_CHK_ALT(headroom,stg_gc_noregs,tag_assts);
249 #define HP_CHK_UNPT_R1(headroom,tag_assts) \
250 GEN_HP_CHK_ALT(headroom,stg_gc_unpt_r1,tag_assts);
251 #define HP_CHK_UNBX_R1(headroom,tag_assts) \
252 GEN_HP_CHK_ALT(headroom,stg_gc_unbx_r1,tag_assts);
253 #define HP_CHK_F1(headroom,tag_assts) \
254 GEN_HP_CHK_ALT(headroom,stg_gc_f1,tag_assts);
255 #define HP_CHK_D1(headroom,tag_assts) \
256 GEN_HP_CHK_ALT(headroom,stg_gc_d1,tag_assts);
258 #define HP_CHK_L1(headroom,tag_assts) \
259 GEN_HP_CHK_ALT(headroom,stg_gc_d1,tag_assts);
261 #define HP_CHK_UT_ALT(headroom, ptrs, nptrs, r, ret, tag_assts) \
262 GEN_HP_CHK_ALT(headroom, stg_gc_ut_##ptrs##_##nptrs, \
263 tag_assts r = (P_)ret;)
265 /* -----------------------------------------------------------------------------
268 These are slow, but have the advantage of being usable in a variety
271 The one restriction is that any relevant SRTs must already be pointed
272 to from the stack. The return address doesn't need to have an info
273 table attached: hence it can be any old code pointer.
275 The liveness mask is a logical 'XOR' of NO_PTRS and zero or more
276 Rn_PTR constants defined below. All registers will be saved, but
277 the garbage collector needs to know which ones contain pointers.
279 Good places to use a generic heap check:
281 - case alternatives (the return address with an SRT is already
284 - primitives (no SRT required).
286 The stack layout is like this:
295 so the liveness mask depends on the size of an StgDouble (FltRegs
296 and R<n> are guaranteed to be 1 word in size).
298 -------------------------------------------------------------------------- */
300 /* VERY MAGIC CONSTANTS!
301 * must agree with code in HeapStackCheck.c, stg_gen_chk
304 #if SIZEOF_DOUBLE > SIZEOF_VOID_P
305 #define ALL_NON_PTRS 0xffff
306 #else /* SIZEOF_DOUBLE == SIZEOF_VOID_P */
307 #define ALL_NON_PTRS 0x3fff
310 #define LIVENESS_MASK(ptr_regs) (ALL_NON_PTRS ^ (ptr_regs))
322 #define HP_CHK_GEN(headroom,liveness,reentry,tag_assts) \
323 if ((Hp += (headroom)) > HpLim ) { \
326 R9.w = (W_)LIVENESS_MASK(liveness); \
327 R10.w = (W_)reentry; \
330 TICK_ALLOC_HEAP(headroom);
332 #define STK_CHK_GEN(headroom,liveness,reentry,tag_assts) \
333 if ((Sp - (headroom)) < SpLim) { \
336 R9.w = (W_)LIVENESS_MASK(liveness); \
337 R10.w = (W_)reentry; \
341 #define MAYBE_GC(liveness,reentry) \
342 if (doYouWantToGC()) { \
344 R9.w = (W_)LIVENESS_MASK(liveness); \
345 R10.w = (W_)reentry; \
349 /* -----------------------------------------------------------------------------
350 Voluntary Yields/Blocks
352 We only have a generic version of this at the moment - if it turns
353 out to be slowing us down we can make specialised ones.
354 -------------------------------------------------------------------------- */
359 #define YIELD(liveness,reentry) \
361 R9.w = (W_)LIVENESS_MASK(liveness); \
362 R10.w = (W_)reentry; \
363 JMP_(stg_gen_yield); \
366 #define BLOCK(liveness,reentry) \
368 R9.w = (W_)LIVENESS_MASK(liveness); \
369 R10.w = (W_)reentry; \
370 JMP_(stg_gen_block); \
373 #define BLOCK_NP(ptrs) \
375 EF_(stg_block_##ptrs); \
376 JMP_(stg_block_##ptrs); \
379 /* -----------------------------------------------------------------------------
380 CCall_GC needs to push a dummy stack frame containing the contents
381 of volatile registers and variables.
383 We use a RET_DYN frame the same as for a dynamic heap check.
384 ------------------------------------------------------------------------- */
387 EI_(stg_gen_chk_info);
389 EDI_(stg_gen_chk_info);
391 /* -----------------------------------------------------------------------------
394 RETVEC(p,t) where 'p' is a pointer to the info table for a
395 vectored return address, returns the address of the return code for
398 Return vectors are placed in *reverse order* immediately before the info
399 table for the return address. Hence the formula for computing the
400 actual return address is (addr - sizeof(InfoTable) - tag - 1).
401 The extra subtraction of one word is because tags start at zero.
402 -------------------------------------------------------------------------- */
404 #ifdef USE_MINIINTERPRETER
405 #define RET_VEC(p,t) ((*(stgCast(StgInfoTable*,p)->vector))[t])
407 #define RET_VEC(p,t) (*((P_)(p) - sizeofW(StgInfoTable) - t - 1))
410 /* -----------------------------------------------------------------------------
412 -------------------------------------------------------------------------- */
414 /* set the tag register (if we have one) */
415 #define SET_TAG(t) /* nothing */
417 /* don't do eager blackholing for now */
418 #define UPD_BH_UPDATABLE(thunk) /* nothing */
419 #define UPD_BH_SINGLE_ENTRY(thunk) /* nothing */
421 /* -----------------------------------------------------------------------------
422 Moving Floats and Doubles
424 ASSIGN_FLT is for assigning a float to memory (usually the
425 stack/heap). The memory address is guaranteed to be
426 StgWord aligned (currently == sizeof(long)).
428 PK_FLT is for pulling a float out of memory. The memory is
429 guaranteed to be StgWord aligned.
430 -------------------------------------------------------------------------- */
432 static inline void ASSIGN_FLT (W_ [], StgFloat);
433 static inline StgFloat PK_FLT (W_ []);
435 #if ALIGNMENT_FLOAT <= ALIGNMENT_LONG
437 static inline void ASSIGN_FLT(W_ p_dest[], StgFloat src) { *(StgFloat *)p_dest = src; }
438 static inline StgFloat PK_FLT (W_ p_src[]) { return *(StgFloat *)p_src; }
440 #else /* ALIGNMENT_FLOAT > ALIGNMENT_UNSIGNED_INT */
442 static inline void ASSIGN_FLT(W_ p_dest[], StgFloat src)
449 static inline StgFloat PK_FLT(W_ p_src[])
456 #endif /* ALIGNMENT_FLOAT > ALIGNMENT_LONG */
458 #if ALIGNMENT_DOUBLE <= ALIGNMENT_LONG
460 static inline void ASSIGN_DBL (W_ [], StgDouble);
461 static inline StgDouble PK_DBL (W_ []);
463 static inline void ASSIGN_DBL(W_ p_dest[], StgDouble src) { *(StgDouble *)p_dest = src; }
464 static inline StgDouble PK_DBL (W_ p_src[]) { return *(StgDouble *)p_src; }
466 #else /* ALIGNMENT_DOUBLE > ALIGNMENT_LONG */
468 /* Sparc uses two floating point registers to hold a double. We can
469 * write ASSIGN_DBL and PK_DBL by directly accessing the registers
470 * independently - unfortunately this code isn't writable in C, we
471 * have to use inline assembler.
473 #if sparc_TARGET_ARCH
475 #define ASSIGN_DBL(dst,src) \
476 __asm__("st %2,%0\n\tst %R2,%1" : "=m" (((P_)(dst))[0]), \
477 "=m" (((P_)(dst))[1]) : "f" (src));
479 #define PK_DBL(src) \
480 ( { register double d; \
481 __asm__("ld %1,%0\n\tld %2,%R0" : "=f" (d) : \
482 "m" (((P_)(src))[0]), "m" (((P_)(src))[1])); d; \
485 #else /* ! sparc_TARGET_ARCH */
487 static inline void ASSIGN_DBL (W_ [], StgDouble);
488 static inline StgDouble PK_DBL (W_ []);
500 static inline void ASSIGN_DBL(W_ p_dest[], StgDouble src)
504 p_dest[0] = y.du.dhi;
505 p_dest[1] = y.du.dlo;
508 /* GCC also works with this version, but it generates
509 the same code as the previous one, and is not ANSI
511 #define ASSIGN_DBL( p_dest, src ) \
512 *p_dest = ((double_thing) src).du.dhi; \
513 *(p_dest+1) = ((double_thing) src).du.dlo \
516 static inline StgDouble PK_DBL(W_ p_src[])
524 #endif /* ! sparc_TARGET_ARCH */
526 #endif /* ALIGNMENT_DOUBLE > ALIGNMENT_UNSIGNED_INT */
528 #ifdef SUPPORT_LONG_LONGS
533 } unpacked_double_word;
537 unpacked_double_word iu;
542 unpacked_double_word wu;
545 static inline void ASSIGN_Word64(W_ p_dest[], StgWord64 src)
549 p_dest[0] = y.wu.dhi;
550 p_dest[1] = y.wu.dlo;
553 static inline StgWord64 PK_Word64(W_ p_src[])
561 static inline void ASSIGN_Int64(W_ p_dest[], StgInt64 src)
565 p_dest[0] = y.iu.dhi;
566 p_dest[1] = y.iu.dlo;
569 static inline StgInt64 PK_Int64(W_ p_src[])
578 /* -----------------------------------------------------------------------------
580 -------------------------------------------------------------------------- */
582 extern DLL_IMPORT_DATA const StgPolyInfoTable catch_frame_info;
584 /* -----------------------------------------------------------------------------
587 A seq frame is very like an update frame, except that it doesn't do
589 -------------------------------------------------------------------------- */
591 extern DLL_IMPORT_DATA const StgPolyInfoTable seq_frame_info;
593 #define PUSH_SEQ_FRAME(sp) \
595 StgSeqFrame *__frame; \
596 TICK_SEQF_PUSHED(); \
597 __frame = (StgSeqFrame *)(sp); \
598 SET_HDR_(__frame,&seq_frame_info,CCCS); \
599 __frame->link = Su; \
600 Su = (StgUpdateFrame *)__frame; \
603 /* -----------------------------------------------------------------------------
605 -------------------------------------------------------------------------- */
607 #if defined(USE_SPLIT_MARKERS)
608 #define __STG_SPLIT_MARKER(n) FN_(__stg_split_marker##n) { }
610 #define __STG_SPLIT_MARKER(n) /* nothing */
613 /* -----------------------------------------------------------------------------
614 Closure and Info Macros with casting.
616 We don't want to mess around with casts in the generated C code, so
617 we use these casting versions of the closure/info tables macros.
618 -------------------------------------------------------------------------- */
620 #define SET_HDR_(c,info,ccs) \
621 SET_HDR((StgClosure *)(c),(StgInfoTable *)(info),ccs)
623 /* -----------------------------------------------------------------------------
624 Saving context for exit from the STG world, and loading up context
625 on entry to STG code.
627 We save all the STG registers (that is, the ones that are mapped to
628 machine registers) in their places in the TSO.
630 The stack registers go into the current stack object, and the heap
631 registers are saved in global locations.
632 -------------------------------------------------------------------------- */
634 static __inline__ void
635 SaveThreadState(void)
637 /* Don't need to save REG_Base, it won't have changed. */
641 CurrentTSO->splim = SpLim;
644 #if defined(PROFILING)
645 CurrentTSO->prof.CCCS = CCCS;
649 static __inline__ void
650 LoadThreadState (void)
653 BaseReg = (StgRegTable*)&MainRegTable;
658 SpLim = CurrentTSO->splim;
659 OpenNursery(Hp,HpLim);
661 # if defined(PROFILING)
662 CCCS = CurrentTSO->prof.CCCS;
666 #endif /* STGMACROS_H */