1 /* -----------------------------------------------------------------------------
2 * $Id: StgMacros.h,v 1.4 1999/01/23 17:51:27 sof Exp $
4 * Macros used for writing STG-ish C code.
6 * ---------------------------------------------------------------------------*/
11 /* -----------------------------------------------------------------------------
12 The following macros create function headers.
14 Each basic block is represented by a C function with no arguments.
15 We therefore always begin with either
23 The macros can be used either to define the function itself, or to provide
24 prototypes (by following with a ';').
26 Note: the various I*_ shorthands in the second block below are used to
27 declare forward references to local symbols. These shorthands *have* to
28 use the 'extern' type specifier and not 'static'. The reason for this is
29 that 'static' declares a reference as being a static/local variable,
30 and *not* as a forward reference to a static variable.
32 This might seem obvious, but it had me stumped as to why my info tables
33 were suddenly all filled with 0s.
37 --------------------------------------------------------------------------- */
39 #define STGFUN(f) StgFunPtr f(void)
40 #define STATICFUN(f) static StgFunPtr f(void)
41 #define EXTFUN(f) extern StgFunPtr f(void)
42 #define FN_(f) F_ f(void)
43 #define IFN_(f) static F_ f(void)
44 #define IF_(f) static F_ f(void)
45 #define EF_(f) extern F_ f(void)
48 #define ED_RO_ extern const
50 #define ID_RO_ extern const
51 #define EI_ extern const StgInfoTable
52 #define II_ extern const StgInfoTable
53 #define EC_ extern StgClosure
54 #define IC_ extern StgClosure
56 /* -----------------------------------------------------------------------------
59 For a block of non-pointer words on the stack, we precede the
60 block with a small-integer tag giving the number of non-pointer
62 -------------------------------------------------------------------------- */
65 #define ARGTAG_MAX 16 /* probably arbitrary */
66 #define ARG_TAG(n) (n)
67 #define ARG_SIZE(n) stgCast(StgWord,n)
71 INT_TAG = sizeofW(StgInt),
72 INT64_TAG = sizeofW(StgInt64),
73 WORD_TAG = sizeofW(StgWord),
74 ADDR_TAG = sizeofW(StgAddr),
75 CHAR_TAG = sizeofW(StgChar),
76 FLOAT_TAG = sizeofW(StgFloat),
77 DOUBLE_TAG = sizeofW(StgDouble),
78 STABLE_TAG = sizeofW(StgWord),
81 #else /* DEBUG_EXTRA */
94 ARGTAG_MAX = DOUBLE_TAG
97 /* putting this in a .h file generates many copies - but its only a
100 static StgWord stg_arg_size[] = {
102 [INT_TAG ] = sizeofW(StgInt),
103 [INT64_TAG ] = sizeofW(StgInt64),
104 [WORD_TAG ] = sizeofW(StgWord),
105 [ADDR_TAG ] = sizeofW(StgAddr),
106 [CHAR_TAG ] = sizeofW(StgChar),
107 [FLOAT_TAG ] = sizeofW(StgFloat),
108 [DOUBLE_TAG] = sizeofW(StgDouble),
109 [STABLE_TAG] = sizeofW(StgWord)
112 #define ARG_SIZE(tag) stg_arg_size[stgCast(StgWord,tag)]
114 #endif /* DEBUG_EXTRA */
116 static inline int IS_ARG_TAG( StgWord p );
117 static inline int IS_ARG_TAG( StgWord p ) { return p <= ARGTAG_MAX; }
119 /* -----------------------------------------------------------------------------
122 If (Sp + <n_args>) > Su { JMP_(stg_updatePAP); }
124 Sp points to the topmost used word on the stack, and Su points to
125 the most recently pushed update frame.
127 Remember that <n_args> must include any tagging of unboxed values.
129 ARGS_CHK_LOAD_NODE is for top-level functions, whose entry
130 convention doesn't require that Node is loaded with a pointer to
131 the closure. Thus we must load node before calling stg_updatePAP if
132 the argument check fails.
133 -------------------------------------------------------------------------- */
135 #define ARGS_CHK(n) \
136 if ((P_)(Sp + (n)) > (P_)Su) { \
137 JMP_(stg_update_PAP); \
140 #define ARGS_CHK_LOAD_NODE(n,closure) \
141 if ((P_)(Sp + (n)) > (P_)Su) { \
142 R1.p = (P_)closure; \
143 JMP_(stg_update_PAP); \
146 /* -----------------------------------------------------------------------------
149 When failing a check, we save a return address on the stack and
150 jump to a pre-compiled code fragment that saves the live registers
151 and returns to the scheduler.
153 The return address in most cases will be the beginning of the basic
154 block in which the check resides, since we need to perform the check
155 again on re-entry because someone else might have stolen the resource
157 ------------------------------------------------------------------------- */
159 #define STK_CHK(headroom,ret,r,layout,tag_assts) \
160 if (Sp - headroom < SpLim) { \
161 EXTFUN(stg_chk_##layout); \
164 JMP_(stg_chk_##layout); \
167 #define HP_CHK(headroom,ret,r,layout,tag_assts) \
168 if ((Hp += headroom) > HpLim) { \
169 EXTFUN(stg_chk_##layout); \
172 JMP_(stg_chk_##layout); \
174 TICK_ALLOC_HEAP(headroom);
176 #define HP_STK_CHK(stk_headroom,hp_headroom,ret,r,layout,tag_assts) \
177 if (Sp - stk_headroom < SpLim || (Hp += hp_headroom) > HpLim) { \
178 EXTFUN(stg_chk_##layout); \
181 JMP_(stg_chk_##layout); \
183 TICK_ALLOC_HEAP(hp_headroom);
185 /* -----------------------------------------------------------------------------
186 A Heap Check in a case alternative are much simpler: everything is
187 on the stack and covered by a liveness mask already, and there is
188 even a return address with an SRT info table there as well.
190 Just push R1 and return to the scheduler saying 'EnterGHC'
192 {STK,HP,HP_STK}_CHK_NP are the various checking macros for
193 bog-standard case alternatives, thunks, and non-top-level
194 functions. In all these cases, node points to a closure that we
195 can just enter to restart the heap check (the NP stands for 'node points').
197 HpLim points to the LAST WORD of valid allocation space.
198 -------------------------------------------------------------------------- */
200 #define STK_CHK_NP(headroom,ptrs,tag_assts) \
201 if ((Sp - (headroom)) < SpLim) { \
202 EXTFUN(stg_gc_enter_##ptrs); \
204 JMP_(stg_gc_enter_##ptrs); \
207 #define HP_CHK_NP(headroom,ptrs,tag_assts) \
208 if ((Hp += (headroom)) > HpLim) { \
209 EXTFUN(stg_gc_enter_##ptrs); \
211 JMP_(stg_gc_enter_##ptrs); \
213 TICK_ALLOC_HEAP(headroom);
215 #define HP_CHK_SEQ_NP(headroom,ptrs,tag_assts) \
216 if ((Hp += (headroom)) > HpLim) { \
217 EXTFUN(stg_gc_seq_##ptrs); \
219 JMP_(stg_gc_seq_##ptrs); \
221 TICK_ALLOC_HEAP(headroom);
223 #define HP_STK_CHK_NP(stk_headroom, hp_headroom, ptrs, tag_assts) \
224 if ((Sp - (stk_headroom)) < SpLim || (Hp += (hp_headroom)) > HpLim) { \
225 EXTFUN(stg_gc_enter_##ptrs); \
227 JMP_(stg_gc_enter_##ptrs); \
229 TICK_ALLOC_HEAP(hp_headroom);
231 /* Heap checks for branches of a primitive case / unboxed tuple return */
233 #define GEN_HP_CHK_ALT(headroom,lbl,tag_assts) \
234 if ((Hp += (headroom)) > HpLim) { \
239 TICK_ALLOC_HEAP(headroom);
241 #define HP_CHK_NOREGS(headroom,tag_assts) \
242 GEN_HP_CHK_ALT(headroom,stg_gc_noregs,tag_assts);
243 #define HP_CHK_UNPT_R1(headroom,tag_assts) \
244 GEN_HP_CHK_ALT(headroom,stg_gc_unpt_r1,tag_assts);
245 #define HP_CHK_UNBX_R1(headroom,tag_assts) \
246 GEN_HP_CHK_ALT(headroom,stg_gc_unbx_r1,tag_assts);
247 #define HP_CHK_F1(headroom,tag_assts) \
248 GEN_HP_CHK_ALT(headroom,stg_gc_f1,tag_assts);
249 #define HP_CHK_D1(headroom,tag_assts) \
250 GEN_HP_CHK_ALT(headroom,stg_gc_d1,tag_assts);
252 #define HP_CHK_L1(headroom,tag_assts) \
253 GEN_HP_CHK_ALT(headroom,stg_gc_d1,tag_assts);
255 #define HP_CHK_UT_ALT(headroom, ptrs, nptrs, r, ret, tag_assts) \
256 GEN_HP_CHK_ALT(headroom, stg_gc_ut_##ptrs##_##nptrs, \
257 tag_assts r = (P_)ret;)
259 /* -----------------------------------------------------------------------------
262 These are slow, but have the advantage of being usable in a variety
265 The one restriction is that any relevant SRTs must already be pointed
266 to from the stack. The return address doesn't need to have an info
267 table attached: hence it can be any old code pointer.
269 The liveness mask is a logical 'XOR' of NO_PTRS and zero or more
270 Rn_PTR constants defined below. All registers will be saved, but
271 the garbage collector needs to know which ones contain pointers.
273 Good places to use a generic heap check:
275 - case alternatives (the return address with an SRT is already
278 - primitives (no SRT required).
280 The stack layout is like this:
289 so the liveness mask depends on the size of an StgDouble (FltRegs
290 and R<n> are guaranteed to be 1 word in size).
292 -------------------------------------------------------------------------- */
294 /* VERY MAGIC CONSTANTS!
295 * must agree with code in HeapStackCheck.c, stg_gen_chk
298 #if SIZEOF_DOUBLE > SIZEOF_VOID_P
299 #define ALL_NON_PTRS 0xffff
300 #else /* SIZEOF_DOUBLE == SIZEOF_VOID_P */
301 #define ALL_NON_PTRS 0x3fff
304 #define LIVENESS_MASK(ptr_regs) (ALL_NON_PTRS ^ (ptr_regs))
316 #define HP_CHK_GEN(headroom,liveness,reentry,tag_assts) \
317 if ((Hp += (headroom)) > HpLim ) { \
320 R9.w = (W_)LIVENESS_MASK(liveness); \
321 R10.w = (W_)reentry; \
324 TICK_ALLOC_HEAP(headroom);
326 #define STK_CHK_GEN(headroom,liveness,reentry,tag_assts) \
327 if ((Sp - (headroom)) < SpLim) { \
330 R9.w = (W_)LIVENESS_MASK(liveness); \
331 R10.w = (W_)reentry; \
334 TICK_ALLOC_HEAP(headroom);
336 #define MAYBE_GC(liveness,reentry) \
337 if (doYouWantToGC()) { \
339 R9.w = (W_)LIVENESS_MASK(liveness); \
340 R10.w = (W_)reentry; \
344 /* -----------------------------------------------------------------------------
345 Voluntary Yields/Blocks
347 We only have a generic version of this at the moment - if it turns
348 out to be slowing us down we can make specialised ones.
349 -------------------------------------------------------------------------- */
351 #define YIELD(liveness,reentry) \
353 EF_(stg_gen_yield); \
354 R9.w = (W_)LIVENESS_MASK(liveness); \
355 R10.w = (W_)reentry; \
356 JMP_(stg_gen_yield); \
359 #define BLOCK(liveness,reentry) \
361 EF_(stg_gen_block); \
362 R9.w = (W_)LIVENESS_MASK(liveness); \
363 R10.w = (W_)reentry; \
364 JMP_(stg_gen_block); \
367 #define BLOCK_NP(ptrs) \
369 EF_(stg_bock_##ptrs); \
370 JMP_(stg_block_##ptrs); \
373 /* -----------------------------------------------------------------------------
374 CCall_GC needs to push a dummy stack frame containing the contents
375 of volatile registers and variables.
377 We use a RET_DYN frame the same as for a dynamic heap check.
378 ------------------------------------------------------------------------- */
380 EI_(stg_gen_chk_info);
382 /* -----------------------------------------------------------------------------
385 RETVEC(p,t) where 'p' is a pointer to the info table for a
386 vectored return address, returns the address of the return code for
389 Return vectors are placed in *reverse order* immediately before the info
390 table for the return address. Hence the formula for computing the
391 actual return address is (addr - sizeof(InfoTable) - tag - 1).
392 The extra subtraction of one word is because tags start at zero.
393 -------------------------------------------------------------------------- */
395 #ifdef USE_MINIINTERPRETER
396 #define RET_VEC(p,t) ((*(stgCast(StgInfoTable*,p)->vector))[t])
398 #define RET_VEC(p,t) (*((P_)(p) - sizeofW(StgInfoTable) - t - 1))
401 /* -----------------------------------------------------------------------------
403 -------------------------------------------------------------------------- */
405 /* set the tag register (if we have one) */
406 #define SET_TAG(t) /* nothing */
408 /* don't do eager blackholing for now */
409 #define UPD_BH_UPDATABLE(thunk) /* nothing */
410 #define UPD_BH_SINGLE_ENTRY(thunk) /* nothing */
412 /* -----------------------------------------------------------------------------
413 Moving Floats and Doubles
415 ASSIGN_FLT is for assigning a float to memory (usually the
416 stack/heap). The memory address is guaranteed to be
417 StgWord aligned (currently == sizeof(long)).
419 PK_FLT is for pulling a float out of memory. The memory is
420 guaranteed to be StgWord aligned.
421 -------------------------------------------------------------------------- */
423 static inline void ASSIGN_FLT (W_ [], StgFloat);
424 static inline StgFloat PK_FLT (W_ []);
426 #if ALIGNMENT_FLOAT <= ALIGNMENT_LONG
428 static inline void ASSIGN_FLT(W_ p_dest[], StgFloat src) { *(StgFloat *)p_dest = src; }
429 static inline StgFloat PK_FLT (W_ p_src[]) { return *(StgFloat *)p_src; }
431 #else /* ALIGNMENT_FLOAT > ALIGNMENT_UNSIGNED_INT */
433 static inline void ASSIGN_FLT(W_ p_dest[], StgFloat src)
440 static inline StgFloat PK_FLT(W_ p_src[])
447 #endif /* ALIGNMENT_FLOAT > ALIGNMENT_LONG */
449 #if ALIGNMENT_DOUBLE <= ALIGNMENT_LONG
451 static inline void ASSIGN_DBL (W_ [], StgDouble);
452 static inline StgDouble PK_DBL (W_ []);
454 static inline void ASSIGN_DBL(W_ p_dest[], StgDouble src) { *(StgDouble *)p_dest = src; }
455 static inline StgDouble PK_DBL (W_ p_src[]) { return *(StgDouble *)p_src; }
457 #else /* ALIGNMENT_DOUBLE > ALIGNMENT_LONG */
459 /* Sparc uses two floating point registers to hold a double. We can
460 * write ASSIGN_DBL and PK_DBL by directly accessing the registers
461 * independently - unfortunately this code isn't writable in C, we
462 * have to use inline assembler.
464 #if sparc_TARGET_ARCH
466 #define ASSIGN_DBL(dst,src) \
467 __asm__("st %2,%0\n\tst %R2,%1" : "=m" (((P_)(dst))[0]), \
468 "=m" (((P_)(dst))[1]) : "f" (src));
470 #define PK_DBL(src) \
471 ( { register double d; \
472 __asm__("ld %1,%0\n\tld %2,%R0" : "=f" (d) : \
473 "m" (((P_)(src))[0]), "m" (((P_)(src))[1])); d; \
476 #else /* ! sparc_TARGET_ARCH */
478 static inline void ASSIGN_DBL (W_ [], StgDouble);
479 static inline StgDouble PK_DBL (W_ []);
491 static inline void ASSIGN_DBL(W_ p_dest[], StgDouble src)
495 p_dest[0] = y.du.dhi;
496 p_dest[1] = y.du.dlo;
499 /* GCC also works with this version, but it generates
500 the same code as the previous one, and is not ANSI
502 #define ASSIGN_DBL( p_dest, src ) \
503 *p_dest = ((double_thing) src).du.dhi; \
504 *(p_dest+1) = ((double_thing) src).du.dlo \
507 static inline StgDouble PK_DBL(W_ p_src[])
515 #endif /* ! sparc_TARGET_ARCH */
517 #endif /* ALIGNMENT_DOUBLE > ALIGNMENT_UNSIGNED_INT */
519 #ifdef SUPPORT_LONG_LONGS
524 } unpacked_double_word;
528 unpacked_double_word iu;
533 unpacked_double_word wu;
536 static inline void ASSIGN_Word64(W_ p_dest[], StgNat64 src)
540 p_dest[0] = y.wu.dhi;
541 p_dest[1] = y.wu.dlo;
544 static inline StgNat64 PK_Word64(W_ p_src[])
552 static inline void ASSIGN_Int64(W_ p_dest[], StgInt64 src)
556 p_dest[0] = y.iu.dhi;
557 p_dest[1] = y.iu.dlo;
560 static inline StgInt64 PK_Int64(W_ p_src[])
569 /* -----------------------------------------------------------------------------
571 -------------------------------------------------------------------------- */
573 extern const StgPolyInfoTable catch_frame_info;
575 /* -----------------------------------------------------------------------------
578 A seq frame is very like an update frame, except that it doesn't do
580 -------------------------------------------------------------------------- */
582 extern const StgPolyInfoTable seq_frame_info;
584 #define PUSH_SEQ_FRAME(sp) \
586 StgSeqFrame *__frame; \
587 TICK_SEQF_PUSHED(); \
588 __frame = (StgSeqFrame *)(sp); \
589 SET_HDR_(__frame,&seq_frame_info,CCCS); \
590 __frame->link = Su; \
591 Su = (StgUpdateFrame *)__frame; \
594 /* -----------------------------------------------------------------------------
596 -------------------------------------------------------------------------- */
598 #if defined(USE_SPLIT_MARKERS)
599 #define __STG_SPLIT_MARKER(n) FN_(__stg_split_marker##n) { }
601 #define __STG_SPLIT_MARKER(n) /* nothing */
604 /* -----------------------------------------------------------------------------
605 Closure and Info Macros with casting.
607 We don't want to mess around with casts in the generated C code, so
608 we use these casting versions of the closure/info tables macros.
609 -------------------------------------------------------------------------- */
611 #define SET_HDR_(c,info,ccs) \
612 SET_HDR((StgClosure *)(c),(StgInfoTable *)(info),ccs)
614 /* -----------------------------------------------------------------------------
615 Saving context for exit from the STG world, and loading up context
616 on entry to STG code.
618 We save all the STG registers (that is, the ones that are mapped to
619 machine registers) in their places in the TSO.
621 The stack registers go into the current stack object, and the heap
622 registers are saved in global locations.
623 -------------------------------------------------------------------------- */
625 static __inline__ void
626 SaveThreadState(void)
628 /* Don't need to save REG_Base, it won't have changed. */
632 CurrentTSO->splim = SpLim;
635 #if defined(PROFILING)
636 CurrentTSO->prof.CCCS = CCCS;
640 static __inline__ void
641 LoadThreadState (void)
644 BaseReg = &MainRegTable;
649 SpLim = CurrentTSO->splim;
650 OpenNursery(Hp,HpLim);
652 # if defined(PROFILING)
653 CCCS = CurrentTSO->prof.CCCS;
657 #endif /* STGMACROS_H */