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