1 /* -----------------------------------------------------------------------------
2 * $Id: StgMiscClosures.hc,v 1.39 2000/03/31 03:09:36 hwloidl Exp $
4 * (c) The GHC Team, 1998-2000
6 * Entry code for various built-in closure types.
8 * ---------------------------------------------------------------------------*/
13 #include "StgMiscClosures.h"
14 #include "HeapStackCheck.h" /* for stg_gen_yield */
16 #include "StoragePriv.h"
20 #if defined(GRAN) || defined(PAR)
21 # include "GranSimRts.h" /* for DumpRawGranEvent */
22 # include "StgRun.h" /* for StgReturn and register saving */
29 /* ToDo: make the printing of panics more Win32-friendly, i.e.,
30 * pop up some lovely message boxes (as well).
32 #define DUMP_ERRMSG(msg) STGCALL2(fprintf,stderr,msg)
35 Template for the entry code of non-enterable closures.
38 #define NON_ENTERABLE_ENTRY_CODE(type) \
39 STGFUN(type##_entry) \
42 DUMP_ERRMSG(#type " object entered!\n"); \
43 STGCALL1(shutdownHaskellAndExit, EXIT_FAILURE); \
47 /* -----------------------------------------------------------------------------
48 Entry code for an indirection.
50 This code assumes R1 is in a register for now.
51 -------------------------------------------------------------------------- */
53 INFO_TABLE(IND_info,IND_entry,1,0,IND,,EF_,0,0);
57 TICK_ENT_IND(Node); /* tick */
59 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
61 JMP_(ENTRY_CODE(*R1.p));
65 INFO_TABLE(IND_STATIC_info,IND_STATIC_entry,1,0,IND_STATIC,,EF_,0,0);
66 STGFUN(IND_STATIC_entry)
69 TICK_ENT_IND(Node); /* tick */
71 R1.p = (P_) ((StgIndStatic*)R1.p)->indirectee;
73 JMP_(ENTRY_CODE(*R1.p));
77 INFO_TABLE(IND_PERM_info,IND_PERM_entry,1,1,IND_PERM,,EF_,0,0);
78 STGFUN(IND_PERM_entry)
81 /* Don't add INDs to granularity cost */
82 /* Dont: TICK_ENT_IND(Node); for ticky-ticky; this ind is here only to help profiling */
84 #if defined(TICKY_TICKY) && !defined(PROFILING)
85 /* TICKY_TICKY && !PROFILING means PERM_IND *replaces* an IND, rather than being extra */
86 TICK_ENT_PERM_IND(R1.p); /* tick */
89 /* Enter PAP cost centre -- lexical scoping only */
90 ENTER_CCS_PAP_CL(R1.cl);
92 /* For ticky-ticky, change the perm_ind to a normal ind on first
93 * entry, so the number of ent_perm_inds is the number of *thunks*
94 * entered again, not the number of subsequent entries.
96 * Since this screws up cost centres, we die if profiling and
97 * ticky_ticky are on at the same time. KSW 1999-01.
102 # error Profiling and ticky-ticky do not mix at present!
103 # endif /* PROFILING */
104 SET_INFO((StgInd*)R1.p,&IND_info);
105 #endif /* TICKY_TICKY */
107 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
109 /* Dont: TICK_ENT_VIA_NODE(); for ticky-ticky; as above */
111 #if defined(TICKY_TICKY) && !defined(PROFILING)
115 JMP_(ENTRY_CODE(*R1.p));
119 INFO_TABLE(IND_OLDGEN_info,IND_OLDGEN_entry,1,1,IND_OLDGEN,,EF_,0,0);
120 STGFUN(IND_OLDGEN_entry)
123 TICK_ENT_IND(Node); /* tick */
125 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
127 JMP_(ENTRY_CODE(*R1.p));
131 INFO_TABLE(IND_OLDGEN_PERM_info,IND_OLDGEN_PERM_entry,1,1,IND_OLDGEN_PERM,,EF_,0,0);
132 STGFUN(IND_OLDGEN_PERM_entry)
135 /* Dont: TICK_ENT_IND(Node); for ticky-ticky; this ind is here only to help profiling */
137 #if defined(TICKY_TICKY) && !defined(PROFILING)
138 /* TICKY_TICKY && !PROFILING means PERM_IND *replaces* an IND, rather than being extra */
139 TICK_ENT_PERM_IND(R1.p); /* tick */
142 /* Enter PAP cost centre -- lexical scoping only */
143 ENTER_CCS_PAP_CL(R1.cl);
145 /* see comment in IND_PERM */
148 # error Profiling and ticky-ticky do not mix at present!
149 # endif /* PROFILING */
150 SET_INFO((StgInd*)R1.p,&IND_OLDGEN_info);
151 #endif /* TICKY_TICKY */
153 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
155 JMP_(ENTRY_CODE(*R1.p));
159 /* -----------------------------------------------------------------------------
162 This code assumes R1 is in a register for now.
163 -------------------------------------------------------------------------- */
165 INFO_TABLE(CAF_UNENTERED_info,CAF_UNENTERED_entry,1,3,CAF_UNENTERED,,EF_,0,0);
166 STGFUN(CAF_UNENTERED_entry)
169 /* ToDo: implement directly in GHC */
172 JMP_(stg_yield_to_Hugs);
176 /* 0,4 is entirely bogus; _do not_ rely on this info */
177 INFO_TABLE(CAF_ENTERED_info,CAF_ENTERED_entry,0,4,CAF_ENTERED,,EF_,0,0);
178 STGFUN(CAF_ENTERED_entry)
181 R1.p = (P_) ((StgCAF*)R1.p)->value; /* just a fancy indirection */
183 JMP_(GET_ENTRY(R1.cl));
187 /* -----------------------------------------------------------------------------
188 Entry code for a black hole.
190 Entering a black hole normally causes a cyclic data dependency, but
191 in the concurrent world, black holes are synchronization points,
192 and they are turned into blocking queues when there are threads
193 waiting for the evaluation of the closure to finish.
194 -------------------------------------------------------------------------- */
196 /* Note: a BLACKHOLE and BLACKHOLE_BQ must be big enough to be
197 * overwritten with an indirection/evacuee/catch. Thus we claim it
198 * has 1 non-pointer word of payload (in addition to the pointer word
199 * for the blocking queue in a BQ), which should be big enough for an
200 * old-generation indirection.
203 INFO_TABLE(BLACKHOLE_info, BLACKHOLE_entry,0,2,BLACKHOLE,,EF_,0,0);
204 STGFUN(BLACKHOLE_entry)
208 /* Before overwriting TSO_LINK */
209 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1.p /*Node*/);
214 bdescr *bd = Bdescr(R1.p);
215 if (bd->back != (bdescr *)BaseReg) {
216 if (bd->gen->no >= 1 || bd->step->no >= 1) {
217 CMPXCHG(R1.cl->header.info, &BLACKHOLE_info, &WHITEHOLE_info);
219 EXTFUN_RTS(stg_gc_enter_1_hponly);
220 JMP_(stg_gc_enter_1_hponly);
227 /* Put ourselves on the blocking queue for this black hole */
228 #if defined(GRAN) || defined(PAR)
229 /* in fact, only difference is the type of the end-of-queue marker! */
230 CurrentTSO->link = END_BQ_QUEUE;
231 ((StgBlockingQueue *)R1.p)->blocking_queue = (StgBlockingQueueElement *)CurrentTSO;
233 CurrentTSO->link = END_TSO_QUEUE;
234 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
236 /* jot down why and on what closure we are blocked */
237 CurrentTSO->why_blocked = BlockedOnBlackHole;
238 CurrentTSO->block_info.closure = R1.cl;
239 /* closure is mutable since something has just been added to its BQ */
240 recordMutable((StgMutClosure *)R1.cl);
241 /* Change the BLACKHOLE into a BLACKHOLE_BQ */
242 ((StgBlockingQueue *)R1.p)->header.info = &BLACKHOLE_BQ_info;
244 /* PAR: dumping of event now done in blockThread -- HWL */
246 /* stg_gen_block is too heavyweight, use a specialised one */
252 INFO_TABLE(BLACKHOLE_BQ_info, BLACKHOLE_BQ_entry,1,1,BLACKHOLE_BQ,,EF_,0,0);
253 STGFUN(BLACKHOLE_BQ_entry)
257 /* Before overwriting TSO_LINK */
258 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1.p /*Node*/);
263 bdescr *bd = Bdescr(R1.p);
264 if (bd->back != (bdescr *)BaseReg) {
265 if (bd->gen->no >= 1 || bd->step->no >= 1) {
266 CMPXCHG(R1.cl->header.info, &BLACKHOLE_info, &WHITEHOLE_info);
268 EXTFUN_RTS(stg_gc_enter_1_hponly);
269 JMP_(stg_gc_enter_1_hponly);
277 /* Put ourselves on the blocking queue for this black hole */
278 CurrentTSO->link = ((StgBlockingQueue *)R1.p)->blocking_queue;
279 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
280 /* jot down why and on what closure we are blocked */
281 CurrentTSO->why_blocked = BlockedOnBlackHole;
282 CurrentTSO->block_info.closure = R1.cl;
284 ((StgBlockingQueue *)R1.p)->header.info = &BLACKHOLE_BQ_info;
287 /* PAR: dumping of event now done in blockThread -- HWL */
289 /* stg_gen_block is too heavyweight, use a specialised one */
295 Revertible black holes are needed in the parallel world, to handle
296 negative acknowledgements of messages containing updatable closures.
297 The idea is that when the original message is transmitted, the closure
298 is turned into a revertible black hole...an object which acts like a
299 black hole when local threads try to enter it, but which can be reverted
300 back to the original closure if necessary.
302 It's actually a lot like a blocking queue (BQ) entry, because revertible
303 black holes are initially set up with an empty blocking queue.
306 #if defined(PAR) || defined(GRAN)
308 INFO_TABLE(RBH_info, RBH_entry,1,1,RBH,,EF_,0,0);
313 /* mainly statistics gathering for GranSim simulation */
314 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1.p /*Node*/);
317 /* exactly the same as a BLACKHOLE_BQ_entry -- HWL */
318 /* Put ourselves on the blocking queue for this black hole */
319 CurrentTSO->link = ((StgBlockingQueue *)R1.p)->blocking_queue;
320 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
321 /* jot down why and on what closure we are blocked */
322 CurrentTSO->why_blocked = BlockedOnBlackHole;
323 CurrentTSO->block_info.closure = R1.cl;
325 /* PAR: dumping of event now done in blockThread -- HWL */
327 /* stg_gen_block is too heavyweight, use a specialised one */
332 INFO_TABLE(RBH_Save_0_info, RBH_Save_0_entry,0,2,CONSTR,,EF_,0,0);
333 NON_ENTERABLE_ENTRY_CODE(RBH_Save_0);
335 INFO_TABLE(RBH_Save_1_info, RBH_Save_1_entry,1,1,CONSTR,,EF_,0,0);
336 NON_ENTERABLE_ENTRY_CODE(RBH_Save_1);
338 INFO_TABLE(RBH_Save_2_info, RBH_Save_2_entry,2,0,CONSTR,,EF_,0,0);
339 NON_ENTERABLE_ENTRY_CODE(RBH_Save_2);
340 #endif /* defined(PAR) || defined(GRAN) */
342 /* identical to BLACKHOLEs except for the infotag */
343 INFO_TABLE(CAF_BLACKHOLE_info, CAF_BLACKHOLE_entry,0,2,CAF_BLACKHOLE,,EF_,0,0);
344 STGFUN(CAF_BLACKHOLE_entry)
348 /* mainly statistics gathering for GranSim simulation */
349 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1.p /*Node*/);
354 bdescr *bd = Bdescr(R1.p);
355 if (bd->back != (bdescr *)BaseReg) {
356 if (bd->gen->no >= 1 || bd->step->no >= 1) {
357 CMPXCHG(R1.cl->header.info, &CAF_BLACKHOLE_info, &WHITEHOLE_info);
359 EXTFUN_RTS(stg_gc_enter_1_hponly);
360 JMP_(stg_gc_enter_1_hponly);
368 /* Put ourselves on the blocking queue for this black hole */
369 #if defined(GRAN) || defined(PAR)
370 /* in fact, only difference is the type of the end-of-queue marker! */
371 CurrentTSO->link = END_BQ_QUEUE;
372 ((StgBlockingQueue *)R1.p)->blocking_queue = (StgBlockingQueueElement *)CurrentTSO;
374 CurrentTSO->link = END_TSO_QUEUE;
375 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
377 /* jot down why and on what closure we are blocked */
378 CurrentTSO->why_blocked = BlockedOnBlackHole;
379 CurrentTSO->block_info.closure = R1.cl;
380 /* closure is mutable since something has just been added to its BQ */
381 recordMutable((StgMutClosure *)R1.cl);
382 /* Change the CAF_BLACKHOLE into a BLACKHOLE_BQ */
383 ((StgBlockingQueue *)R1.p)->header.info = &BLACKHOLE_BQ_info;
385 /* PAR: dumping of event now done in blockThread -- HWL */
387 /* stg_gen_block is too heavyweight, use a specialised one */
393 INFO_TABLE(SE_BLACKHOLE_info, SE_BLACKHOLE_entry,0,2,SE_BLACKHOLE,,EF_,0,0);
394 STGFUN(SE_BLACKHOLE_entry)
397 STGCALL3(fprintf,stderr,"SE_BLACKHOLE at %p entered!\n",R1.p);
398 STGCALL1(shutdownHaskellAndExit,EXIT_FAILURE);
402 INFO_TABLE(SE_CAF_BLACKHOLE_info, SE_CAF_BLACKHOLE_entry,0,2,SE_CAF_BLACKHOLE,,EF_,0,0);
403 STGFUN(SE_CAF_BLACKHOLE_entry)
406 STGCALL3(fprintf,stderr,"SE_CAF_BLACKHOLE at %p entered!\n",R1.p);
407 STGCALL1(shutdownHaskellAndExit,EXIT_FAILURE);
413 INFO_TABLE(WHITEHOLE_info, WHITEHOLE_entry,0,2,CONSTR_NOCAF_STATIC,,EF_,0,0);
414 STGFUN(WHITEHOLE_entry)
417 JMP_(GET_ENTRY(R1.cl));
422 /* -----------------------------------------------------------------------------
423 The code for a BCO returns to the scheduler
424 -------------------------------------------------------------------------- */
425 INFO_TABLE(BCO_info,BCO_entry,0,0,BCO,,EF_,0,0);
430 JMP_(stg_yield_to_Hugs);
434 /* -----------------------------------------------------------------------------
435 Some static info tables for things that don't get entered, and
436 therefore don't need entry code (i.e. boxed but unpointed objects)
437 NON_ENTERABLE_ENTRY_CODE now defined at the beginning of the file
438 -------------------------------------------------------------------------- */
440 INFO_TABLE(TSO_info, TSO_entry, 0,0,TSO,,EF_,0,0);
441 NON_ENTERABLE_ENTRY_CODE(TSO);
443 /* -----------------------------------------------------------------------------
444 Evacuees are left behind by the garbage collector. Any attempt to enter
446 -------------------------------------------------------------------------- */
448 INFO_TABLE(EVACUATED_info,EVACUATED_entry,1,0,EVACUATED,,EF_,0,0);
449 NON_ENTERABLE_ENTRY_CODE(EVACUATED);
451 /* -----------------------------------------------------------------------------
454 Live weak pointers have a special closure type. Dead ones are just
455 nullary constructors (although they live on the heap - we overwrite
456 live weak pointers with dead ones).
457 -------------------------------------------------------------------------- */
459 INFO_TABLE(WEAK_info,WEAK_entry,0,4,WEAK,,EF_,0,0);
460 NON_ENTERABLE_ENTRY_CODE(WEAK);
462 INFO_TABLE_CONSTR(DEAD_WEAK_info,DEAD_WEAK_entry,0,1,0,CONSTR,,EF_,0,0);
463 NON_ENTERABLE_ENTRY_CODE(DEAD_WEAK);
465 /* -----------------------------------------------------------------------------
468 This is a static nullary constructor (like []) that we use to mark an empty
469 finalizer in a weak pointer object.
470 -------------------------------------------------------------------------- */
472 INFO_TABLE_CONSTR(NO_FINALIZER_info,NO_FINALIZER_entry,0,0,0,CONSTR_NOCAF_STATIC,,EF_,0,0);
473 NON_ENTERABLE_ENTRY_CODE(NO_FINALIZER);
475 SET_STATIC_HDR(NO_FINALIZER_closure,NO_FINALIZER_info,0/*CC*/,,EI_)
478 /* -----------------------------------------------------------------------------
479 Foreign Objects are unlifted and therefore never entered.
480 -------------------------------------------------------------------------- */
482 INFO_TABLE(FOREIGN_info,FOREIGN_entry,0,1,FOREIGN,,EF_,0,0);
483 NON_ENTERABLE_ENTRY_CODE(FOREIGN);
485 /* -----------------------------------------------------------------------------
486 Stable Names are unlifted too.
487 -------------------------------------------------------------------------- */
489 INFO_TABLE(STABLE_NAME_info,STABLE_NAME_entry,0,1,STABLE_NAME,,EF_,0,0);
490 NON_ENTERABLE_ENTRY_CODE(STABLE_NAME);
492 /* -----------------------------------------------------------------------------
495 There are two kinds of these: full and empty. We need an info table
496 and entry code for each type.
497 -------------------------------------------------------------------------- */
499 INFO_TABLE(FULL_MVAR_info,FULL_MVAR_entry,4,0,MVAR,,EF_,0,0);
500 NON_ENTERABLE_ENTRY_CODE(FULL_MVAR);
502 INFO_TABLE(EMPTY_MVAR_info,EMPTY_MVAR_entry,4,0,MVAR,,EF_,0,0);
503 NON_ENTERABLE_ENTRY_CODE(EMPTY_MVAR);
505 /* -----------------------------------------------------------------------------
508 This is a static nullary constructor (like []) that we use to mark the
509 end of a linked TSO queue.
510 -------------------------------------------------------------------------- */
512 INFO_TABLE_CONSTR(END_TSO_QUEUE_info,END_TSO_QUEUE_entry,0,0,0,CONSTR_NOCAF_STATIC,,EF_,0,0);
513 NON_ENTERABLE_ENTRY_CODE(END_TSO_QUEUE);
515 SET_STATIC_HDR(END_TSO_QUEUE_closure,END_TSO_QUEUE_info,0/*CC*/,,EI_)
518 /* -----------------------------------------------------------------------------
521 Mutable lists (used by the garbage collector) consist of a chain of
522 StgMutClosures connected through their mut_link fields, ending in
523 an END_MUT_LIST closure.
524 -------------------------------------------------------------------------- */
526 INFO_TABLE_CONSTR(END_MUT_LIST_info,END_MUT_LIST_entry,0,0,0,CONSTR_NOCAF_STATIC,,EF_,0,0);
527 NON_ENTERABLE_ENTRY_CODE(END_MUT_LIST);
529 SET_STATIC_HDR(END_MUT_LIST_closure,END_MUT_LIST_info,0/*CC*/,,EI_)
532 INFO_TABLE(MUT_CONS_info, MUT_CONS_entry, 1, 1, MUT_VAR, , EF_, 0, 0);
533 NON_ENTERABLE_ENTRY_CODE(MUT_CONS);
535 /* -----------------------------------------------------------------------------
537 -------------------------------------------------------------------------- */
539 INFO_TABLE_CONSTR(END_EXCEPTION_LIST_info,END_EXCEPTION_LIST_entry,0,0,0,CONSTR_NOCAF_STATIC,,EF_,0,0);
540 NON_ENTERABLE_ENTRY_CODE(END_EXCEPTION_LIST);
542 SET_STATIC_HDR(END_EXCEPTION_LIST_closure,END_EXCEPTION_LIST_info,0/*CC*/,,EI_)
545 INFO_TABLE(EXCEPTION_CONS_info, EXCEPTION_CONS_entry, 1, 1, CONSTR, , EF_, 0, 0);
546 NON_ENTERABLE_ENTRY_CODE(EXCEPTION_CONS);
548 /* -----------------------------------------------------------------------------
551 These come in two basic flavours: arrays of data (StgArrWords) and arrays of
552 pointers (StgArrPtrs). They all have a similar layout:
554 ___________________________
555 | Info | No. of | data....
557 ---------------------------
559 These are *unpointed* objects: i.e. they cannot be entered.
561 -------------------------------------------------------------------------- */
563 #define ArrayInfo(type) \
564 INFO_TABLE(type##_info, type##_entry, 0, 0, type, , EF_,0,0);
566 ArrayInfo(ARR_WORDS);
567 NON_ENTERABLE_ENTRY_CODE(ARR_WORDS);
568 ArrayInfo(MUT_ARR_PTRS);
569 NON_ENTERABLE_ENTRY_CODE(MUT_ARR_PTRS);
570 ArrayInfo(MUT_ARR_PTRS_FROZEN);
571 NON_ENTERABLE_ENTRY_CODE(MUT_ARR_PTRS_FROZEN);
575 /* -----------------------------------------------------------------------------
577 -------------------------------------------------------------------------- */
579 INFO_TABLE(MUT_VAR_info, MUT_VAR_entry, 1, 1, MUT_VAR, , EF_, 0, 0);
580 NON_ENTERABLE_ENTRY_CODE(MUT_VAR);
582 /* -----------------------------------------------------------------------------
583 Standard Error Entry.
585 This is used for filling in vector-table entries that can never happen,
587 -------------------------------------------------------------------------- */
589 STGFUN(stg_error_entry) \
592 DUMP_ERRMSG("fatal: stg_error_entry"); \
593 STGCALL1(shutdownHaskellAndExit, EXIT_FAILURE); \
597 /* -----------------------------------------------------------------------------
600 Entering this closure will just return to the address on the top of the
601 stack. Useful for getting a thread in a canonical form where we can
602 just enter the top stack word to start the thread. (see deleteThread)
603 * -------------------------------------------------------------------------- */
605 INFO_TABLE(dummy_ret_info, dummy_ret_entry, 0, 0, CONSTR_NOCAF_STATIC, , EF_, 0, 0);
612 JMP_(ENTRY_CODE(ret_addr));
615 SET_STATIC_HDR(dummy_ret_closure,dummy_ret_info,CCS_DONTZuCARE,,EI_)
618 /* -----------------------------------------------------------------------------
619 Strict IO application - performing an IO action and entering its result.
621 rts_evalIO() lets you perform Haskell IO actions from outside of Haskell-land,
622 returning back to you their result. Want this result to be evaluated to WHNF
623 by that time, so that we can easily get at the int/char/whatever using the
624 various get{Ty} functions provided by the RTS API.
626 forceIO takes care of this, performing the IO action and entering the
627 results that comes back.
629 * -------------------------------------------------------------------------- */
632 INFO_TABLE_SRT_BITMAP(forceIO_ret_info,forceIO_ret_entry,0,0,0,0,RET_SMALL,,EF_,0,0);
633 FN_(forceIO_ret_entry)
637 Sp -= sizeofW(StgSeqFrame);
639 JMP_(GET_ENTRY(R1.cl));
642 INFO_TABLE_SRT_BITMAP(forceIO_ret_info,forceIO_ret_entry,0,0,0,0,RET_SMALL,,EF_,0,0);
643 FN_(forceIO_ret_entry)
647 rval = (StgClosure *)Sp[0];
649 Sp -= sizeofW(StgSeqFrame);
652 JMP_(GET_ENTRY(R1.cl));
656 INFO_TABLE(forceIO_info,forceIO_entry,1,0,FUN_STATIC,,EF_,0,0);
660 /* Sp[0] contains the IO action we want to perform */
662 /* Replace it with the return continuation that enters the result. */
663 Sp[0] = (W_)&forceIO_ret_info;
665 /* Push the RealWorld# tag and enter */
666 Sp[0] =(W_)REALWORLD_TAG;
667 JMP_(GET_ENTRY(R1.cl));
670 SET_STATIC_HDR(forceIO_closure,forceIO_info,CCS_DONTZuCARE,,EI_)
674 /* -----------------------------------------------------------------------------
675 Standard Infotables (for use in interpreter)
676 -------------------------------------------------------------------------- */
680 STGFUN(Hugs_CONSTR_entry)
682 /* R1 points at the constructor */
683 JMP_(ENTRY_CODE(((StgPtr*)Sp)[0]));
686 #define RET_BCO_ENTRY_TEMPLATE(label) \
691 ((StgPtr*)Sp)[0] = R1.p; \
692 JMP_(stg_yield_to_Hugs); \
696 RET_BCO_ENTRY_TEMPLATE(ret_bco_entry );
697 RET_BCO_ENTRY_TEMPLATE(ret_bco_0_entry);
698 RET_BCO_ENTRY_TEMPLATE(ret_bco_1_entry);
699 RET_BCO_ENTRY_TEMPLATE(ret_bco_2_entry);
700 RET_BCO_ENTRY_TEMPLATE(ret_bco_3_entry);
701 RET_BCO_ENTRY_TEMPLATE(ret_bco_4_entry);
702 RET_BCO_ENTRY_TEMPLATE(ret_bco_5_entry);
703 RET_BCO_ENTRY_TEMPLATE(ret_bco_6_entry);
704 RET_BCO_ENTRY_TEMPLATE(ret_bco_7_entry);
706 VEC_POLY_INFO_TABLE(ret_bco,0, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, RET_BCO,, EF_);
708 #endif /* INTERPRETER */
710 /* -----------------------------------------------------------------------------
711 CHARLIKE and INTLIKE closures.
713 These are static representations of Chars and small Ints, so that
714 we can remove dynamic Chars and Ints during garbage collection and
715 replace them with references to the static objects.
716 -------------------------------------------------------------------------- */
718 #if defined(INTERPRETER) || defined(ENABLE_WIN32_DLL_SUPPORT)
720 * When sticking the RTS in a DLL, we delay populating the
721 * Charlike and Intlike tables until load-time, which is only
722 * when we've got the real addresses to the C# and I# closures.
725 static INFO_TBL_CONST StgInfoTable czh_static_info;
726 static INFO_TBL_CONST StgInfoTable izh_static_info;
727 #define Char_hash_static_info czh_static_info
728 #define Int_hash_static_info izh_static_info
730 #define Char_hash_static_info PrelBase_Czh_static_info
731 #define Int_hash_static_info PrelBase_Izh_static_info
734 #define CHARLIKE_HDR(n) \
736 STATIC_HDR(Char_hash_static_info, /* C# */ \
741 #define INTLIKE_HDR(n) \
743 STATIC_HDR(Int_hash_static_info, /* I# */ \
748 /* put these in the *data* section, since the garbage collector relies
749 * on the fact that static closures live in the data section.
752 /* end the name with _closure, to convince the mangler this is a closure */
754 StgIntCharlikeClosure CHARLIKE_closure[] = {
1013 StgIntCharlikeClosure INTLIKE_closure[] = {
1014 INTLIKE_HDR(-16), /* MIN_INTLIKE == -16 */
1046 INTLIKE_HDR(16) /* MAX_INTLIKE == 16 */