1 /* ----------------------------------------------------------------------------
2 * $Id: ClosureMacros.h,v 1.4 1999/02/05 16:02:20 simonm Exp $
4 * (c) The GHC Team, 1998-1999
6 * Macros for building and manipulating closures
8 * -------------------------------------------------------------------------- */
10 #ifndef CLOSUREMACROS_H
11 #define CLOSUREMACROS_H
13 /* -----------------------------------------------------------------------------
16 The compiler tries to abstract away from the actual value of this
18 -------------------------------------------------------------------------- */
20 #define _FHS sizeof(StgHeader)
22 /* -----------------------------------------------------------------------------
23 Info tables are slammed up against the entry code, and the label
24 for the info table is at the *end* of the table itself. This
25 inline function adjusts an info pointer to point to the beginning
26 of the table, so we can use standard C structure indexing on it.
28 Note: this works for SRT info tables as long as you don't want to
29 access the SRT, since they are laid out the same with the SRT
30 pointer as the first word in the table.
32 NOTES ABOUT MANGLED C VS. MINI-INTERPRETER:
34 A couple of definitions:
36 "info pointer" The first word of the closure. Might point
37 to either the end or the beginning of the
38 info table, depending on whether we're using
39 the mini interpretter or not. GET_INFO(c)
40 retrieves the info pointer of a closure.
42 "info table" The info table structure associated with a
43 closure. This is always a pointer to the
44 beginning of the structure, so we can
45 use standard C structure indexing to pull out
46 the fields. get_itbl(c) returns a pointer to
47 the info table for closure c.
49 An address of the form xxxx_info points to the end of the info
50 table or the beginning of the info table depending on whether we're
51 mangling or not respectively. So,
53 c->header.info = xxx_info
55 makes absolute sense, whether mangling or not.
57 -------------------------------------------------------------------------- */
59 #define INIT_INFO(i) info : &(i)
60 #define SET_INFO(c,i) ((c)->header.info = (i))
61 #define GET_INFO(c) ((c)->header.info)
63 #if USE_MINIINTERPRETER
64 #define INIT_ENTRY(e) entry : (F_)(e)
65 #define GET_ENTRY(c) ((c)->header.info->entry)
66 #define ENTRY_CODE(info) (stgCast(StgInfoTable*,info)->entry)
67 #define INFO_PTR_TO_STRUCT(info) (info)
68 #define get_itbl(c) ((c)->header.info)
69 static __inline__ StgFunPtr get_entry(const StgInfoTable *itbl) {
73 #define INIT_ENTRY(e) code : {}
74 #define GET_ENTRY(c) stgCast(StgFunPtr,((c)->header.info))
75 #define ENTRY_CODE(info) (info)
76 #define INFO_PTR_TO_STRUCT(info) (stgCast(StgInfoTable*,info) - 1)
77 #define get_itbl(c) (stgCast(StgInfoTable*,(c)->header.info) -1)
78 static __inline__ StgFunPtr get_entry(const StgInfoTable *itbl) {
79 return stgCast(StgFunPtr,itbl+1);
83 /* -----------------------------------------------------------------------------
84 Macros for distinguishing data pointers from code pointers
85 -------------------------------------------------------------------------- */
87 * We use some symbols inserted automatically by the linker to decide
88 * whether a pointer points to text, data, or user space. These tests
89 * assume that text is lower in the address space than data, which in
90 * turn is lower than user allocated memory.
92 * If this assumption is false (say on some strange architecture) then
93 * the tests IS_CODE_PTR and IS_DATA_PTR below will need to be
94 * modified (and that should be all that's necessary).
96 * _start } start of read-only text space
97 * _etext } end of read-only text space
98 * _end } end of read-write data space
101 extern StgFun TEXT_SECTION_END_MARKER_DECL;
102 extern StgFun DATA_SECTION_END_MARKER_DECL;
104 #define IS_CODE_PTR(p) ((P_)(p) < (P_)&TEXT_SECTION_END_MARKER)
105 #define IS_DATA_PTR(p) ((P_)(p) >= (P_)&TEXT_SECTION_END_MARKER && (P_)(p) < (P_)&DATA_SECTION_END_MARKER)
106 #define IS_USER_PTR(p) ((P_)(p) >= (P_)&DATA_SECTION_END_MARKER)
108 /* -----------------------------------------------------------------------------
109 Macros for distinguishing infotables from closures.
111 You'd think it'd be easy to tell an info pointer from a closure pointer:
112 closures live on the heap and infotables are in read only memory. Right?
113 Wrong! Static closures live in read only memory and Hugs allocates
114 infotables for constructors on the (writable) C heap.
116 ToDo: in the combined Hugs-GHC system, the following are but crude
117 approximations. This absolutely has to be fixed.
118 -------------------------------------------------------------------------- */
120 #ifdef USE_MINIINTERPRETER
121 /* yoiks: one of the dreaded pointer equality tests */
122 #define IS_HUGS_CONSTR_INFO(info) (stgCast(StgInfoTable*,info)->entry == stgCast(StgFunPtr,&Hugs_CONSTR_entry))
124 #define IS_HUGS_CONSTR_INFO(info) 0 /* ToDo: more than mildly bogus */
127 #ifdef USE_MINIINTERPRETER
128 /* in the mininterpreter, we put infotables on closures */
129 #define LOOKS_LIKE_GHC_INFO(info) IS_CODE_PTR(info)
131 /* otherwise we have entry pointers on closures */
132 #define LOOKS_LIKE_GHC_INFO(info) IS_CODE_PTR(info)
135 #define LOOKS_LIKE_STATIC(r) IS_DATA_PTR(r)
137 /* -----------------------------------------------------------------------------
138 Macros for calculating how big a closure will be (used during allocation)
139 -------------------------------------------------------------------------- */
141 /* ToDo: replace unsigned int by nat. The only fly in the ointment is that
142 * nat comes from Rts.h which many folk dont include. Sigh!
144 static __inline__ StgOffset AP_sizeW ( unsigned int n_args )
145 { return sizeofW(StgAP_UPD) + n_args; }
147 static __inline__ StgOffset PAP_sizeW ( unsigned int n_args )
148 { return sizeofW(StgPAP) + n_args; }
150 static __inline__ StgOffset CONSTR_sizeW( unsigned int p, unsigned int np )
151 { return sizeofW(StgHeader) + p + np; }
153 static __inline__ StgOffset BCO_sizeW ( unsigned int p, unsigned int np, unsigned int is )
154 { return sizeofW(StgBCO) + p + np + (is+sizeof(StgWord)-1)/sizeof(StgWord); }
156 static __inline__ StgOffset THUNK_SELECTOR_sizeW ( void )
157 { return sizeofW(StgHeader) + MIN_UPD_SIZE; }
159 static __inline__ StgOffset BLACKHOLE_sizeW ( void )
160 { return sizeofW(StgHeader) + MIN_UPD_SIZE; }
162 static __inline__ StgOffset CAF_sizeW ( void )
163 { return sizeofW(StgCAF); }
165 /* --------------------------------------------------------------------------
167 * ------------------------------------------------------------------------*/
169 static __inline__ StgOffset size_fromITBL( const StgInfoTable* itbl )
170 { return sizeof(StgClosure)
171 + sizeof(StgPtr) * itbl->layout.payload.ptrs
172 + sizeof(StgWord) * itbl->layout.payload.nptrs; }
174 static __inline__ StgOffset sizeW_fromITBL( const StgInfoTable* itbl )
175 { return sizeofW(StgClosure)
176 + sizeofW(StgPtr) * itbl->layout.payload.ptrs
177 + sizeofW(StgWord) * itbl->layout.payload.nptrs; }
179 static __inline__ StgOffset pap_size( StgPAP* x )
180 { return sizeof(StgPAP)
181 + sizeof(StgWord) * x->n_args; }
183 static __inline__ StgOffset pap_sizeW( StgPAP* x )
184 { return PAP_sizeW(x->n_args); }
186 /* These two functions give the same result - but have slightly
189 static __inline__ StgOffset arr_words_sizeW( StgArrWords* x )
190 { return sizeofW(StgArrWords) + x->words; }
191 static __inline__ StgOffset mut_arr_ptrs_sizeW( StgMutArrPtrs* x )
192 { return sizeofW(StgMutArrPtrs) + x->ptrs; }
194 static __inline__ StgWord bco_sizeW( StgBCO* bco )
195 { return BCO_sizeW(bco->n_ptrs,bco->n_words,bco->n_instrs); }
197 static __inline__ StgWord tso_sizeW ( StgTSO *tso )
198 { return TSO_STRUCT_SIZEW + tso->stack_size; }
200 /* -----------------------------------------------------------------------------
201 Macros for building closures
202 -------------------------------------------------------------------------- */
205 #define SET_PROF_HDR(c,ccs_) (c)->header.prof.ccs = ccs_
206 #define SET_STATIC_PROF_HDR(ccs_) prof : { ccs : ccs_ },
208 #define SET_PROF_HDR(c,ccs)
209 #define SET_STATIC_PROF_HDR(ccs)
213 #define SET_GRAN_HDR(c,pe) (c)->header.gran.procs = pe
214 #define SET_STATIC_GRAN_HDR gran : { procs : Everywhere },
216 #define SET_GRAN_HDR(c,pe)
217 #define SET_STATIC_GRAN_HDR
220 /* there is no PAR header, as far as I can tell -- SDM */
223 #define SET_PAR_HDR(c,stuff)
224 #define SET_STATIC_PAR_HDR(stuff)
226 #define SET_PAR_HDR(c,stuff)
227 #define SET_STATIC_PAR_HDR(stuff)
231 #define SET_TICKY_HDR(c,stuff) (c)->header.ticky.updated = stuff
232 #define SET_STATIC_TICKY_HDR(stuff) ticky : { updated : stuff }
234 #define SET_TICKY_HDR(c,stuff)
235 #define SET_STATIC_TICKY_HDR(stuff)
237 #define SET_HDR(c,info,ccs) \
240 SET_GRAN_HDR((StgClosure *)(c),ThisPE); \
241 SET_PAR_HDR((StgClosure *)(c),LOCAL_GA); \
242 SET_PROF_HDR((StgClosure *)(c),ccs); \
243 SET_TICKY_HDR((StgClosure *)(c),0); \
246 #define SET_ARR_HDR(c,info,costCentreStack,n_words) \
247 SET_HDR(c,info,costCentreStack); \
248 (c)->words = n_words;
250 /* -----------------------------------------------------------------------------
251 Static closures are defined as follows:
254 SET_STATIC_HDR(PrelBase_CZh_closure,PrelBase_CZh_info,costCentreStack,const);
256 The info argument must have type 'StgInfoTable' or
257 'StgSRTInfoTable', since we use '&' to get its address in the macro.
258 -------------------------------------------------------------------------- */
260 #define SET_STATIC_HDR(label,info,costCentreStack,closure_class,info_class) \
262 closure_class StgClosure label = { \
263 STATIC_HDR(info,costCentreStack)
265 #define STATIC_HDR(info,ccs) \
268 SET_STATIC_GRAN_HDR \
269 SET_STATIC_PAR_HDR(LOCAL_GA) \
270 SET_STATIC_PROF_HDR(ccs) \
271 SET_STATIC_TICKY_HDR(0) \
274 /* how to get hold of the static link field for a static closure.
276 * Note that we have to use (*cast(T*,&e)) instead of cast(T,e)
277 * because C won't let us take the address of a casted expression. Huh?
279 #define STATIC_LINK(info,p) \
280 (*stgCast(StgClosure**,&((p)->payload[info->layout.payload.ptrs + \
281 info->layout.payload.nptrs])))
282 #define STATIC_LINK2(info,p) \
283 (*stgCast(StgClosure**,&((p)->payload[info->layout.payload.ptrs + \
284 info->layout.payload.nptrs + 1])))
286 /* -----------------------------------------------------------------------------
287 INTLIKE and CHARLIKE closures.
288 -------------------------------------------------------------------------- */
290 #define CHARLIKE_CLOSURE(n) ((P_)&CHARLIKE_closure[n])
291 #define INTLIKE_CLOSURE(n) ((P_)&INTLIKE_closure[(n)-MIN_INTLIKE])
293 /* -----------------------------------------------------------------------------
295 -------------------------------------------------------------------------- */
297 #define payloadPtr( c, i ) (*stgCast(StgPtr*, ((c)->payload+(i))))
298 #define payloadCPtr( c, i ) (*stgCast(StgClosure**, ((c)->payload+(i))))
299 #define payloadWord( c, i ) (*stgCast(StgWord*, ((c)->payload+(i))))
301 /* -----------------------------------------------------------------------------
303 -------------------------------------------------------------------------- */
305 /* constructors don't have SRTs */
306 #define GET_TAG(info) (INFO_PTR_TO_STRUCT(info)->srt_len)
308 /* -----------------------------------------------------------------------------
310 -------------------------------------------------------------------------- */
312 #define bcoConstPtr( bco, i ) (*stgCast(StgPtr*, ((bco)->payload+(i))))
313 #define bcoConstCPtr( bco, i ) (*stgCast(StgClosurePtr*,((bco)->payload+(i))))
314 #define bcoConstInfoPtr( bco, i )(*stgCast(StgInfoTable**,((bco)->payload+(bco)->n_ptrs+i)))
315 #define bcoConstInt( bco, i ) (*stgCast(StgInt*, ((bco)->payload+(bco)->n_ptrs+i)))
316 #define bcoConstInt64( bco, i ) (PK_Int64(stgCast(StgWord*,(bco)->payload+(bco)->n_ptrs+i)))
317 #define bcoConstWord( bco, i ) (*stgCast(StgWord*, ((bco)->payload+(bco)->n_ptrs+i)))
318 #define bcoConstAddr( bco, i ) (*stgCast(StgAddr*, ((bco)->payload+(bco)->n_ptrs+i)))
319 #define bcoConstChar( bco, i ) (*stgCast(StgChar*, ((bco)->payload+(bco)->n_ptrs+i)))
320 #define bcoConstFloat( bco, i ) (PK_FLT(stgCast(StgWord*,(bco)->payload+(bco)->n_ptrs+i)))
321 #define bcoConstDouble( bco, i ) (PK_DBL(stgCast(StgWord*,(bco)->payload+(bco)->n_ptrs+i)))
322 #define bcoInstr( bco, i ) (stgCast(StgNat8*, ((bco)->payload+(bco)->n_ptrs+(bco)->n_words))[i])
324 #endif /* CLOSUREMACROS_H */