[project @ 2004-02-12 02:04:59 by mthomas]
[ghc-hetmet.git] / ghc / rts / StgStdThunks.hc
1 /* -----------------------------------------------------------------------------
2  * $Id: StgStdThunks.hc,v 1.22 2003/04/18 09:40:10 simonmar Exp $
3  *
4  * (c) The GHC Team, 1998-2000
5  *
6  * Canned "Standard Form" Thunks
7  *
8  * ---------------------------------------------------------------------------*/
9
10 #include "Stg.h"
11 #include "Rts.h"
12 #include "StoragePriv.h"
13
14 /* -----------------------------------------------------------------------------
15    The code for a thunk that simply extracts a field from a
16    single-constructor datatype depends only on the offset of the field
17    to be selected.
18
19    Here we define some canned "selector" thunks that do just that; any
20    selector thunk appearing in a program will refer to one of these
21    instead of being compiled independently.
22
23    The garbage collector spots selector thunks and reduces them if
24    possible, in order to avoid space leaks resulting from lazy pattern
25    matching.
26    -------------------------------------------------------------------------- */
27
28 #define UPD_FRAME_SIZE (sizeofW(StgUpdateFrame)+sizeofW(StgHeader))
29 #define NOUPD_FRAME_SIZE (sizeofW(StgHeader))
30
31 #ifdef PROFILING
32 #define SAVE_CCCS(fs)   CCS_HDR(Sp-fs)=CCCS
33 #define GET_SAVED_CCCS  RESTORE_CCCS(CCS_HDR(Sp))
34 #define ENTER_CCS(p)    ENTER_CCS_TCL(p)
35 #define RET_BITMAP    3
36 #define RET_FRAMESIZE 2
37 #else
38 #define SAVE_CCCS(fs)   /* empty */
39 #define GET_SAVED_CCCS  /* empty */
40 #define ENTER_CCS(p)    /* empty */
41 #define RET_BITMAP    0
42 #define RET_FRAMESIZE 0
43 #endif
44
45 #define SELECTOR_CODE_UPD(offset) \
46   IF_(stg_sel_ret_##offset##_upd_ret);                                  \
47   INFO_TABLE_RET(stg_sel_ret_##offset##_upd_info,stg_sel_ret_##offset##_upd_ret, MK_SMALL_BITMAP(RET_FRAMESIZE, RET_BITMAP), 0, 0, 0, RET_SMALL, static, EF_, 0, 0);    \
48   EF_(stg_sel_ret_##offset##_upd_ret) {                                 \
49     FB_                                                                 \
50       R1.p=(P_)R1.cl->payload[offset];                                  \
51       GET_SAVED_CCCS;                                                   \
52       Sp=Sp+sizeofW(StgHeader);                                         \
53       ENTER();                                                          \
54     FE_                                                                 \
55   }                                                                     \
56                                                                         \
57   EF_(stg_sel_##offset##_upd_entry);                                    \
58   INFO_TABLE_SELECTOR(stg_sel_##offset##_upd_info, stg_sel_##offset##_upd_entry, offset,, EF_, "stg_sel" #offset "_upd_entry", "stg_sel" #offset "_upd_entry");\
59   EF_(stg_sel_##offset##_upd_entry) {                                   \
60     FB_                                                                 \
61       TICK_ENT_DYN_THK();  /* is it static or dynamic?? */              \
62       STK_CHK_NP(UPD_FRAME_SIZE,);                                      \
63       UPD_BH_UPDATABLE(&stg_sel_##offset##_upd_info);                   \
64       LDV_ENTER(R1.cl);                                                 \
65       PUSH_UPD_FRAME(R1.p,0);                                           \
66       ENTER_CCS(R1.p);                                                  \
67       SAVE_CCCS(UPD_FRAME_SIZE);                                        \
68       Sp[-UPD_FRAME_SIZE]=(W_)&stg_sel_ret_##offset##_upd_info;         \
69       R1.p = (P_)R1.cl->payload[0];                                     \
70       Sp=Sp-UPD_FRAME_SIZE;                                             \
71       ENTER();                                                          \
72     FE_                                                                 \
73   }
74
75 SELECTOR_CODE_UPD(0);
76 SELECTOR_CODE_UPD(1);
77 SELECTOR_CODE_UPD(2);
78 SELECTOR_CODE_UPD(3);
79 SELECTOR_CODE_UPD(4);
80 SELECTOR_CODE_UPD(5);
81 SELECTOR_CODE_UPD(6);
82 SELECTOR_CODE_UPD(7);
83 SELECTOR_CODE_UPD(8);
84 SELECTOR_CODE_UPD(9);
85 SELECTOR_CODE_UPD(10);
86 SELECTOR_CODE_UPD(11);
87 SELECTOR_CODE_UPD(12);
88 SELECTOR_CODE_UPD(13);
89 SELECTOR_CODE_UPD(14);
90 SELECTOR_CODE_UPD(15);
91
92 #define SELECTOR_CODE_NOUPD(offset) \
93   IF_(stg_sel_ret_##offset##_noupd_ret); \
94   INFO_TABLE_RET(stg_sel_ret_##offset##_noupd_info, stg_sel_ret_##offset##_noupd_ret, MK_SMALL_BITMAP(RET_FRAMESIZE, RET_BITMAP), 0, 0, 0, RET_SMALL, static, EF_, 0, 0);       \
95   IF_(stg_sel_ret_##offset##_noupd_ret) {                                       \
96     FB_                                                                 \
97       R1.p=(P_)R1.cl->payload[offset];                                  \
98       GET_SAVED_CCCS;                                                   \
99       Sp=Sp+sizeofW(StgHeader);                                         \
100       JMP_(ENTRY_CODE(*R1.p));                                          \
101     FE_                                                                 \
102   }                                                                     \
103                                                                         \
104   EF_(stg_sel_##offset##_noupd_entry);                                  \
105   INFO_TABLE_SELECTOR(stg_sel_##offset##_noupd_info, stg_sel_##offset##_noupd_entry, offset,, EF_, "stg_sel" #offset "_noupd_entry", "stg_sel" #offset "_noupd_entry");\
106   EF_(stg_sel_##offset##_noupd_entry) {                                 \
107     FB_                                                                 \
108       TICK_ENT_DYN_THK();  /* is it static or dynamic?? */              \
109       STK_CHK_NP(NOUPD_FRAME_SIZE,)                                     \
110       UPD_BH_SINGLE_ENTRY(&stg_sel_##offset##_noupd_info);              \
111       LDV_ENTER(R1.cl);                                                 \
112       TICK_UPDF_OMITTED();                                              \
113       ENTER_CCS(R1.p);                                                  \
114       SAVE_CCCS(NOUPD_FRAME_SIZE);                                      \
115       Sp[-NOUPD_FRAME_SIZE]=(W_)&stg_sel_ret_##offset##_noupd_info;     \
116       R1.p = (P_)R1.cl->payload[0];                                     \
117       Sp=Sp-NOUPD_FRAME_SIZE;                                           \
118       JMP_(ENTRY_CODE(*R1.p));                                          \
119     FE_                                                                 \
120   }
121
122 SELECTOR_CODE_NOUPD(0);
123 SELECTOR_CODE_NOUPD(1);
124 SELECTOR_CODE_NOUPD(2);
125 SELECTOR_CODE_NOUPD(3);
126 SELECTOR_CODE_NOUPD(4);
127 SELECTOR_CODE_NOUPD(5);
128 SELECTOR_CODE_NOUPD(6);
129 SELECTOR_CODE_NOUPD(7);
130 SELECTOR_CODE_NOUPD(8);
131 SELECTOR_CODE_NOUPD(9);
132 SELECTOR_CODE_NOUPD(10);
133 SELECTOR_CODE_NOUPD(11);
134 SELECTOR_CODE_NOUPD(12);
135 SELECTOR_CODE_NOUPD(13);
136 SELECTOR_CODE_NOUPD(14);
137 SELECTOR_CODE_NOUPD(15);
138
139 /* -----------------------------------------------------------------------------
140    Apply thunks
141
142    An apply thunk is a thunk of the form
143         
144                 let z = [x1...xn] \u x1...xn
145                 in ...
146
147    We pre-compile some of these because the code is always the same.
148
149    These have to be independent of the update frame size, so the code
150    works when profiling etc.
151    -------------------------------------------------------------------------- */
152
153 FN_(stg_ap_1_upd_entry);
154 FN_(stg_ap_2_upd_entry);
155 FN_(stg_ap_3_upd_entry);
156 FN_(stg_ap_4_upd_entry);
157 FN_(stg_ap_5_upd_entry);
158 FN_(stg_ap_6_upd_entry);
159 FN_(stg_ap_7_upd_entry);
160 FN_(stg_ap_8_upd_entry);
161
162 #define UF_SIZE (sizeofW(StgUpdateFrame))
163
164 /* stg_ap_1_upd_info is a bit redundant, but there appears to be a bug
165  * in the compiler that means stg_ap_1 is generated occasionally (ToDo)
166  */
167
168 INFO_TABLE_THUNK(stg_ap_1_upd_info,stg_ap_1_upd_entry,1,1,0,0,0,THUNK_1_0,,EF_,"stg_ap_1_upd_info","stg_ap_1_upd_info");
169 FN_(stg_ap_1_upd_entry) {
170   FB_
171   TICK_ENT_DYN_THK();  /* is it static or dynamic?? */
172   STK_CHK_NP(sizeofW(StgUpdateFrame)+1,);
173   UPD_BH_UPDATABLE(&stg_ap_1_upd_info);
174   LDV_ENTER(R1.cl);
175   ENTER_CCS(R1.p);
176   PUSH_UPD_FRAME(R1.p,0);
177   R1.p=(P_)(R1.cl->payload[0]);
178   Sp -= sizeofW(StgUpdateFrame);
179   Sp--; // for stg_ap_0_ret
180   JMP_(stg_ap_0_ret);
181   FE_
182 }
183
184 INFO_TABLE_THUNK(stg_ap_2_upd_info,stg_ap_2_upd_entry,2,0,0,0,0,THUNK_2_0,,EF_,"stg_ap_2_upd_info","stg_ap_2_upd_info");
185 FN_(stg_ap_2_upd_entry) {
186   FB_
187   TICK_ENT_DYN_THK();  /* is it static or dynamic?? */
188   STK_CHK_NP(sizeofW(StgUpdateFrame)+2,);
189   UPD_BH_UPDATABLE(&stg_ap_2_upd_info);
190   LDV_ENTER(R1.cl);
191   ENTER_CCS(R1.p);
192   PUSH_UPD_FRAME(R1.p,0);
193   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[1]);
194   R1.p=(P_)(R1.cl->payload[0]);
195   Sp -= sizeofW(StgUpdateFrame)+1;
196   Sp--; // for stg_ap_1_ret
197   JMP_(stg_ap_p_ret);
198   FE_
199 }
200
201 INFO_TABLE_THUNK(stg_ap_3_upd_info,stg_ap_3_upd_entry,3,0,0,0,0,THUNK,,EF_,"stg_ap_3_upd_info","stg_ap_3_upd_info");
202 FN_(stg_ap_3_upd_entry) {
203   FB_
204   TICK_ENT_DYN_THK();  /* is it static or dynamic?? */
205   STK_CHK_NP(sizeofW(StgUpdateFrame)+3,);
206   UPD_BH_UPDATABLE(&stg_ap_3_upd_info);
207   LDV_ENTER(R1.cl);
208   ENTER_CCS(R1.p);
209   PUSH_UPD_FRAME(R1.p,0);
210   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[2]);
211   Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[1]);
212   R1.p=(P_)(R1.cl->payload[0]);
213   Sp -= sizeofW(StgUpdateFrame)+2;
214   Sp--; // for stg_ap_pp_ret
215   JMP_(stg_ap_pp_ret);
216   FE_
217 }
218
219 INFO_TABLE_THUNK(stg_ap_4_upd_info,stg_ap_4_upd_entry,4,0,0,0,0,THUNK,,EF_,"stg_ap_4_upd_info","stg_ap_4_upd_info");
220 FN_(stg_ap_4_upd_entry) {
221   FB_
222   TICK_ENT_DYN_THK();  /* is it static or dynamic?? */
223   STK_CHK_NP(sizeofW(StgUpdateFrame)+4,);
224   UPD_BH_UPDATABLE(&stg_ap_4_upd_info);
225   LDV_ENTER(R1.cl);
226   ENTER_CCS(R1.p);
227   PUSH_UPD_FRAME(R1.p,0);
228   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[3]);
229   Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[2]);
230   Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[1]);
231   R1.p=(P_)(R1.cl->payload[0]);
232   Sp = Sp - (sizeofW(StgUpdateFrame)+3);
233   Sp--; // for stg_ap_ppp_ret
234   JMP_(stg_ap_ppp_ret);
235   FE_
236 }
237
238 INFO_TABLE_THUNK(stg_ap_5_upd_info,stg_ap_5_upd_entry,5,0,0,0,0,THUNK,,EF_,"stg_ap_5_upd_info","stg_ap_5_upd_info");
239 FN_(stg_ap_5_upd_entry) {
240   FB_
241   TICK_ENT_DYN_THK();  /* is it static or dynamic?? */
242   STK_CHK_NP(sizeofW(StgUpdateFrame)+5,);
243   UPD_BH_UPDATABLE(&stg_ap_5_upd_info);
244   LDV_ENTER(R1.cl);
245   ENTER_CCS(R1.p);
246   PUSH_UPD_FRAME(R1.p,0);
247   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[4]);
248   Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[3]);
249   Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[2]);
250   Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[1]);
251   R1.p=(P_)(R1.cl->payload[0]);
252   Sp = Sp - (sizeofW(StgUpdateFrame)+4);
253   Sp--; // for stg_ap_pppp_ret
254   JMP_(stg_ap_pppp_ret);
255   FE_
256 }
257
258 INFO_TABLE_THUNK(stg_ap_6_upd_info,stg_ap_6_upd_entry,6,0,0,0,0,THUNK,,EF_,"stg_ap_6_upd_info","stg_ap_6_upd_info");
259 FN_(stg_ap_6_upd_entry) {
260   FB_
261   TICK_ENT_DYN_THK();  /* is it static or dynamic?? */
262   STK_CHK_NP(sizeofW(StgUpdateFrame)+6,);
263   UPD_BH_UPDATABLE(&stg_ap_6_upd_info);
264   LDV_ENTER(R1.cl);
265   ENTER_CCS(R1.p);
266   PUSH_UPD_FRAME(R1.p,0);
267   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[5]);
268   Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[4]);
269   Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[3]);
270   Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[2]);
271   Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[1]);
272   R1.p=(P_)(R1.cl->payload[0]);
273   Sp = Sp - (sizeofW(StgUpdateFrame)+5);
274   Sp--; // for stg_ap_ppppp_ret
275   JMP_(stg_ap_ppppp_ret);
276   FE_
277 }
278
279 INFO_TABLE_THUNK(stg_ap_7_upd_info,stg_ap_7_upd_entry,7,0,0,0,0,THUNK,,EF_,"stg_ap_7_upd_info","stg_ap_7_upd_info");
280 FN_(stg_ap_7_upd_entry) {
281   FB_
282   TICK_ENT_DYN_THK();  /* is it static or dynamic?? */
283   STK_CHK_NP(sizeofW(StgUpdateFrame)+7,);
284   UPD_BH_UPDATABLE(&stg_ap_7_upd_info);
285   LDV_ENTER(R1.cl);
286   ENTER_CCS(R1.p);
287   PUSH_UPD_FRAME(R1.p,0);
288   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[6]);
289   Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[5]);
290   Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[4]);
291   Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[3]);
292   Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[2]);
293   Sp[-UF_SIZE-6]=(W_)(R1.cl->payload[1]);
294   R1.p=(P_)(R1.cl->payload[0]);
295   Sp = Sp - (sizeofW(StgUpdateFrame)+6);
296   Sp--; // for stg_ap_pppppp_ret
297   JMP_(stg_ap_pppppp_ret);
298   FE_
299 }
300
301 INFO_TABLE_THUNK(stg_ap_8_upd_info,stg_ap_8_upd_entry,8,0,0,0,0,THUNK,,EF_,"stg_ap_8_upd_info","stg_ap_8_upd_info");
302 FN_(stg_ap_8_upd_entry) {
303   FB_
304   TICK_ENT_DYN_THK();  /* is it static or dynamic?? */
305   STK_CHK_NP(sizeofW(StgUpdateFrame)+8,);
306   UPD_BH_UPDATABLE(&stg_ap_8_upd_info);
307   LDV_ENTER(R1.cl);
308   ENTER_CCS(R1.p);
309   PUSH_UPD_FRAME(R1.p,0);
310   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[7]);
311   Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[6]);
312   Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[5]);
313   Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[4]);
314   Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[3]);
315   Sp[-UF_SIZE-6]=(W_)(R1.cl->payload[2]);
316   Sp[-UF_SIZE-7]=(W_)(R1.cl->payload[1]);
317   R1.p=(P_)(R1.cl->payload[0]);
318   Sp = Sp - (sizeofW(StgUpdateFrame)+7);
319   Sp--; // for stg_ap_ppppppp_ret
320   JMP_(stg_ap_ppppppp_ret);
321   FE_
322 }