1 /* -----------------------------------------------------------------------------
2 * $Id: StgMacros.h,v 1.5 1999/02/05 16:02:28 simonm 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 STATICFUN(f) static StgFunPtr f(void)
43 #define EXTFUN(f) extern 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)
50 #define ED_RO_ extern const
52 #define ID_RO_ extern const
53 #define EI_ extern const StgInfoTable
54 #define II_ extern const StgInfoTable
55 #define EC_ extern StgClosure
56 #define IC_ extern StgClosure
58 /* -----------------------------------------------------------------------------
61 For a block of non-pointer words on the stack, we precede the
62 block with a small-integer tag giving the number of non-pointer
64 -------------------------------------------------------------------------- */
67 #define ARGTAG_MAX 16 /* probably arbitrary */
68 #define ARG_TAG(n) (n)
69 #define ARG_SIZE(n) stgCast(StgWord,n)
73 INT_TAG = sizeofW(StgInt),
74 INT64_TAG = sizeofW(StgInt64),
75 WORD_TAG = sizeofW(StgWord),
76 ADDR_TAG = sizeofW(StgAddr),
77 CHAR_TAG = sizeofW(StgChar),
78 FLOAT_TAG = sizeofW(StgFloat),
79 DOUBLE_TAG = sizeofW(StgDouble),
80 STABLE_TAG = sizeofW(StgWord),
83 #else /* DEBUG_EXTRA */
96 ARGTAG_MAX = DOUBLE_TAG
99 /* putting this in a .h file generates many copies - but its only a
102 static StgWord stg_arg_size[] = {
104 [INT_TAG ] = sizeofW(StgInt),
105 [INT64_TAG ] = sizeofW(StgInt64),
106 [WORD_TAG ] = sizeofW(StgWord),
107 [ADDR_TAG ] = sizeofW(StgAddr),
108 [CHAR_TAG ] = sizeofW(StgChar),
109 [FLOAT_TAG ] = sizeofW(StgFloat),
110 [DOUBLE_TAG] = sizeofW(StgDouble),
111 [STABLE_TAG] = sizeofW(StgWord)
114 #define ARG_SIZE(tag) stg_arg_size[stgCast(StgWord,tag)]
116 #endif /* DEBUG_EXTRA */
118 static inline int IS_ARG_TAG( StgWord p );
119 static inline int IS_ARG_TAG( StgWord p ) { return p <= ARGTAG_MAX; }
121 /* -----------------------------------------------------------------------------
124 If (Sp + <n_args>) > Su { JMP_(stg_updatePAP); }
126 Sp points to the topmost used word on the stack, and Su points to
127 the most recently pushed update frame.
129 Remember that <n_args> must include any tagging of unboxed values.
131 ARGS_CHK_LOAD_NODE is for top-level functions, whose entry
132 convention doesn't require that Node is loaded with a pointer to
133 the closure. Thus we must load node before calling stg_updatePAP if
134 the argument check fails.
135 -------------------------------------------------------------------------- */
137 #define ARGS_CHK(n) \
138 if ((P_)(Sp + (n)) > (P_)Su) { \
139 JMP_(stg_update_PAP); \
142 #define ARGS_CHK_LOAD_NODE(n,closure) \
143 if ((P_)(Sp + (n)) > (P_)Su) { \
144 R1.p = (P_)closure; \
145 JMP_(stg_update_PAP); \
148 /* -----------------------------------------------------------------------------
151 When failing a check, we save a return address on the stack and
152 jump to a pre-compiled code fragment that saves the live registers
153 and returns to the scheduler.
155 The return address in most cases will be the beginning of the basic
156 block in which the check resides, since we need to perform the check
157 again on re-entry because someone else might have stolen the resource
159 ------------------------------------------------------------------------- */
161 #define STK_CHK(headroom,ret,r,layout,tag_assts) \
162 if (Sp - headroom < SpLim) { \
163 EXTFUN(stg_chk_##layout); \
166 JMP_(stg_chk_##layout); \
169 #define HP_CHK(headroom,ret,r,layout,tag_assts) \
170 if ((Hp += headroom) > HpLim) { \
171 EXTFUN(stg_chk_##layout); \
174 JMP_(stg_chk_##layout); \
176 TICK_ALLOC_HEAP(headroom);
178 #define HP_STK_CHK(stk_headroom,hp_headroom,ret,r,layout,tag_assts) \
179 if (Sp - stk_headroom < SpLim || (Hp += hp_headroom) > HpLim) { \
180 EXTFUN(stg_chk_##layout); \
183 JMP_(stg_chk_##layout); \
185 TICK_ALLOC_HEAP(hp_headroom);
187 /* -----------------------------------------------------------------------------
188 A Heap Check in a case alternative are much simpler: everything is
189 on the stack and covered by a liveness mask already, and there is
190 even a return address with an SRT info table there as well.
192 Just push R1 and return to the scheduler saying 'EnterGHC'
194 {STK,HP,HP_STK}_CHK_NP are the various checking macros for
195 bog-standard case alternatives, thunks, and non-top-level
196 functions. In all these cases, node points to a closure that we
197 can just enter to restart the heap check (the NP stands for 'node points').
199 HpLim points to the LAST WORD of valid allocation space.
200 -------------------------------------------------------------------------- */
202 #define STK_CHK_NP(headroom,ptrs,tag_assts) \
203 if ((Sp - (headroom)) < SpLim) { \
204 EXTFUN(stg_gc_enter_##ptrs); \
206 JMP_(stg_gc_enter_##ptrs); \
209 #define HP_CHK_NP(headroom,ptrs,tag_assts) \
210 if ((Hp += (headroom)) > HpLim) { \
211 EXTFUN(stg_gc_enter_##ptrs); \
213 JMP_(stg_gc_enter_##ptrs); \
215 TICK_ALLOC_HEAP(headroom);
217 #define HP_CHK_SEQ_NP(headroom,ptrs,tag_assts) \
218 if ((Hp += (headroom)) > HpLim) { \
219 EXTFUN(stg_gc_seq_##ptrs); \
221 JMP_(stg_gc_seq_##ptrs); \
223 TICK_ALLOC_HEAP(headroom);
225 #define HP_STK_CHK_NP(stk_headroom, hp_headroom, ptrs, tag_assts) \
226 if ((Sp - (stk_headroom)) < SpLim || (Hp += (hp_headroom)) > HpLim) { \
227 EXTFUN(stg_gc_enter_##ptrs); \
229 JMP_(stg_gc_enter_##ptrs); \
231 TICK_ALLOC_HEAP(hp_headroom);
233 /* Heap checks for branches of a primitive case / unboxed tuple return */
235 #define GEN_HP_CHK_ALT(headroom,lbl,tag_assts) \
236 if ((Hp += (headroom)) > HpLim) { \
241 TICK_ALLOC_HEAP(headroom);
243 #define HP_CHK_NOREGS(headroom,tag_assts) \
244 GEN_HP_CHK_ALT(headroom,stg_gc_noregs,tag_assts);
245 #define HP_CHK_UNPT_R1(headroom,tag_assts) \
246 GEN_HP_CHK_ALT(headroom,stg_gc_unpt_r1,tag_assts);
247 #define HP_CHK_UNBX_R1(headroom,tag_assts) \
248 GEN_HP_CHK_ALT(headroom,stg_gc_unbx_r1,tag_assts);
249 #define HP_CHK_F1(headroom,tag_assts) \
250 GEN_HP_CHK_ALT(headroom,stg_gc_f1,tag_assts);
251 #define HP_CHK_D1(headroom,tag_assts) \
252 GEN_HP_CHK_ALT(headroom,stg_gc_d1,tag_assts);
254 #define HP_CHK_L1(headroom,tag_assts) \
255 GEN_HP_CHK_ALT(headroom,stg_gc_d1,tag_assts);
257 #define HP_CHK_UT_ALT(headroom, ptrs, nptrs, r, ret, tag_assts) \
258 GEN_HP_CHK_ALT(headroom, stg_gc_ut_##ptrs##_##nptrs, \
259 tag_assts r = (P_)ret;)
261 /* -----------------------------------------------------------------------------
264 These are slow, but have the advantage of being usable in a variety
267 The one restriction is that any relevant SRTs must already be pointed
268 to from the stack. The return address doesn't need to have an info
269 table attached: hence it can be any old code pointer.
271 The liveness mask is a logical 'XOR' of NO_PTRS and zero or more
272 Rn_PTR constants defined below. All registers will be saved, but
273 the garbage collector needs to know which ones contain pointers.
275 Good places to use a generic heap check:
277 - case alternatives (the return address with an SRT is already
280 - primitives (no SRT required).
282 The stack layout is like this:
291 so the liveness mask depends on the size of an StgDouble (FltRegs
292 and R<n> are guaranteed to be 1 word in size).
294 -------------------------------------------------------------------------- */
296 /* VERY MAGIC CONSTANTS!
297 * must agree with code in HeapStackCheck.c, stg_gen_chk
300 #if SIZEOF_DOUBLE > SIZEOF_VOID_P
301 #define ALL_NON_PTRS 0xffff
302 #else /* SIZEOF_DOUBLE == SIZEOF_VOID_P */
303 #define ALL_NON_PTRS 0x3fff
306 #define LIVENESS_MASK(ptr_regs) (ALL_NON_PTRS ^ (ptr_regs))
318 #define HP_CHK_GEN(headroom,liveness,reentry,tag_assts) \
319 if ((Hp += (headroom)) > HpLim ) { \
322 R9.w = (W_)LIVENESS_MASK(liveness); \
323 R10.w = (W_)reentry; \
326 TICK_ALLOC_HEAP(headroom);
328 #define STK_CHK_GEN(headroom,liveness,reentry,tag_assts) \
329 if ((Sp - (headroom)) < SpLim) { \
332 R9.w = (W_)LIVENESS_MASK(liveness); \
333 R10.w = (W_)reentry; \
336 TICK_ALLOC_HEAP(headroom);
338 #define MAYBE_GC(liveness,reentry) \
339 if (doYouWantToGC()) { \
341 R9.w = (W_)LIVENESS_MASK(liveness); \
342 R10.w = (W_)reentry; \
346 /* -----------------------------------------------------------------------------
347 Voluntary Yields/Blocks
349 We only have a generic version of this at the moment - if it turns
350 out to be slowing us down we can make specialised ones.
351 -------------------------------------------------------------------------- */
353 #define YIELD(liveness,reentry) \
355 EF_(stg_gen_yield); \
356 R9.w = (W_)LIVENESS_MASK(liveness); \
357 R10.w = (W_)reentry; \
358 JMP_(stg_gen_yield); \
361 #define BLOCK(liveness,reentry) \
363 EF_(stg_gen_block); \
364 R9.w = (W_)LIVENESS_MASK(liveness); \
365 R10.w = (W_)reentry; \
366 JMP_(stg_gen_block); \
369 #define BLOCK_NP(ptrs) \
371 EF_(stg_bock_##ptrs); \
372 JMP_(stg_block_##ptrs); \
375 /* -----------------------------------------------------------------------------
376 CCall_GC needs to push a dummy stack frame containing the contents
377 of volatile registers and variables.
379 We use a RET_DYN frame the same as for a dynamic heap check.
380 ------------------------------------------------------------------------- */
382 EI_(stg_gen_chk_info);
384 /* -----------------------------------------------------------------------------
387 RETVEC(p,t) where 'p' is a pointer to the info table for a
388 vectored return address, returns the address of the return code for
391 Return vectors are placed in *reverse order* immediately before the info
392 table for the return address. Hence the formula for computing the
393 actual return address is (addr - sizeof(InfoTable) - tag - 1).
394 The extra subtraction of one word is because tags start at zero.
395 -------------------------------------------------------------------------- */
397 #ifdef USE_MINIINTERPRETER
398 #define RET_VEC(p,t) ((*(stgCast(StgInfoTable*,p)->vector))[t])
400 #define RET_VEC(p,t) (*((P_)(p) - sizeofW(StgInfoTable) - t - 1))
403 /* -----------------------------------------------------------------------------
405 -------------------------------------------------------------------------- */
407 /* set the tag register (if we have one) */
408 #define SET_TAG(t) /* nothing */
410 /* don't do eager blackholing for now */
411 #define UPD_BH_UPDATABLE(thunk) /* nothing */
412 #define UPD_BH_SINGLE_ENTRY(thunk) /* nothing */
414 /* -----------------------------------------------------------------------------
415 Moving Floats and Doubles
417 ASSIGN_FLT is for assigning a float to memory (usually the
418 stack/heap). The memory address is guaranteed to be
419 StgWord aligned (currently == sizeof(long)).
421 PK_FLT is for pulling a float out of memory. The memory is
422 guaranteed to be StgWord aligned.
423 -------------------------------------------------------------------------- */
425 static inline void ASSIGN_FLT (W_ [], StgFloat);
426 static inline StgFloat PK_FLT (W_ []);
428 #if ALIGNMENT_FLOAT <= ALIGNMENT_LONG
430 static inline void ASSIGN_FLT(W_ p_dest[], StgFloat src) { *(StgFloat *)p_dest = src; }
431 static inline StgFloat PK_FLT (W_ p_src[]) { return *(StgFloat *)p_src; }
433 #else /* ALIGNMENT_FLOAT > ALIGNMENT_UNSIGNED_INT */
435 static inline void ASSIGN_FLT(W_ p_dest[], StgFloat src)
442 static inline StgFloat PK_FLT(W_ p_src[])
449 #endif /* ALIGNMENT_FLOAT > ALIGNMENT_LONG */
451 #if ALIGNMENT_DOUBLE <= ALIGNMENT_LONG
453 static inline void ASSIGN_DBL (W_ [], StgDouble);
454 static inline StgDouble PK_DBL (W_ []);
456 static inline void ASSIGN_DBL(W_ p_dest[], StgDouble src) { *(StgDouble *)p_dest = src; }
457 static inline StgDouble PK_DBL (W_ p_src[]) { return *(StgDouble *)p_src; }
459 #else /* ALIGNMENT_DOUBLE > ALIGNMENT_LONG */
461 /* Sparc uses two floating point registers to hold a double. We can
462 * write ASSIGN_DBL and PK_DBL by directly accessing the registers
463 * independently - unfortunately this code isn't writable in C, we
464 * have to use inline assembler.
466 #if sparc_TARGET_ARCH
468 #define ASSIGN_DBL(dst,src) \
469 __asm__("st %2,%0\n\tst %R2,%1" : "=m" (((P_)(dst))[0]), \
470 "=m" (((P_)(dst))[1]) : "f" (src));
472 #define PK_DBL(src) \
473 ( { register double d; \
474 __asm__("ld %1,%0\n\tld %2,%R0" : "=f" (d) : \
475 "m" (((P_)(src))[0]), "m" (((P_)(src))[1])); d; \
478 #else /* ! sparc_TARGET_ARCH */
480 static inline void ASSIGN_DBL (W_ [], StgDouble);
481 static inline StgDouble PK_DBL (W_ []);
493 static inline void ASSIGN_DBL(W_ p_dest[], StgDouble src)
497 p_dest[0] = y.du.dhi;
498 p_dest[1] = y.du.dlo;
501 /* GCC also works with this version, but it generates
502 the same code as the previous one, and is not ANSI
504 #define ASSIGN_DBL( p_dest, src ) \
505 *p_dest = ((double_thing) src).du.dhi; \
506 *(p_dest+1) = ((double_thing) src).du.dlo \
509 static inline StgDouble PK_DBL(W_ p_src[])
517 #endif /* ! sparc_TARGET_ARCH */
519 #endif /* ALIGNMENT_DOUBLE > ALIGNMENT_UNSIGNED_INT */
521 #ifdef SUPPORT_LONG_LONGS
526 } unpacked_double_word;
530 unpacked_double_word iu;
535 unpacked_double_word wu;
538 static inline void ASSIGN_Word64(W_ p_dest[], StgNat64 src)
542 p_dest[0] = y.wu.dhi;
543 p_dest[1] = y.wu.dlo;
546 static inline StgNat64 PK_Word64(W_ p_src[])
554 static inline void ASSIGN_Int64(W_ p_dest[], StgInt64 src)
558 p_dest[0] = y.iu.dhi;
559 p_dest[1] = y.iu.dlo;
562 static inline StgInt64 PK_Int64(W_ p_src[])
571 /* -----------------------------------------------------------------------------
573 -------------------------------------------------------------------------- */
575 extern const StgPolyInfoTable catch_frame_info;
577 /* -----------------------------------------------------------------------------
580 A seq frame is very like an update frame, except that it doesn't do
582 -------------------------------------------------------------------------- */
584 extern const StgPolyInfoTable seq_frame_info;
586 #define PUSH_SEQ_FRAME(sp) \
588 StgSeqFrame *__frame; \
589 TICK_SEQF_PUSHED(); \
590 __frame = (StgSeqFrame *)(sp); \
591 SET_HDR_(__frame,&seq_frame_info,CCCS); \
592 __frame->link = Su; \
593 Su = (StgUpdateFrame *)__frame; \
596 /* -----------------------------------------------------------------------------
598 -------------------------------------------------------------------------- */
600 #if defined(USE_SPLIT_MARKERS)
601 #define __STG_SPLIT_MARKER(n) FN_(__stg_split_marker##n) { }
603 #define __STG_SPLIT_MARKER(n) /* nothing */
606 /* -----------------------------------------------------------------------------
607 Closure and Info Macros with casting.
609 We don't want to mess around with casts in the generated C code, so
610 we use these casting versions of the closure/info tables macros.
611 -------------------------------------------------------------------------- */
613 #define SET_HDR_(c,info,ccs) \
614 SET_HDR((StgClosure *)(c),(StgInfoTable *)(info),ccs)
616 /* -----------------------------------------------------------------------------
617 Saving context for exit from the STG world, and loading up context
618 on entry to STG code.
620 We save all the STG registers (that is, the ones that are mapped to
621 machine registers) in their places in the TSO.
623 The stack registers go into the current stack object, and the heap
624 registers are saved in global locations.
625 -------------------------------------------------------------------------- */
627 static __inline__ void
628 SaveThreadState(void)
630 /* Don't need to save REG_Base, it won't have changed. */
634 CurrentTSO->splim = SpLim;
637 #if defined(PROFILING)
638 CurrentTSO->prof.CCCS = CCCS;
642 static __inline__ void
643 LoadThreadState (void)
646 BaseReg = &MainRegTable;
651 SpLim = CurrentTSO->splim;
652 OpenNursery(Hp,HpLim);
654 # if defined(PROFILING)
655 CCCS = CurrentTSO->prof.CCCS;
659 #endif /* STGMACROS_H */