[project @ 1999-06-25 09:13:37 by simonmar]
[ghc-hetmet.git] / ghc / includes / ClosureMacros.h
1 /* ----------------------------------------------------------------------------
2  * $Id: ClosureMacros.h,v 1.17 1999/06/25 09:13:37 simonmar Exp $
3  *
4  * (c) The GHC Team, 1998-1999
5  *
6  * Macros for building and manipulating closures
7  *
8  * -------------------------------------------------------------------------- */
9
10 #ifndef CLOSUREMACROS_H
11 #define CLOSUREMACROS_H
12
13 /* -----------------------------------------------------------------------------
14    Fixed Header Size
15
16    The compiler tries to abstract away from the actual value of this
17    constant.
18    -------------------------------------------------------------------------- */
19
20 #define _FHS  sizeof(StgHeader)
21
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.
27
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.
31
32    NOTES ABOUT MANGLED C VS. MINI-INTERPRETER:
33
34    A couple of definitions:
35
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.
41
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.
48
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, 
52
53          c->header.info = xxx_info 
54
55    makes absolute sense, whether mangling or not.
56  
57    -------------------------------------------------------------------------- */
58
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)
62
63 #ifdef TABLES_NEXT_TO_CODE
64 #define INIT_ENTRY(e)    code : {}
65 #define GET_ENTRY(c)     ((StgFunPtr)((c)->header.info))
66 #define ENTRY_CODE(info) (info)
67 #define INFO_PTR_TO_STRUCT(info) ((StgInfoTable *)(info) - 1)
68 #define get_itbl(c)      (((c)->header.info) - 1)
69 static __inline__ StgFunPtr get_entry(const StgInfoTable *itbl) {
70     return (StgFunPtr)(itbl+1);
71 }
72 #else
73 #define INIT_ENTRY(e)    entry : (F_)(e)
74 #define GET_ENTRY(c)     ((c)->header.info->entry)
75 #define ENTRY_CODE(info) (((StgInfoTable *)info)->entry)
76 #define INFO_PTR_TO_STRUCT(info) ((StgInfoTable *)info)
77 #define get_itbl(c)      ((c)->header.info)
78 static __inline__ StgFunPtr get_entry(const StgInfoTable *itbl) {
79     return itbl->entry;
80 }
81 #endif
82
83 /* -----------------------------------------------------------------------------
84    Macros for distinguishing data pointers from code pointers
85    -------------------------------------------------------------------------- */
86 /*
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.  
91  *
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).
95  *
96  * _start      } start of read-only text space
97  * _etext      } end   of read-only text space
98  * _end } end of read-write data space 
99  */
100 extern StgFun start;
101
102 extern void* TEXT_SECTION_END_MARKER_DECL;
103 extern void* DATA_SECTION_END_MARKER_DECL;
104
105 #define IS_CODE_PTR(p) ((P_)(p) < (P_)&TEXT_SECTION_END_MARKER)
106 #define IS_DATA_PTR(p) ((P_)(p) >= (P_)&TEXT_SECTION_END_MARKER && (P_)(p) < (P_)&DATA_SECTION_END_MARKER)
107 #define IS_USER_PTR(p) ((P_)(p) >= (P_)&DATA_SECTION_END_MARKER)
108
109 #ifdef HAVE_WIN32_DLL_SUPPORT
110 extern int is_heap_alloced(const void* x);
111 # define HEAP_ALLOCED(x)  (is_heap_alloced(x))
112 #else
113 # define HEAP_ALLOCED(x)  IS_USER_PTR(x)
114 #endif
115
116 /* When working with Win32 DLLs, static closures are identified by
117    being prefixed with a zero word. This is needed so that we can
118    distinguish between pointers to static closures and (reversed!)
119    info tables.
120
121    This 'scheme' breaks down for closure tables such as CHARLIKE,
122    so we catch these separately.
123    
124    LOOKS_LIKE_STATIC_CLOSURE() 
125        - discriminates between static closures and info tbls
126          (needed by LOOKS_LIKE_GHC_INFO() below - [Win32 DLLs only.])
127    LOOKS_LIKE_STATIC() 
128        - distinguishes between static and heap allocated data.
129  */
130 #ifdef HAVE_WIN32_DLL_SUPPORT
131 #define LOOKS_LIKE_STATIC(r) (!(HEAP_ALLOCED(r)))
132
133 /* Tiresome predicates needed to check for pointers into the closure tables */
134 #define IS_CHARLIKE_CLOSURE(p)  ( (P_)(p) >= (P_)CHARLIKE_closure && (char*)(p) <= ((char*)CHARLIKE_closure + 255 * sizeof(StgIntCharlikeClosure)) )
135 #define IS_INTLIKE_CLOSURE(p)  ( (P_)(p) >= (P_)INTLIKE_closure && (char*)(p) <= ((char*)INTLIKE_closure + 32 * sizeof(StgIntCharlikeClosure)) )
136
137 #define LOOKS_LIKE_STATIC_CLOSURE(r) (((*(((unsigned long *)(r))-1)) == 0) || IS_CHARLIKE_CLOSURE(r) || IS_INTLIKE_CLOSURE(r))
138 #else
139 #define LOOKS_LIKE_STATIC(r) IS_DATA_PTR(r)
140 #define LOOKS_LIKE_STATIC_CLOSURE(r) IS_DATA_PTR(r)
141 #endif
142
143
144 /* -----------------------------------------------------------------------------
145    Macros for distinguishing infotables from closures.
146    
147    You'd think it'd be easy to tell an info pointer from a closure pointer:
148    closures live on the heap and infotables are in read only memory.  Right?
149    Wrong!  Static closures live in read only memory and Hugs allocates
150    infotables for constructors on the (writable) C heap.
151
152    ToDo: in the combined Hugs-GHC system, the following are but crude
153    approximations.  This absolutely has to be fixed.
154    -------------------------------------------------------------------------- */
155
156 #ifdef INTERPRETER
157 #ifdef USE_MINIINTERPRETER
158 /* yoiks: one of the dreaded pointer equality tests */
159 #define IS_HUGS_CONSTR_INFO(info) (((StgInfoTable *)(info))->entry == (StgFunPtr)&Hugs_CONSTR_entry)
160 #else
161 #define IS_HUGS_CONSTR_INFO(info) 0 /* ToDo: more than mildly bogus */
162 #endif
163 #else
164 #define IS_HUGS_CONSTR_INFO(info) 0 /* ToDo: more than mildly bogus */
165 #endif
166
167 #ifdef HAVE_WIN32_DLL_SUPPORT
168 # define LOOKS_LIKE_GHC_INFO(info) (!HEAP_ALLOCED(info) && !LOOKS_LIKE_STATIC_CLOSURE(info))
169 #else
170 # define LOOKS_LIKE_GHC_INFO(info) IS_CODE_PTR(info)
171 #endif
172
173 /* -----------------------------------------------------------------------------
174    Macros for calculating how big a closure will be (used during allocation)
175    -------------------------------------------------------------------------- */
176
177 /* ToDo: replace unsigned int by nat.  The only fly in the ointment is that
178  * nat comes from Rts.h which many folk dont include.  Sigh!
179  */
180 static __inline__ StgOffset AP_sizeW    ( unsigned int n_args )              
181 { return sizeofW(StgAP_UPD) + n_args; }
182
183 static __inline__ StgOffset PAP_sizeW   ( unsigned int n_args )              
184 { return sizeofW(StgPAP)    + n_args; }
185
186 static __inline__ StgOffset CONSTR_sizeW( unsigned int p, unsigned int np )  
187 { return sizeofW(StgHeader) + p + np; }
188
189 static __inline__ StgOffset BCO_sizeW   ( unsigned int p, unsigned int np, unsigned int is ) 
190 { return sizeofW(StgBCO) + p + np + (is+sizeof(StgWord)-1)/sizeof(StgWord); }
191
192 static __inline__ StgOffset THUNK_SELECTOR_sizeW ( void )                    
193 { return sizeofW(StgHeader) + MIN_UPD_SIZE; }
194
195 static __inline__ StgOffset BLACKHOLE_sizeW ( void )                    
196 { return sizeofW(StgHeader) + MIN_UPD_SIZE; }
197
198 static __inline__ StgOffset CAF_sizeW ( void )                    
199 { return sizeofW(StgCAF); }
200
201 /* --------------------------------------------------------------------------
202  * Sizes of closures
203  * ------------------------------------------------------------------------*/
204
205 static __inline__ StgOffset size_fromITBL( const StgInfoTable* itbl ) 
206 { return sizeof(StgClosure) 
207        + sizeof(StgPtr)  * itbl->layout.payload.ptrs 
208        + sizeof(StgWord) * itbl->layout.payload.nptrs; }
209
210 static __inline__ StgOffset sizeW_fromITBL( const StgInfoTable* itbl ) 
211 { return sizeofW(StgClosure) 
212        + sizeofW(StgPtr)  * itbl->layout.payload.ptrs 
213        + sizeofW(StgWord) * itbl->layout.payload.nptrs; }
214
215 static __inline__ StgOffset pap_size( StgPAP* x )
216 { return sizeof(StgPAP) 
217        + sizeof(StgWord)  * x->n_args; }
218
219 static __inline__ StgOffset pap_sizeW( StgPAP* x )
220 { return PAP_sizeW(x->n_args); }
221
222 /* These two functions give the same result - but have slightly
223  * different types. 
224  */
225 static __inline__ StgOffset arr_words_sizeW( StgArrWords* x )
226 { return sizeofW(StgArrWords) + x->words; }
227 static __inline__ StgOffset mut_arr_ptrs_sizeW( StgMutArrPtrs* x )
228 { return sizeofW(StgMutArrPtrs) + x->ptrs; }
229
230 static __inline__ StgWord bco_sizeW( StgBCO* bco )
231 { return BCO_sizeW(bco->n_ptrs,bco->n_words,bco->n_instrs); }
232
233 static __inline__ StgWord tso_sizeW ( StgTSO *tso )
234 { return TSO_STRUCT_SIZEW + tso->stack_size; }
235
236 /* -----------------------------------------------------------------------------
237    Macros for building closures
238    -------------------------------------------------------------------------- */
239
240 #ifdef PROFILING
241 #define SET_PROF_HDR(c,ccs_)            (c)->header.prof.ccs = ccs_
242 #define SET_STATIC_PROF_HDR(ccs_)       prof : { ccs : ccs_ },
243 #else
244 #define SET_PROF_HDR(c,ccs)
245 #define SET_STATIC_PROF_HDR(ccs)
246 #endif
247
248 #ifdef GRAN
249 #define SET_GRAN_HDR(c,pe)              (c)->header.gran.procs = pe
250 #define SET_STATIC_GRAN_HDR             gran : { procs : Everywhere },
251 #else
252 #define SET_GRAN_HDR(c,pe)
253 #define SET_STATIC_GRAN_HDR
254 #endif
255
256 /* there is no PAR header, as far as I can tell -- SDM */
257
258 #ifdef PAR
259 #define SET_PAR_HDR(c,stuff)
260 #define SET_STATIC_PAR_HDR(stuff)
261 #else
262 #define SET_PAR_HDR(c,stuff)
263 #define SET_STATIC_PAR_HDR(stuff)
264 #endif
265
266 #ifdef TICKY_TICKY
267 #define SET_TICKY_HDR(c,stuff)          /* old: (c)->header.ticky.updated = stuff */
268 #define SET_STATIC_TICKY_HDR(stuff)     /* old: ticky : { updated : stuff } */
269 #else
270 #define SET_TICKY_HDR(c,stuff)
271 #define SET_STATIC_TICKY_HDR(stuff)
272 #endif
273 #define SET_HDR(c,info,ccs) \
274    {                                    \
275         SET_INFO(c,info);                               \
276         SET_GRAN_HDR((StgClosure *)(c),ThisPE);         \
277         SET_PAR_HDR((StgClosure *)(c),LOCAL_GA);        \
278         SET_PROF_HDR((StgClosure *)(c),ccs);            \
279         SET_TICKY_HDR((StgClosure *)(c),0);             \
280    }
281
282 #define SET_ARR_HDR(c,info,costCentreStack,n_words) \
283    SET_HDR(c,info,costCentreStack); \
284    (c)->words = n_words;
285
286 /* -----------------------------------------------------------------------------
287    Static closures are defined as follows:
288
289
290 SET_STATIC_HDR(PrelBase_CZh_closure,PrelBase_CZh_info,costCentreStack,const);
291
292    The info argument must have type 'StgInfoTable' or
293    'StgSRTInfoTable', since we use '&' to get its address in the macro.
294    -------------------------------------------------------------------------- */
295
296 #define SET_STATIC_HDR(label,info,costCentreStack,closure_class,info_class) \
297    info_class info;                        \
298    closure_class StgClosure label = {                   \
299    STATIC_HDR(info,costCentreStack)
300
301 #define STATIC_HDR(info,ccs) \
302         header : {                            \
303                 INIT_INFO(info),              \
304                 SET_STATIC_GRAN_HDR           \
305                 SET_STATIC_PAR_HDR(LOCAL_GA)  \
306                 SET_STATIC_PROF_HDR(ccs)       \
307                 SET_STATIC_TICKY_HDR(0)       \
308         }
309
310 /* how to get hold of the static link field for a static closure.
311  *
312  * Note that we have to use (*cast(T*,&e)) instead of cast(T,e)
313  * because C won't let us take the address of a casted expression. Huh?
314  */
315 #define STATIC_LINK(info,p) \
316    (*stgCast(StgClosure**,&((p)->payload[info->layout.payload.ptrs + \
317                                         info->layout.payload.nptrs])))
318 /* These macros are optimised versions of the above for certain
319  * closure types.  They *must* be equivalent to the generic
320  * STATIC_LINK.
321  */
322 #define FUN_STATIC_LINK(p)   ((p)->payload[0])
323 #define THUNK_STATIC_LINK(p) ((p)->payload[2])
324 #define IND_STATIC_LINK(p)   ((p)->payload[1])
325
326 #define STATIC_LINK2(info,p) \
327    (*stgCast(StgClosure**,&((p)->payload[info->layout.payload.ptrs + \
328                                         info->layout.payload.nptrs + 1])))
329
330 /* -----------------------------------------------------------------------------
331    INTLIKE and CHARLIKE closures.
332    -------------------------------------------------------------------------- */
333
334 #define CHARLIKE_CLOSURE(n) ((P_)&CHARLIKE_closure[n])
335 #define INTLIKE_CLOSURE(n)  ((P_)&INTLIKE_closure[(n)-MIN_INTLIKE])
336
337 /* -----------------------------------------------------------------------------
338    Closure Tables (for enumerated data types)
339    -------------------------------------------------------------------------- */
340
341 #define CLOSURE_TBL(lbl) const StgClosure *lbl[] = {
342
343 /* -----------------------------------------------------------------------------
344    Payload access
345    -------------------------------------------------------------------------- */
346
347 #define payloadPtr( c, i )    (*stgCast(StgPtr*,       ((c)->payload+(i))))
348 #define payloadCPtr( c, i )   (*stgCast(StgClosure**,  ((c)->payload+(i))))
349 #define payloadWord( c, i )   (*stgCast(StgWord*,      ((c)->payload+(i))))
350
351 /* -----------------------------------------------------------------------------
352    CONSTRs.
353    -------------------------------------------------------------------------- */
354
355 /* constructors don't have SRTs */
356 #define GET_TAG(info) (INFO_PTR_TO_STRUCT(info)->srt_len)
357
358 /* -----------------------------------------------------------------------------
359    BCOs.
360    -------------------------------------------------------------------------- */
361
362 #define bcoConstPtr( bco, i )    (*stgCast(StgPtr*,       ((bco)->payload+(i))))
363 #define bcoConstCPtr( bco, i )   (*stgCast(StgClosurePtr*,((bco)->payload+(i))))
364 #define bcoConstInfoPtr( bco, i )(*stgCast(StgInfoTable**,((bco)->payload+(bco)->n_ptrs+i)))
365 #define bcoConstInt( bco, i )    (*stgCast(StgInt*,       ((bco)->payload+(bco)->n_ptrs+i)))
366 #define bcoConstInt64( bco, i )  (PK_Int64(stgCast(StgWord*,(bco)->payload+(bco)->n_ptrs+i)))
367 #define bcoConstWord( bco, i )   (*stgCast(StgWord*,      ((bco)->payload+(bco)->n_ptrs+i)))
368 #define bcoConstAddr( bco, i )   (*stgCast(StgAddr*,      ((bco)->payload+(bco)->n_ptrs+i)))
369 #define bcoConstChar( bco, i )   (*stgCast(StgChar*,      ((bco)->payload+(bco)->n_ptrs+i)))
370 #define bcoConstFloat( bco, i )  (PK_FLT(stgCast(StgWord*,(bco)->payload+(bco)->n_ptrs+i)))
371 #define bcoConstDouble( bco, i ) (PK_DBL(stgCast(StgWord*,(bco)->payload+(bco)->n_ptrs+i)))
372 #define bcoInstr( bco, i )       (stgCast(StgWord8*,      ((bco)->payload+(bco)->n_ptrs+(bco)->n_words))[i])
373 static __inline__ StgInt bcoInstr16 ( StgBCO* bco, unsigned int i )
374 { StgInt x = (bcoInstr(bco,i) << 8) + bcoInstr(bco,i+1); return x; }
375
376 #endif /* CLOSUREMACROS_H */