[project @ 1999-02-05 16:02:18 by simonm]
[ghc-hetmet.git] / ghc / rts / StgStdThunks.hc
1 /* -----------------------------------------------------------------------------
2  * $Id: StgStdThunks.hc,v 1.3 1999/02/05 16:03:00 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 /* __ap_1_upd_info is a bit redundant, but there appears to be a bug
149  * in the compiler that means __ap_1 is generated occasionally (ToDo)
150  */
151
152 INFO_TABLE_SRT(__ap_1_upd_info,__ap_1_upd_entry,1,0,0,0,0,THUNK, const,EF_,0,0);
153 FN_(__ap_1_upd_entry) {
154   FB_
155   STK_CHK_NP(sizeofW(StgUpdateFrame),1,);
156   UPD_BH_UPDATABLE(R1.p);
157   PUSH_UPD_FRAME(R1.p,0);
158   R1.p=(P_)(R1.cl->payload[0]);
159   Sp = Sp - sizeofW(StgUpdateFrame);
160   JMP_(ENTRY_CODE(*R1.p));
161   FE_
162 }
163
164 INFO_TABLE_SRT(__ap_2_upd_info,__ap_2_upd_entry,2,0,0,0,0,THUNK, const,EF_,0,0);
165 FN_(__ap_2_upd_entry) {
166   FB_
167   STK_CHK_NP(sizeofW(StgUpdateFrame)+1,1,);
168   UPD_BH_UPDATABLE(R1.p);
169   PUSH_UPD_FRAME(R1.p,0);
170   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[1]);
171   R1.p=(P_)(R1.cl->payload[0]);
172   Sp = Sp - (sizeofW(StgUpdateFrame)+1);
173   JMP_(ENTRY_CODE(*R1.p));
174   FE_
175 }
176
177 INFO_TABLE_SRT(__ap_3_upd_info,__ap_3_upd_entry,3,0,0,0,0,THUNK, const,EF_,0,0);
178 FN_(__ap_3_upd_entry) {
179   FB_
180   STK_CHK_NP(sizeofW(StgUpdateFrame)+2,1,);
181   UPD_BH_UPDATABLE(R1.p);
182   PUSH_UPD_FRAME(R1.p,0);
183   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[2]);
184   Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[1]);
185   R1.p=(P_)(R1.cl->payload[0]);
186   Sp = Sp - (sizeofW(StgUpdateFrame)+2);
187   JMP_(ENTRY_CODE(*R1.p));
188   FE_
189 }
190
191 INFO_TABLE_SRT(__ap_4_upd_info,__ap_4_upd_entry,4,0,0,0,0,THUNK, const,EF_,0,0);
192 FN_(__ap_4_upd_entry) {
193   FB_
194   STK_CHK_NP(sizeofW(StgUpdateFrame)+3,1,);
195   UPD_BH_UPDATABLE(R1.p);
196   PUSH_UPD_FRAME(R1.p,0);
197   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[3]);
198   Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[2]);
199   Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[1]);
200   R1.p=(P_)(R1.cl->payload[0]);
201   Sp = Sp - (sizeofW(StgUpdateFrame)+3);
202   JMP_(ENTRY_CODE(*R1.p));
203   FE_
204 }
205
206 INFO_TABLE_SRT(__ap_5_upd_info,__ap_5_upd_entry,5,0,0,0,0,THUNK, const,EF_,0,0);
207 FN_(__ap_5_upd_entry) {
208   FB_
209   STK_CHK_NP(sizeofW(StgUpdateFrame)+4,1,);
210   UPD_BH_UPDATABLE(R1.p);
211   PUSH_UPD_FRAME(R1.p,0);
212   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[4]);
213   Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[3]);
214   Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[2]);
215   Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[1]);
216   R1.p=(P_)(R1.cl->payload[0]);
217   Sp = Sp - (sizeofW(StgUpdateFrame)+4);
218   JMP_(ENTRY_CODE(*R1.p));
219   FE_
220 }
221
222 INFO_TABLE_SRT(__ap_6_upd_info,__ap_6_upd_entry,6,0,0,0,0,THUNK, const,EF_,0,0);
223 FN_(__ap_6_upd_entry) {
224   FB_
225   STK_CHK_NP(sizeofW(StgUpdateFrame)+5,1,);
226   UPD_BH_UPDATABLE(R1.p);
227   PUSH_UPD_FRAME(R1.p,0);
228   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[5]);
229   Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[4]);
230   Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[3]);
231   Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[2]);
232   Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[1]);
233   R1.p=(P_)(R1.cl->payload[0]);
234   Sp = Sp - (sizeofW(StgUpdateFrame)+5);
235   JMP_(ENTRY_CODE(*R1.p));
236   FE_
237 }
238
239 INFO_TABLE_SRT(__ap_7_upd_info,__ap_7_upd_entry,7,0,0,0,0,THUNK, const,EF_,0,0);
240 FN_(__ap_7_upd_entry) {
241   FB_
242   STK_CHK_NP(sizeofW(StgUpdateFrame)+6,1,);
243   UPD_BH_UPDATABLE(R1.p);
244   PUSH_UPD_FRAME(R1.p,0);
245   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[6]);
246   Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[5]);
247   Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[4]);
248   Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[3]);
249   Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[2]);
250   Sp[-UF_SIZE-6]=(W_)(R1.cl->payload[1]);
251   R1.p=(P_)(R1.cl->payload[0]);
252   Sp = Sp - (sizeofW(StgUpdateFrame)+6);
253   JMP_(ENTRY_CODE(*R1.p));
254   FE_
255 }
256
257 INFO_TABLE_SRT(__ap_8_upd_info,__ap_8_upd_entry,8,0,0,0,0,THUNK, const,EF_,0,0);
258 FN_(__ap_8_upd_entry) {
259   FB_
260   STK_CHK_NP(sizeofW(StgUpdateFrame)+7,1,);
261   UPD_BH_UPDATABLE(R1.p);
262   PUSH_UPD_FRAME(R1.p,0);
263   Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[7]);
264   Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[6]);
265   Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[5]);
266   Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[4]);
267   Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[3]);
268   Sp[-UF_SIZE-6]=(W_)(R1.cl->payload[2]);
269   Sp[-UF_SIZE-7]=(W_)(R1.cl->payload[1]);
270   R1.p=(P_)(R1.cl->payload[0]);
271   Sp=Sp-10;
272   JMP_(ENTRY_CODE(*R1.p));
273   FE_
274 }