1 /* -----------------------------------------------------------------------------
2 * $Id: StgMiscClosures.hc,v 1.32 2000/01/14 11:45:21 hwloidl Exp $
4 * (c) The GHC Team, 1998-1999
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"
19 #if defined(GRAN) || defined(PAR)
20 # include "GranSimRts.h" /* for DumpRawGranEvent */
21 # include "StgRun.h" /* for StgReturn and register saving */
28 /* ToDo: make the printing of panics more Win32-friendly, i.e.,
29 * pop up some lovely message boxes (as well).
31 #define DUMP_ERRMSG(msg) STGCALL2(fprintf,stderr,msg)
34 Template for the entry code of non-enterable closures.
37 #define NON_ENTERABLE_ENTRY_CODE(type) \
38 STGFUN(type##_entry) \
41 DUMP_ERRMSG(#type " object entered!\n"); \
42 STGCALL1(shutdownHaskellAndExit, EXIT_FAILURE); \
46 /* -----------------------------------------------------------------------------
47 Entry code for an indirection.
49 This code assumes R1 is in a register for now.
50 -------------------------------------------------------------------------- */
52 INFO_TABLE(IND_info,IND_entry,1,0,IND,,EF_,0,0);
56 TICK_ENT_IND(Node); /* tick */
58 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
60 JMP_(ENTRY_CODE(*R1.p));
64 INFO_TABLE(IND_STATIC_info,IND_STATIC_entry,1,0,IND_STATIC,,EF_,0,0);
65 STGFUN(IND_STATIC_entry)
68 TICK_ENT_IND(Node); /* tick */
70 R1.p = (P_) ((StgIndStatic*)R1.p)->indirectee;
72 JMP_(ENTRY_CODE(*R1.p));
76 INFO_TABLE(IND_PERM_info,IND_PERM_entry,1,1,IND_PERM,,EF_,0,0);
77 STGFUN(IND_PERM_entry)
80 /* Don't add INDs to granularity cost */
81 /* Dont: TICK_ENT_IND(Node); for ticky-ticky; this ind is here only to help profiling */
83 #if defined(TICKY_TICKY) && !defined(PROFILING)
84 /* TICKY_TICKY && !PROFILING means PERM_IND *replaces* an IND, rather than being extra */
85 TICK_ENT_PERM_IND(R1.p); /* tick */
88 /* Enter PAP cost centre -- lexical scoping only */
89 ENTER_CCS_PAP_CL(R1.cl);
91 /* For ticky-ticky, change the perm_ind to a normal ind on first
92 * entry, so the number of ent_perm_inds is the number of *thunks*
93 * entered again, not the number of subsequent entries.
95 * Since this screws up cost centres, we die if profiling and
96 * ticky_ticky are on at the same time. KSW 1999-01.
101 # error Profiling and ticky-ticky do not mix at present!
102 # endif /* PROFILING */
103 SET_INFO((StgInd*)R1.p,&IND_info);
104 #endif /* TICKY_TICKY */
106 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
108 /* Dont: TICK_ENT_VIA_NODE(); for ticky-ticky; as above */
110 #if defined(TICKY_TICKY) && !defined(PROFILING)
114 JMP_(ENTRY_CODE(*R1.p));
118 INFO_TABLE(IND_OLDGEN_info,IND_OLDGEN_entry,1,1,IND_OLDGEN,,EF_,0,0);
119 STGFUN(IND_OLDGEN_entry)
122 TICK_ENT_IND(Node); /* tick */
124 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
126 JMP_(ENTRY_CODE(*R1.p));
130 INFO_TABLE(IND_OLDGEN_PERM_info,IND_OLDGEN_PERM_entry,1,1,IND_OLDGEN_PERM,,EF_,0,0);
131 STGFUN(IND_OLDGEN_PERM_entry)
134 /* Dont: TICK_ENT_IND(Node); for ticky-ticky; this ind is here only to help profiling */
136 #if defined(TICKY_TICKY) && !defined(PROFILING)
137 /* TICKY_TICKY && !PROFILING means PERM_IND *replaces* an IND, rather than being extra */
138 TICK_ENT_PERM_IND(R1.p); /* tick */
141 /* Enter PAP cost centre -- lexical scoping only */
142 ENTER_CCS_PAP_CL(R1.cl);
144 /* see comment in IND_PERM */
147 # error Profiling and ticky-ticky do not mix at present!
148 # endif /* PROFILING */
149 SET_INFO((StgInd*)R1.p,&IND_OLDGEN_info);
150 #endif /* TICKY_TICKY */
152 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
154 JMP_(ENTRY_CODE(*R1.p));
158 /* -----------------------------------------------------------------------------
161 This code assumes R1 is in a register for now.
162 -------------------------------------------------------------------------- */
164 INFO_TABLE(CAF_UNENTERED_info,CAF_UNENTERED_entry,1,3,CAF_UNENTERED,,EF_,0,0);
165 STGFUN(CAF_UNENTERED_entry)
168 /* ToDo: implement directly in GHC */
171 JMP_(stg_yield_to_Hugs);
175 /* 0,4 is entirely bogus; _do not_ rely on this info */
176 INFO_TABLE(CAF_ENTERED_info,CAF_ENTERED_entry,0,4,CAF_ENTERED,,EF_,0,0);
177 STGFUN(CAF_ENTERED_entry)
180 R1.p = (P_) ((StgCAF*)R1.p)->value; /* just a fancy indirection */
182 JMP_(GET_ENTRY(R1.cl));
186 /* -----------------------------------------------------------------------------
187 Entry code for a black hole.
189 Entering a black hole normally causes a cyclic data dependency, but
190 in the concurrent world, black holes are synchronization points,
191 and they are turned into blocking queues when there are threads
192 waiting for the evaluation of the closure to finish.
193 -------------------------------------------------------------------------- */
195 /* Note: a BLACKHOLE and BLACKHOLE_BQ must be big enough to be
196 * overwritten with an indirection/evacuee/catch. Thus we claim it
197 * has 1 non-pointer word of payload (in addition to the pointer word
198 * for the blocking queue in a BQ), which should be big enough for an
199 * old-generation indirection.
202 INFO_TABLE(BLACKHOLE_info, BLACKHOLE_entry,0,2,BLACKHOLE,,EF_,0,0);
203 STGFUN(BLACKHOLE_entry)
207 /* Before overwriting TSO_LINK */
208 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1.p /*Node*/);
212 CMPXCHG(R1.cl->header.info, &BLACKHOLE_info, &WHITEHOLE_info);
217 /* Put ourselves on the blocking queue for this black hole */
218 #if defined(GRAN) || defined(PAR)
219 /* in fact, only difference is the type of the end-of-queue marker! */
220 CurrentTSO->link = END_BQ_QUEUE;
221 ((StgBlockingQueue *)R1.p)->blocking_queue = (StgBlockingQueueElement *)CurrentTSO;
223 CurrentTSO->link = END_TSO_QUEUE;
224 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
226 /* jot down why and on what closure we are blocked */
227 CurrentTSO->why_blocked = BlockedOnBlackHole;
228 CurrentTSO->block_info.closure = R1.cl;
229 /* closure is mutable since something has just been added to its BQ */
230 recordMutable((StgMutClosure *)R1.cl);
231 /* Change the BLACKHOLE into a BLACKHOLE_BQ */
232 ((StgBlockingQueue *)R1.p)->header.info = &BLACKHOLE_BQ_info;
235 /* Save the Thread State here, before calling RTS routines below! */
236 SAVE_THREAD_STATE(1);
238 /* if collecting stats update the execution time etc */
239 if (RtsFlags.ParFlags.ParStats.Full) {
240 /* Note that CURRENT_TIME may perform an unsafe call */
241 //rtsTime now = CURRENT_TIME; /* Now */
242 CurrentTSO->par.exectime += CURRENT_TIME - CurrentTSO->par.blockedat;
243 CurrentTSO->par.blockcount++;
244 CurrentTSO->par.blockedat = CURRENT_TIME;
245 DumpRawGranEvent(CURRENT_PROC, thisPE,
246 GR_BLOCK, CurrentTSO, (StgClosure *)R1.p, 0);
249 THREAD_RETURN(1); /* back to the scheduler */
251 /* stg_gen_block is too heavyweight, use a specialised one */
258 INFO_TABLE(BLACKHOLE_BQ_info, BLACKHOLE_BQ_entry,1,1,BLACKHOLE_BQ,,EF_,0,0);
259 STGFUN(BLACKHOLE_BQ_entry)
263 /* Before overwriting TSO_LINK */
264 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1.p /*Node*/);
268 CMPXCHG(R1.cl->header.info, &BLACKHOLE_BQ_info, &WHITEHOLE_info);
273 /* Put ourselves on the blocking queue for this black hole */
274 CurrentTSO->link = ((StgBlockingQueue *)R1.p)->blocking_queue;
275 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
276 /* jot down why and on what closure we are blocked */
277 CurrentTSO->why_blocked = BlockedOnBlackHole;
278 CurrentTSO->block_info.closure = R1.cl;
280 ((StgBlockingQueue *)R1.p)->header.info = &BLACKHOLE_BQ_info;
284 /* Save the Thread State here, before calling RTS routines below! */
285 SAVE_THREAD_STATE(1);
287 /* if collecting stats update the execution time etc */
288 if (RtsFlags.ParFlags.ParStats.Full) {
289 /* Note that CURRENT_TIME may perform an unsafe call */
290 //rtsTime now = CURRENT_TIME; /* Now */
291 CurrentTSO->par.exectime += CURRENT_TIME - CurrentTSO->par.blockedat;
292 CurrentTSO->par.blockcount++;
293 CurrentTSO->par.blockedat = CURRENT_TIME;
294 DumpRawGranEvent(CURRENT_PROC, thisPE,
295 GR_BLOCK, CurrentTSO, (StgClosure *)R1.p, 0);
298 THREAD_RETURN(1); /* back to the scheduler */
300 /* stg_gen_block is too heavyweight, use a specialised one */
307 Revertible black holes are needed in the parallel world, to handle
308 negative acknowledgements of messages containing updatable closures.
309 The idea is that when the original message is transmitted, the closure
310 is turned into a revertible black hole...an object which acts like a
311 black hole when local threads try to enter it, but which can be reverted
312 back to the original closure if necessary.
314 It's actually a lot like a blocking queue (BQ) entry, because revertible
315 black holes are initially set up with an empty blocking queue.
318 #if defined(PAR) || defined(GRAN)
320 INFO_TABLE(RBH_info, RBH_entry,1,1,RBH,,EF_,0,0);
325 /* mainly statistics gathering for GranSim simulation */
326 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1.p /*Node*/);
329 /* exactly the same as a BLACKHOLE_BQ_entry -- HWL */
330 /* Put ourselves on the blocking queue for this black hole */
331 CurrentTSO->link = ((StgBlockingQueue *)R1.p)->blocking_queue;
332 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
333 /* jot down why and on what closure we are blocked */
334 CurrentTSO->why_blocked = BlockedOnBlackHole;
335 CurrentTSO->block_info.closure = R1.cl;
338 /* Save the Thread State here, before calling RTS routines below! */
339 SAVE_THREAD_STATE(1);
341 /* if collecting stats update the execution time etc */
342 if (RtsFlags.ParFlags.ParStats.Full) {
343 /* Note that CURRENT_TIME may perform an unsafe call */
344 //rtsTime now = CURRENT_TIME; /* Now */
345 CurrentTSO->par.exectime += CURRENT_TIME - CurrentTSO->par.blockedat;
346 CurrentTSO->par.blockcount++;
347 CurrentTSO->par.blockedat = CURRENT_TIME;
348 DumpRawGranEvent(CURRENT_PROC, thisPE,
349 GR_BLOCK, CurrentTSO, (StgClosure *)R1.p, 0);
352 THREAD_RETURN(1); /* back to the scheduler */
354 /* saves thread state and leaves thread in ThreadEnterGHC state; */
355 /* stg_gen_block is too heavyweight, use a specialised one */
362 INFO_TABLE(RBH_Save_0_info, RBH_Save_0_entry,0,2,CONSTR,,EF_,0,0);
363 NON_ENTERABLE_ENTRY_CODE(RBH_Save_0);
365 INFO_TABLE(RBH_Save_1_info, RBH_Save_1_entry,1,1,CONSTR,,EF_,0,0);
366 NON_ENTERABLE_ENTRY_CODE(RBH_Save_1);
368 INFO_TABLE(RBH_Save_2_info, RBH_Save_2_entry,2,0,CONSTR,,EF_,0,0);
369 NON_ENTERABLE_ENTRY_CODE(RBH_Save_2);
370 #endif /* defined(PAR) || defined(GRAN) */
372 /* identical to BLACKHOLEs except for the infotag */
373 INFO_TABLE(CAF_BLACKHOLE_info, CAF_BLACKHOLE_entry,0,2,CAF_BLACKHOLE,,EF_,0,0);
374 STGFUN(CAF_BLACKHOLE_entry)
378 /* mainly statistics gathering for GranSim simulation */
379 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1.p /*Node*/);
383 CMPXCHG(R1.cl->header.info, &CAF_BLACKHOLE_info, &WHITEHOLE_info);
388 /* Put ourselves on the blocking queue for this black hole */
389 #if defined(GRAN) || defined(PAR)
390 /* in fact, only difference is the type of the end-of-queue marker! */
391 CurrentTSO->link = END_BQ_QUEUE;
392 ((StgBlockingQueue *)R1.p)->blocking_queue = (StgBlockingQueueElement *)CurrentTSO;
394 CurrentTSO->link = END_TSO_QUEUE;
395 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
397 /* jot down why and on what closure we are blocked */
398 CurrentTSO->why_blocked = BlockedOnBlackHole;
399 CurrentTSO->block_info.closure = R1.cl;
400 /* closure is mutable since something has just been added to its BQ */
401 recordMutable((StgMutClosure *)R1.cl);
402 /* Change the CAF_BLACKHOLE into a BLACKHOLE_BQ */
403 ((StgBlockingQueue *)R1.p)->header.info = &BLACKHOLE_BQ_info;
406 /* Save the Thread State here, before calling RTS routines below! */
407 SAVE_THREAD_STATE(1);
409 /* if collecting stats update the execution time etc */
410 if (RtsFlags.ParFlags.ParStats.Full) {
411 /* Note that CURRENT_TIME may perform an unsafe call */
412 //rtsTime now = CURRENT_TIME; /* Now */
413 CurrentTSO->par.exectime += CURRENT_TIME - CurrentTSO->par.blockedat;
414 CurrentTSO->par.blockcount++;
415 CurrentTSO->par.blockedat = CURRENT_TIME;
416 DumpRawGranEvent(CURRENT_PROC, thisPE,
417 GR_BLOCK, CurrentTSO, (StgClosure *)R1.p, 0);
420 THREAD_RETURN(1); /* back to the scheduler */
422 /* stg_gen_block is too heavyweight, use a specialised one */
430 INFO_TABLE(SE_BLACKHOLE_info, SE_BLACKHOLE_entry,0,2,SE_BLACKHOLE,,EF_,0,0);
431 STGFUN(SE_BLACKHOLE_entry)
434 STGCALL3(fprintf,stderr,"SE_BLACKHOLE at %p entered!\n",R1.p);
435 STGCALL1(shutdownHaskellAndExit,EXIT_FAILURE);
439 INFO_TABLE(SE_CAF_BLACKHOLE_info, SE_CAF_BLACKHOLE_entry,0,2,SE_CAF_BLACKHOLE,,EF_,0,0);
440 STGFUN(SE_CAF_BLACKHOLE_entry)
443 STGCALL3(fprintf,stderr,"SE_CAF_BLACKHOLE at %p entered!\n",R1.p);
444 STGCALL1(shutdownHaskellAndExit,EXIT_FAILURE);
450 INFO_TABLE(WHITEHOLE_info, WHITEHOLE_entry,0,2,CONSTR_NOCAF_STATIC,,EF_,0,0);
451 STGFUN(WHITEHOLE_entry)
454 JMP_(GET_ENTRY(R1.cl));
459 /* -----------------------------------------------------------------------------
460 The code for a BCO returns to the scheduler
461 -------------------------------------------------------------------------- */
462 INFO_TABLE(BCO_info,BCO_entry,0,0,BCO,,EF_,0,0);
467 JMP_(stg_yield_to_Hugs);
471 /* -----------------------------------------------------------------------------
472 Some static info tables for things that don't get entered, and
473 therefore don't need entry code (i.e. boxed but unpointed objects)
474 NON_ENTERABLE_ENTRY_CODE now defined at the beginning of the file
475 -------------------------------------------------------------------------- */
477 INFO_TABLE(TSO_info, TSO_entry, 0,0,TSO,,EF_,0,0);
478 NON_ENTERABLE_ENTRY_CODE(TSO);
480 /* -----------------------------------------------------------------------------
481 Evacuees are left behind by the garbage collector. Any attempt to enter
483 -------------------------------------------------------------------------- */
485 INFO_TABLE(EVACUATED_info,EVACUATED_entry,1,0,EVACUATED,,EF_,0,0);
486 NON_ENTERABLE_ENTRY_CODE(EVACUATED);
488 /* -----------------------------------------------------------------------------
491 Live weak pointers have a special closure type. Dead ones are just
492 nullary constructors (although they live on the heap - we overwrite
493 live weak pointers with dead ones).
494 -------------------------------------------------------------------------- */
496 INFO_TABLE(WEAK_info,WEAK_entry,0,4,WEAK,,EF_,0,0);
497 NON_ENTERABLE_ENTRY_CODE(WEAK);
499 INFO_TABLE_CONSTR(DEAD_WEAK_info,DEAD_WEAK_entry,0,1,0,CONSTR,,EF_,0,0);
500 NON_ENTERABLE_ENTRY_CODE(DEAD_WEAK);
502 /* -----------------------------------------------------------------------------
505 This is a static nullary constructor (like []) that we use to mark an empty
506 finalizer in a weak pointer object.
507 -------------------------------------------------------------------------- */
509 INFO_TABLE_CONSTR(NO_FINALIZER_info,NO_FINALIZER_entry,0,0,0,CONSTR_NOCAF_STATIC,,EF_,0,0);
510 NON_ENTERABLE_ENTRY_CODE(NO_FINALIZER);
512 SET_STATIC_HDR(NO_FINALIZER_closure,NO_FINALIZER_info,0/*CC*/,,EI_)
515 /* -----------------------------------------------------------------------------
516 Foreign Objects are unlifted and therefore never entered.
517 -------------------------------------------------------------------------- */
519 INFO_TABLE(FOREIGN_info,FOREIGN_entry,0,1,FOREIGN,,EF_,0,0);
520 NON_ENTERABLE_ENTRY_CODE(FOREIGN);
522 /* -----------------------------------------------------------------------------
523 Stable Names are unlifted too.
524 -------------------------------------------------------------------------- */
526 INFO_TABLE(STABLE_NAME_info,STABLE_NAME_entry,0,1,STABLE_NAME,,EF_,0,0);
527 NON_ENTERABLE_ENTRY_CODE(STABLE_NAME);
529 /* -----------------------------------------------------------------------------
532 There are two kinds of these: full and empty. We need an info table
533 and entry code for each type.
534 -------------------------------------------------------------------------- */
536 INFO_TABLE(FULL_MVAR_info,FULL_MVAR_entry,4,0,MVAR,,EF_,0,0);
537 NON_ENTERABLE_ENTRY_CODE(FULL_MVAR);
539 INFO_TABLE(EMPTY_MVAR_info,EMPTY_MVAR_entry,4,0,MVAR,,EF_,0,0);
540 NON_ENTERABLE_ENTRY_CODE(EMPTY_MVAR);
542 /* -----------------------------------------------------------------------------
545 This is a static nullary constructor (like []) that we use to mark the
546 end of a linked TSO queue.
547 -------------------------------------------------------------------------- */
549 INFO_TABLE_CONSTR(END_TSO_QUEUE_info,END_TSO_QUEUE_entry,0,0,0,CONSTR_NOCAF_STATIC,,EF_,0,0);
550 NON_ENTERABLE_ENTRY_CODE(END_TSO_QUEUE);
552 SET_STATIC_HDR(END_TSO_QUEUE_closure,END_TSO_QUEUE_info,0/*CC*/,,EI_)
555 /* -----------------------------------------------------------------------------
558 Mutable lists (used by the garbage collector) consist of a chain of
559 StgMutClosures connected through their mut_link fields, ending in
560 an END_MUT_LIST closure.
561 -------------------------------------------------------------------------- */
563 INFO_TABLE_CONSTR(END_MUT_LIST_info,END_MUT_LIST_entry,0,0,0,CONSTR_NOCAF_STATIC,,EF_,0,0);
564 NON_ENTERABLE_ENTRY_CODE(END_MUT_LIST);
566 SET_STATIC_HDR(END_MUT_LIST_closure,END_MUT_LIST_info,0/*CC*/,,EI_)
569 INFO_TABLE(MUT_CONS_info, MUT_CONS_entry, 1, 1, MUT_VAR, , EF_, 0, 0);
570 NON_ENTERABLE_ENTRY_CODE(MUT_CONS);
572 /* -----------------------------------------------------------------------------
574 -------------------------------------------------------------------------- */
576 INFO_TABLE_CONSTR(END_EXCEPTION_LIST_info,END_EXCEPTION_LIST_entry,0,0,0,CONSTR_NOCAF_STATIC,,EF_,0,0);
577 NON_ENTERABLE_ENTRY_CODE(END_EXCEPTION_LIST);
579 SET_STATIC_HDR(END_EXCEPTION_LIST_closure,END_EXCEPTION_LIST_info,0/*CC*/,,EI_)
582 INFO_TABLE(EXCEPTION_CONS_info, EXCEPTION_CONS_entry, 1, 1, CONSTR, , EF_, 0, 0);
583 NON_ENTERABLE_ENTRY_CODE(EXCEPTION_CONS);
585 /* -----------------------------------------------------------------------------
588 These come in two basic flavours: arrays of data (StgArrWords) and arrays of
589 pointers (StgArrPtrs). They all have a similar layout:
591 ___________________________
592 | Info | No. of | data....
594 ---------------------------
596 These are *unpointed* objects: i.e. they cannot be entered.
598 -------------------------------------------------------------------------- */
600 #define ArrayInfo(type) \
601 INFO_TABLE(type##_info, type##_entry, 0, 0, type, , EF_,0,0);
603 ArrayInfo(ARR_WORDS);
604 NON_ENTERABLE_ENTRY_CODE(ARR_WORDS);
605 ArrayInfo(MUT_ARR_PTRS);
606 NON_ENTERABLE_ENTRY_CODE(MUT_ARR_PTRS);
607 ArrayInfo(MUT_ARR_PTRS_FROZEN);
608 NON_ENTERABLE_ENTRY_CODE(MUT_ARR_PTRS_FROZEN);
612 /* -----------------------------------------------------------------------------
614 -------------------------------------------------------------------------- */
616 INFO_TABLE(MUT_VAR_info, MUT_VAR_entry, 1, 1, MUT_VAR, , EF_, 0, 0);
617 NON_ENTERABLE_ENTRY_CODE(MUT_VAR);
619 /* -----------------------------------------------------------------------------
620 Standard Error Entry.
622 This is used for filling in vector-table entries that can never happen,
624 -------------------------------------------------------------------------- */
626 STGFUN(stg_error_entry) \
629 DUMP_ERRMSG("fatal: stg_error_entry"); \
630 STGCALL1(shutdownHaskellAndExit, EXIT_FAILURE); \
634 /* -----------------------------------------------------------------------------
637 Entering this closure will just return to the address on the top of the
638 stack. Useful for getting a thread in a canonical form where we can
639 just enter the top stack word to start the thread. (see deleteThread)
640 * -------------------------------------------------------------------------- */
642 INFO_TABLE(dummy_ret_info, dummy_ret_entry, 0, 0, CONSTR_NOCAF_STATIC, , EF_, 0, 0);
649 JMP_(ENTRY_CODE(ret_addr));
652 SET_STATIC_HDR(dummy_ret_closure,dummy_ret_info,CCS_DONTZuCARE,,EI_)
655 /* -----------------------------------------------------------------------------
656 Strict IO application - performing an IO action and entering its result.
658 rts_evalIO() lets you perform Haskell IO actions from outside of Haskell-land,
659 returning back to you their result. Want this result to be evaluated to WHNF
660 by that time, so that we can easily get at the int/char/whatever using the
661 various get{Ty} functions provided by the RTS API.
663 forceIO takes care of this, performing the IO action and entering the
664 results that comes back.
666 * -------------------------------------------------------------------------- */
668 INFO_TABLE_SRT_BITMAP(forceIO_ret_info,forceIO_ret_entry,0,0,0,0,RET_SMALL,,EF_,0,0);
669 FN_(forceIO_ret_entry)
673 Sp -= sizeofW(StgSeqFrame);
675 JMP_(GET_ENTRY(R1.cl));
679 INFO_TABLE(forceIO_info,forceIO_entry,1,0,FUN,,EF_,0,0);
683 /* Sp[0] contains the IO action we want to perform */
685 /* Replace it with the return continuation that enters the result. */
686 Sp[0] = (W_)&forceIO_ret_info;
688 /* Push the RealWorld# tag and enter */
689 Sp[0] =(W_)REALWORLD_TAG;
690 JMP_(GET_ENTRY(R1.cl));
693 SET_STATIC_HDR(forceIO_closure,forceIO_info,CCS_DONTZuCARE,,EI_)
697 /* -----------------------------------------------------------------------------
698 Standard Infotables (for use in interpreter)
699 -------------------------------------------------------------------------- */
703 STGFUN(Hugs_CONSTR_entry)
705 /* R1 points at the constructor */
706 JMP_(ENTRY_CODE(((StgPtr*)Sp)[0]));
709 #define RET_BCO_ENTRY_TEMPLATE(label) \
714 ((StgPtr*)Sp)[0] = R1.p; \
715 JMP_(stg_yield_to_Hugs); \
719 RET_BCO_ENTRY_TEMPLATE(ret_bco_entry );
720 RET_BCO_ENTRY_TEMPLATE(ret_bco_0_entry);
721 RET_BCO_ENTRY_TEMPLATE(ret_bco_1_entry);
722 RET_BCO_ENTRY_TEMPLATE(ret_bco_2_entry);
723 RET_BCO_ENTRY_TEMPLATE(ret_bco_3_entry);
724 RET_BCO_ENTRY_TEMPLATE(ret_bco_4_entry);
725 RET_BCO_ENTRY_TEMPLATE(ret_bco_5_entry);
726 RET_BCO_ENTRY_TEMPLATE(ret_bco_6_entry);
727 RET_BCO_ENTRY_TEMPLATE(ret_bco_7_entry);
729 VEC_POLY_INFO_TABLE(ret_bco,0, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, RET_BCO,, EF_);
731 #endif /* INTERPRETER */
735 INFO_TABLE_CONSTR(Czh_con_info,Hugs_CONSTR_entry,0,sizeofW(StgChar),0,CONSTR,,EF_,0,0);
736 INFO_TABLE_CONSTR(Izh_con_info,Hugs_CONSTR_entry,0,sizeofW(StgInt),0,CONSTR,,EF_,0,0);
737 INFO_TABLE_CONSTR(I64zh_con_info,Hugs_CONSTR_entry,0,sizeofW(StgInt64),0,CONSTR,,EF_,0,0);
738 INFO_TABLE_CONSTR(Fzh_con_info,Hugs_CONSTR_entry,0,sizeofW(StgFloat),0,CONSTR,,EF_,0,0);
739 INFO_TABLE_CONSTR(Dzh_con_info,Hugs_CONSTR_entry,0,sizeofW(StgDouble),0,CONSTR,,EF_,0,0);
740 INFO_TABLE_CONSTR(Azh_con_info,Hugs_CONSTR_entry,0,sizeofW(StgAddr),0,CONSTR,,EF_,0,0);
741 INFO_TABLE_CONSTR(Wzh_con_info,Hugs_CONSTR_entry,0,sizeofW(StgWord),0,CONSTR,,EF_,0,0);
742 INFO_TABLE_CONSTR(StablePtr_con_info,Hugs_CONSTR_entry,0,sizeofW(StgStablePtr),0,CONSTR,,EF_,0,0);
744 /* These might seem redundant but {I,C}zh_static_info are used in
745 * {INT,CHAR}LIKE and the rest are used in RtsAPI.c
747 INFO_TABLE_CONSTR(Czh_static_info,Hugs_CONSTR_entry,0,sizeofW(StgChar),0,CONSTR_NOCAF_STATIC,,EF_,0,0);
748 INFO_TABLE_CONSTR(Izh_static_info,Hugs_CONSTR_entry,0,sizeofW(StgInt),0,CONSTR_NOCAF_STATIC,,EF_,0,0);
749 INFO_TABLE_CONSTR(I64zh_static_info,Hugs_CONSTR_entry,0,sizeofW(StgInt64),0,CONSTR_NOCAF_STATIC,,EF_,0,0);
750 INFO_TABLE_CONSTR(Fzh_static_info,Hugs_CONSTR_entry,0,sizeofW(StgFloat),0,CONSTR_NOCAF_STATIC,,EF_,0,0);
751 INFO_TABLE_CONSTR(Dzh_static_info,Hugs_CONSTR_entry,0,sizeofW(StgDouble),0,CONSTR_NOCAF_STATIC,,EF_,0,0);
752 INFO_TABLE_CONSTR(Azh_static_info,Hugs_CONSTR_entry,0,sizeofW(StgAddr),0,CONSTR_NOCAF_STATIC,,EF_,0,0);
753 INFO_TABLE_CONSTR(Wzh_static_info,Hugs_CONSTR_entry,0,sizeofW(StgWord),0,CONSTR_NOCAF_STATIC,,EF_,0,0);
754 INFO_TABLE_CONSTR(StablePtr_static_info,Hugs_CONSTR_entry,0,sizeofW(StgStablePtr),0,CONSTR_NOCAF_STATIC,,EF_,0,0);
756 #endif /* !defined(COMPILER) */
758 /* -----------------------------------------------------------------------------
759 CHARLIKE and INTLIKE closures.
761 These are static representations of Chars and small Ints, so that
762 we can remove dynamic Chars and Ints during garbage collection and
763 replace them with references to the static objects.
764 -------------------------------------------------------------------------- */
766 #ifdef ENABLE_WIN32_DLL_SUPPORT
768 * When sticking the RTS in a DLL, we delay populating the
769 * Charlike and Intlike tables until load-time, which is only
770 * when we've got the real addresses to the C# and I# closures.
773 static INFO_TBL_CONST StgInfoTable czh_static_info;
774 static INFO_TBL_CONST StgInfoTable izh_static_info;
775 #define Char_hash_static_info czh_static_info
776 #define Int_hash_static_info izh_static_info
778 #define Char_hash_static_info Czh_static_info
779 #define Int_hash_static_info Izh_static_info
782 #define CHARLIKE_HDR(n) \
784 STATIC_HDR(Char_hash_static_info, /* C# */ \
789 #define INTLIKE_HDR(n) \
791 STATIC_HDR(Int_hash_static_info, /* I# */ \
796 /* put these in the *data* section, since the garbage collector relies
797 * on the fact that static closures live in the data section.
800 /* end the name with _closure, to convince the mangler this is a closure */
802 StgIntCharlikeClosure CHARLIKE_closure[] = {
1061 StgIntCharlikeClosure INTLIKE_closure[] = {
1062 INTLIKE_HDR(-16), /* MIN_INTLIKE == -16 */
1094 INTLIKE_HDR(16) /* MAX_INTLIKE == 16 */