+/* -----------------------------------------------------------------------------
+ Generic function entry heap check code.
+
+ At a function entry point, the arguments are as per the calling convention,
+ i.e. some in regs and some on the stack. There may or may not be
+ a pointer to the function closure in R1 - if there isn't, then the heap
+ check failure code in the function will arrange to load it.
+
+ The function's argument types are described in its info table, so we
+ can just jump to this bit of generic code to save away all the
+ registers and return to the scheduler.
+
+ This code arranges the stack like this:
+
+ | .... |
+ | args |
+ +---------------------+
+ | f_closure |
+ +---------------------+
+ | size |
+ +---------------------+
+ | stg_gc_fun_info |
+ +---------------------+
+
+ The size is the number of words of arguments on the stack, and is cached
+ in the frame in order to simplify stack walking: otherwise the size of
+ this stack frame would have to be calculated by looking at f's info table.
+
+ -------------------------------------------------------------------------- */
+
+EXTFUN(__stg_gc_fun)
+{
+ StgWord size;
+ StgFunInfoTable *info;
+ FB_
+
+ info = get_fun_itbl(R1.cl);
+
+ // cache the size
+ if (info->fun_type == ARG_GEN) {
+ size = BITMAP_SIZE(info->bitmap);
+ } else if (info->fun_type == ARG_GEN_BIG) {
+ size = ((StgLargeBitmap *)info->bitmap)->size;
+ } else {
+ size = BITMAP_SIZE(stg_arg_bitmaps[info->fun_type]);
+ }
+
+#ifdef NO_ARG_REGS
+ // we don't have to save any registers away
+ Sp -= 3;
+ Sp[2] = R1.w;
+ Sp[1] = size;
+ Sp[0] = (W_)&stg_gc_fun_info;
+ GC_GENERIC
+#else
+ if (info->fun_type == ARG_GEN || info->fun_type == ARG_GEN_BIG) {
+ // regs already saved by the heap check code
+ Sp -= 3;
+ Sp[2] = R1.w;
+ Sp[1] = size;
+ Sp[0] = (W_)&stg_gc_fun_info;
+ DEBUG_ONLY(fprintf(stderr, "stg_fun_gc_gen(ARG_GEN)"););
+ GC_GENERIC
+ } else {
+ JMP_(stg_stack_save_entries[info->fun_type]);
+ // jumps to stg_gc_noregs after saving stuff
+ }
+#endif // !NO_ARG_REGS
+
+ FE_
+}
+
+/* -----------------------------------------------------------------------------
+ Generic Apply (return point)
+
+ The dual to stg_fun_gc_gen (above): this fragment returns to the
+ function, passing arguments in the stack and in registers
+ appropriately. The stack layout is given above.
+ -------------------------------------------------------------------------- */
+
+INFO_TABLE_RET( stg_gc_fun_info,stg_gc_fun_ret,
+ MK_SMALL_BITMAP(0/*framesize*/, 0/*bitmap*/),
+ 0/*SRT*/, 0/*SRT_OFF*/, 0/*SRT_BITMAP*/,
+ RET_FUN,, EF_, 0, 0);
+
+EXTFUN(stg_gc_fun_ret)