[project @ 1999-04-23 09:45:27 by simonm]
[ghc-hetmet.git] / ghc / rts / StgStdThunks.hc
1 /* -----------------------------------------------------------------------------
2  * $Id: StgStdThunks.hc,v 1.5 1999/04/23 09:45:27 simonm 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   IF_(__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 const, IF_, 0, 0);           \
44   IF_(__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       JMP_(ENTRY_CODE(*R1.p));                                          \
50     FE_                                                                 \
51   }                                                                     \
52                                                                         \
53   EF_(__sel_##offset##_upd_entry);                                      \
54   INFO_TABLE_SELECTOR(__sel_##offset##_upd_info, __sel_##offset##_upd_entry, offset, const, EF_, 0,0);\
55   EF_(__sel_##offset##_upd_entry) {                                     \
56     FB_                                                                 \
57       STK_CHK_NP(UPD_FRAME_SIZE,1,);                                    \
58       UPD_BH_UPDATABLE(R1.p);                                           \
59       PUSH_UPD_FRAME(R1.p,0);                                           \
60       ENTER_CCS(R1.p);                                                  \
61       SAVE_CCCS(UPD_FRAME_SIZE);                                        \
62       Sp[-UPD_FRAME_SIZE]=(W_)__sel_ret_##offset##_upd_ret;             \
63       R1.p = (P_)R1.cl->payload[0];                                     \
64       Sp=Sp-UPD_FRAME_SIZE;                                             \
65       JMP_(ENTRY_CODE(*R1.p));                                          \
66     FE_                                                                 \
67   }
68
69 SELECTOR_CODE_UPD(0);
70 SELECTOR_CODE_UPD(1);
71 SELECTOR_CODE_UPD(2);
72 SELECTOR_CODE_UPD(3);
73 SELECTOR_CODE_UPD(4);
74 SELECTOR_CODE_UPD(5);
75 SELECTOR_CODE_UPD(6);
76 SELECTOR_CODE_UPD(7);
77 SELECTOR_CODE_UPD(8);
78 SELECTOR_CODE_UPD(9);
79 SELECTOR_CODE_UPD(10);
80 SELECTOR_CODE_UPD(11);
81 SELECTOR_CODE_UPD(12);
82 SELECTOR_CODE_UPD(13);
83 SELECTOR_CODE_UPD(14);
84 SELECTOR_CODE_UPD(15);
85
86 #define SELECTOR_CODE_NOUPD(offset) \
87   IF_(__sel_ret_##offset##_noupd_ret);                                  \
88   INFO_TABLE_SRT_BITMAP(__sel_ret_##offset##_noupd_info, __sel_ret_##offset##_noupd_ret, RET_BITMAP, 0, 0, 0, RET_SMALL, static const, IF_, 0, 0);      \
89   IF_(__sel_ret_##offset##_noupd_ret) {                                 \
90     FB_                                                                 \
91       R1.p=(P_)R1.cl->payload[offset];                                  \
92       GET_SAVED_CCCS;                                                   \
93       Sp=Sp+sizeofW(StgHeader);                                         \
94       JMP_(ENTRY_CODE(*R1.p));                                          \
95     FE_                                                                 \
96   }                                                                     \
97                                                                         \
98   EF_(__sel_##offset##_noupd_entry);                                    \
99   INFO_TABLE_SELECTOR(__sel_##offset##_noupd_info, __sel_##offset##_noupd_entry, offset, const, EF_, 0,0);\
100   EF_(__sel_##offset##_noupd_entry) {                                   \
101     FB_                                                                 \
102       STK_CHK_NP(NOUPD_FRAME_SIZE,1,)                                   \
103       ENTER_CCS(R1.p);                                                  \
104       SAVE_CCCS(NOUPD_FRAME_SIZE);                                      \
105       Sp[-NOUPD_FRAME_SIZE]=(W_)__sel_ret_##offset##_noupd_ret;         \
106       R1.p = (P_)R1.cl->payload[0];                                     \
107       Sp=Sp-NOUPD_FRAME_SIZE;                                           \
108       JMP_(ENTRY_CODE(*R1.p));                                          \
109     FE_                                                                 \
110   }
111
112 SELECTOR_CODE_NOUPD(0);
113 SELECTOR_CODE_NOUPD(1);
114 SELECTOR_CODE_NOUPD(2);
115 SELECTOR_CODE_NOUPD(3);
116 SELECTOR_CODE_NOUPD(4);
117 SELECTOR_CODE_NOUPD(5);
118 SELECTOR_CODE_NOUPD(6);
119 SELECTOR_CODE_NOUPD(7);
120 SELECTOR_CODE_NOUPD(8);
121 SELECTOR_CODE_NOUPD(9);
122 SELECTOR_CODE_NOUPD(10);
123 SELECTOR_CODE_NOUPD(11);
124 SELECTOR_CODE_NOUPD(12);
125 SELECTOR_CODE_NOUPD(13);
126 SELECTOR_CODE_NOUPD(14);
127 SELECTOR_CODE_NOUPD(15);
128
129 /* -----------------------------------------------------------------------------
130    Apply thunks
131
132    An apply thunk is a thunk of the form
133         
134                 let z = [x1...xn] \u x1...xn
135                 in ...
136
137    We pre-compile some of these because the code is always the same.
138
139    These have to be independent of the update frame size, so the code
140    works when profiling etc.
141    -------------------------------------------------------------------------- */
142
143 FN_(__ap_1_upd_entry);
144 FN_(__ap_2_upd_entry);
145 FN_(__ap_3_upd_entry);
146 FN_(__ap_4_upd_entry);
147 FN_(__ap_5_upd_entry);
148 FN_(__ap_6_upd_entry);
149 FN_(__ap_7_upd_entry);
150 FN_(__ap_8_upd_entry);
151
152 #define UF_SIZE (sizeofW(StgUpdateFrame))
153
154 /* __ap_1_upd_info is a bit redundant, but there appears to be a bug
155  * in the compiler that means __ap_1 is generated occasionally (ToDo)
156  */
157
158 INFO_TABLE_SRT(__ap_1_upd_info,__ap_1_upd_entry,1,0,0,0,0,THUNK, const,EF_,0,0);
159 FN_(__ap_1_upd_entry) {
160   FB_
161   STK_CHK_NP(sizeofW(StgUpdateFrame),1,);
162   UPD_BH_UPDATABLE(R1.p);
163   ENTER_CCS(R1.p);
164   PUSH_UPD_FRAME(R1.p,0);
165   R1.p=(P_)(R1.cl->payload[0]);
166   Sp = Sp - sizeofW(StgUpdateFrame);
167   JMP_(ENTRY_CODE(*R1.p));
168   FE_
169 }
170
171 INFO_TABLE_SRT(__ap_2_upd_info,__ap_2_upd_entry,2,0,0,0,0,THUNK, const,EF_,0,0);
172 FN_(__ap_2_upd_entry) {
173   FB_
174   STK_CHK_NP(sizeofW(StgUpdateFrame)+1,1,);
175   UPD_BH_UPDATABLE(R1.p);
176   ENTER_CCS(R1.p);
177   PUSH_UPD_FRAME(R1.p,0);
178   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[1]);
179   R1.p=(P_)(R1.cl->payload[0]);
180   Sp = Sp - (sizeofW(StgUpdateFrame)+1);
181   JMP_(ENTRY_CODE(*R1.p));
182   FE_
183 }
184
185 INFO_TABLE_SRT(__ap_3_upd_info,__ap_3_upd_entry,3,0,0,0,0,THUNK, const,EF_,0,0);
186 FN_(__ap_3_upd_entry) {
187   FB_
188   STK_CHK_NP(sizeofW(StgUpdateFrame)+2,1,);
189   UPD_BH_UPDATABLE(R1.p);
190   ENTER_CCS(R1.p);
191   PUSH_UPD_FRAME(R1.p,0);
192   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[2]);
193   Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[1]);
194   R1.p=(P_)(R1.cl->payload[0]);
195   Sp = Sp - (sizeofW(StgUpdateFrame)+2);
196   JMP_(ENTRY_CODE(*R1.p));
197   FE_
198 }
199
200 INFO_TABLE_SRT(__ap_4_upd_info,__ap_4_upd_entry,4,0,0,0,0,THUNK, const,EF_,0,0);
201 FN_(__ap_4_upd_entry) {
202   FB_
203   STK_CHK_NP(sizeofW(StgUpdateFrame)+3,1,);
204   UPD_BH_UPDATABLE(R1.p);
205   ENTER_CCS(R1.p);
206   PUSH_UPD_FRAME(R1.p,0);
207   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[3]);
208   Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[2]);
209   Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[1]);
210   R1.p=(P_)(R1.cl->payload[0]);
211   Sp = Sp - (sizeofW(StgUpdateFrame)+3);
212   JMP_(ENTRY_CODE(*R1.p));
213   FE_
214 }
215
216 INFO_TABLE_SRT(__ap_5_upd_info,__ap_5_upd_entry,5,0,0,0,0,THUNK, const,EF_,0,0);
217 FN_(__ap_5_upd_entry) {
218   FB_
219   STK_CHK_NP(sizeofW(StgUpdateFrame)+4,1,);
220   UPD_BH_UPDATABLE(R1.p);
221   ENTER_CCS(R1.p);
222   PUSH_UPD_FRAME(R1.p,0);
223   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[4]);
224   Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[3]);
225   Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[2]);
226   Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[1]);
227   R1.p=(P_)(R1.cl->payload[0]);
228   Sp = Sp - (sizeofW(StgUpdateFrame)+4);
229   JMP_(ENTRY_CODE(*R1.p));
230   FE_
231 }
232
233 INFO_TABLE_SRT(__ap_6_upd_info,__ap_6_upd_entry,6,0,0,0,0,THUNK, const,EF_,0,0);
234 FN_(__ap_6_upd_entry) {
235   FB_
236   STK_CHK_NP(sizeofW(StgUpdateFrame)+5,1,);
237   UPD_BH_UPDATABLE(R1.p);
238   ENTER_CCS(R1.p);
239   PUSH_UPD_FRAME(R1.p,0);
240   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[5]);
241   Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[4]);
242   Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[3]);
243   Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[2]);
244   Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[1]);
245   R1.p=(P_)(R1.cl->payload[0]);
246   Sp = Sp - (sizeofW(StgUpdateFrame)+5);
247   JMP_(ENTRY_CODE(*R1.p));
248   FE_
249 }
250
251 INFO_TABLE_SRT(__ap_7_upd_info,__ap_7_upd_entry,7,0,0,0,0,THUNK, const,EF_,0,0);
252 FN_(__ap_7_upd_entry) {
253   FB_
254   STK_CHK_NP(sizeofW(StgUpdateFrame)+6,1,);
255   UPD_BH_UPDATABLE(R1.p);
256   ENTER_CCS(R1.p);
257   PUSH_UPD_FRAME(R1.p,0);
258   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[6]);
259   Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[5]);
260   Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[4]);
261   Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[3]);
262   Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[2]);
263   Sp[-UF_SIZE-6]=(W_)(R1.cl->payload[1]);
264   R1.p=(P_)(R1.cl->payload[0]);
265   Sp = Sp - (sizeofW(StgUpdateFrame)+6);
266   JMP_(ENTRY_CODE(*R1.p));
267   FE_
268 }
269
270 INFO_TABLE_SRT(__ap_8_upd_info,__ap_8_upd_entry,8,0,0,0,0,THUNK, const,EF_,0,0);
271 FN_(__ap_8_upd_entry) {
272   FB_
273   STK_CHK_NP(sizeofW(StgUpdateFrame)+7,1,);
274   UPD_BH_UPDATABLE(R1.p);
275   ENTER_CCS(R1.p);
276   PUSH_UPD_FRAME(R1.p,0);
277   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[7]);
278   Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[6]);
279   Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[5]);
280   Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[4]);
281   Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[3]);
282   Sp[-UF_SIZE-6]=(W_)(R1.cl->payload[2]);
283   Sp[-UF_SIZE-7]=(W_)(R1.cl->payload[1]);
284   R1.p=(P_)(R1.cl->payload[0]);
285   Sp=Sp-10;
286   JMP_(ENTRY_CODE(*R1.p));
287   FE_
288 }