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