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 /* ----------------------------------------------------------------------------
16 Support for the bytecode interpreter.
17 ------------------------------------------------------------------------- */
19 /* 9 bits of return code for constructors created by the interpreter. */
20 stg_interp_constr_entry
22 /* R1 points at the constructor */
23 jump %ENTRY_CODE(Sp(0));
26 /* Some info tables to be used when compiled code returns a value to
27 the interpreter, i.e. the interpreter pushes one of these onto the
28 stack before entering a value. What the code does is to
29 impedance-match the compiled return convention (in R1p/R1n/F1/D1 etc) to
30 the interpreter's convention (returned value is on top of stack),
31 and then cause the scheduler to enter the interpreter.
33 On entry, the stack (growing down) looks like this:
35 ptr to BCO holding return continuation
36 ptr to one of these info tables.
38 The info table code, both direct and vectored, must:
39 * push R1/F1/D1 on the stack, and its tag if necessary
40 * push the BCO (so it's now on the stack twice)
41 * Yield, ie, go to the scheduler.
43 Scheduler examines the t.o.s, discovers it is a BCO, and proceeds
44 directly to the bytecode interpreter. That pops the top element
45 (the BCO, containing the return continuation), and interprets it.
46 Net result: return continuation gets interpreted, with the
50 ptr to the info table just jumped thru
53 which is just what we want -- the "standard" return layout for the
56 Don't ask me how unboxed tuple returns are supposed to work. We
57 haven't got a good story about that yet.
60 INFO_TABLE_RET( stg_ctoi_R1p,
61 0/*size*/, 0/*bitmap*/, /* special layout! */
66 Sp(0) = stg_enter_info;
67 jump stg_yield_to_interpreter;
71 * When the returned value is a pointer, but unlifted, in R1 ...
73 INFO_TABLE_RET( stg_ctoi_R1unpt,
74 0/*size*/, 0/*bitmap*/, /* special layout! */
79 Sp(0) = stg_gc_unpt_r1_info;
80 jump stg_yield_to_interpreter;
84 * When the returned value is a non-pointer in R1 ...
86 INFO_TABLE_RET( stg_ctoi_R1n,
87 0/*size*/, 0/*bitmap*/, /* special layout! */
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,
100 0/*size*/, 0/*bitmap*/, /* special layout! */
104 F_[Sp + WDS(1)] = F1;
105 Sp(0) = stg_gc_f1_info;
106 jump stg_yield_to_interpreter;
110 * When the returned value is in D1
112 INFO_TABLE_RET( stg_ctoi_D1,
113 0/*size*/, 0/*bitmap*/, /* special layout! */
116 Sp_adj(-1) - SIZEOF_DOUBLE;
117 D_[Sp + WDS(1)] = D1;
118 Sp(0) = stg_gc_d1_info;
119 jump stg_yield_to_interpreter;
123 * When the returned value is in L1
125 INFO_TABLE_RET( stg_ctoi_L1,
126 0/*size*/, 0/*bitmap*/, /* special layout! */
130 L_[Sp + WDS(1)] = L1;
131 Sp(0) = stg_gc_l1_info;
132 jump stg_yield_to_interpreter;
136 * When the returned value is a void
138 INFO_TABLE_RET( stg_ctoi_V,
139 0/*size*/, 0/*bitmap*/, /* special layout! */
143 Sp(0) = stg_gc_void_info;
144 jump stg_yield_to_interpreter;
148 * Dummy info table pushed on the top of the stack when the interpreter
149 * should apply the BCO on the stack to its arguments, also on the
152 INFO_TABLE_RET( stg_apply_interp,
153 0/*size*/, 0/*bitmap*/, /* special layout! */
156 /* Just in case we end up in here... (we shouldn't) */
157 jump stg_yield_to_interpreter;
160 /* ----------------------------------------------------------------------------
162 ------------------------------------------------------------------------- */
164 INFO_TABLE_FUN( stg_BCO, 4, 0, BCO, "BCO", "BCO", ARG_BCO )
166 /* entering a BCO means "apply it", same as a function */
169 Sp(0) = stg_apply_interp_info;
170 jump stg_yield_to_interpreter;
173 /* ----------------------------------------------------------------------------
174 Info tables for indirections.
176 SPECIALISED INDIRECTIONS: we have a specialised indirection for direct returns,
177 so that we can avoid entering
178 the object when we know it points directly to a value. The update
179 code (Updates.cmm) updates objects with the appropriate kind of
180 indirection. We only do this for young-gen indirections.
181 ------------------------------------------------------------------------- */
183 INFO_TABLE(stg_IND,1,0,IND,"IND","IND")
185 TICK_ENT_DYN_IND(); /* tick */
186 R1 = StgInd_indirectee(R1);
191 INFO_TABLE(stg_IND_direct,1,0,IND,"IND","IND")
193 TICK_ENT_DYN_IND(); /* tick */
194 R1 = StgInd_indirectee(R1);
196 jump %ENTRY_CODE(Sp(0));
199 INFO_TABLE(stg_IND_STATIC,1,0,IND_STATIC,"IND_STATIC","IND_STATIC")
201 TICK_ENT_STATIC_IND(); /* tick */
202 R1 = StgInd_indirectee(R1);
207 INFO_TABLE(stg_IND_PERM,1,0,IND_PERM,"IND_PERM","IND_PERM")
209 /* Don't add INDs to granularity cost */
211 /* Don't: TICK_ENT_STATIC_IND(Node); for ticky-ticky; this ind is
212 here only to help profiling */
214 #if defined(TICKY_TICKY) && !defined(PROFILING)
215 /* TICKY_TICKY && !PROFILING means PERM_IND *replaces* an IND, rather than
222 /* Enter PAP cost centre */
223 ENTER_CCS_PAP_CL(R1);
225 /* For ticky-ticky, change the perm_ind to a normal ind on first
226 * entry, so the number of ent_perm_inds is the number of *thunks*
227 * entered again, not the number of subsequent entries.
229 * Since this screws up cost centres, we die if profiling and
230 * ticky_ticky are on at the same time. KSW 1999-01.
234 # error Profiling and ticky-ticky do not mix at present!
235 # endif /* PROFILING */
236 StgHeader_info(R1) = stg_IND_info;
237 #endif /* TICKY_TICKY */
239 R1 = StgInd_indirectee(R1);
241 #if defined(TICKY_TICKY) && !defined(PROFILING)
249 INFO_TABLE(stg_IND_OLDGEN,1,0,IND_OLDGEN,"IND_OLDGEN","IND_OLDGEN")
251 TICK_ENT_STATIC_IND(); /* tick */
252 R1 = StgInd_indirectee(R1);
257 INFO_TABLE(stg_IND_OLDGEN_PERM,1,0,IND_OLDGEN_PERM,"IND_OLDGEN_PERM","IND_OLDGEN_PERM")
259 /* Don't: TICK_ENT_STATIC_IND(Node); for ticky-ticky;
260 this ind is here only to help profiling */
262 #if defined(TICKY_TICKY) && !defined(PROFILING)
263 /* TICKY_TICKY && !PROFILING means PERM_IND *replaces* an IND,
264 rather than being extra */
265 TICK_ENT_PERM_IND(); /* tick */
270 /* Enter PAP cost centre -- lexical scoping only */
271 ENTER_CCS_PAP_CL(R1);
273 /* see comment in IND_PERM */
276 # error Profiling and ticky-ticky do not mix at present!
277 # endif /* PROFILING */
278 StgHeader_info(R1) = stg_IND_OLDGEN_info;
279 #endif /* TICKY_TICKY */
281 R1 = StgInd_indirectee(R1);
287 /* ----------------------------------------------------------------------------
290 Entering a black hole normally causes a cyclic data dependency, but
291 in the concurrent world, black holes are synchronization points,
292 and they are turned into blocking queues when there are threads
293 waiting for the evaluation of the closure to finish.
294 ------------------------------------------------------------------------- */
296 /* Note: a BLACKHOLE must be big enough to be
297 * overwritten with an indirection/evacuee/catch. Thus we claim it
298 * has 1 non-pointer word of payload.
300 INFO_TABLE(stg_BLACKHOLE,0,1,BLACKHOLE,"BLACKHOLE","BLACKHOLE")
303 /* Before overwriting TSO_LINK */
304 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1 /*Node*/);
310 // foreign "C" debugBelch("BLACKHOLE entry\n");
313 /* Actually this is not necessary because R1 is about to be destroyed. */
316 #if defined(THREADED_RTS)
317 foreign "C" ACQUIRE_LOCK(sched_mutex "ptr");
318 // released in stg_block_blackhole_finally
321 /* Put ourselves on the blackhole queue */
322 StgTSO_link(CurrentTSO) = W_[blackhole_queue];
323 W_[blackhole_queue] = CurrentTSO;
325 /* jot down why and on what closure we are blocked */
326 StgTSO_why_blocked(CurrentTSO) = BlockedOnBlackHole::I16;
327 StgTSO_block_info(CurrentTSO) = R1;
329 jump stg_block_blackhole;
332 #if defined(PAR) || defined(GRAN)
334 INFO_TABLE(stg_RBH,1,1,RBH,"RBH","RBH")
337 /* mainly statistics gathering for GranSim simulation */
338 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1 /*Node*/);
341 /* exactly the same as a BLACKHOLE_BQ_entry -- HWL */
342 /* Put ourselves on the blocking queue for this black hole */
343 TSO_link(CurrentTSO) = StgBlockingQueue_blocking_queue(R1);
344 StgBlockingQueue_blocking_queue(R1) = CurrentTSO;
345 /* jot down why and on what closure we are blocked */
346 TSO_why_blocked(CurrentTSO) = BlockedOnBlackHole::I16;
347 TSO_block_info(CurrentTSO) = R1;
349 /* PAR: dumping of event now done in blockThread -- HWL */
351 /* stg_gen_block is too heavyweight, use a specialised one */
355 INFO_TABLE(stg_RBH_Save_0,0,2,CONSTR,"RBH_Save_0","RBH_Save_0")
356 { foreign "C" barf("RBH_Save_0 object entered!"); }
358 INFO_TABLE(stg_RBH_Save_1,1,1,CONSTR,"RBH_Save_1","RBH_Save_1");
359 { foreign "C" barf("RBH_Save_1 object entered!"); }
361 INFO_TABLE(stg_RBH_Save_2,2,0,CONSTR,"RBH_Save_2","RBH_Save_2");
362 { foreign "C" barf("RBH_Save_2 object entered!"); }
364 #endif /* defined(PAR) || defined(GRAN) */
366 /* identical to BLACKHOLEs except for the infotag */
367 INFO_TABLE(stg_CAF_BLACKHOLE,0,1,CAF_BLACKHOLE,"CAF_BLACKHOLE","CAF_BLACKHOLE")
370 /* mainly statistics gathering for GranSim simulation */
371 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1 /*Node*/);
377 #if defined(THREADED_RTS)
378 // foreign "C" debugBelch("BLACKHOLE entry\n");
381 #if defined(THREADED_RTS)
382 foreign "C" ACQUIRE_LOCK(sched_mutex "ptr");
383 // released in stg_block_blackhole_finally
386 /* Put ourselves on the blackhole queue */
387 StgTSO_link(CurrentTSO) = W_[blackhole_queue];
388 W_[blackhole_queue] = CurrentTSO;
390 /* jot down why and on what closure we are blocked */
391 StgTSO_why_blocked(CurrentTSO) = BlockedOnBlackHole::I16;
392 StgTSO_block_info(CurrentTSO) = R1;
394 jump stg_block_blackhole;
397 #ifdef EAGER_BLACKHOLING
398 INFO_TABLE(stg_SE_BLACKHOLE,0,1,SE_BLACKHOLE,"SE_BLACKHOLE","SE_BLACKHOLE")
399 { foreign "C" barf("SE_BLACKHOLE object entered!"); }
401 INFO_TABLE(stg_SE_CAF_BLACKHOLE,0,1,SE_CAF_BLACKHOLE,"SE_CAF_BLACKHOLE","SE_CAF_BLACKHOLE")
402 { foreign "C" barf("SE_CAF_BLACKHOLE object entered!"); }
405 /* ----------------------------------------------------------------------------
406 Whiteholes are used for the "locked" state of a closure (see lockClosure())
408 The closure type is BLAKCHOLE, just because we need a valid closure type
410 ------------------------------------------------------------------------- */
412 INFO_TABLE(stg_WHITEHOLE, 0,0, BLACKHOLE, "WHITEHOLE", "WHITEHOLE")
413 { foreign "C" barf("WHITEHOLE object entered!"); }
415 /* ----------------------------------------------------------------------------
416 Some static info tables for things that don't get entered, and
417 therefore don't need entry code (i.e. boxed but unpointed objects)
418 NON_ENTERABLE_ENTRY_CODE now defined at the beginning of the file
419 ------------------------------------------------------------------------- */
421 INFO_TABLE(stg_TSO, 0,0,TSO, "TSO", "TSO")
422 { foreign "C" barf("TSO object entered!"); }
424 /* ----------------------------------------------------------------------------
425 Evacuees are left behind by the garbage collector. Any attempt to enter
427 ------------------------------------------------------------------------- */
429 INFO_TABLE(stg_EVACUATED,1,0,EVACUATED,"EVACUATED","EVACUATED")
430 { foreign "C" barf("EVACUATED object entered!"); }
432 /* ----------------------------------------------------------------------------
435 Live weak pointers have a special closure type. Dead ones are just
436 nullary constructors (although they live on the heap - we overwrite
437 live weak pointers with dead ones).
438 ------------------------------------------------------------------------- */
440 INFO_TABLE(stg_WEAK,0,4,WEAK,"WEAK","WEAK")
441 { foreign "C" barf("WEAK object entered!"); }
444 * It's important when turning an existing WEAK into a DEAD_WEAK
445 * (which is what finalizeWeak# does) that we don't lose the link
446 * field and break the linked list of weak pointers. Hence, we give
447 * DEAD_WEAK 4 non-pointer fields, the same as WEAK.
449 INFO_TABLE_CONSTR(stg_DEAD_WEAK,0,4,0,CONSTR,"DEAD_WEAK","DEAD_WEAK")
450 { foreign "C" barf("DEAD_WEAK object entered!"); }
452 /* ----------------------------------------------------------------------------
455 This is a static nullary constructor (like []) that we use to mark an empty
456 finalizer in a weak pointer object.
457 ------------------------------------------------------------------------- */
459 INFO_TABLE_CONSTR(stg_NO_FINALIZER,0,0,0,CONSTR_NOCAF_STATIC,"NO_FINALIZER","NO_FINALIZER")
460 { foreign "C" barf("NO_FINALIZER object entered!"); }
462 CLOSURE(stg_NO_FINALIZER_closure,stg_NO_FINALIZER);
464 /* ----------------------------------------------------------------------------
465 Stable Names are unlifted too.
466 ------------------------------------------------------------------------- */
468 INFO_TABLE(stg_STABLE_NAME,0,1,STABLE_NAME,"STABLE_NAME","STABLE_NAME")
469 { foreign "C" barf("STABLE_NAME object entered!"); }
471 /* ----------------------------------------------------------------------------
474 There are two kinds of these: full and empty. We need an info table
475 and entry code for each type.
476 ------------------------------------------------------------------------- */
478 INFO_TABLE(stg_FULL_MVAR,3,0,MVAR,"MVAR","MVAR")
479 { foreign "C" barf("FULL_MVAR object entered!"); }
481 INFO_TABLE(stg_EMPTY_MVAR,3,0,MVAR,"MVAR","MVAR")
482 { foreign "C" barf("EMPTY_MVAR object entered!"); }
484 /* -----------------------------------------------------------------------------
486 -------------------------------------------------------------------------- */
488 INFO_TABLE(stg_TVAR, 0, 0, TVAR, "TVAR", "TVAR")
489 { foreign "C" barf("TVAR object entered!"); }
491 INFO_TABLE(stg_TVAR_WATCH_QUEUE, 0, 0, TVAR_WATCH_QUEUE, "TVAR_WATCH_QUEUE", "TVAR_WATCH_QUEUE")
492 { foreign "C" barf("TVAR_WATCH_QUEUE object entered!"); }
494 INFO_TABLE(stg_ATOMIC_INVARIANT, 0, 0, ATOMIC_INVARIANT, "ATOMIC_INVARIANT", "ATOMIC_INVARIANT")
495 { foreign "C" barf("ATOMIC_INVARIANT object entered!"); }
497 INFO_TABLE(stg_INVARIANT_CHECK_QUEUE, 0, 0, INVARIANT_CHECK_QUEUE, "INVARIANT_CHECK_QUEUE", "INVARIANT_CHECK_QUEUE")
498 { foreign "C" barf("INVARIANT_CHECK_QUEUE object entered!"); }
500 INFO_TABLE(stg_TREC_CHUNK, 0, 0, TREC_CHUNK, "TREC_CHUNK", "TREC_CHUNK")
501 { foreign "C" barf("TREC_CHUNK object entered!"); }
503 INFO_TABLE(stg_TREC_HEADER, 0, 0, TREC_HEADER, "TREC_HEADER", "TREC_HEADER")
504 { foreign "C" barf("TREC_HEADER object entered!"); }
506 INFO_TABLE_CONSTR(stg_END_STM_WATCH_QUEUE,0,0,0,CONSTR_NOCAF_STATIC,"END_STM_WATCH_QUEUE","END_STM_WATCH_QUEUE")
507 { foreign "C" barf("END_STM_WATCH_QUEUE object entered!"); }
509 INFO_TABLE_CONSTR(stg_END_INVARIANT_CHECK_QUEUE,0,0,0,CONSTR_NOCAF_STATIC,"END_INVARIANT_CHECK_QUEUE","END_INVARIANT_CHECK_QUEUE")
510 { foreign "C" barf("END_INVARIANT_CHECK_QUEUE object entered!"); }
512 INFO_TABLE_CONSTR(stg_END_STM_CHUNK_LIST,0,0,0,CONSTR_NOCAF_STATIC,"END_STM_CHUNK_LIST","END_STM_CHUNK_LIST")
513 { foreign "C" barf("END_STM_CHUNK_LIST object entered!"); }
515 INFO_TABLE_CONSTR(stg_NO_TREC,0,0,0,CONSTR_NOCAF_STATIC,"NO_TREC","NO_TREC")
516 { foreign "C" barf("NO_TREC object entered!"); }
518 CLOSURE(stg_END_STM_WATCH_QUEUE_closure,stg_END_STM_WATCH_QUEUE);
520 CLOSURE(stg_END_INVARIANT_CHECK_QUEUE_closure,stg_END_INVARIANT_CHECK_QUEUE);
522 CLOSURE(stg_END_STM_CHUNK_LIST_closure,stg_END_STM_CHUNK_LIST);
524 CLOSURE(stg_NO_TREC_closure,stg_NO_TREC);
526 /* ----------------------------------------------------------------------------
529 This is a static nullary constructor (like []) that we use to mark the
530 end of a linked TSO queue.
531 ------------------------------------------------------------------------- */
533 INFO_TABLE_CONSTR(stg_END_TSO_QUEUE,0,0,0,CONSTR_NOCAF_STATIC,"END_TSO_QUEUE","END_TSO_QUEUE")
534 { foreign "C" barf("END_TSO_QUEUE object entered!"); }
536 CLOSURE(stg_END_TSO_QUEUE_closure,stg_END_TSO_QUEUE);
538 /* ----------------------------------------------------------------------------
540 ------------------------------------------------------------------------- */
542 INFO_TABLE_CONSTR(stg_END_EXCEPTION_LIST,0,0,0,CONSTR_NOCAF_STATIC,"END_EXCEPTION_LIST","END_EXCEPTION_LIST")
543 { foreign "C" barf("END_EXCEPTION_LIST object entered!"); }
545 CLOSURE(stg_END_EXCEPTION_LIST_closure,stg_END_EXCEPTION_LIST);
547 INFO_TABLE(stg_EXCEPTION_CONS,1,1,CONSTR,"EXCEPTION_CONS","EXCEPTION_CONS")
548 { foreign "C" barf("EXCEPTION_CONS object entered!"); }
550 /* ----------------------------------------------------------------------------
553 These come in two basic flavours: arrays of data (StgArrWords) and arrays of
554 pointers (StgArrPtrs). They all have a similar layout:
556 ___________________________
557 | Info | No. of | data....
559 ---------------------------
561 These are *unpointed* objects: i.e. they cannot be entered.
563 ------------------------------------------------------------------------- */
565 INFO_TABLE(stg_ARR_WORDS, 0, 0, ARR_WORDS, "ARR_WORDS", "ARR_WORDS")
566 { foreign "C" barf("ARR_WORDS object entered!"); }
568 INFO_TABLE(stg_MUT_ARR_PTRS_CLEAN, 0, 0, MUT_ARR_PTRS_CLEAN, "MUT_ARR_PTRS_CLEAN", "MUT_ARR_PTRS_CLEAN")
569 { foreign "C" barf("MUT_ARR_PTRS_CLEAN object entered!"); }
571 INFO_TABLE(stg_MUT_ARR_PTRS_DIRTY, 0, 0, MUT_ARR_PTRS_DIRTY, "MUT_ARR_PTRS_DIRTY", "MUT_ARR_PTRS_DIRTY")
572 { foreign "C" barf("MUT_ARR_PTRS_DIRTY object entered!"); }
574 INFO_TABLE(stg_MUT_ARR_PTRS_FROZEN, 0, 0, MUT_ARR_PTRS_FROZEN, "MUT_ARR_PTRS_FROZEN", "MUT_ARR_PTRS_FROZEN")
575 { foreign "C" barf("MUT_ARR_PTRS_FROZEN object entered!"); }
577 INFO_TABLE(stg_MUT_ARR_PTRS_FROZEN0, 0, 0, MUT_ARR_PTRS_FROZEN0, "MUT_ARR_PTRS_FROZEN0", "MUT_ARR_PTRS_FROZEN0")
578 { foreign "C" barf("MUT_ARR_PTRS_FROZEN0 object entered!"); }
580 /* ----------------------------------------------------------------------------
582 ------------------------------------------------------------------------- */
584 INFO_TABLE(stg_MUT_VAR_CLEAN, 1, 0, MUT_VAR_CLEAN, "MUT_VAR_CLEAN", "MUT_VAR_CLEAN")
585 { foreign "C" barf("MUT_VAR_CLEAN object entered!"); }
586 INFO_TABLE(stg_MUT_VAR_DIRTY, 1, 0, MUT_VAR_DIRTY, "MUT_VAR_DIRTY", "MUT_VAR_DIRTY")
587 { foreign "C" barf("MUT_VAR_DIRTY object entered!"); }
589 /* ----------------------------------------------------------------------------
592 Entering this closure will just return to the address on the top of the
593 stack. Useful for getting a thread in a canonical form where we can
594 just enter the top stack word to start the thread. (see deleteThread)
595 * ------------------------------------------------------------------------- */
597 INFO_TABLE( stg_dummy_ret, 0, 0, CONSTR_NOCAF_STATIC, "DUMMY_RET", "DUMMY_RET")
599 jump %ENTRY_CODE(Sp(0));
601 CLOSURE(stg_dummy_ret_closure,stg_dummy_ret);
603 /* ----------------------------------------------------------------------------
604 CHARLIKE and INTLIKE closures.
606 These are static representations of Chars and small Ints, so that
607 we can remove dynamic Chars and Ints during garbage collection and
608 replace them with references to the static objects.
609 ------------------------------------------------------------------------- */
611 #if defined(ENABLE_WIN32_DLL_SUPPORT)
613 * When sticking the RTS in a DLL, we delay populating the
614 * Charlike and Intlike tables until load-time, which is only
615 * when we've got the real addresses to the C# and I# closures.
618 static INFO_TBL_CONST StgInfoTable czh_static_info;
619 static INFO_TBL_CONST StgInfoTable izh_static_info;
620 #define Char_hash_static_info czh_static_info
621 #define Int_hash_static_info izh_static_info
623 #define Char_hash_static_info base_GHCziBase_Czh_static
624 #define Int_hash_static_info base_GHCziBase_Izh_static
628 #define CHARLIKE_HDR(n) CLOSURE(Char_hash_static_info, n)
629 #define INTLIKE_HDR(n) CLOSURE(Int_hash_static_info, n)
631 /* put these in the *data* section, since the garbage collector relies
632 * on the fact that static closures live in the data section.
635 /* end the name with _closure, to convince the mangler this is a closure */
638 stg_CHARLIKE_closure:
899 INTLIKE_HDR(-16) /* MIN_INTLIKE == -16 */
931 INTLIKE_HDR(16) /* MAX_INTLIKE == 16 */