1 /* -----------------------------------------------------------------------------
2 * $Id: StgStdThunks.hc,v 1.7 1999/06/29 12:00:42 simonmar Exp $
4 * (c) The GHC Team, 1998-1999
6 * Canned "Standard Form" Thunks
8 * ---------------------------------------------------------------------------*/
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
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.
21 The garbage collector spots selector thunks and reduces them if
22 possible, in order to avoid space leaks resulting from lazy pattern
24 -------------------------------------------------------------------------- */
26 #define UPD_FRAME_SIZE (sizeofW(StgUpdateFrame)+sizeofW(StgHeader))
27 #define NOUPD_FRAME_SIZE (sizeofW(StgHeader))
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)
35 #define SAVE_CCCS(fs) /* empty */
36 #define GET_SAVED_CCCS /* empty */
37 #define ENTER_CCS(p) /* empty */
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) { \
46 R1.p=(P_)R1.cl->payload[offset]; \
48 Sp=Sp+sizeofW(StgHeader); \
49 JMP_(ENTRY_CODE(*R1.p)); \
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) { \
57 STK_CHK_NP(UPD_FRAME_SIZE,1,); \
58 UPD_BH_UPDATABLE(R1.p); \
59 PUSH_UPD_FRAME(R1.p,0); \
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)); \
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);
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) { \
90 R1.p=(P_)R1.cl->payload[offset]; \
92 Sp=Sp+sizeofW(StgHeader); \
93 JMP_(ENTRY_CODE(*R1.p)); \
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) { \
101 STK_CHK_NP(NOUPD_FRAME_SIZE,1,) \
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)); \
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);
128 /* -----------------------------------------------------------------------------
131 An apply thunk is a thunk of the form
133 let z = [x1...xn] \u x1...xn
136 We pre-compile some of these because the code is always the same.
138 These have to be independent of the update frame size, so the code
139 works when profiling etc.
140 -------------------------------------------------------------------------- */
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);
151 #define UF_SIZE (sizeofW(StgUpdateFrame))
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)
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) {
160 STK_CHK_NP(sizeofW(StgUpdateFrame),1,);
161 UPD_BH_UPDATABLE(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));
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) {
173 STK_CHK_NP(sizeofW(StgUpdateFrame)+1,1,);
174 UPD_BH_UPDATABLE(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));
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) {
187 STK_CHK_NP(sizeofW(StgUpdateFrame)+2,1,);
188 UPD_BH_UPDATABLE(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));
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) {
202 STK_CHK_NP(sizeofW(StgUpdateFrame)+3,1,);
203 UPD_BH_UPDATABLE(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));
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) {
218 STK_CHK_NP(sizeofW(StgUpdateFrame)+4,1,);
219 UPD_BH_UPDATABLE(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));
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) {
235 STK_CHK_NP(sizeofW(StgUpdateFrame)+5,1,);
236 UPD_BH_UPDATABLE(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));
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) {
253 STK_CHK_NP(sizeofW(StgUpdateFrame)+6,1,);
254 UPD_BH_UPDATABLE(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));
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) {
272 STK_CHK_NP(sizeofW(StgUpdateFrame)+7,1,);
273 UPD_BH_UPDATABLE(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]);
285 JMP_(ENTRY_CODE(*R1.p));