1 /* ----------------------------------------------------------------------------
3 * (c) The GHC Team, 1998-2004
5 * Entry code for various built-in closure types.
7 * This file is written in a subset of C--, extended with various
8 * features specific to GHC. It is compiled by GHC directly. For the
9 * syntax of .cmm files, see the parser in ghc/compiler/cmm/CmmParse.y.
11 * --------------------------------------------------------------------------*/
15 import pthread_mutex_lock;
16 import base_GHCziBase_Czh_static_info;
17 import base_GHCziBase_Izh_static_info;
18 import EnterCriticalSection;
19 import LeaveCriticalSection;
21 /* ----------------------------------------------------------------------------
22 Support for the bytecode interpreter.
23 ------------------------------------------------------------------------- */
25 /* 9 bits of return code for constructors created by the interpreter. */
26 stg_interp_constr_entry
28 /* R1 points at the constructor */
29 jump %ENTRY_CODE(Sp(0));
32 /* Some info tables to be used when compiled code returns a value to
33 the interpreter, i.e. the interpreter pushes one of these onto the
34 stack before entering a value. What the code does is to
35 impedance-match the compiled return convention (in R1p/R1n/F1/D1 etc) to
36 the interpreter's convention (returned value is on top of stack),
37 and then cause the scheduler to enter the interpreter.
39 On entry, the stack (growing down) looks like this:
41 ptr to BCO holding return continuation
42 ptr to one of these info tables.
44 The info table code, both direct and vectored, must:
45 * push R1/F1/D1 on the stack, and its tag if necessary
46 * push the BCO (so it's now on the stack twice)
47 * Yield, ie, go to the scheduler.
49 Scheduler examines the t.o.s, discovers it is a BCO, and proceeds
50 directly to the bytecode interpreter. That pops the top element
51 (the BCO, containing the return continuation), and interprets it.
52 Net result: return continuation gets interpreted, with the
56 ptr to the info table just jumped thru
59 which is just what we want -- the "standard" return layout for the
62 Don't ask me how unboxed tuple returns are supposed to work. We
63 haven't got a good story about that yet.
66 INFO_TABLE_RET( stg_ctoi_R1p, RET_BCO)
70 Sp(0) = stg_enter_info;
71 jump stg_yield_to_interpreter;
75 * When the returned value is a pointer, but unlifted, in R1 ...
77 INFO_TABLE_RET( stg_ctoi_R1unpt, RET_BCO )
81 Sp(0) = stg_gc_unpt_r1_info;
82 jump stg_yield_to_interpreter;
86 * When the returned value is a non-pointer in R1 ...
88 INFO_TABLE_RET( stg_ctoi_R1n, RET_BCO )
92 Sp(0) = stg_gc_unbx_r1_info;
93 jump stg_yield_to_interpreter;
97 * When the returned value is in F1
99 INFO_TABLE_RET( stg_ctoi_F1, RET_BCO )
102 F_[Sp + WDS(1)] = F1;
103 Sp(0) = stg_gc_f1_info;
104 jump stg_yield_to_interpreter;
108 * When the returned value is in D1
110 INFO_TABLE_RET( stg_ctoi_D1, RET_BCO )
112 Sp_adj(-1) - SIZEOF_DOUBLE;
113 D_[Sp + WDS(1)] = D1;
114 Sp(0) = stg_gc_d1_info;
115 jump stg_yield_to_interpreter;
119 * When the returned value is in L1
121 INFO_TABLE_RET( stg_ctoi_L1, RET_BCO )
124 L_[Sp + WDS(1)] = L1;
125 Sp(0) = stg_gc_l1_info;
126 jump stg_yield_to_interpreter;
130 * When the returned value is a void
132 INFO_TABLE_RET( stg_ctoi_V, RET_BCO )
135 Sp(0) = stg_gc_void_info;
136 jump stg_yield_to_interpreter;
140 * Dummy info table pushed on the top of the stack when the interpreter
141 * should apply the BCO on the stack to its arguments, also on the
144 INFO_TABLE_RET( stg_apply_interp, RET_BCO )
146 /* Just in case we end up in here... (we shouldn't) */
147 jump stg_yield_to_interpreter;
150 /* ----------------------------------------------------------------------------
152 ------------------------------------------------------------------------- */
154 INFO_TABLE_FUN( stg_BCO, 4, 0, BCO, "BCO", "BCO", ARG_BCO )
156 /* entering a BCO means "apply it", same as a function */
159 Sp(0) = stg_apply_interp_info;
160 jump stg_yield_to_interpreter;
163 /* ----------------------------------------------------------------------------
164 Info tables for indirections.
166 SPECIALISED INDIRECTIONS: we have a specialised indirection for direct returns,
167 so that we can avoid entering
168 the object when we know it points directly to a value. The update
169 code (Updates.cmm) updates objects with the appropriate kind of
170 indirection. We only do this for young-gen indirections.
171 ------------------------------------------------------------------------- */
173 INFO_TABLE(stg_IND,1,0,IND,"IND","IND")
175 TICK_ENT_DYN_IND(); /* tick */
176 R1 = UNTAG(StgInd_indirectee(R1));
181 INFO_TABLE(stg_IND_direct,1,0,IND,"IND","IND")
183 TICK_ENT_DYN_IND(); /* tick */
184 R1 = StgInd_indirectee(R1);
186 jump %ENTRY_CODE(Sp(0));
189 INFO_TABLE(stg_IND_STATIC,1,0,IND_STATIC,"IND_STATIC","IND_STATIC")
191 TICK_ENT_STATIC_IND(); /* tick */
192 R1 = UNTAG(StgInd_indirectee(R1));
197 INFO_TABLE(stg_IND_PERM,1,0,IND_PERM,"IND_PERM","IND_PERM")
199 /* Don't add INDs to granularity cost */
201 /* Don't: TICK_ENT_STATIC_IND(Node); for ticky-ticky; this ind is
202 here only to help profiling */
204 #if defined(TICKY_TICKY) && !defined(PROFILING)
205 /* TICKY_TICKY && !PROFILING means PERM_IND *replaces* an IND, rather than
212 /* Enter PAP cost centre */
213 ENTER_CCS_PAP_CL(R1);
215 /* For ticky-ticky, change the perm_ind to a normal ind on first
216 * entry, so the number of ent_perm_inds is the number of *thunks*
217 * entered again, not the number of subsequent entries.
219 * Since this screws up cost centres, we die if profiling and
220 * ticky_ticky are on at the same time. KSW 1999-01.
224 # error Profiling and ticky-ticky do not mix at present!
225 # endif /* PROFILING */
226 StgHeader_info(R1) = stg_IND_info;
227 #endif /* TICKY_TICKY */
229 R1 = UNTAG(StgInd_indirectee(R1));
231 #if defined(TICKY_TICKY) && !defined(PROFILING)
239 INFO_TABLE(stg_IND_OLDGEN,1,0,IND_OLDGEN,"IND_OLDGEN","IND_OLDGEN")
241 TICK_ENT_STATIC_IND(); /* tick */
242 R1 = UNTAG(StgInd_indirectee(R1));
247 INFO_TABLE(stg_IND_OLDGEN_PERM,1,0,IND_OLDGEN_PERM,"IND_OLDGEN_PERM","IND_OLDGEN_PERM")
249 /* Don't: TICK_ENT_STATIC_IND(Node); for ticky-ticky;
250 this ind is here only to help profiling */
252 #if defined(TICKY_TICKY) && !defined(PROFILING)
253 /* TICKY_TICKY && !PROFILING means PERM_IND *replaces* an IND,
254 rather than being extra */
255 TICK_ENT_PERM_IND(); /* tick */
260 /* Enter PAP cost centre -- lexical scoping only */
261 ENTER_CCS_PAP_CL(R1);
263 /* see comment in IND_PERM */
266 # error Profiling and ticky-ticky do not mix at present!
267 # endif /* PROFILING */
268 StgHeader_info(R1) = stg_IND_OLDGEN_info;
269 #endif /* TICKY_TICKY */
271 R1 = UNTAG(StgInd_indirectee(R1));
277 /* ----------------------------------------------------------------------------
280 Entering a black hole normally causes a cyclic data dependency, but
281 in the concurrent world, black holes are synchronization points,
282 and they are turned into blocking queues when there are threads
283 waiting for the evaluation of the closure to finish.
284 ------------------------------------------------------------------------- */
286 /* Note: a BLACKHOLE must be big enough to be
287 * overwritten with an indirection/evacuee/catch. Thus we claim it
288 * has 1 non-pointer word of payload.
290 INFO_TABLE(stg_BLACKHOLE,0,1,BLACKHOLE,"BLACKHOLE","BLACKHOLE")
293 /* Before overwriting TSO_LINK */
294 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1 /*Node*/);
300 // foreign "C" debugBelch("BLACKHOLE entry\n");
303 /* Actually this is not necessary because R1 is about to be destroyed. */
306 #if defined(THREADED_RTS)
307 ACQUIRE_LOCK(sched_mutex "ptr");
308 // released in stg_block_blackhole_finally
311 /* Put ourselves on the blackhole queue */
312 StgTSO_link(CurrentTSO) = W_[blackhole_queue];
313 W_[blackhole_queue] = CurrentTSO;
315 /* jot down why and on what closure we are blocked */
316 StgTSO_why_blocked(CurrentTSO) = BlockedOnBlackHole::I16;
317 StgTSO_block_info(CurrentTSO) = R1;
319 jump stg_block_blackhole;
322 #if defined(PAR) || defined(GRAN)
324 INFO_TABLE(stg_RBH,1,1,RBH,"RBH","RBH")
327 /* mainly statistics gathering for GranSim simulation */
328 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1 /*Node*/);
331 /* exactly the same as a BLACKHOLE_BQ_entry -- HWL */
332 /* Put ourselves on the blocking queue for this black hole */
333 TSO_link(CurrentTSO) = StgBlockingQueue_blocking_queue(R1);
334 StgBlockingQueue_blocking_queue(R1) = CurrentTSO;
335 /* jot down why and on what closure we are blocked */
336 TSO_why_blocked(CurrentTSO) = BlockedOnBlackHole::I16;
337 TSO_block_info(CurrentTSO) = R1;
339 /* PAR: dumping of event now done in blockThread -- HWL */
341 /* stg_gen_block is too heavyweight, use a specialised one */
345 INFO_TABLE(stg_RBH_Save_0,0,2,CONSTR,"RBH_Save_0","RBH_Save_0")
346 { foreign "C" barf("RBH_Save_0 object entered!") never returns; }
348 INFO_TABLE(stg_RBH_Save_1,1,1,CONSTR,"RBH_Save_1","RBH_Save_1");
349 { foreign "C" barf("RBH_Save_1 object entered!") never returns; }
351 INFO_TABLE(stg_RBH_Save_2,2,0,CONSTR,"RBH_Save_2","RBH_Save_2");
352 { foreign "C" barf("RBH_Save_2 object entered!") never returns; }
354 #endif /* defined(PAR) || defined(GRAN) */
356 /* identical to BLACKHOLEs except for the infotag */
357 INFO_TABLE(stg_CAF_BLACKHOLE,0,1,CAF_BLACKHOLE,"CAF_BLACKHOLE","CAF_BLACKHOLE")
360 /* mainly statistics gathering for GranSim simulation */
361 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1 /*Node*/);
367 #if defined(THREADED_RTS)
368 // foreign "C" debugBelch("BLACKHOLE entry\n");
371 #if defined(THREADED_RTS)
372 ACQUIRE_LOCK(sched_mutex "ptr");
373 // released in stg_block_blackhole_finally
376 /* Put ourselves on the blackhole queue */
377 StgTSO_link(CurrentTSO) = W_[blackhole_queue];
378 W_[blackhole_queue] = CurrentTSO;
380 /* jot down why and on what closure we are blocked */
381 StgTSO_why_blocked(CurrentTSO) = BlockedOnBlackHole::I16;
382 StgTSO_block_info(CurrentTSO) = R1;
384 jump stg_block_blackhole;
387 #ifdef EAGER_BLACKHOLING
388 INFO_TABLE(stg_SE_BLACKHOLE,0,1,SE_BLACKHOLE,"SE_BLACKHOLE","SE_BLACKHOLE")
389 { foreign "C" barf("SE_BLACKHOLE object entered!") never returns; }
391 INFO_TABLE(stg_SE_CAF_BLACKHOLE,0,1,SE_CAF_BLACKHOLE,"SE_CAF_BLACKHOLE","SE_CAF_BLACKHOLE")
392 { foreign "C" barf("SE_CAF_BLACKHOLE object entered!") never returns; }
395 /* ----------------------------------------------------------------------------
396 Whiteholes are used for the "locked" state of a closure (see lockClosure())
397 ------------------------------------------------------------------------- */
399 INFO_TABLE(stg_WHITEHOLE, 0,0, WHITEHOLE, "WHITEHOLE", "WHITEHOLE")
400 { foreign "C" barf("WHITEHOLE object entered!") never returns; }
402 /* ----------------------------------------------------------------------------
403 Some static info tables for things that don't get entered, and
404 therefore don't need entry code (i.e. boxed but unpointed objects)
405 NON_ENTERABLE_ENTRY_CODE now defined at the beginning of the file
406 ------------------------------------------------------------------------- */
408 INFO_TABLE(stg_TSO, 0,0,TSO, "TSO", "TSO")
409 { foreign "C" barf("TSO object entered!") never returns; }
411 /* ----------------------------------------------------------------------------
412 Evacuees are left behind by the garbage collector. Any attempt to enter
414 ------------------------------------------------------------------------- */
416 INFO_TABLE(stg_EVACUATED,1,0,EVACUATED,"EVACUATED","EVACUATED")
417 { foreign "C" barf("EVACUATED object entered!") never returns; }
419 /* ----------------------------------------------------------------------------
422 Live weak pointers have a special closure type. Dead ones are just
423 nullary constructors (although they live on the heap - we overwrite
424 live weak pointers with dead ones).
425 ------------------------------------------------------------------------- */
427 INFO_TABLE(stg_WEAK,0,4,WEAK,"WEAK","WEAK")
428 { foreign "C" barf("WEAK object entered!") never returns; }
431 * It's important when turning an existing WEAK into a DEAD_WEAK
432 * (which is what finalizeWeak# does) that we don't lose the link
433 * field and break the linked list of weak pointers. Hence, we give
434 * DEAD_WEAK 4 non-pointer fields, the same as WEAK.
436 INFO_TABLE_CONSTR(stg_DEAD_WEAK,0,4,0,CONSTR,"DEAD_WEAK","DEAD_WEAK")
437 { foreign "C" barf("DEAD_WEAK object entered!") never returns; }
439 /* ----------------------------------------------------------------------------
442 This is a static nullary constructor (like []) that we use to mark an empty
443 finalizer in a weak pointer object.
444 ------------------------------------------------------------------------- */
446 INFO_TABLE_CONSTR(stg_NO_FINALIZER,0,0,0,CONSTR_NOCAF_STATIC,"NO_FINALIZER","NO_FINALIZER")
447 { foreign "C" barf("NO_FINALIZER object entered!") never returns; }
449 CLOSURE(stg_NO_FINALIZER_closure,stg_NO_FINALIZER);
451 /* ----------------------------------------------------------------------------
452 Stable Names are unlifted too.
453 ------------------------------------------------------------------------- */
455 INFO_TABLE(stg_STABLE_NAME,0,1,STABLE_NAME,"STABLE_NAME","STABLE_NAME")
456 { foreign "C" barf("STABLE_NAME object entered!") never returns; }
458 /* ----------------------------------------------------------------------------
461 There are two kinds of these: full and empty. We need an info table
462 and entry code for each type.
463 ------------------------------------------------------------------------- */
465 INFO_TABLE(stg_MVAR_CLEAN,3,0,MVAR_CLEAN,"MVAR","MVAR")
466 { foreign "C" barf("MVAR object entered!") never returns; }
468 INFO_TABLE(stg_MVAR_DIRTY,3,0,MVAR_DIRTY,"MVAR","MVAR")
469 { foreign "C" barf("MVAR object entered!") never returns; }
471 /* -----------------------------------------------------------------------------
473 -------------------------------------------------------------------------- */
475 INFO_TABLE(stg_TVAR, 0, 0, TVAR, "TVAR", "TVAR")
476 { foreign "C" barf("TVAR object entered!") never returns; }
478 INFO_TABLE(stg_TVAR_WATCH_QUEUE, 0, 0, TVAR_WATCH_QUEUE, "TVAR_WATCH_QUEUE", "TVAR_WATCH_QUEUE")
479 { foreign "C" barf("TVAR_WATCH_QUEUE object entered!") never returns; }
481 INFO_TABLE(stg_ATOMIC_INVARIANT, 0, 0, ATOMIC_INVARIANT, "ATOMIC_INVARIANT", "ATOMIC_INVARIANT")
482 { foreign "C" barf("ATOMIC_INVARIANT object entered!") never returns; }
484 INFO_TABLE(stg_INVARIANT_CHECK_QUEUE, 0, 0, INVARIANT_CHECK_QUEUE, "INVARIANT_CHECK_QUEUE", "INVARIANT_CHECK_QUEUE")
485 { foreign "C" barf("INVARIANT_CHECK_QUEUE object entered!") never returns; }
487 INFO_TABLE(stg_TREC_CHUNK, 0, 0, TREC_CHUNK, "TREC_CHUNK", "TREC_CHUNK")
488 { foreign "C" barf("TREC_CHUNK object entered!") never returns; }
490 INFO_TABLE(stg_TREC_HEADER, 0, 0, TREC_HEADER, "TREC_HEADER", "TREC_HEADER")
491 { foreign "C" barf("TREC_HEADER object entered!") never returns; }
493 INFO_TABLE_CONSTR(stg_END_STM_WATCH_QUEUE,0,0,0,CONSTR_NOCAF_STATIC,"END_STM_WATCH_QUEUE","END_STM_WATCH_QUEUE")
494 { foreign "C" barf("END_STM_WATCH_QUEUE object entered!") never returns; }
496 INFO_TABLE_CONSTR(stg_END_INVARIANT_CHECK_QUEUE,0,0,0,CONSTR_NOCAF_STATIC,"END_INVARIANT_CHECK_QUEUE","END_INVARIANT_CHECK_QUEUE")
497 { foreign "C" barf("END_INVARIANT_CHECK_QUEUE object entered!") never returns; }
499 INFO_TABLE_CONSTR(stg_END_STM_CHUNK_LIST,0,0,0,CONSTR_NOCAF_STATIC,"END_STM_CHUNK_LIST","END_STM_CHUNK_LIST")
500 { foreign "C" barf("END_STM_CHUNK_LIST object entered!") never returns; }
502 INFO_TABLE_CONSTR(stg_NO_TREC,0,0,0,CONSTR_NOCAF_STATIC,"NO_TREC","NO_TREC")
503 { foreign "C" barf("NO_TREC object entered!") never returns; }
505 CLOSURE(stg_END_STM_WATCH_QUEUE_closure,stg_END_STM_WATCH_QUEUE);
507 CLOSURE(stg_END_INVARIANT_CHECK_QUEUE_closure,stg_END_INVARIANT_CHECK_QUEUE);
509 CLOSURE(stg_END_STM_CHUNK_LIST_closure,stg_END_STM_CHUNK_LIST);
511 CLOSURE(stg_NO_TREC_closure,stg_NO_TREC);
513 /* ----------------------------------------------------------------------------
516 This is a static nullary constructor (like []) that we use to mark the
517 end of a linked TSO queue.
518 ------------------------------------------------------------------------- */
520 INFO_TABLE_CONSTR(stg_END_TSO_QUEUE,0,0,0,CONSTR_NOCAF_STATIC,"END_TSO_QUEUE","END_TSO_QUEUE")
521 { foreign "C" barf("END_TSO_QUEUE object entered!") never returns; }
523 CLOSURE(stg_END_TSO_QUEUE_closure,stg_END_TSO_QUEUE);
525 /* ----------------------------------------------------------------------------
527 ------------------------------------------------------------------------- */
529 INFO_TABLE_CONSTR(stg_END_EXCEPTION_LIST,0,0,0,CONSTR_NOCAF_STATIC,"END_EXCEPTION_LIST","END_EXCEPTION_LIST")
530 { foreign "C" barf("END_EXCEPTION_LIST object entered!") never returns; }
532 CLOSURE(stg_END_EXCEPTION_LIST_closure,stg_END_EXCEPTION_LIST);
534 INFO_TABLE(stg_EXCEPTION_CONS,1,1,CONSTR,"EXCEPTION_CONS","EXCEPTION_CONS")
535 { foreign "C" barf("EXCEPTION_CONS object entered!") never returns; }
537 /* ----------------------------------------------------------------------------
540 These come in two basic flavours: arrays of data (StgArrWords) and arrays of
541 pointers (StgArrPtrs). They all have a similar layout:
543 ___________________________
544 | Info | No. of | data....
546 ---------------------------
548 These are *unpointed* objects: i.e. they cannot be entered.
550 ------------------------------------------------------------------------- */
552 INFO_TABLE(stg_ARR_WORDS, 0, 0, ARR_WORDS, "ARR_WORDS", "ARR_WORDS")
553 { foreign "C" barf("ARR_WORDS object entered!") never returns; }
555 INFO_TABLE(stg_MUT_ARR_PTRS_CLEAN, 0, 0, MUT_ARR_PTRS_CLEAN, "MUT_ARR_PTRS_CLEAN", "MUT_ARR_PTRS_CLEAN")
556 { foreign "C" barf("MUT_ARR_PTRS_CLEAN object entered!") never returns; }
558 INFO_TABLE(stg_MUT_ARR_PTRS_DIRTY, 0, 0, MUT_ARR_PTRS_DIRTY, "MUT_ARR_PTRS_DIRTY", "MUT_ARR_PTRS_DIRTY")
559 { foreign "C" barf("MUT_ARR_PTRS_DIRTY object entered!") never returns; }
561 INFO_TABLE(stg_MUT_ARR_PTRS_FROZEN, 0, 0, MUT_ARR_PTRS_FROZEN, "MUT_ARR_PTRS_FROZEN", "MUT_ARR_PTRS_FROZEN")
562 { foreign "C" barf("MUT_ARR_PTRS_FROZEN object entered!") never returns; }
564 INFO_TABLE(stg_MUT_ARR_PTRS_FROZEN0, 0, 0, MUT_ARR_PTRS_FROZEN0, "MUT_ARR_PTRS_FROZEN0", "MUT_ARR_PTRS_FROZEN0")
565 { foreign "C" barf("MUT_ARR_PTRS_FROZEN0 object entered!") never returns; }
567 /* ----------------------------------------------------------------------------
569 ------------------------------------------------------------------------- */
571 INFO_TABLE(stg_MUT_VAR_CLEAN, 1, 0, MUT_VAR_CLEAN, "MUT_VAR_CLEAN", "MUT_VAR_CLEAN")
572 { foreign "C" barf("MUT_VAR_CLEAN object entered!") never returns; }
573 INFO_TABLE(stg_MUT_VAR_DIRTY, 1, 0, MUT_VAR_DIRTY, "MUT_VAR_DIRTY", "MUT_VAR_DIRTY")
574 { foreign "C" barf("MUT_VAR_DIRTY object entered!") never returns; }
576 /* ----------------------------------------------------------------------------
579 Entering this closure will just return to the address on the top of the
580 stack. Useful for getting a thread in a canonical form where we can
581 just enter the top stack word to start the thread. (see deleteThread)
582 * ------------------------------------------------------------------------- */
584 INFO_TABLE( stg_dummy_ret, 0, 0, CONSTR_NOCAF_STATIC, "DUMMY_RET", "DUMMY_RET")
586 jump %ENTRY_CODE(Sp(0));
588 CLOSURE(stg_dummy_ret_closure,stg_dummy_ret);
590 /* ----------------------------------------------------------------------------
591 CHARLIKE and INTLIKE closures.
593 These are static representations of Chars and small Ints, so that
594 we can remove dynamic Chars and Ints during garbage collection and
595 replace them with references to the static objects.
596 ------------------------------------------------------------------------- */
598 #if defined(__PIC__) && defined(mingw32_TARGET_OS)
600 * When sticking the RTS in a DLL, we delay populating the
601 * Charlike and Intlike tables until load-time, which is only
602 * when we've got the real addresses to the C# and I# closures.
605 #warning Is this correct? _imp is a pointer!
606 #define Char_hash_static_info _imp__base_GHCziBase_Czh_static_info
607 #define Int_hash_static_info _imp__base_GHCziBase_Izh_static_info
609 #define Char_hash_static_info base_GHCziBase_Czh_static_info
610 #define Int_hash_static_info base_GHCziBase_Izh_static_info
614 #define CHARLIKE_HDR(n) CLOSURE(Char_hash_static_info, n)
615 #define INTLIKE_HDR(n) CLOSURE(Int_hash_static_info, n)
617 /* put these in the *data* section, since the garbage collector relies
618 * on the fact that static closures live in the data section.
621 /* end the name with _closure, to convince the mangler this is a closure */
624 stg_CHARLIKE_closure:
885 INTLIKE_HDR(-16) /* MIN_INTLIKE == -16 */
917 INTLIKE_HDR(16) /* MAX_INTLIKE == 16 */