[project @ 2004-11-10 02:13:12 by wolfgang]
[ghc-hetmet.git] / ghc / includes / Cmm.h
1 /* -----------------------------------------------------------------------------
2  *
3  * (c) The University of Glasgow 2004
4  *
5  * This file is included at the top of all .cmm source files (and
6  * *only* .cmm files).  It defines a collection of useful macros for
7  * making .cmm code a bit less error-prone to write, and a bit easier
8  * on the eye for the reader.
9  *
10  * For the syntax of .cmm files, see the parser in ghc/compiler/cmm/CmmParse.y.
11  *
12  * If you're used to the old HC file syntax, here's a quick cheat sheet
13  * for converting HC code:
14  *
15  *       - Remove FB_/FE_
16  *       - Remove all type casts
17  *       - Remove '&'
18  *       - STGFUN(foo) { ... }  ==>  foo { ... }
19  *       - FN_(foo) { ... }  ==>  foo { ... }
20  *       - JMP_(e)  ==> jump e;
21  *       - Remove EXTFUN(foo)
22  *       - Sp[n]  ==>  Sp(n)
23  *       - Hp[n]  ==>  Hp(n)
24  *       - Sp += n  ==> Sp_adj(n)
25  *       - Hp += n  ==> Hp_adj(n)
26  *       - R1.i   ==>  R1   (similarly for R1.w, R1.cl etc.)
27  *       - You need to explicitly dereference variables; eg. 
28  *             context_switch   ==>  CInt[context_switch]
29  *       - convert all word offsets into byte offsets:
30  *              - e ==> WDS(e)
31  *       - sizeofW(StgFoo)  ==>  SIZEOF_StgFoo
32  *       - ENTRY_CODE(e)  ==>  %ENTRY_CODE(e)
33  *       - get_itbl(c)  ==>  %GET_STD_INFO(c)
34  *       - Change liveness masks in STK_CHK_GEN, HP_CHK_GEN:
35  *              R1_PTR | R2_PTR  ==>  R1_PTR & R2_PTR
36  *              (NOTE: | becomes &)
37  *       - Declarations like 'StgPtr p;' become just 'W_ p;'
38  *       - e->payload[n] ==> PAYLOAD(e,n)
39  *       - Be very careful with comparisons: the infix versions (>, >=, etc.)
40  *         are unsigned, so use %lt(a,b) to get signed less-than for example.
41  *
42  * Accessing fields of structures defined in the RTS header files is
43  * done via automatically-generated macros in DerivedConstants.h.  For
44  * example, where previously we used
45  *
46  *          CurrentTSO->what_next = x
47  *
48  * in C-- we now use
49  *
50  *          StgTSO_what_next(CurrentTSO) = x
51  *
52  * where the StgTSO_what_next() macro is automatically generated by
53  * mkDerivedConstnants.c.  If you need to access a field that doesn't
54  * already have a macro, edit that file (it's pretty self-explanatory).
55  *
56  * -------------------------------------------------------------------------- */
57
58 #ifndef CMM_H
59 #define CMM_H
60
61 // In files that are included into both C and C-- (and perhaps
62 // Haskell) sources, we sometimes need to conditionally compile bits
63 // depending on the language.  CMINUSMINUS==1 in .cmm sources:
64 #define CMINUSMINUS 1
65
66 #include "ghcconfig.h"
67 #include "RtsConfig.h"
68
69 /* -----------------------------------------------------------------------------
70    Types 
71
72    The following synonyms for C-- types are declared here:
73
74      I8, I16, I32, I64    MachRep-style names for convenience
75
76      W_                   is shorthand for the word type (== StgWord)
77      F_                   shorthand for float  (F_ == StgFloat == C's float)
78      D_                   shorthand for double (D_ == StgDouble == C's double)
79
80      CInt                 has the same size as an int in C on this platform
81      CLong                has the same size as a long in C on this platform
82    
83   --------------------------------------------------------------------------- */
84
85 #define I8  bits8
86 #define I16 bits16
87 #define I32 bits32
88 #define I64 bits64
89
90 #if SIZEOF_VOID_P == 4
91 #define W_ bits32
92 #elif SIZEOF_VOID_P == 8
93 #define W_ bits64
94 #else
95 #error Unknown word size
96 #endif
97
98 #if SIZEOF_INT == 4
99 #define CInt bits32
100 #elif SIZEOF_INT == 8
101 #define CInt bits64
102 #else
103 #error Unknown int size
104 #endif
105
106 #if SIZEOF_LONG == 4
107 #define CLong bits32
108 #elif SIZEOF_LONG == 8
109 #define CLong bits64
110 #else
111 #error Unknown long size
112 #endif
113
114 #define F_ float32
115 #define D_ float64
116 #define L_ bits64
117
118 #define SIZEOF_StgDouble 8
119 #define SIZEOF_StgWord64 8
120
121 /* -----------------------------------------------------------------------------
122    Misc useful stuff
123    -------------------------------------------------------------------------- */
124
125 #define NULL (0::W_)
126
127 #define STRING(name,str)                        \
128   section "rodata" {                            \
129         name : bits8[] str;                     \
130   }                                             \
131
132 /* -----------------------------------------------------------------------------
133    Byte/word macros
134
135    Everything in C-- is in byte offsets (well, most things).  We use
136    some macros to allow us to express offsets in words and to try to
137    avoid byte/word confusion.
138    -------------------------------------------------------------------------- */
139
140 #define SIZEOF_W  SIZEOF_VOID_P
141 #define W_MASK    (SIZEOF_W-1)
142
143 #if SIZEOF_W == 4
144 #define W_SHIFT 2
145 #elif SIZEOF_W == 8
146 #define W_SHIFT 4
147 #endif
148
149 // Converting quantities of words to bytes
150 #define WDS(n) ((n)*SIZEOF_W)
151
152 // Converting quantities of bytes to words
153 // NB. these work on *unsigned* values only
154 #define BYTES_TO_WDS(n) ((n) / SIZEOF_W)
155 #define ROUNDUP_BYTES_TO_WDS(n) (((n) + SIZEOF_W - 1) / SIZEOF_W)
156
157 // TO_W_(n) converts n to W_ type from a smaller type
158 #if SIZEOF_W == 4
159 #define TO_W_(x) %sx32(x)
160 #define HALF_W_(x) %lobits16(x)
161 #elif SIZEOF_W == 8
162 #define TO_W_(x) %sx64(x)
163 #define HALF_W_(x) %lobits32(x)
164 #endif
165
166 #if SIZEOF_INT == 4 && SIZEOF_W == 8
167 #define W_TO_INT(x) %lobits32(x)
168 #elif SIZEOF_INT == SIZEOF_W
169 #define W_TO_INT(x) (x)
170 #endif
171
172 /* -----------------------------------------------------------------------------
173    Heap/stack access, and adjusting the heap/stack pointers.
174    -------------------------------------------------------------------------- */
175
176 #define Sp(n)  W_[Sp + WDS(n)]
177 #define Hp(n)  W_[Hp + WDS(n)]
178
179 #define Sp_adj(n) Sp = Sp + WDS(n)
180 #define Hp_adj(n) Hp = Hp + WDS(n)
181
182 /* -----------------------------------------------------------------------------
183    Assertions and Debuggery
184    -------------------------------------------------------------------------- */
185
186 #ifdef DEBUG
187 #define ASSERT(predicate)                       \
188         if (predicate) {                        \
189             /*null*/;                           \
190         } else {                                \
191             foreign "C" _stgAssert(NULL, __LINE__); \
192         }
193 #else
194 #define ASSERT(p) /* nothing */
195 #endif
196
197 #ifdef DEBUG
198 #define DEBUG_ONLY(s) s
199 #else
200 #define DEBUG_ONLY(s) /* nothing */
201 #endif
202
203 //
204 // The IF_DEBUG macro is useful for debug messages that depend on one
205 // of the RTS debug options.  For example:
206 // 
207 //   IF_DEBUG(RtsFlags_DebugFlags_apply,
208 //      foreign "C" fprintf(stderr, stg_ap_0_ret_str));
209 //
210 // Note the syntax is slightly different to the C version of this macro.
211 //
212 #ifdef DEBUG
213 #define IF_DEBUG(c,s)  if (RtsFlags_DebugFlags_##c(RtsFlags)) { s; }
214 #else
215 #define IF_DEBUG(c,s)  /* nothing */
216 #endif
217
218 /* -----------------------------------------------------------------------------
219    Entering 
220
221    It isn't safe to "enter" every closure.  Functions in particular
222    have no entry code as such; their entry point contains the code to
223    apply the function.
224
225    ToDo: range should end in N_CLOSURE_TYPES-1, not N_CLOSURE_TYPES,
226    but switch doesn't allow us to use exprs there yet.
227    -------------------------------------------------------------------------- */
228
229 #define ENTER()                                         \
230  again:                                                 \
231   switch [INVALID_OBJECT .. N_CLOSURE_TYPES]            \
232          (TO_W_( %INFO_TYPE(%GET_STD_INFO(R1)) )) {     \
233   case                                                  \
234     IND,                                                \
235     IND_OLDGEN,                                         \
236     IND_PERM,                                           \
237     IND_OLDGEN_PERM,                                    \
238     IND_STATIC:                                         \
239    {                                                    \
240       R1 = StgInd_indirectee(R1);                       \
241       goto again;                                       \
242    }                                                    \
243   case                                                  \
244     BCO,                                                \
245     FUN,                                                \
246     FUN_1_0,                                            \
247     FUN_0_1,                                            \
248     FUN_2_0,                                            \
249     FUN_1_1,                                            \
250     FUN_0_2,                                            \
251     FUN_STATIC,                                         \
252     PAP:                                                \
253    {                                                    \
254       jump %ENTRY_CODE(Sp(0));                          \
255    }                                                    \
256   default:                                              \
257    {                                                    \
258       jump %GET_ENTRY(R1);                              \
259    }                                                    \
260   }
261
262 /* -----------------------------------------------------------------------------
263    Constants.
264    -------------------------------------------------------------------------- */
265
266 #include "Constants.h"
267 #include "DerivedConstants.h"
268 #include "ClosureTypes.h"
269 #include "StgFun.h"
270
271 //
272 // Need MachRegs, because some of the RTS code is conditionally
273 // compiled based on REG_R1, REG_R2, etc.
274 //
275 #define STOLEN_X86_REGS 4
276 #include "MachRegs.h"
277
278 #include "Liveness.h"
279 #include "StgLdvProf.h"
280
281 #undef BLOCK_SIZE
282 #undef MBLOCK_SIZE
283 #include "Block.h"  // For Bdescr()
284
285
286 // Can't think of a better place to put this.
287 #if SIZEOF_mp_limb_t != SIZEOF_VOID_P
288 #error mp_limb_t != StgWord: assumptions in PrimOps.cmm are now false
289 #endif
290
291 /* -------------------------------------------------------------------------
292    Allocation and garbage collection
293    ------------------------------------------------------------------------- */
294
295 // ALLOC_PRIM is for allocating memory on the heap for a primitive
296 // object.  It is used all over PrimOps.cmm.
297 //
298 // We make the simplifying assumption that the "admin" part of a
299 // primitive closure is just the header when calculating sizes for
300 // ticky-ticky.  It's not clear whether eg. the size field of an array
301 // should be counted as "admin", or the various fields of a BCO.
302 //
303 #define ALLOC_PRIM(bytes,liveness,reentry)                      \
304    HP_CHK_GEN_TICKY(bytes,liveness,reentry);                    \
305    TICK_ALLOC_PRIM(SIZEOF_StgHeader,bytes-SIZEOF_StgHeader,0);  \
306    CCCS_ALLOC(bytes);
307
308 // CCS_ALLOC wants the size in words, because ccs->mem_alloc is in words
309 #define CCCS_ALLOC(__alloc) CCS_ALLOC(BYTES_TO_WDS(__alloc), W_[CCCS])
310
311 #define HP_CHK_GEN_TICKY(alloc,liveness,reentry)        \
312    HP_CHK_GEN(alloc,liveness,reentry);                  \
313    TICK_ALLOC_HEAP_NOCTR(alloc);
314
315 #define MAYBE_GC(liveness,reentry)                      \
316    if (W_[alloc_blocks] >= W_[alloc_blocks_lim]) {      \
317         R9  = liveness;                                 \
318         R10 = reentry;                                  \
319         jump stg_gc_gen_hp;                             \
320    }
321
322 /* -----------------------------------------------------------------------------
323    Closures
324    -------------------------------------------------------------------------- */
325
326 // The offset of the payload of an array
327 #define BYTE_ARR_CTS(arr)  ((arr) + SIZEOF_StgArrWords)
328
329 // Getting/setting the info pointer of a closure
330 #define SET_INFO(p,info) StgHeader_info(p) = info
331 #define GET_INFO(p) StgHeader_info(p)
332
333 // Determine the size of an ordinary closure from its info table
334 #define sizeW_fromITBL(itbl) \
335   SIZEOF_StgHeader + WDS(%INFO_PTRS(itbl)) + WDS(%INFO_NPTRS(itbl))
336
337 // NB. duplicated from InfoTables.h!
338 #define BITMAP_SIZE(bitmap) ((bitmap) & BITMAP_SIZE_MASK)
339 #define BITMAP_BITS(bitmap) ((bitmap) >> BITMAP_BITS_SHIFT)
340
341 // Debugging macros
342 #define LOOKS_LIKE_INFO_PTR(p)                          \
343    ((p) != NULL &&                                      \
344      (TO_W_(%INFO_TYPE(%STD_INFO(p))) != INVALID_OBJECT) &&     \
345      (TO_W_(%INFO_TYPE(%STD_INFO(p))) <  N_CLOSURE_TYPES))
346
347 #define LOOKS_LIKE_CLOSURE_PTR(p) (LOOKS_LIKE_INFO_PTR(GET_INFO(p)))
348
349 //
350 // The layout of the StgFunInfoExtra part of an info table changes
351 // depending on TABLES_NEXT_TO_CODE.  So we define field access
352 // macros which use the appropriate version here:
353 //
354 #ifdef TABLES_NEXT_TO_CODE
355         // when TABLES_NEXT_TO_CODE, slow_apply is stored as an offset
356         // instead of the normal pointer.
357         
358 #define StgFunInfoExtra_slow_apply(fun_info)    \
359         (StgFunInfoExtraRev_slow_apply_offset(fun_info)    \
360         + (fun_info) + SIZEOF_StgFunInfoExtraRev + SIZEOF_StgInfoTable)
361
362 #define StgFunInfoExtra_fun_type(i)   StgFunInfoExtraRev_fun_type(i)
363 #define StgFunInfoExtra_arity(i)      StgFunInfoExtraRev_arity(i)
364 #define StgFunInfoExtra_bitmap(i)     StgFunInfoExtraRev_bitmap(i)
365 #else
366 #define StgFunInfoExtra_slow_apply(i) StgFunInfoExtraFwd_slow_apply(i)
367 #define StgFunInfoExtra_fun_type(i)   StgFunInfoExtraFwd_fun_type(i)
368 #define StgFunInfoExtra_arity(i)      StgFunInfoExtraFwd_arity(i)
369 #define StgFunInfoExtra_bitmap(i)     StgFunInfoExtraFwd_bitmap(i)
370 #endif
371
372 /* -----------------------------------------------------------------------------
373    Voluntary Yields/Blocks
374
375    We only have a generic version of this at the moment - if it turns
376    out to be slowing us down we can make specialised ones.
377    -------------------------------------------------------------------------- */
378
379 #define YIELD(liveness,reentry)                 \
380    R9  = liveness;                              \
381    R10 = reentry;                               \
382    jump stg_gen_yield;
383
384 #define BLOCK(liveness,reentry)                 \
385    R9  = liveness;                              \
386    R10 = reentry;                               \
387    jump stg_gen_block;
388
389 /* -----------------------------------------------------------------------------
390    Ticky macros 
391    -------------------------------------------------------------------------- */
392
393 #ifdef TICKY_TICKY
394 #define TICK_BUMP_BY(ctr,n) CLong[ctr] = CLong[ctr] + n
395 #else
396 #define TICK_BUMP_BY(ctr,n) /* nothing */
397 #endif
398
399 #define TICK_BUMP(ctr)      TICK_BUMP_BY(ctr,1)
400
401 #define TICK_ENT_DYN_IND()              TICK_BUMP(ENT_DYN_IND_ctr)
402 #define TICK_ENT_DYN_THK()              TICK_BUMP(ENT_DYN_THK_ctr)
403 #define TICK_ENT_VIA_NODE()             TICK_BUMP(ENT_VIA_NODE_ctr)
404 #define TICK_ENT_STATIC_IND()           TICK_BUMP(ENT_STATIC_IND_ctr)
405 #define TICK_ENT_PERM_IND()             TICK_BUMP(ENT_PERM_IND_ctr)
406 #define TICK_ENT_PAP()                  TICK_BUMP(ENT_PAP_ctr)
407 #define TICK_ENT_AP()                   TICK_BUMP(ENT_AP_ctr)
408 #define TICK_ENT_AP_STACK()             TICK_BUMP(ENT_AP_STACK_ctr)
409 #define TICK_ENT_BH()                   TICK_BUMP(ENT_BH_ctr)
410 #define TICK_UNKNOWN_CALL()             TICK_BUMP(UNKNOWN_CALL_ctr)
411 #define TICK_UPDF_PUSHED()              TICK_BUMP(UPDF_PUSHED_ctr)
412 #define TICK_CATCHF_PUSHED()            TICK_BUMP(CATCHF_PUSHED_ctr)
413 #define TICK_UPDF_OMITTED()             TICK_BUMP(UPDF_OMITTED_ctr)
414 #define TICK_UPD_NEW_IND()              TICK_BUMP(UPD_NEW_IND_ctr)
415 #define TICK_UPD_NEW_PERM_IND()         TICK_BUMP(UPD_NEW_PERM_IND_ctr)
416 #define TICK_UPD_OLD_IND()              TICK_BUMP(UPD_OLD_IND_ctr)
417 #define TICK_UPD_OLD_PERM_IND()         TICK_BUMP(UPD_OLD_PERM_IND_ctr)
418   
419 #define TICK_SLOW_CALL_FUN_TOO_FEW()    TICK_BUMP(SLOW_CALL_FUN_TOO_FEW_ctr)
420 #define TICK_SLOW_CALL_FUN_CORRECT()    TICK_BUMP(SLOW_CALL_FUN_CORRECT_ctr)
421 #define TICK_SLOW_CALL_FUN_TOO_MANY()   TICK_BUMP(SLOW_CALL_FUN_TOO_MANY_ctr)
422 #define TICK_SLOW_CALL_PAP_TOO_FEW()    TICK_BUMP(SLOW_CALL_PAP_TOO_FEW_ctr)
423 #define TICK_SLOW_CALL_PAP_CORRECT()    TICK_BUMP(SLOW_CALL_PAP_CORRECT_ctr)
424 #define TICK_SLOW_CALL_PAP_TOO_MANY()   TICK_BUMP(SLOW_CALL_PAP_TOO_MANY_ctr)
425
426 #define TICK_SLOW_CALL_v()              TICK_BUMP(SLOW_CALL_v_ctr)
427 #define TICK_SLOW_CALL_p()              TICK_BUMP(SLOW_CALL_p_ctr)
428 #define TICK_SLOW_CALL_pv()             TICK_BUMP(SLOW_CALL_pv_ctr)
429 #define TICK_SLOW_CALL_pp()             TICK_BUMP(SLOW_CALL_pp_ctr)
430 #define TICK_SLOW_CALL_ppp()            TICK_BUMP(SLOW_CALL_ppp_ctr)
431 #define TICK_SLOW_CALL_pppp()           TICK_BUMP(SLOW_CALL_pppp_ctr)
432 #define TICK_SLOW_CALL_ppppp()          TICK_BUMP(SLOW_CALL_ppppp_ctr)
433 #define TICK_SLOW_CALL_pppppp()         TICK_BUMP(SLOW_CALL_pppppp_ctr)
434
435 #ifdef TICKY_TICKY
436 #define TICK_HISTO_BY(histo,n,i)                        \
437          W_ __idx;                                      \
438          __idx = (n);                                   \
439          if (__idx > 8) {                               \
440             __idx = 8;                                  \
441          }                                              \
442          CLong[histo##_hst + _idx*SIZEOF_LONG]          \
443            = histo##_hst + __idx*SIZEOF_LONG] + i;
444 #else
445 #define TICK_HISTO_BY(histo,n,i) /* nothing */
446 #endif
447
448 #define TICK_HISTO(histo,n) TICK_HISTO_BY(histo,n,1)
449
450 // An unboxed tuple with n components.
451 #define TICK_RET_UNBOXED_TUP(n)                 \
452   TICK_BUMP(RET_UNBOXED_TUP_ctr++);             \
453   TICK_HISTO(RET_UNBOXED_TUP,n)
454
455 // A slow call with n arguments.  In the unevald case, this call has
456 // already been counted once, so don't count it again.
457 #define TICK_SLOW_CALL(n)                       \
458   TICK_BUMP(SLOW_CALL_ctr);                     \
459   TICK_HISTO(SLOW_CALL,n)
460
461 // This slow call was found to be to an unevaluated function; undo the
462 // ticks we did in TICK_SLOW_CALL.
463 #define TICK_SLOW_CALL_UNEVALD(n)               \
464   TICK_BUMP(SLOW_CALL_UNEVALD_ctr);             \
465   TICK_BUMP_BY(SLOW_CALL_ctr,-1);               \
466   TICK_HISTO_BY(SLOW_CALL,n,-1);
467
468 // Updating a closure with a new CON
469 #define TICK_UPD_CON_IN_NEW(n)                  \
470   TICK_BUMP(UPD_CON_IN_NEW_ctr);                \
471   TICK_HISTO(UPD_CON_IN_NEW,n)
472
473 #define TICK_ALLOC_HEAP_NOCTR(n)                \
474     TICK_BUMP(ALLOC_HEAP_ctr);                  \
475     TICK_BUMP_BY(ALLOC_HEAP_tot,n)
476
477 #endif // CMM_H