1 /* -----------------------------------------------------------------------------
2 * $Id: StgStdThunks.hc,v 1.5 1999/04/23 09:45:27 simonm 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 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) { \
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, const, 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_ret; \
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 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) { \
91 R1.p=(P_)R1.cl->payload[offset]; \
93 Sp=Sp+sizeofW(StgHeader); \
94 JMP_(ENTRY_CODE(*R1.p)); \
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) { \
102 STK_CHK_NP(NOUPD_FRAME_SIZE,1,) \
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)); \
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);
129 /* -----------------------------------------------------------------------------
132 An apply thunk is a thunk of the form
134 let z = [x1...xn] \u x1...xn
137 We pre-compile some of these because the code is always the same.
139 These have to be independent of the update frame size, so the code
140 works when profiling etc.
141 -------------------------------------------------------------------------- */
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);
152 #define UF_SIZE (sizeofW(StgUpdateFrame))
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)
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) {
161 STK_CHK_NP(sizeofW(StgUpdateFrame),1,);
162 UPD_BH_UPDATABLE(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));
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) {
174 STK_CHK_NP(sizeofW(StgUpdateFrame)+1,1,);
175 UPD_BH_UPDATABLE(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));
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) {
188 STK_CHK_NP(sizeofW(StgUpdateFrame)+2,1,);
189 UPD_BH_UPDATABLE(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));
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) {
203 STK_CHK_NP(sizeofW(StgUpdateFrame)+3,1,);
204 UPD_BH_UPDATABLE(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));
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) {
219 STK_CHK_NP(sizeofW(StgUpdateFrame)+4,1,);
220 UPD_BH_UPDATABLE(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));
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) {
236 STK_CHK_NP(sizeofW(StgUpdateFrame)+5,1,);
237 UPD_BH_UPDATABLE(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));
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) {
254 STK_CHK_NP(sizeofW(StgUpdateFrame)+6,1,);
255 UPD_BH_UPDATABLE(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));
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) {
273 STK_CHK_NP(sizeofW(StgUpdateFrame)+7,1,);
274 UPD_BH_UPDATABLE(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]);
286 JMP_(ENTRY_CODE(*R1.p));