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