1 /* -----------------------------------------------------------------------------
3 * (c) The University of Glasgow 2004
5 * Application-related bits.
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 * Evaluate a closure and return it.
18 * There isn't an info table / return address version of stg_ap_0, because
19 * everything being returned is guaranteed evaluated, so it would be a no-op.
22 STRING(stg_ap_0_ret_str,"stg_ap_0_ret... ")
26 // fn is in R1, no args on the stack
29 foreign "C" debugBelch(stg_ap_0_ret_str) [R1];
30 foreign "C" printClosure(R1 "ptr") [R1]);
33 foreign "C" checkStackChunk(Sp "ptr",
34 CurrentTSO + TSO_OFFSET_StgTSO_stack +
35 WDS(StgTSO_stack_size(CurrentTSO)) "ptr") [R1]);
40 /* -----------------------------------------------------------------------------
43 This entry code is *only* called by one of the stg_ap functions.
44 On entry: Sp points to the remaining arguments on the stack. If
45 the stack check fails, we can just push the PAP on the stack and
46 return to the scheduler.
48 On entry: R1 points to the PAP. The rest of the function's
49 arguments (apart from those that are already in the PAP) are on the
50 stack, starting at Sp(0). R2 contains an info table which
51 describes these arguments, which is used in the event that the
52 stack check in the entry code below fails. The info table is
53 currently one of the stg_ap_*_ret family, as this code is always
54 entered from those functions.
56 The idea is to copy the chunk of stack from the PAP object onto the
57 stack / into registers, and enter the function.
58 -------------------------------------------------------------------------- */
60 INFO_TABLE(stg_PAP,/*special layout*/0,0,PAP,"PAP","PAP")
67 Words = TO_W_(StgPAP_n_args(pap));
70 // Check for stack overflow and bump the stack pointer.
71 // We have a hand-rolled stack check fragment here, because none of
72 // the canned ones suit this situation.
74 if ((Sp - WDS(Words)) < SpLim) {
75 // there is a return address in R2 in the event of a
76 // stack check failure. The various stg_apply functions arrange
77 // this before calling stg_PAP_entry.
87 // Enter PAP cost centre
88 ENTER_CCS_PAP_CL(pap);
95 p = pap + SIZEOF_StgHeader + OFFSET_StgPAP_payload;
112 info = %GET_FUN_INFO(R1);
114 type = TO_W_(StgFunInfoExtra_fun_type(info));
115 if (type == ARG_GEN) {
116 jump StgFunInfoExtra_slow_apply(info);
118 if (type == ARG_GEN_BIG) {
119 jump StgFunInfoExtra_slow_apply(info);
121 if (type == ARG_BCO) {
124 Sp(0) = stg_apply_interp_info;
125 jump stg_yield_to_interpreter;
127 jump W_[stg_ap_stack_entries +
128 WDS(TO_W_(StgFunInfoExtra_fun_type(info)))];
132 /* -----------------------------------------------------------------------------
133 Entry Code for an AP (a PAP with arity zero).
135 The entry code is very similar to a PAP, except there are no
136 further arguments on the stack to worry about, so the stack check
137 is simpler. We must also push an update frame on the stack before
138 applying the function.
139 -------------------------------------------------------------------------- */
141 INFO_TABLE(stg_AP,/*special layout*/0,0,AP,"AP","AP")
148 Words = TO_W_(StgAP_n_args(ap));
151 * Check for stack overflow. IMPORTANT: use a _NP check here,
152 * because if the check fails, we might end up blackholing this very
153 * closure, in which case we must enter the blackhole on return rather
154 * than continuing to evaluate the now-defunct closure.
156 STK_CHK_NP(WDS(Words) + SIZEOF_StgUpdateFrame);
158 PUSH_UPD_FRAME(Sp - SIZEOF_StgUpdateFrame, R1);
159 Sp = Sp - SIZEOF_StgUpdateFrame - WDS(Words);
164 // Enter PAP cost centre
165 ENTER_CCS_PAP_CL(ap); // ToDo: ENTER_CC_AP_CL
172 p = ap + SIZEOF_StgHeader + OFFSET_StgAP_payload;
189 info = %GET_FUN_INFO(R1);
191 type = TO_W_(StgFunInfoExtra_fun_type(info));
192 if (type == ARG_GEN) {
193 jump StgFunInfoExtra_slow_apply(info);
195 if (type == ARG_GEN_BIG) {
196 jump StgFunInfoExtra_slow_apply(info);
198 if (type == ARG_BCO) {
201 Sp(0) = stg_apply_interp_info;
202 jump stg_yield_to_interpreter;
204 jump W_[stg_ap_stack_entries +
205 WDS(TO_W_(StgFunInfoExtra_fun_type(info)))];
209 /* -----------------------------------------------------------------------------
210 Entry Code for an AP_STACK.
212 Very similar to a PAP and AP. The layout is the same as PAP
213 and AP, except that the payload is a chunk of stack instead of
214 being described by the function's info table. Like an AP,
215 there are no further arguments on the stack to worry about.
216 However, the function closure (ap->fun) does not necessarily point
217 directly to a function, so we have to enter it using stg_ap_0.
218 -------------------------------------------------------------------------- */
220 INFO_TABLE(stg_AP_STACK,/*special layout*/0,0,AP_STACK,"AP_STACK","AP_STACK")
227 Words = StgAP_STACK_size(ap);
230 * Check for stack overflow. IMPORTANT: use a _NP check here,
231 * because if the check fails, we might end up blackholing this very
232 * closure, in which case we must enter the blackhole on return rather
233 * than continuing to evaluate the now-defunct closure.
235 STK_CHK_NP(WDS(Words) + SIZEOF_StgUpdateFrame);
237 PUSH_UPD_FRAME(Sp - SIZEOF_StgUpdateFrame, R1);
238 Sp = Sp - SIZEOF_StgUpdateFrame - WDS(Words);
243 // Enter PAP cost centre
244 ENTER_CCS_PAP_CL(ap); // ToDo: ENTER_CC_AP_CL
246 R1 = StgAP_STACK_fun(ap);
251 p = ap + SIZEOF_StgHeader + OFFSET_StgAP_STACK_payload;