1 /* -----------------------------------------------------------------------------
2 * $Id: StgMacros.h,v 1.6 1999/02/26 09:28:43 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; \
337 #define MAYBE_GC(liveness,reentry) \
338 if (doYouWantToGC()) { \
340 R9.w = (W_)LIVENESS_MASK(liveness); \
341 R10.w = (W_)reentry; \
345 /* -----------------------------------------------------------------------------
346 Voluntary Yields/Blocks
348 We only have a generic version of this at the moment - if it turns
349 out to be slowing us down we can make specialised ones.
350 -------------------------------------------------------------------------- */
352 #define YIELD(liveness,reentry) \
354 EF_(stg_gen_yield); \
355 R9.w = (W_)LIVENESS_MASK(liveness); \
356 R10.w = (W_)reentry; \
357 JMP_(stg_gen_yield); \
360 #define BLOCK(liveness,reentry) \
362 EF_(stg_gen_block); \
363 R9.w = (W_)LIVENESS_MASK(liveness); \
364 R10.w = (W_)reentry; \
365 JMP_(stg_gen_block); \
368 #define BLOCK_NP(ptrs) \
370 EF_(stg_bock_##ptrs); \
371 JMP_(stg_block_##ptrs); \
374 /* -----------------------------------------------------------------------------
375 CCall_GC needs to push a dummy stack frame containing the contents
376 of volatile registers and variables.
378 We use a RET_DYN frame the same as for a dynamic heap check.
379 ------------------------------------------------------------------------- */
381 EI_(stg_gen_chk_info);
383 /* -----------------------------------------------------------------------------
386 RETVEC(p,t) where 'p' is a pointer to the info table for a
387 vectored return address, returns the address of the return code for
390 Return vectors are placed in *reverse order* immediately before the info
391 table for the return address. Hence the formula for computing the
392 actual return address is (addr - sizeof(InfoTable) - tag - 1).
393 The extra subtraction of one word is because tags start at zero.
394 -------------------------------------------------------------------------- */
396 #ifdef USE_MINIINTERPRETER
397 #define RET_VEC(p,t) ((*(stgCast(StgInfoTable*,p)->vector))[t])
399 #define RET_VEC(p,t) (*((P_)(p) - sizeofW(StgInfoTable) - t - 1))
402 /* -----------------------------------------------------------------------------
404 -------------------------------------------------------------------------- */
406 /* set the tag register (if we have one) */
407 #define SET_TAG(t) /* nothing */
409 /* don't do eager blackholing for now */
410 #define UPD_BH_UPDATABLE(thunk) /* nothing */
411 #define UPD_BH_SINGLE_ENTRY(thunk) /* nothing */
413 /* -----------------------------------------------------------------------------
414 Moving Floats and Doubles
416 ASSIGN_FLT is for assigning a float to memory (usually the
417 stack/heap). The memory address is guaranteed to be
418 StgWord aligned (currently == sizeof(long)).
420 PK_FLT is for pulling a float out of memory. The memory is
421 guaranteed to be StgWord aligned.
422 -------------------------------------------------------------------------- */
424 static inline void ASSIGN_FLT (W_ [], StgFloat);
425 static inline StgFloat PK_FLT (W_ []);
427 #if ALIGNMENT_FLOAT <= ALIGNMENT_LONG
429 static inline void ASSIGN_FLT(W_ p_dest[], StgFloat src) { *(StgFloat *)p_dest = src; }
430 static inline StgFloat PK_FLT (W_ p_src[]) { return *(StgFloat *)p_src; }
432 #else /* ALIGNMENT_FLOAT > ALIGNMENT_UNSIGNED_INT */
434 static inline void ASSIGN_FLT(W_ p_dest[], StgFloat src)
441 static inline StgFloat PK_FLT(W_ p_src[])
448 #endif /* ALIGNMENT_FLOAT > ALIGNMENT_LONG */
450 #if ALIGNMENT_DOUBLE <= ALIGNMENT_LONG
452 static inline void ASSIGN_DBL (W_ [], StgDouble);
453 static inline StgDouble PK_DBL (W_ []);
455 static inline void ASSIGN_DBL(W_ p_dest[], StgDouble src) { *(StgDouble *)p_dest = src; }
456 static inline StgDouble PK_DBL (W_ p_src[]) { return *(StgDouble *)p_src; }
458 #else /* ALIGNMENT_DOUBLE > ALIGNMENT_LONG */
460 /* Sparc uses two floating point registers to hold a double. We can
461 * write ASSIGN_DBL and PK_DBL by directly accessing the registers
462 * independently - unfortunately this code isn't writable in C, we
463 * have to use inline assembler.
465 #if sparc_TARGET_ARCH
467 #define ASSIGN_DBL(dst,src) \
468 __asm__("st %2,%0\n\tst %R2,%1" : "=m" (((P_)(dst))[0]), \
469 "=m" (((P_)(dst))[1]) : "f" (src));
471 #define PK_DBL(src) \
472 ( { register double d; \
473 __asm__("ld %1,%0\n\tld %2,%R0" : "=f" (d) : \
474 "m" (((P_)(src))[0]), "m" (((P_)(src))[1])); d; \
477 #else /* ! sparc_TARGET_ARCH */
479 static inline void ASSIGN_DBL (W_ [], StgDouble);
480 static inline StgDouble PK_DBL (W_ []);
492 static inline void ASSIGN_DBL(W_ p_dest[], StgDouble src)
496 p_dest[0] = y.du.dhi;
497 p_dest[1] = y.du.dlo;
500 /* GCC also works with this version, but it generates
501 the same code as the previous one, and is not ANSI
503 #define ASSIGN_DBL( p_dest, src ) \
504 *p_dest = ((double_thing) src).du.dhi; \
505 *(p_dest+1) = ((double_thing) src).du.dlo \
508 static inline StgDouble PK_DBL(W_ p_src[])
516 #endif /* ! sparc_TARGET_ARCH */
518 #endif /* ALIGNMENT_DOUBLE > ALIGNMENT_UNSIGNED_INT */
520 #ifdef SUPPORT_LONG_LONGS
525 } unpacked_double_word;
529 unpacked_double_word iu;
534 unpacked_double_word wu;
537 static inline void ASSIGN_Word64(W_ p_dest[], StgNat64 src)
541 p_dest[0] = y.wu.dhi;
542 p_dest[1] = y.wu.dlo;
545 static inline StgNat64 PK_Word64(W_ p_src[])
553 static inline void ASSIGN_Int64(W_ p_dest[], StgInt64 src)
557 p_dest[0] = y.iu.dhi;
558 p_dest[1] = y.iu.dlo;
561 static inline StgInt64 PK_Int64(W_ p_src[])
570 /* -----------------------------------------------------------------------------
572 -------------------------------------------------------------------------- */
574 extern const StgPolyInfoTable catch_frame_info;
576 /* -----------------------------------------------------------------------------
579 A seq frame is very like an update frame, except that it doesn't do
581 -------------------------------------------------------------------------- */
583 extern const StgPolyInfoTable seq_frame_info;
585 #define PUSH_SEQ_FRAME(sp) \
587 StgSeqFrame *__frame; \
588 TICK_SEQF_PUSHED(); \
589 __frame = (StgSeqFrame *)(sp); \
590 SET_HDR_(__frame,&seq_frame_info,CCCS); \
591 __frame->link = Su; \
592 Su = (StgUpdateFrame *)__frame; \
595 /* -----------------------------------------------------------------------------
597 -------------------------------------------------------------------------- */
599 #if defined(USE_SPLIT_MARKERS)
600 #define __STG_SPLIT_MARKER(n) FN_(__stg_split_marker##n) { }
602 #define __STG_SPLIT_MARKER(n) /* nothing */
605 /* -----------------------------------------------------------------------------
606 Closure and Info Macros with casting.
608 We don't want to mess around with casts in the generated C code, so
609 we use these casting versions of the closure/info tables macros.
610 -------------------------------------------------------------------------- */
612 #define SET_HDR_(c,info,ccs) \
613 SET_HDR((StgClosure *)(c),(StgInfoTable *)(info),ccs)
615 /* -----------------------------------------------------------------------------
616 Saving context for exit from the STG world, and loading up context
617 on entry to STG code.
619 We save all the STG registers (that is, the ones that are mapped to
620 machine registers) in their places in the TSO.
622 The stack registers go into the current stack object, and the heap
623 registers are saved in global locations.
624 -------------------------------------------------------------------------- */
626 static __inline__ void
627 SaveThreadState(void)
629 /* Don't need to save REG_Base, it won't have changed. */
633 CurrentTSO->splim = SpLim;
636 #if defined(PROFILING)
637 CurrentTSO->prof.CCCS = CCCS;
641 static __inline__ void
642 LoadThreadState (void)
645 BaseReg = &MainRegTable;
650 SpLim = CurrentTSO->splim;
651 OpenNursery(Hp,HpLim);
653 # if defined(PROFILING)
654 CCCS = CurrentTSO->prof.CCCS;
658 #endif /* STGMACROS_H */