[project @ 2002-03-01 18:11:20 by keithw]
[ghc-hetmet.git] / ghc / rts / StgStdThunks.hc
1 /* -----------------------------------------------------------------------------
2  * $Id: StgStdThunks.hc,v 1.19 2002/03/01 18:11:20 keithw 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 #else
37 #define SAVE_CCCS(fs)   /* empty */
38 #define GET_SAVED_CCCS  /* empty */
39 #define ENTER_CCS(p)    /* empty */
40 #define RET_BITMAP 0
41 #endif
42
43 #define SELECTOR_CODE_UPD(offset) \
44   IF_(stg_sel_ret_##offset##_upd_ret);                                  \
45   INFO_TABLE_SRT_BITMAP(stg_sel_ret_##offset##_upd_info,stg_sel_ret_##offset##_upd_ret, RET_BITMAP, 0, 0, 0, RET_SMALL, static, EF_, 0, 0);                     \
46   EF_(stg_sel_ret_##offset##_upd_ret) {                                 \
47     FB_                                                                 \
48       R1.p=(P_)R1.cl->payload[offset];                                  \
49       GET_SAVED_CCCS;                                                   \
50       Sp=Sp+sizeofW(StgHeader);                                         \
51       JMP_(ENTRY_CODE(*R1.p));                                          \
52     FE_                                                                 \
53   }                                                                     \
54                                                                         \
55   EF_(stg_sel_##offset##_upd_entry);                                    \
56   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");\
57   EF_(stg_sel_##offset##_upd_entry) {                                   \
58     FB_                                                                 \
59       TICK_ENT_DYN_THK();  /* is it static or dynamic?? */              \
60       STK_CHK_NP(UPD_FRAME_SIZE,1,);                                    \
61       UPD_BH_UPDATABLE(&stg_sel_##offset##_upd_info);                   \
62       LDV_ENTER(R1.cl);                                                 \
63       PUSH_UPD_FRAME(R1.p,0);                                           \
64       ENTER_CCS(R1.p);                                                  \
65       SAVE_CCCS(UPD_FRAME_SIZE);                                        \
66       Sp[-UPD_FRAME_SIZE]=(W_)&stg_sel_ret_##offset##_upd_info;         \
67       R1.p = (P_)R1.cl->payload[0];                                     \
68       Sp=Sp-UPD_FRAME_SIZE;                                             \
69       JMP_(ENTRY_CODE(*R1.p));                                          \
70     FE_                                                                 \
71   }
72
73 SELECTOR_CODE_UPD(0);
74 SELECTOR_CODE_UPD(1);
75 SELECTOR_CODE_UPD(2);
76 SELECTOR_CODE_UPD(3);
77 SELECTOR_CODE_UPD(4);
78 SELECTOR_CODE_UPD(5);
79 SELECTOR_CODE_UPD(6);
80 SELECTOR_CODE_UPD(7);
81 SELECTOR_CODE_UPD(8);
82 SELECTOR_CODE_UPD(9);
83 SELECTOR_CODE_UPD(10);
84 SELECTOR_CODE_UPD(11);
85 SELECTOR_CODE_UPD(12);
86 SELECTOR_CODE_UPD(13);
87 SELECTOR_CODE_UPD(14);
88 SELECTOR_CODE_UPD(15);
89
90 #define SELECTOR_CODE_NOUPD(offset) \
91   IF_(stg_sel_ret_##offset##_noupd_ret); \
92   INFO_TABLE_SRT_BITMAP(stg_sel_ret_##offset##_noupd_info, stg_sel_ret_##offset##_noupd_ret, RET_BITMAP, 0, 0, 0, RET_SMALL, static, EF_, 0, 0);        \
93   IF_(stg_sel_ret_##offset##_noupd_ret) {                                       \
94     FB_                                                                 \
95       R1.p=(P_)R1.cl->payload[offset];                                  \
96       GET_SAVED_CCCS;                                                   \
97       Sp=Sp+sizeofW(StgHeader);                                         \
98       JMP_(ENTRY_CODE(*R1.p));                                          \
99     FE_                                                                 \
100   }                                                                     \
101                                                                         \
102   EF_(stg_sel_##offset##_noupd_entry);                                  \
103   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");\
104   EF_(stg_sel_##offset##_noupd_entry) {                                 \
105     FB_                                                                 \
106       TICK_ENT_DYN_THK();  /* is it static or dynamic?? */              \
107       STK_CHK_NP(NOUPD_FRAME_SIZE,1,)                                   \
108       UPD_BH_SINGLE_ENTRY(&stg_sel_##offset##_noupd_info);              \
109       LDV_ENTER(R1.cl);                                                 \
110       TICK_UPDF_OMITTED();                                              \
111       ENTER_CCS(R1.p);                                                  \
112       SAVE_CCCS(NOUPD_FRAME_SIZE);                                      \
113       Sp[-NOUPD_FRAME_SIZE]=(W_)&stg_sel_ret_##offset##_noupd_info;     \
114       R1.p = (P_)R1.cl->payload[0];                                     \
115       Sp=Sp-NOUPD_FRAME_SIZE;                                           \
116       JMP_(ENTRY_CODE(*R1.p));                                          \
117     FE_                                                                 \
118   }
119
120 SELECTOR_CODE_NOUPD(0);
121 SELECTOR_CODE_NOUPD(1);
122 SELECTOR_CODE_NOUPD(2);
123 SELECTOR_CODE_NOUPD(3);
124 SELECTOR_CODE_NOUPD(4);
125 SELECTOR_CODE_NOUPD(5);
126 SELECTOR_CODE_NOUPD(6);
127 SELECTOR_CODE_NOUPD(7);
128 SELECTOR_CODE_NOUPD(8);
129 SELECTOR_CODE_NOUPD(9);
130 SELECTOR_CODE_NOUPD(10);
131 SELECTOR_CODE_NOUPD(11);
132 SELECTOR_CODE_NOUPD(12);
133 SELECTOR_CODE_NOUPD(13);
134 SELECTOR_CODE_NOUPD(14);
135 SELECTOR_CODE_NOUPD(15);
136
137 /* -----------------------------------------------------------------------------
138    Apply thunks
139
140    An apply thunk is a thunk of the form
141         
142                 let z = [x1...xn] \u x1...xn
143                 in ...
144
145    We pre-compile some of these because the code is always the same.
146
147    These have to be independent of the update frame size, so the code
148    works when profiling etc.
149    -------------------------------------------------------------------------- */
150
151 FN_(stg_ap_1_upd_entry);
152 FN_(stg_ap_2_upd_entry);
153 FN_(stg_ap_3_upd_entry);
154 FN_(stg_ap_4_upd_entry);
155 FN_(stg_ap_5_upd_entry);
156 FN_(stg_ap_6_upd_entry);
157 FN_(stg_ap_7_upd_entry);
158 FN_(stg_ap_8_upd_entry);
159
160 #define UF_SIZE (sizeofW(StgUpdateFrame))
161
162 /* stg_ap_1_upd_info is a bit redundant, but there appears to be a bug
163  * in the compiler that means stg_ap_1 is generated occasionally (ToDo)
164  */
165
166 INFO_TABLE_SRT(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");
167 FN_(stg_ap_1_upd_entry) {
168   FB_
169   TICK_ENT_DYN_THK();  /* is it static or dynamic?? */
170   STK_CHK_NP(sizeofW(StgUpdateFrame),1,);
171   UPD_BH_UPDATABLE(&stg_ap_1_upd_info);
172   LDV_ENTER(R1.cl);
173   ENTER_CCS(R1.p);
174   PUSH_UPD_FRAME(R1.p,0);
175   R1.p=(P_)(R1.cl->payload[0]);
176   Sp = Sp - sizeofW(StgUpdateFrame);
177   JMP_(ENTRY_CODE(*R1.p));
178   FE_
179 }
180
181 INFO_TABLE_SRT(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");
182 FN_(stg_ap_2_upd_entry) {
183   FB_
184   TICK_ENT_DYN_THK();  /* is it static or dynamic?? */
185   STK_CHK_NP(sizeofW(StgUpdateFrame)+1,1,);
186   UPD_BH_UPDATABLE(&stg_ap_2_upd_info);
187   LDV_ENTER(R1.cl);
188   ENTER_CCS(R1.p);
189   PUSH_UPD_FRAME(R1.p,0);
190   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[1]);
191   R1.p=(P_)(R1.cl->payload[0]);
192   Sp = Sp - (sizeofW(StgUpdateFrame)+1);
193   JMP_(ENTRY_CODE(*R1.p));
194   FE_
195 }
196
197 INFO_TABLE_SRT(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");
198 FN_(stg_ap_3_upd_entry) {
199   FB_
200   TICK_ENT_DYN_THK();  /* is it static or dynamic?? */
201   STK_CHK_NP(sizeofW(StgUpdateFrame)+2,1,);
202   UPD_BH_UPDATABLE(&stg_ap_3_upd_info);
203   LDV_ENTER(R1.cl);
204   ENTER_CCS(R1.p);
205   PUSH_UPD_FRAME(R1.p,0);
206   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[2]);
207   Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[1]);
208   R1.p=(P_)(R1.cl->payload[0]);
209   Sp = Sp - (sizeofW(StgUpdateFrame)+2);
210   JMP_(ENTRY_CODE(*R1.p));
211   FE_
212 }
213
214 INFO_TABLE_SRT(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");
215 FN_(stg_ap_4_upd_entry) {
216   FB_
217   TICK_ENT_DYN_THK();  /* is it static or dynamic?? */
218   STK_CHK_NP(sizeofW(StgUpdateFrame)+3,1,);
219   UPD_BH_UPDATABLE(&stg_ap_4_upd_info);
220   LDV_ENTER(R1.cl);
221   ENTER_CCS(R1.p);
222   PUSH_UPD_FRAME(R1.p,0);
223   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[3]);
224   Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[2]);
225   Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[1]);
226   R1.p=(P_)(R1.cl->payload[0]);
227   Sp = Sp - (sizeofW(StgUpdateFrame)+3);
228   JMP_(ENTRY_CODE(*R1.p));
229   FE_
230 }
231
232 INFO_TABLE_SRT(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");
233 FN_(stg_ap_5_upd_entry) {
234   FB_
235   TICK_ENT_DYN_THK();  /* is it static or dynamic?? */
236   STK_CHK_NP(sizeofW(StgUpdateFrame)+4,1,);
237   UPD_BH_UPDATABLE(&stg_ap_5_upd_info);
238   LDV_ENTER(R1.cl);
239   ENTER_CCS(R1.p);
240   PUSH_UPD_FRAME(R1.p,0);
241   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[4]);
242   Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[3]);
243   Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[2]);
244   Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[1]);
245   R1.p=(P_)(R1.cl->payload[0]);
246   Sp = Sp - (sizeofW(StgUpdateFrame)+4);
247   JMP_(ENTRY_CODE(*R1.p));
248   FE_
249 }
250
251 INFO_TABLE_SRT(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");
252 FN_(stg_ap_6_upd_entry) {
253   FB_
254   TICK_ENT_DYN_THK();  /* is it static or dynamic?? */
255   STK_CHK_NP(sizeofW(StgUpdateFrame)+5,1,);
256   UPD_BH_UPDATABLE(&stg_ap_6_upd_info);
257   LDV_ENTER(R1.cl);
258   ENTER_CCS(R1.p);
259   PUSH_UPD_FRAME(R1.p,0);
260   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[5]);
261   Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[4]);
262   Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[3]);
263   Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[2]);
264   Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[1]);
265   R1.p=(P_)(R1.cl->payload[0]);
266   Sp = Sp - (sizeofW(StgUpdateFrame)+5);
267   JMP_(ENTRY_CODE(*R1.p));
268   FE_
269 }
270
271 INFO_TABLE_SRT(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");
272 FN_(stg_ap_7_upd_entry) {
273   FB_
274   TICK_ENT_DYN_THK();  /* is it static or dynamic?? */
275   STK_CHK_NP(sizeofW(StgUpdateFrame)+6,1,);
276   UPD_BH_UPDATABLE(&stg_ap_7_upd_info);
277   LDV_ENTER(R1.cl);
278   ENTER_CCS(R1.p);
279   PUSH_UPD_FRAME(R1.p,0);
280   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[6]);
281   Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[5]);
282   Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[4]);
283   Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[3]);
284   Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[2]);
285   Sp[-UF_SIZE-6]=(W_)(R1.cl->payload[1]);
286   R1.p=(P_)(R1.cl->payload[0]);
287   Sp = Sp - (sizeofW(StgUpdateFrame)+6);
288   JMP_(ENTRY_CODE(*R1.p));
289   FE_
290 }
291
292 INFO_TABLE_SRT(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");
293 FN_(stg_ap_8_upd_entry) {
294   FB_
295   TICK_ENT_DYN_THK();  /* is it static or dynamic?? */
296   STK_CHK_NP(sizeofW(StgUpdateFrame)+7,1,);
297   UPD_BH_UPDATABLE(&stg_ap_8_upd_info);
298   LDV_ENTER(R1.cl);
299   ENTER_CCS(R1.p);
300   PUSH_UPD_FRAME(R1.p,0);
301   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[7]);
302   Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[6]);
303   Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[5]);
304   Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[4]);
305   Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[3]);
306   Sp[-UF_SIZE-6]=(W_)(R1.cl->payload[2]);
307   Sp[-UF_SIZE-7]=(W_)(R1.cl->payload[1]);
308   R1.p=(P_)(R1.cl->payload[0]);
309   Sp=Sp-10;
310   JMP_(ENTRY_CODE(*R1.p));
311   FE_
312 }