9db42e8635a8d2c579d75bdc28ab2a13004dc780
[ghc-hetmet.git] / ghc / includes / StgMacros.lh
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1993-1994
3 %
4 \section[StgMacros]{C macros used in GHC-generated \tr{.hc} files}
5
6 \begin{code}
7 #ifndef STGMACROS_H
8 #define STGMACROS_H
9 \end{code}
10
11 %************************************************************************
12 %*                                                                      *
13 \subsection[StgMacros-abbrev]{Abbreviatory(?) and general macros}
14 %*                                                                      *
15 %************************************************************************
16
17 Mere abbreviations:
18 \begin{code}
19 /* for function declarations */
20 #define STGFUN(f)  F_ f(STG_NO_ARGS)
21 #define STATICFUN(f) static F_ f(STG_NO_ARGS)
22
23 /* for functions/data that are really external to this module */
24 #define EXTFUN(f)       extern F_ f(STG_NO_ARGS)
25 #define EXTDATA(d)      extern W_ d[]
26 #define EXTDATA_RO(d)   extern const W_ d[] /* read-only */
27
28 /* for fwd decls to functions/data somewhere else in this module */
29 /* (identical for the mo') */
30 #define INTFUN(f)       static F_ f(STG_NO_ARGS)
31 #define INTDATA(d)      extern W_ d[]
32 #define INTDATA_RO(d)   extern const W_ d[] /* read-only */
33
34 /* short forms of most of the above */
35
36 #define FN_(f)          F_ f(STG_NO_ARGS)
37 #define IFN_(f)         static F_ f(STG_NO_ARGS)
38 #define EF_(f)          extern F_ f(STG_NO_ARGS)
39 #define ED_(d)          extern W_ d[]
40 #define ED_RO_(d)       extern const W_ d[] /* read-only */
41 #define IF_(f)          static F_ f(STG_NO_ARGS)
42
43 /* GCC is uncooperative about the next one: */
44 /* But, the "extern" prevents initialisation... ADR */
45 #if defined(__GNUC__)
46 #define ID_(d)          extern W_ d[]
47 #define ID_RO_(d)       extern const W_ d[] /* read-only */
48 #else
49 #define ID_(d)          static W_ d[]
50 #define ID_RO_(d)       static const W_ d[] /* read-only */
51 #endif /* not GCC */
52 \end{code}
53
54 General things; note: general-but-``machine-dependent'' macros are
55 given in \tr{StgMachDeps.lh}.
56 \begin{code}
57 I_ STG_MAX PROTO((I_, I_)); /* GCC -Wall loves prototypes */
58
59 extern STG_INLINE
60 I_
61 STG_MAX(I_ a, I_ b) { return((a >= b) ? a : b); }
62 /* NB: the naive #define macro version of STG_MAX
63    can lead to exponential CPP explosion, if you
64    have very-nested STG_MAXes.
65 */
66
67 /*
68 Macros to combine two short words into a single
69 word and split such a word back into two.
70
71 Dependent on machine word size :-)
72 */
73
74 #define COMBINE_WORDS(word,short1,short2)               \
75         do {                                            \
76             ((packed_shorts *)&(word))->wu.s1 = short1; \
77             ((packed_shorts *)&(word))->wu.s2 = short2; \
78         } while(0)
79
80 #define SPLIT_WORD(word,short1,short2)                  \
81         do {                                            \
82             short1 = ((packed_shorts *)&(word))->wu.s1; \
83             short2 = ((packed_shorts *)&(word))->wu.s2; \
84         } while(0)
85
86 \end{code}
87
88 %************************************************************************
89 %*                                                                      *
90 \subsection[StgMacros-gen-stg]{General STGish macros}
91 %*                                                                      *
92 %************************************************************************
93
94 Common sizes of vector-return tables.
95
96 Claim: don't need fwd decls for return pts in \tr{VECTBL*}, because
97 the AbsC flattener ensures that things come out sufficiently
98 ``backwards''.
99
100 \begin{code}
101 #ifdef __STG_REV_TBLS__
102 #define UNVECTBL(staticp,label,a)   /* nothing */
103 #else
104 #define UNVECTBL(staticp,label,a) \
105 EXTFUN(a); \
106 staticp const W_ label[] = { \
107   (W_) a \
108 };
109 #endif
110 \end{code}
111
112 \begin{code}
113 #if defined(USE_SPLIT_MARKERS)
114 #define __STG_SPLIT_MARKER(n) FN_(CAT2(__stg_split_marker,n)){ }
115 #else
116 #define __STG_SPLIT_MARKER(n) /* nothing */
117 #endif
118 \end{code}
119
120 %************************************************************************
121 %*                                                                      *
122 \subsection[StgMacros-exceptions]{Exception-checking macros}
123 %*                                                                      *
124 %************************************************************************
125
126 Argument-satisfaction check, stack(s) overflow check, heap overflow
127 check.
128
129 The @SUBTRACT(upper, lower)@ macros return a positive result in words
130 indicating the amount by which upper is above lower on the stack.
131
132 \begin{code}
133 #define SUBTRACT_A_STK( upper, lower ) AREL( (lower) - (upper) )
134 #define SUBTRACT_B_STK( upper, lower ) BREL( (lower) - (upper) )
135 \end{code}
136
137 %************************************************************************
138 %*                                                                      *
139 \subsubsection[StgMacros-arg-satis]{Argument-satisfaction checks}
140 %*                                                                      *
141 %************************************************************************
142
143 @ARGS_CHK(n)@ sees of there are @n@ words of args on the A/B stack.
144 If not, it jumps to @UpdatePAP@.
145
146 @ARGS_CHK@ args are pre-directionified.
147 Notice that we do the comparisons in the form (x < a+n), for
148 some constant n.  This generates more efficient code (with GCC at least)
149 than (x-a < n).
150
151 \begin{code}
152 #define ARGS_CHK_A(n)                                           \
153         if (SuA /*SUBTRACT_A_STK( SpA, SuA )*/ < (SpA+(n))) {   \
154                 JMP_( UpdatePAP );                              \
155         }
156
157 #define ARGS_CHK_A_LOAD_NODE(n, closure_addr)                   \
158         if (SuA /*SUBTRACT_A_STK( SpA, SuA )*/ < (SpA+(n))) {   \
159                 Node = (P_) closure_addr;                       \
160                 JMP_( UpdatePAP );                              \
161         }
162
163 #define ARGS_CHK_B(n)                                           \
164         if (SpB /*SUBTRACT_B_STK( SpB, SuB )*/ < (SuB-(n))) {   \
165                 JMP_( UpdatePAP );                              \
166         }
167
168
169 #define ARGS_CHK_B_LOAD_NODE(n, closure_addr)                   \
170         if (SpB /*SUBTRACT_B_STK( SpB, SuB )*/ < (SuB-(n))) {   \
171                 Node = (P_) closure_addr;                       \
172                 JMP_( UpdatePAP );                              \
173         }
174 \end{code}
175
176 %************************************************************************
177 %*                                                                      *
178 \subsubsection[StgMacros-stk-chks]{Stack-overflow check}
179 %*                                                                      *
180 %************************************************************************
181
182 @STK_CHK(a,b)@ [misc args omitted...] checks that we can allocate @a@
183 words of A stack and @b@ words of B stack.  If not, it calls
184 @StackOverflow@ (which dies).
185
186 (It will be different in the parallel case.)
187
188 NB: args @a@ and @b@ are pre-direction-ified!
189 \begin{code}
190 I_ SqueezeUpdateFrames PROTO((P_, P_, P_));
191 int sanityChk_StkO (P_ stko); /* ToDo: move to a sane place */
192
193 #if ! defined(CONCURRENT)
194
195 extern void StackOverflow(STG_NO_ARGS) STG_NORETURN;
196
197 #if STACK_CHECK_BY_PAGE_FAULT
198
199 #define STACK_OVERFLOW(liveness,hda,hdb,spa,spb,rtype,reenter)  \
200     /* use memory protection instead; still need ticky-ness */
201
202 #else
203
204 #define STACK_OVERFLOW(liveness,hda,hdb,spa,spb,rtype,reenter)  \
205     ULTRASAFESTGCALL0(void,(void *),StackOverflow)
206
207 #endif /* not using page-faulting */
208
209 #else /* threaded */
210
211 I_ StackOverflow PROTO((W_, W_));
212
213 /*
214  * On a uniprocessor, we do *NOT* context switch on a stack overflow 
215  * (though we may GC).  Therefore, we never have to reenter node.
216  */
217
218 #define STACK_OVERFLOW(liveness,hda,hdb,spa,spb,rtype,reenter) \
219     DO_STACKOVERFLOW((hda+hdb)<<2|((rtype)<<1)|(reenter),((spa)<<20)|((spb)<<8)|(liveness))
220
221 #define STACK_OVERFLOW_HEADROOM(args,y)     ((args) >> 2)
222 #define STACK_OVERFLOW_PRIM_RETURN(args,y)  ((args) & 2)
223 #define STACK_OVERFLOW_REENTER(args,y)      ((args) & 1)
224
225 #define STACK_OVERFLOW_AWORDS(x,args)       (((args) >> 20) & 0x0fff)
226 #define STACK_OVERFLOW_BWORDS(x,args)       (((args) >> 8) & 0x0fff)
227 #define STACK_OVERFLOW_LIVENESS(x,args)     ((args) & 0xff)
228
229 #endif  /* CONCURRENT */
230
231 #define STK_CHK(liveness_mask,a_headroom,b_headroom,spa,spb,ret_type,reenter)\
232 do {                                                            \
233   DO_ASTK_HWM(); /* ticky-ticky profiling */                    \
234   DO_BSTK_HWM();                                                \
235   if (STKS_OVERFLOW_OP(((a_headroom) + 1), ((b_headroom) + 1))) {       \
236     STACK_OVERFLOW(liveness_mask,a_headroom,b_headroom,spa,spb,ret_type,reenter);\
237   }                                                             \
238 }while(0)
239 \end{code}
240
241 %************************************************************************
242 %*                                                                      *
243 \subsubsection[StgMacros-heap-chks]{Heap-overflow checks}
244 %*                                                                      *
245 %************************************************************************
246
247 Please see the general discussion/commentary about ``what really
248 happens in a GC,'' in \tr{SMinterface.lh}.
249
250 \begin{code}
251 void PerformGC PROTO((W_));
252 void RealPerformGC PROTO((W_ liveness, W_ reqsize, W_  always_reenter_node, rtsBool do_full_collection));
253 void checkInCCallGC(STG_NO_ARGS);
254
255 #ifndef PAR
256 void StgPerformGarbageCollection(STG_NO_ARGS);
257 #endif
258
259 #ifndef CONCURRENT
260
261 #define OR_MSG_PENDING  /* never */
262
263 #define HEAP_OVERFLOW(liveness,n,reenter)       \
264     do {                                        \
265     DO_GC((((W_)n)<<8)|(liveness));             \
266     } while (0)
267
268 #define REQSIZE_BITMASK ((1L << ((BITS_IN(W_) - 8 + 1))) - 1)
269 #define HEAP_OVERFLOW_REQSIZE(args)     (((args) >> 8) & REQSIZE_BITMASK)
270 #define HEAP_OVERFLOW_REENTER(args)     0
271 #define HEAP_OVERFLOW_LIVENESS(args)    ((args) & 0xff)
272
273 #else /* CONCURRENT */
274
275 void ReallyPerformThreadGC PROTO((W_, rtsBool));
276
277 #define HEAP_OVERFLOW(liveness,n,reenter)       \
278     do {                                        \
279     DO_GC((((W_)(n))<<9)|((reenter)<<8)|(liveness)); \
280     } while (0)
281
282 #define REQSIZE_BITMASK ((1L << ((BITS_IN(W_) - 9 + 1))) - 1)
283 #define HEAP_OVERFLOW_REQSIZE(args)     (((args) >> 9) & REQSIZE_BITMASK)
284 #define HEAP_OVERFLOW_REENTER(args)     (((args) >> 8) & 0x1)
285 #define HEAP_OVERFLOW_LIVENESS(args)    ((args) & 0xff)
286
287 #ifndef PAR
288
289 #define OR_MSG_PENDING  /* never */
290
291 #else 
292
293 extern int PacketsWaiting;              /*Probes for incoming messages*/
294 extern int heapChkCounter;              /*Not currently used! We check for messages when*/
295                                         /*a thread is resheduled PWT*/
296 /* #define OR_MSG_PENDING       || (--heapChkCounter == 0 && PacketsWaiting())*/
297 #define OR_MSG_PENDING  /* never */
298
299 #endif  /* PAR */
300 #endif  /* CONCURRENT */
301
302 #if 0 /* alpha_TARGET_ARCH */
303 #define CACHE_LINE  4   /* words */
304 #define LINES_AHEAD 3
305 #define PRE_FETCH(n)                                    \
306 do {                                                    \
307  StgInt j;                                              \
308  j = ((STG_VOLATILE StgInt *) Hp)[LINES_AHEAD * CACHE_LINE];    \
309 } while(0);
310 #define EXTRA_HEAP_WORDS (CACHE_LINE * LINES_AHEAD)
311 #else
312 #define PRE_FETCH(reg)
313 #define EXTRA_HEAP_WORDS 0
314 #endif
315
316 #if defined(GRAN)
317 #define HEAP_CHK(liveness_mask,n,reenter)                       \
318         do {                                                    \
319         /* TICKY_PARANOIA(__FILE__, __LINE__); */               \
320         /* THREAD_CONTEXT_SWITCH(liveness_mask,reenter); */             \
321         ALLOC_HEAP(n); /* ticky profiling */                    \
322         GRAN_ALLOC_HEAP(n,liveness_mask); /* Granularity Simulation */ \
323         if (((Hp = Hp + (n)) > HpLim)) {                        \
324             /* Old:  STGCALL3_GC(PerformGC,liveness_mask,n,StgFalse); */\
325             HEAP_OVERFLOW(liveness_mask,n,StgFalse); \
326         }}while(0)
327
328 #else
329
330 #define HEAP_CHK(liveness_mask,n,reenter)               \
331 do {                                                    \
332   /* TICKY_PARANOIA(__FILE__, __LINE__); */             \
333   PRE_FETCH(n);                                         \
334   ALLOC_HEAP(n); /* ticky profiling */                  \
335   if (((Hp = Hp + (n)) > HpLim) OR_INTERVAL_EXPIRED OR_CONTEXT_SWITCH OR_MSG_PENDING) { \
336     HEAP_OVERFLOW(liveness_mask,n,reenter);             \
337   }                                                     \
338 } while(0)
339
340 #endif  /* GRAN */
341
342 #ifdef CONCURRENT
343
344 #define HEAP_CHK_AND_RESTORE_N(liveness_mask,n,reenter) \
345 do {                                                    \
346   /* TICKY_PARANOIA(__FILE__, __LINE__); */             \
347   PRE_FETCH(n);                                         \
348   ALLOC_HEAP(n); /* ticky profiling */                  \
349   if (((Hp = Hp + (n)) > HpLim) OR_INTERVAL_EXPIRED OR_CONTEXT_SWITCH OR_MSG_PENDING) { \
350     HEAP_OVERFLOW(liveness_mask,n,reenter);             \
351     n = TSO_ARG1(CurrentTSO);                           \
352   }} while(0)
353
354 #else
355
356 #define HEAP_CHK_AND_RESTORE_N(liveness_mask,n,reenter)     \
357     HEAP_CHK(liveness_mask,n,reenter)
358
359 #endif
360
361 \end{code}
362
363
364 %************************************************************************
365 %*                                                                      *
366 \subsection[StgMacros-prim-ops]{Primitive operations}
367 %*                                                                      *
368 %************************************************************************
369
370 One thing to be {\em very careful about} with these macros that assign
371 to results is that the assignment must come {\em last}.  Some of the
372 other arguments may be in terms of addressing modes that get clobbered
373 by the assignment.  (Dirty imperative programming RULES!)
374
375 The order here is roughly that in \tr{compiler/prelude/PrimOps.lhs}.
376
377 %************************************************************************
378 %*                                                                      *
379 \subsubsection[StgMacros-compare-primops]{Primitive comparison ops on basic types}
380 %*                                                                      *
381 %************************************************************************
382
383 We cast the chars in case one of them is a literal (so C things work right
384 even for 8-bit chars).
385 \begin{code}
386 #define gtCharZh(r,a,b) r=(I_)((a)> (b))
387 #define geCharZh(r,a,b) r=(I_)((a)>=(b))
388 #define eqCharZh(r,a,b) r=(I_)((a)==(b))
389 #define neCharZh(r,a,b) r=(I_)((a)!=(b))
390 #define ltCharZh(r,a,b) r=(I_)((a)< (b))
391 #define leCharZh(r,a,b) r=(I_)((a)<=(b))
392
393 /* Int comparisons: >#, >=# etc */
394 #define ZgZh(r,a,b)     r=(I_)((a) >(b))
395 #define ZgZeZh(r,a,b)   r=(I_)((a)>=(b))
396 #define ZeZeZh(r,a,b)   r=(I_)((a)==(b))
397 #define ZdZeZh(r,a,b)   r=(I_)((a)!=(b))
398 #define ZlZh(r,a,b)     r=(I_)((a) <(b))
399 #define ZlZeZh(r,a,b)   r=(I_)((a)<=(b))
400
401 #define gtWordZh(r,a,b) r=(I_)((a) >(b))
402 #define geWordZh(r,a,b) r=(I_)((a)>=(b))
403 #define eqWordZh(r,a,b) r=(I_)((a)==(b))
404 #define neWordZh(r,a,b) r=(I_)((a)!=(b))
405 #define ltWordZh(r,a,b) r=(I_)((a) <(b))
406 #define leWordZh(r,a,b) r=(I_)((a)<=(b))
407
408 #define gtAddrZh(r,a,b) r=(I_)((a) >(b))
409 #define geAddrZh(r,a,b) r=(I_)((a)>=(b))
410 #define eqAddrZh(r,a,b) r=(I_)((a)==(b))
411 #define neAddrZh(r,a,b) r=(I_)((a)!=(b))
412 #define ltAddrZh(r,a,b) r=(I_)((a) <(b))
413 #define leAddrZh(r,a,b) r=(I_)((a)<=(b))
414
415 #define gtFloatZh(r,a,b)  r=(I_)((a)> (b))
416 #define geFloatZh(r,a,b)  r=(I_)((a)>=(b))
417 #define eqFloatZh(r,a,b)  r=(I_)((a)==(b))
418 #define neFloatZh(r,a,b)  r=(I_)((a)!=(b))
419 #define ltFloatZh(r,a,b)  r=(I_)((a)< (b))
420 #define leFloatZh(r,a,b)  r=(I_)((a)<=(b))
421
422 /* Double comparisons: >##, >=#@ etc */
423 #define ZgZhZh(r,a,b)   r=(I_)((a) >(b))
424 #define ZgZeZhZh(r,a,b) r=(I_)((a)>=(b))
425 #define ZeZeZhZh(r,a,b) r=(I_)((a)==(b))
426 #define ZdZeZhZh(r,a,b) r=(I_)((a)!=(b))
427 #define ZlZhZh(r,a,b)   r=(I_)((a) <(b))
428 #define ZlZeZhZh(r,a,b) r=(I_)((a)<=(b))
429 \end{code}
430
431 %************************************************************************
432 %*                                                                      *
433 \subsubsection[StgMacros-char-primops]{Primitive @Char#@ ops (and @LitString#@ish things, too)}
434 %*                                                                      *
435 %************************************************************************
436
437 We cast the chars in case one of them is a literal (so C things work right
438 even for 8-bit chars).
439 \begin{code}
440 #define ordZh(r,a)      r=(I_)((W_) (a))
441 #define chrZh(r,a)      r=(StgChar)((W_)(a))
442 \end{code}
443
444 %************************************************************************
445 %*                                                                      *
446 \subsubsection[StgMacros-int-primops]{Primitive @Int#@ ops}
447 %*                                                                      *
448 %************************************************************************
449
450 \begin{code}
451 I_ stg_div PROTO((I_ a, I_ b));
452
453 #define ZpZh(r,a,b)             r=(a)+(b)
454 #define ZmZh(r,a,b)             r=(a)-(b)
455 #define ZtZh(r,a,b)             r=(a)*(b)
456 #define quotIntZh(r,a,b)        r=(a)/(b)
457 /* ZdZh not used??? --SDM */
458 #define ZdZh(r,a,b)             r=ULTRASAFESTGCALL2(I_,(void *, I_, I_),stg_div,(a),(b))
459 #define remIntZh(r,a,b)         r=(a)%(b)
460 #define negateIntZh(r,a)        r=-(a)
461 /* Ever used ? -- SOF */
462 #define absIntZh(a)             r=(( (a) >= 0 ) ? (a) : (-(a)))
463 \end{code}
464
465 %************************************************************************
466 %*                                                                      *
467 \subsubsection[StgMacros-word-primops]{Primitive @Word#@ ops}
468 %*                                                                      *
469 %************************************************************************
470
471 \begin{code}
472 #define quotWordZh(r,a,b)       r=((W_)a)/((W_)b)
473 #define remWordZh(r,a,b)        r=((W_)a)%((W_)b)
474
475 #define andZh(r,a,b)    r=(a)&(b)
476 #define orZh(r,a,b)     r=(a)|(b)
477 #define xorZh(r,a,b)    r=(a)^(b)
478 #define notZh(r,a)      r=~(a)
479
480 #define shiftLZh(r,a,b)   r=(a)<<(b)
481 #define shiftRAZh(r,a,b)  r=(a)>>(b)
482 #define shiftRLZh(r,a,b)  r=(a)>>(b)
483 #define iShiftLZh(r,a,b)  r=(a)<<(b)
484 #define iShiftRAZh(r,a,b) r=(a)>>(b)
485 #define iShiftRLZh(r,a,b) r=(a)>>(b)
486
487 #define int2WordZh(r,a) r=(W_)(a)
488 #define word2IntZh(r,a) r=(I_)(a)
489 \end{code}
490
491 %************************************************************************
492 %*                                                                      *
493 \subsubsection[StgMacros-addr-primops]{Primitive @Addr#@ ops}
494 %*                                                                      *
495 %************************************************************************
496
497 \begin{code}
498 #define int2AddrZh(r,a) r=(A_)(a)
499 #define addr2IntZh(r,a) r=(I_)(a)
500 \end{code}
501
502 %************************************************************************
503 %*                                                                      *
504 \subsubsection[StgMacros-float-primops]{Primitive @Float#@ ops}
505 %*                                                                      *
506 %************************************************************************
507
508 \begin{code}
509 #define plusFloatZh(r,a,b)      r=(a)+(b)
510 #define minusFloatZh(r,a,b)     r=(a)-(b)
511 #define timesFloatZh(r,a,b)     r=(a)*(b)
512 #define divideFloatZh(r,a,b)    r=(a)/(b)
513 #define negateFloatZh(r,a)      r=-(a)
514
515 #define int2FloatZh(r,a)        r=(StgFloat)(a)
516 #define float2IntZh(r,a)        r=(I_)(a)
517
518 #define expFloatZh(r,a)         r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),exp,a)
519 #define logFloatZh(r,a)         r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),log,a)
520 #define sqrtFloatZh(r,a)        r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),sqrt,a)
521 #define sinFloatZh(r,a)         r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),sin,a)
522 #define cosFloatZh(r,a)         r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),cos,a)
523 #define tanFloatZh(r,a)         r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),tan,a)
524 #define asinFloatZh(r,a)        r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),asin,a)
525 #define acosFloatZh(r,a)        r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),acos,a)
526 #define atanFloatZh(r,a)        r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),atan,a)
527 #define sinhFloatZh(r,a)        r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),sinh,a)
528 #define coshFloatZh(r,a)        r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),cosh,a)
529 #define tanhFloatZh(r,a)        r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),tanh,a)
530 #define powerFloatZh(r,a,b)     r=(StgFloat) SAFESTGCALL2(StgDouble,(void *, StgDouble,StgDouble),pow,a,b)
531
532 /* encoding/decoding given w/ Integer stuff */
533 \end{code}
534
535 %************************************************************************
536 %*                                                                      *
537 \subsubsection[StgMacros-double-primops]{Primitive @Double#@ ops}
538 %*                                                                      *
539 %************************************************************************
540
541 \begin{code}
542 #define ZpZhZh(r,a,b)           r=(a)+(b)
543 #define ZmZhZh(r,a,b)           r=(a)-(b)
544 #define ZtZhZh(r,a,b)           r=(a)*(b)
545 #define ZdZhZh(r,a,b)           r=(a)/(b)
546 #define negateDoubleZh(r,a)     r=-(a)
547
548 #define int2DoubleZh(r,a)       r=(StgDouble)(a)
549 #define double2IntZh(r,a)       r=(I_)(a)
550
551 #define float2DoubleZh(r,a)     r=(StgDouble)(a)
552 #define double2FloatZh(r,a)     r=(StgFloat)(a)
553
554 #define expDoubleZh(r,a)        r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),exp,a)
555 #define logDoubleZh(r,a)        r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),log,a)
556 #define sqrtDoubleZh(r,a)       r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),sqrt,a)
557 #define sinDoubleZh(r,a)        r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),sin,a)
558 #define cosDoubleZh(r,a)        r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),cos,a)
559 #define tanDoubleZh(r,a)        r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),tan,a)
560 #define asinDoubleZh(r,a)       r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),asin,a)
561 #define acosDoubleZh(r,a)       r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),acos,a)
562 #define atanDoubleZh(r,a)       r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),atan,a)
563 #define sinhDoubleZh(r,a)       r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),sinh,a)
564 #define coshDoubleZh(r,a)       r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),cosh,a)
565 #define tanhDoubleZh(r,a)       r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),tanh,a)
566 /* Power: **## */
567 #define ZtZtZhZh(r,a,b) r=(StgDouble) SAFESTGCALL2(StgDouble,(void *, StgDouble,StgDouble),pow,a,b)
568 \end{code}
569
570 %************************************************************************
571 %*                                                                      *
572 \subsubsection[StgMacros-integer-primops]{Primitive @Integer@-related ops (GMP stuff)}
573 %*                                                                      *
574 %************************************************************************
575
576 Dirty macros we use for the real business.
577
578 INVARIANT: When one of these macros is called, the only live data is
579 tidily on the STG stacks or in the STG registers (the code generator
580 ensures this).  If there are any pointer-arguments, they will be in
581 the first \tr{Ret*} registers (e.g., \tr{da} arg of \tr{gmpTake1Return1}).
582
583 OK, here are the real macros:
584 \begin{code}
585 #define gmpTake1Return1(size_chk_macro, liveness, mpz_op, ar,sr,dr, aa,sa,da)   \
586 { MP_INT arg;                                                                   \
587   MP_INT result;                                                                \
588   I_ space = size_chk_macro(sa);                                                \
589                                                                                 \
590   /* Check that there will be enough heap & make Hp visible to GMP allocator */ \
591   GMP_HEAP_LOOKAHEAD(liveness,space);                                           \
592                                                                                 \
593   /* Now we can initialise (post possible GC) */                                \
594   arg.alloc     = (aa);                                                         \
595   arg.size      = (sa);                                                         \
596   arg.d         = (unsigned long int *) (BYTE_ARR_CTS(da));                     \
597                                                                                 \
598   SAFESTGCALL1(void,(void *, MP_INT *),mpz_init,&result);                       \
599                                                                                 \
600   /* Perform the operation */                                                   \
601   SAFESTGCALL2(void,(void *, MP_INT *, MP_INT *),mpz_op,&result,&arg);          \
602                                                                                 \
603   GMP_HEAP_HANDBACK();          /* restore Hp */                                \
604   (ar) = result.alloc;                                                          \
605   (sr) = result.size;                                                           \
606   (dr) = (B_) (result.d - DATA_HS);                                             \
607   /* pt to *beginning* of object (GMP has been monkeying around in the middle) */ \
608 }
609
610
611 #define gmpTake2Return1(size_chk_macro, liveness, mpz_op, ar,sr,dr, a1,s1,d1, a2,s2,d2)\
612 { MP_INT arg1;                                                                  \
613   MP_INT arg2;                                                                  \
614   MP_INT result;                                                                \
615   I_ space = size_chk_macro(s1,s2);                                             \
616                                                                                 \
617   /* Check that there will be enough heap & make Hp visible to GMP allocator */ \
618   GMP_HEAP_LOOKAHEAD(liveness,space);                                           \
619                                                                                 \
620   /* Now we can initialise (post possible GC) */                                \
621   arg1.alloc    = (a1);                                                         \
622   arg1.size     = (s1);                                                         \
623   arg1.d        = (unsigned long int *) (BYTE_ARR_CTS(d1));                     \
624   arg2.alloc    = (a2);                                                         \
625   arg2.size     = (s2);                                                         \
626   arg2.d        = (unsigned long int *) (BYTE_ARR_CTS(d2));                     \
627                                                                                 \
628   SAFESTGCALL1(void,(void *, MP_INT *),mpz_init,&result);                       \
629                                                                                 \
630   /* Perform the operation */                                                   \
631   SAFESTGCALL3(void,(void *, MP_INT *, MP_INT *, MP_INT *),mpz_op,&result,&arg1,&arg2); \
632                                                                                 \
633   GMP_HEAP_HANDBACK();          /* restore Hp */                                \
634   (ar) = result.alloc;                                                          \
635   (sr) = result.size;                                                           \
636   (dr) = (B_) (result.d - DATA_HS);                                             \
637   /* pt to *beginning* of object (GMP has been monkeying around in the middle) */ \
638 }
639
640 #define gmpTake2Return2(size_chk_macro, liveness, mpz_op, ar1,sr1,dr1, ar2,sr2,dr2, a1,s1,d1, a2,s2,d2) \
641 { MP_INT arg1;                                                                  \
642   MP_INT arg2;                                                                  \
643   MP_INT result1;                                                               \
644   MP_INT result2;                                                               \
645   I_ space = size_chk_macro(s1,s2);                                             \
646                                                                                 \
647   /* Check that there will be enough heap & make Hp visible to GMP allocator */ \
648   GMP_HEAP_LOOKAHEAD(liveness,space);                                           \
649                                                                                 \
650   /* Now we can initialise (post possible GC) */                                \
651   arg1.alloc    = (a1);                                                         \
652   arg1.size     = (s1);                                                         \
653   arg1.d        = (unsigned long int *) (BYTE_ARR_CTS(d1));                     \
654   arg2.alloc    = (a2);                                                         \
655   arg2.size     = (s2);                                                         \
656   arg2.d        = (unsigned long int *) (BYTE_ARR_CTS(d2));                     \
657                                                                                 \
658   SAFESTGCALL1(void,(void *, MP_INT *),mpz_init,&result1);                      \
659   SAFESTGCALL1(void,(void *, MP_INT *),mpz_init,&result2);                      \
660                                                                                 \
661   /* Perform the operation */                                                   \
662   SAFESTGCALL4(void,(void *, MP_INT *, MP_INT *, MP_INT *, MP_INT *),mpz_op,&result1,&result2,&arg1,&arg2); \
663                                                                                 \
664   GMP_HEAP_HANDBACK();          /* restore Hp */                                \
665   (ar1) = result1.alloc;                                                        \
666   (sr1) = result1.size;                                                         \
667   (dr1) = (B_) (result1.d - DATA_HS);                                           \
668   (ar2) = result2.alloc;                                                        \
669   (sr2) = result2.size;                                                         \
670   (dr2) = (B_) (result2.d - DATA_HS);                                           \
671 }
672 \end{code}
673
674 Some handy size-munging macros: sometimes gratuitously {\em conservative}.
675 The \tr{+16} is to allow for the initial allocation of \tr{MP_INT} results.
676 The \tr{__abs} stuff is because negative-ness of GMP things is encoded
677 in their ``size''...
678 \begin{code}
679 #define __abs(a)                (( (a) >= 0 ) ? (a) : (-(a)))
680 #define GMP_SIZE_ONE()          (2 + DATA_HS + 16)
681 #define GMP_SAME_SIZE(a)        (__abs(a) + DATA_HS + 16)
682 #define GMP_MAX_SIZE(a,b)       ((__abs(a) > __abs(b) ? __abs(a) : __abs(b)) + 1 + DATA_HS + 16)
683                                 /* NB: the +1 is for the carry (or whatever) */
684 #define GMP_2MAX_SIZE(a,b)      (2 * GMP_MAX_SIZE(a,b))
685 #define GMP_ADD_SIZES(a,b)      (__abs(a) + __abs(b) + 1 + DATA_HS + 16)
686                                 /* the +1 may just be paranoia */
687 \end{code}
688
689 For the Integer/GMP stuff, we have macros that {\em look ahead} for
690 some space, but don't actually grab it.
691
692 If there are live pointers at the time of the lookahead, the caller
693 must make sure they are in \tr{Ret1}, \tr{Ret2}, ..., so they can be
694 handled normally.  We achieve this by having the code generator {\em
695 always} pass args to may-invoke-GC primitives in registers, using the
696 normal pointers-first policy.  This means that, if we do go to garbage
697 collection, everything is already in the Right Place.
698
699 Saving and restoring Hp register so the MP allocator can see them. If we are
700 performing liftime profiling need to save and restore HpLim as well so that
701 it can be bumped if allocation occurs.
702
703 The second argument to @GMP_HEAP_LOOKAHEAD@ must be an lvalue so that
704 it can be restored from @TSO_ARG1@ after a failed @HEAP_CHK@ in
705 threaded land.
706
707 \begin{code}
708 #define GMP_HEAP_LOOKAHEAD(liveness,n)                  \
709         do {                                            \
710         HEAP_CHK_AND_RESTORE_N(liveness,n,0);           \
711         Hp = Hp - (n);                                  \
712         UN_ALLOC_HEAP(n);       /* Undo ticky-ticky */  \
713         SAVE_Hp = Hp;           /* Hand over the hp */  \
714         DEBUG_SetGMPAllocBudget(n)                      \
715         }while(0)
716
717 #define GMP_HEAP_HANDBACK()                             \
718         Hp = SAVE_Hp;                                   \
719         DEBUG_ResetGMPAllocBudget()
720 \end{code}
721
722 \begin{code}
723 void *stgAllocForGMP   PROTO((size_t size_in_bytes));
724 void *stgReallocForGMP PROTO((void *ptr, size_t old_size, size_t new_size));
725 void stgDeallocForGMP  PROTO((void *ptr, size_t size));
726
727 #ifdef ALLOC_DEBUG
728 extern StgInt DEBUG_GMPAllocBudget;
729 #define DEBUG_SetGMPAllocBudget(n)  DEBUG_GMPAllocBudget = (n);
730 #define DEBUG_ResetGMPAllocBudget() DEBUG_GMPAllocBudget = 0;
731 #else
732 #define DEBUG_SetGMPAllocBudget(n)  /*nothing*/
733 #define DEBUG_ResetGMPAllocBudget() /*nothing*/
734 #endif
735 \end{code}
736
737 The real business (defining Integer primops):
738 \begin{code}
739 #define negateIntegerZh(ar,sr,dr, liveness, aa,sa,da) \
740         gmpTake1Return1(GMP_SAME_SIZE, liveness, mpz_neg, ar,sr,dr, aa,sa,da)
741
742 #define plusIntegerZh(ar,sr,dr, liveness, a1,s1,d1, a2,s2,d2) \
743         gmpTake2Return1(GMP_MAX_SIZE, liveness, mpz_add, ar,sr,dr, a1,s1,d1, a2,s2,d2)
744 #define minusIntegerZh(ar,sr,dr, liveness, a1,s1,d1, a2,s2,d2) \
745         gmpTake2Return1(GMP_MAX_SIZE, liveness, mpz_sub, ar,sr,dr, a1,s1,d1, a2,s2,d2)
746 #define timesIntegerZh(ar,sr,dr, liveness, a1,s1,d1, a2,s2,d2) \
747         gmpTake2Return1(GMP_ADD_SIZES, liveness, mpz_mul, ar,sr,dr, a1,s1,d1, a2,s2,d2)
748
749 /* div, mod, quot, rem are defined w/ quotRem & divMod */
750
751 #define quotRemIntegerZh(ar1,sr1,dr1, ar2,sr2,dr2, liveness, a1,s1,d1, a2,s2,d2) \
752         gmpTake2Return2(GMP_2MAX_SIZE, liveness, mpz_divmod, ar1,sr1,dr1, ar2,sr2,dr2, a1,s1,d1, a2,s2,d2)
753 #define divModIntegerZh(ar1,sr1,dr1, ar2,sr2,dr2, liveness,  a1,s1,d1, a2,s2,d2) \
754         gmpTake2Return2(GMP_2MAX_SIZE, liveness, mpz_mdivmod, ar1,sr1,dr1, ar2,sr2,dr2, a1,s1,d1, a2,s2,d2)
755 \end{code}
756
757 Comparison ops (@<@, @>=@, etc.) are defined in terms of the cmp
758 fellow (returns -ve, 0, or +ve).
759 \begin{code}
760 #define cmpIntegerZh(r, hp, a1,s1,d1, a2,s2,d2) /* calls mpz_cmp */             \
761 { MP_INT arg1;                                                                  \
762   MP_INT arg2;                                                                  \
763   /* Does not allocate memory */                                                \
764                                                                                 \
765   arg1.alloc    = (a1);                                                         \
766   arg1.size     = (s1);                                                         \
767   arg1.d        = (unsigned long int *) (BYTE_ARR_CTS(d1));                     \
768   arg2.alloc    = (a2);                                                         \
769   arg2.size     = (s2);                                                         \
770   arg2.d        = (unsigned long int *) (BYTE_ARR_CTS(d2));                     \
771                                                                                 \
772   (r) = SAFESTGCALL2(I_,(void *, MP_INT *, MP_INT *),mpz_cmp,&arg1,&arg2);      \
773 }
774 \end{code}
775
776 Coercions:
777
778 \begin{code}
779 #define integer2IntZh(r, hp, aa,sa,da)                                          \
780 { MP_INT arg;                                                                   \
781   /* Does not allocate memory */                                                \
782                                                                                 \
783   arg.alloc     = (aa);                                                         \
784   arg.size      = (sa);                                                         \
785   arg.d         = (unsigned long int *) (BYTE_ARR_CTS(da));                     \
786                                                                                 \
787   (r) = SAFESTGCALL1(I_,(void *, MP_INT *),mpz_get_si,&arg);                    \
788 }
789
790 /* Since we're forced to know a little bit about MP_INT layout to do this with
791    pre-allocated heap, we just inline the whole of mpz_init_set_si here.
792         ** DIRE WARNING.  if mpz_init_set_si changes, so does this! ***
793 */
794
795 #define int2IntegerZh(ar,sr,dr, hp, i)                                          \
796 { StgInt val; /* to snaffle arg to avoid aliasing */                            \
797                                                                                 \
798   val = (i);  /* snaffle... */                                                  \
799                                                                                 \
800   SET_DATA_HDR((hp),ArrayOfData_info,CCC,DATA_VHS+MIN_MP_INT_SIZE,0);           \
801                                                                                 \
802   if      ((val) < 0) { (sr) = -1; (hp)[DATA_HS] = -(val); }                    \
803   else if ((val) > 0) { (sr) =  1; (hp)[DATA_HS] =  (val); }                    \
804   else /* val==0 */   { (sr) =  0; }                                            \
805   (ar) = 1;                                                                     \
806   (dr) = (B_)(hp);              /* dr is an StgByteArray */                     \
807 }
808
809 #define word2IntegerZh(ar,sr,dr, hp, i)                                         \
810 { StgWord val; /* to snaffle arg to avoid aliasing */                           \
811                                                                                 \
812   val = (i);  /* snaffle... */                                                  \
813                                                                                 \
814   SET_DATA_HDR((hp),ArrayOfData_info,CCC,DATA_VHS+MIN_MP_INT_SIZE,0);           \
815                                                                                 \
816   if ((val) != 0)     { (sr) =  1; (hp)[DATA_HS] =  (val); }                    \
817   else /* val==0 */   { (sr) =  0; }                                            \
818   (ar) = 1;                                                                     \
819   (dr) = (B_)(hp);              /* dr is an StgByteArray */                     \
820 }
821
822 #define integer2WordZh(r, hp, aa,sa,da)                                         \
823 { MP_INT arg;                                                                   \
824   /* Does not allocate memory */                                                \
825                                                                                 \
826   arg.alloc     = (aa);                                                         \
827   arg.size      = (sa);                                                         \
828   arg.d         = (unsigned long int *) (BYTE_ARR_CTS(da));                     \
829                                                                                 \
830   (r) = SAFESTGCALL1(I_,(void *, MP_INT *),mpz_get_ui,&arg);                    \
831 }
832
833 \end{code}
834
835 Then there are a few oddments to make life easier:
836 \begin{code}
837 /*
838    DIRE WARNING.
839    The "str" argument must be a literal C string.
840
841         addr2Integer( ..., "foo")   OK!
842
843         x = "foo";
844         addr2Integer( ..., x)       NO! NO!
845 */
846
847 #define addr2IntegerZh(ar,sr,dr, liveness, str)                                 \
848 { MP_INT result;                                                                \
849   /* taking the number of bytes/8 as the number of words of lookahead           \
850      is plenty conservative */                                                  \
851   I_ space = GMP_SAME_SIZE(sizeof(str) / 8 + 1);                                \
852                                                                                 \
853   GMP_HEAP_LOOKAHEAD(liveness, space);                                          \
854                                                                                 \
855   /* Perform the operation */                                                   \
856   if (SAFESTGCALL3(I_,(void *, MP_INT *, char *, int), mpz_init_set_str,&result,(str),/*base*/10)) \
857       abort();                                                                  \
858                                                                                 \
859   GMP_HEAP_HANDBACK();          /* restore Hp */                                \
860   (ar) = result.alloc;                                                          \
861   (sr) = result.size;                                                           \
862   (dr) = (B_) (result.d - DATA_HS);                                             \
863   /* pt to *beginning* of object (GMP has been monkeying around in the middle) */ \
864 }
865 \end{code}
866
867 Encoding and decoding float-ish things is pretty Integer-ish.  We use
868 these pretty magical support functions, essentially stolen from Lennart:
869 \begin{code}
870 StgFloat  __encodeFloat  PROTO((MP_INT *, I_));
871 void      __decodeFloat  PROTO((MP_INT * /*result1*/,
872                                 I_ * /*result2*/,
873                                 StgFloat));
874
875 StgDouble __encodeDouble PROTO((MP_INT *, I_));
876 void      __decodeDouble PROTO((MP_INT * /*result1*/,
877                                 I_ * /*result2*/,
878                                 StgDouble));
879 \end{code}
880
881 Some floating-point format info, made with the \tr{enquire} program
882 (version~4.3) [comes with gcc].
883 \begin{code}
884 /* this should be done by CPU architecture, insofar as possible [WDP] */
885
886 #if sparc_TARGET_ARCH   \
887  || alpha_TARGET_ARCH   \
888  || hppa1_1_TARGET_ARCH \
889  || i386_TARGET_ARCH    \
890  || m68k_TARGET_ARCH    \
891  || mipsel_TARGET_ARCH  \
892  || mipseb_TARGET_ARCH  \
893  || powerpc_TARGET_ARCH \
894  || rs6000_TARGET_ARCH
895
896 /* yes, it is IEEE floating point */
897 #include "ieee-flpt.h"
898
899 #if alpha_TARGET_ARCH   \
900  || i386_TARGET_ARCH            \
901  || mipsel_TARGET_ARCH
902
903 #undef BIGENDIAN /* little-endian weirdos... */
904 #else
905 #define BIGENDIAN 1
906 #endif
907
908 #else /* unknown floating-point format */
909
910 ******* ERROR *********** Any ideas about floating-point format?
911
912 #endif /* unknown floating-point */
913 \end{code}
914
915 \begin{code}
916 #if alpha_TARGET_ARCH
917 #define encodeFloatZh(r, hp, aa,sa,da, expon)   encodeDoubleZh(r, hp, aa,sa,da, expon)
918 #else
919 #define encodeFloatZh(r, hp, aa,sa,da, expon)   \
920 { MP_INT arg;                                   \
921   /* Does not allocate memory */                \
922                                                 \
923   arg.alloc     = aa;                           \
924   arg.size      = sa;                           \
925   arg.d         = (unsigned long int *) (BYTE_ARR_CTS(da)); \
926                                                 \
927   r = SAFESTGCALL2(StgFloat,(void *, MP_INT *, I_), __encodeFloat,&arg,(expon));        \
928 }
929 #endif /* ! alpha */
930
931 #define encodeDoubleZh(r, hp, aa,sa,da, expon)  \
932 { MP_INT arg;                                   \
933   /* Does not allocate memory */                \
934                                                 \
935   arg.alloc     = aa;                           \
936   arg.size      = sa;                           \
937   arg.d         = (unsigned long int *) (BYTE_ARR_CTS(da)); \
938                                                 \
939   r = SAFESTGCALL2(StgDouble,(void *, MP_INT *, I_), __encodeDouble,&arg,(expon));\
940 }
941
942 #if alpha_TARGET_ARCH
943 #define decodeFloatZh(exponr, ar,sr,dr, hp, f)  decodeDoubleZh(exponr, ar,sr,dr, hp, f)
944 #else
945 #define decodeFloatZh(exponr, ar,sr,dr, hp, f)                          \
946 { MP_INT mantissa;                                                      \
947   I_ exponent;                                                          \
948   StgFloat arg = (f);                                                   \
949                                                                         \
950   /* Be prepared to tell Lennart-coded __decodeFloat    */              \
951   /* where mantissa.d can be put (it does not care about the rest) */   \
952   SET_DATA_HDR(hp,ArrayOfData_info,CCC,DATA_VHS+MIN_MP_INT_SIZE,0);     \
953   mantissa.d = (hp) + DATA_HS;                                          \
954                                                                         \
955   /* Perform the operation */                                           \
956   SAFESTGCALL3(void,(void *, MP_INT *, I_ *, StgFloat),__decodeFloat,&mantissa,&exponent,arg);          \
957   exponr= exponent;                                                     \
958   ar    = mantissa.alloc;                                               \
959   sr    = mantissa.size;                                                \
960   dr    = (B_)(hp);                                                     \
961 }
962 #endif /* !alpha */
963
964 #define decodeDoubleZh(exponr, ar,sr,dr, hp, f)                         \
965 { MP_INT mantissa;                                                      \
966   I_ exponent;                                                          \
967   StgDouble arg = (f);                                                  \
968                                                                         \
969   /* Be prepared to tell Lennart-coded __decodeDouble   */              \
970   /* where mantissa.d can be put (it does not care about the rest) */   \
971   SET_DATA_HDR(hp,ArrayOfData_info,CCC,DATA_VHS+MIN_MP_INT_SIZE,0);     \
972   mantissa.d = (hp) + DATA_HS;                                          \
973                                                                         \
974   /* Perform the operation */                                           \
975   SAFESTGCALL3(void,(void *, MP_INT *, I_ *, StgDouble),__decodeDouble,&mantissa,&exponent,arg);                \
976   exponr= exponent;                                                     \
977   ar    = mantissa.alloc;                                               \
978   sr    = mantissa.size;                                                \
979   dr    = (B_)(hp);                                                     \
980 }
981 \end{code}
982
983 %************************************************************************
984 %*                                                                      *
985 \subsubsection[StgMacros-mv-floats]{Moving floats and doubles around (e.g., to/from stacks)}
986 %*                                                                      *
987 %************************************************************************
988
989 With GCC, we use magic non-standard inlining; for other compilers, we
990 just use functions (see also \tr{runtime/prims/PrimArith.lc}).
991
992 (The @OMIT_...@ is only used in compiling some of the RTS, none of
993 which uses these anyway.)
994
995 \begin{code}
996 #if alpha_TARGET_ARCH   \
997  || i386_TARGET_ARCH    \
998  || m68k_TARGET_ARCH
999
1000 #define ASSIGN_FLT(dst, src) *(StgFloat *)(dst) = (src);
1001 #define PK_FLT(src) (*(StgFloat *)(src))
1002
1003 #define ASSIGN_DBL(dst, src) *(StgDouble *)(dst) = (src);
1004 #define PK_DBL(src) (*(StgDouble *)(src))
1005
1006 #else   /* not m68k || alpha || i[34]86 */
1007
1008 /* Special handling for machines with troublesome alignment constraints */
1009
1010 #define FLOAT_ALIGNMENT_TROUBLES    TRUE
1011
1012 #if ! defined(__GNUC__) || ! defined(__STG_GCC_REGS__)
1013
1014 void        ASSIGN_DBL PROTO((W_ [], StgDouble));
1015 StgDouble   PK_DBL     PROTO((W_ []));
1016 void        ASSIGN_FLT PROTO((W_ [], StgFloat));
1017 StgFloat    PK_FLT     PROTO((W_ []));
1018
1019 #else /* yes, its __GNUC__ && we really want them */
1020
1021 #if sparc_TARGET_ARCH
1022
1023 #define ASSIGN_FLT(dst, src) *(StgFloat *)(dst) = (src);
1024 #define PK_FLT(src) (*(StgFloat *)(src))
1025
1026 #define ASSIGN_DBL(dst,src) \
1027       __asm__("st %2,%0\n\tst %R2,%1" : "=m" (((P_)(dst))[0]), \
1028         "=m" (((P_)(dst))[1]) : "f" (src));
1029
1030 #define PK_DBL(src) \
1031     ( { register double d; \
1032       __asm__("ld %1,%0\n\tld %2,%R0" : "=f" (d) : \
1033         "m" (((P_)(src))[0]), "m" (((P_)(src))[1])); d; \
1034     } )
1035
1036 #else /* ! sparc */
1037
1038 /* (not very) forward prototype declarations */
1039 void        ASSIGN_DBL PROTO((W_ [], StgDouble));
1040 StgDouble   PK_DBL     PROTO((W_ []));
1041 void        ASSIGN_FLT PROTO((W_ [], StgFloat));
1042 StgFloat    PK_FLT     PROTO((W_ []));
1043
1044 extern STG_INLINE
1045 void
1046 ASSIGN_DBL(W_ p_dest[], StgDouble src)
1047 {
1048     double_thing y;
1049     y.d = src;
1050     p_dest[0] = y.du.dhi;
1051     p_dest[1] = y.du.dlo;
1052 }
1053
1054 /* GCC also works with this version, but it generates
1055    the same code as the previous one, and is not ANSI
1056
1057 #define ASSIGN_DBL( p_dest, src ) \
1058         *p_dest = ((double_thing) src).du.dhi; \
1059         *(p_dest+1) = ((double_thing) src).du.dlo \
1060 */
1061
1062 extern STG_INLINE
1063 StgDouble
1064 PK_DBL(W_ p_src[])
1065 {
1066     double_thing y;
1067     y.du.dhi = p_src[0];
1068     y.du.dlo = p_src[1];
1069     return(y.d);
1070 }
1071
1072 extern STG_INLINE
1073 void
1074 ASSIGN_FLT(W_ p_dest[], StgFloat src)
1075 {
1076     float_thing y;
1077     y.f = src;
1078     *p_dest = y.fu;
1079 }
1080
1081 extern STG_INLINE
1082 StgFloat
1083 PK_FLT(W_ p_src[])
1084 {
1085     float_thing y;
1086     y.fu = *p_src;
1087     return(y.f);
1088 }
1089
1090 #endif /* ! sparc */
1091
1092 #endif /* __GNUC__ */
1093
1094 #endif /* not __m68k__ */
1095 \end{code}
1096
1097 %************************************************************************
1098 %*                                                                      *
1099 \subsubsection[StgMacros-array-primops]{Primitive arrays}
1100 %*                                                                      *
1101 %************************************************************************
1102
1103 We regularly use this macro to fish the ``contents'' part
1104 out of a DATA or TUPLE closure, which is what is used for
1105 non-ptr and ptr arrays (respectively).
1106
1107 BYTE_ARR_CTS returns a @C_ *@!
1108
1109 We {\em ASSUME} we can use the same macro for both!!
1110 \begin{code}
1111
1112 #ifdef DEBUG
1113 #define BYTE_ARR_CTS(a)                                 \
1114  ({ ASSERT(INFO_PTR(a) == (W_) ArrayOfData_info);       \
1115     ((C_ *) (((StgPtr) (a))+DATA_HS)); })
1116 #define PTRS_ARR_CTS(a)                                 \
1117  ({ ASSERT((INFO_PTR(a) == (W_) ArrayOfPtrs_info)       \
1118         || (INFO_PTR(a) == (W_) ImMutArrayOfPtrs_info));\
1119     ((a)+MUTUPLE_HS);} )
1120 #else
1121 #define BYTE_ARR_CTS(a)         ((char *) (((StgPtr) (a))+DATA_HS))
1122 #define PTRS_ARR_CTS(a)         ((a)+MUTUPLE_HS)
1123 #endif
1124
1125 /* sigh */
1126 extern I_ genSymZh(STG_NO_ARGS);
1127 extern I_ resetGenSymZh(STG_NO_ARGS);
1128 extern I_ incSeqWorldZh(STG_NO_ARGS);
1129
1130 extern I_ byteArrayHasNUL__ PROTO((const char *, I_));
1131 \end{code}
1132
1133 OK, the easy ops first: (all except \tr{newArr*}:
1134
1135 (OLD:) VERY IMPORTANT! The read/write/index primitive ops
1136 on @ByteArray#@s index the array using a {\em BYTE} offset, even
1137 if the thing begin gotten out is a multi-byte @Int#@, @Float#@ etc.
1138 This is because you might be trying to take apart a C struct, where
1139 the offset from the start of the struct isn't a multiple of the
1140 size of the thing you're getting.  Hence the @(char *)@ casts.
1141
1142 EVEN MORE IMPORTANT! The above is a lie.  The offsets for BlahArrays
1143 are in Blahs.  WDP 95/08
1144
1145 In the case of messing with @StgAddrs@ (@A_@), which are really \tr{void *},
1146 we cast to @P_@, because you can't index off an uncast \tr{void *}.
1147
1148 In the case of @Array#@ (which contain pointers), the offset is in units
1149 of one ptr (not bytes).
1150
1151 \begin{code}
1152 #define sameMutableArrayZh(r,a,b)       r=(I_)((a)==(b))
1153 #define sameMutableByteArrayZh(r,a,b)   r=(I_)((B_)(a)==(B_)(b))
1154
1155 #define readArrayZh(r,a,i)       r=((PP_) PTRS_ARR_CTS(a))[(i)]
1156
1157 #define readCharArrayZh(r,a,i)   indexCharOffAddrZh(r,BYTE_ARR_CTS(a),i)
1158 #define readIntArrayZh(r,a,i)    indexIntOffAddrZh(r,BYTE_ARR_CTS(a),i)
1159 #define readAddrArrayZh(r,a,i)   indexAddrOffAddrZh(r,BYTE_ARR_CTS(a),i)
1160 #define readFloatArrayZh(r,a,i)  indexFloatOffAddrZh(r,BYTE_ARR_CTS(a),i)
1161 #define readDoubleArrayZh(r,a,i) indexDoubleOffAddrZh(r,BYTE_ARR_CTS(a),i)
1162
1163 /* result ("r") arg ignored in write macros! */
1164 #define writeArrayZh(a,i,v)     ((PP_) PTRS_ARR_CTS(a))[(i)]=(v)
1165
1166 #define writeCharArrayZh(a,i,v)   ((C_ *)(BYTE_ARR_CTS(a)))[i] = (v)
1167 #define writeIntArrayZh(a,i,v)    ((I_ *)(BYTE_ARR_CTS(a)))[i] = (v)
1168 #define writeAddrArrayZh(a,i,v)   ((PP_)(BYTE_ARR_CTS(a)))[i] = (v)
1169 #define writeFloatArrayZh(a,i,v)  \
1170         ASSIGN_FLT((P_) (((StgFloat *)(BYTE_ARR_CTS(a))) + i),v)
1171 #define writeDoubleArrayZh(a,i,v) \
1172         ASSIGN_DBL((P_) (((StgDouble *)(BYTE_ARR_CTS(a))) + i),v)
1173
1174 #define indexArrayZh(r,a,i)       r=((PP_) PTRS_ARR_CTS(a))[(i)]
1175
1176 #define indexCharArrayZh(r,a,i)   indexCharOffAddrZh(r,BYTE_ARR_CTS(a),i)
1177 #define indexIntArrayZh(r,a,i)    indexIntOffAddrZh(r,BYTE_ARR_CTS(a),i)
1178 #define indexAddrArrayZh(r,a,i)   indexAddrOffAddrZh(r,BYTE_ARR_CTS(a),i)
1179 #define indexFloatArrayZh(r,a,i)  indexFloatOffAddrZh(r,BYTE_ARR_CTS(a),i)
1180 #define indexDoubleArrayZh(r,a,i) indexDoubleOffAddrZh(r,BYTE_ARR_CTS(a),i)
1181
1182 #define indexCharOffForeignObjZh(r,fo,i)   indexCharOffAddrZh(r,ForeignObj_CLOSURE_DATA(fo),i)
1183 #define indexIntOffForeignObjZh(r,fo,i)    indexIntOffAddrZh(r,ForeignObj_CLOSURE_DATA(fo),i)
1184 #define indexAddrOffForeignObjZh(r,fo,i)   indexAddrOffAddrZh(r,ForeignObj_CLOSURE_DATA(fo),i)
1185 #define indexFloatOffForeignObjZh(r,fo,i)  indexFloatOffAddrZh(r,ForeignObj_CLOSURE_DATA(fo),i)
1186 #define indexDoubleOffForeignObjZh(r,fo,i) indexDoubleOffAddrZh(r,ForeignObj_CLOSURE_DATA(fo),i)
1187
1188 #define indexCharOffAddrZh(r,a,i)   r= ((C_ *)(a))[i]
1189 #define indexIntOffAddrZh(r,a,i)    r= ((I_ *)(a))[i]
1190 #define indexAddrOffAddrZh(r,a,i)   r= ((PP_)(a))[i]
1191 #define indexFloatOffAddrZh(r,a,i)  r= PK_FLT((P_) (((StgFloat *)(a)) + i))
1192 #define indexDoubleOffAddrZh(r,a,i) r= PK_DBL((P_) (((StgDouble *)(a)) + i))
1193
1194 /* Freezing arrays-of-ptrs requires changing an info table, for the
1195    benefit of the generational collector.  It needs to scavenge mutable
1196    objects, even if they are in old space.  When they become immutable,
1197    they can be removed from this scavenge list.  */
1198 #define unsafeFreezeArrayZh(r,a)                                \
1199         do {                                            \
1200         P_ result;                                      \
1201         result=(P_) (a);                                \
1202         FREEZE_MUT_HDR(result,ImMutArrayOfPtrs_info);   \
1203         r = result;                                     \
1204         }while(0)
1205
1206 #define unsafeFreezeByteArrayZh(r,a)    r=(B_)(a)
1207 \end{code}
1208
1209 Now the \tr{newArr*} ops:
1210
1211 \begin{code}
1212 /*
1213 --------------------
1214 Will: ToDo: we need to find suitable places to put this comment, and the
1215 "in-general" one which follows.
1216
1217 ************ Nota Bene.  The "n" in this macro is guaranteed to
1218 be a register, *not* (say) Node[1].  That means that it is guaranteed
1219 to survive GC, provided only that the register is kept unaltered.
1220 This is important, because "n" is used after the HEAP_CHK.
1221
1222 In general, *all* parameters to these primitive-op macros are always
1223 registers.  (Will: For exactly *which* primitive-op macros is this guaranteed?
1224 Exactly those which can trigger GC?)
1225 ------------------------
1226
1227 NOTE: the above may now be OLD (WDP 94/02/10)
1228 */
1229 \end{code}
1230
1231 For char arrays, the size is in {\em BYTES}.
1232
1233 \begin{code}
1234 #define newCharArrayZh(r,liveness,n)    newByteArray(r,liveness,(n) * sizeof(C_))
1235 #define newIntArrayZh(r,liveness,n)     newByteArray(r,liveness,(n) * sizeof(I_))
1236 #define newAddrArrayZh(r,liveness,n)    newByteArray(r,liveness,(n) * sizeof(P_))
1237 #define newFloatArrayZh(r,liveness,n)   newByteArray(r,liveness,(n) * sizeof(StgFloat))
1238 #define newDoubleArrayZh(r,liveness,n)  newByteArray(r,liveness,(n) * sizeof(StgDouble))
1239
1240 #define newByteArray(r,liveness,n)                              \
1241 {                                                               \
1242   P_ result;                                                    \
1243   I_ size;                                                      \
1244                                                                 \
1245   HEAP_CHK(liveness,DATA_HS+BYTES_TO_STGWORDS(n),0);            \
1246   size = BYTES_TO_STGWORDS(n);                                  \
1247   ALLOC_PRIM(DATA_HS,size,0,DATA_HS+size) /* ticky ticky */;    \
1248   CC_ALLOC(CCC,DATA_HS+size,ARR_K);                             \
1249                                                                 \
1250   result = Hp-(DATA_HS+size)+1;                                 \
1251   SET_DATA_HDR(result,ArrayOfData_info,CCC,DATA_VHS+size,0);    \
1252   r = (B_) result;                                              \
1253 }
1254 \end{code}
1255
1256 Arrays of pointers need to be initialised; uses \tr{TUPLES}!
1257 The initialisation value is guaranteed to be in a register,
1258 and will be indicated by the liveness mask, so it's ok to do
1259 a \tr{HEAP_CHK}, which may trigger GC.
1260
1261 \begin{code}
1262 /* The new array initialization routine for the NCG */
1263 void newArrZh_init PROTO((P_ result, I_ n, P_ init));
1264
1265 #define newArrayZh(r,liveness,n,init)                   \
1266 {                                                       \
1267   P_ p;                                                 \
1268   P_ result;                                            \
1269                                                         \
1270   HEAP_CHK(liveness, MUTUPLE_HS+(n),0);                 \
1271   ALLOC_PRIM(MUTUPLE_HS,(n),0,MUTUPLE_HS+(n)) /* ticky ticky */; \
1272   CC_ALLOC(CCC,MUTUPLE_HS+(n),ARR_K); /* cc prof */     \
1273                                                         \
1274   result = Hp + 1 - (MUTUPLE_HS+(n));                   \
1275   SET_MUTUPLE_HDR(result,ArrayOfPtrs_info,CCC,MUTUPLE_VHS+(n),0) \
1276   for (p = result+MUTUPLE_HS; p < (result+MUTUPLE_HS+(n)); p++) { \
1277         *p = (W_) (init);                               \
1278   }                                                     \
1279                                                         \
1280   r = result;                                           \
1281 }
1282 \end{code}
1283
1284 %************************************************************************
1285 %*                                                                      *
1286 \subsubsection[StgMacros-SynchVar-primops]{Synchronizing Variables PrimOps}
1287 %*                                                                      *
1288 %************************************************************************
1289
1290 \begin{code}
1291 ED_(PrelBase_Z91Z93_closure);
1292
1293 #define newSynchVarZh(r, hp)                            \
1294 {                                                       \
1295   ALLOC_PRIM(MUTUPLE_HS,3,0,MUTUPLE_HS+3) /* ticky ticky */; \
1296   CC_ALLOC(CCC,MUTUPLE_HS+3,ARR_K); /* cc prof */       \
1297   SET_SVAR_HDR(hp,EmptySVar_info,CCC);                  \
1298   SVAR_HEAD(hp) = SVAR_TAIL(hp) = SVAR_VALUE(hp) = PrelBase_Z91Z93_closure;     \
1299   r = hp;                                               \
1300 }
1301 \end{code}
1302
1303 \begin{code}
1304 #ifdef CONCURRENT
1305
1306 void Yield PROTO((W_));
1307
1308 #define takeMVarZh(r, liveness, node)                   \
1309 {                                                       \
1310   while (INFO_PTR(node) != (W_) FullSVar_info) {        \
1311     if (SVAR_HEAD(node) == PrelBase_Z91Z93_closure)             \
1312       SVAR_HEAD(node) = CurrentTSO;                     \
1313     else                                                \
1314       TSO_LINK(SVAR_TAIL(node)) = CurrentTSO;           \
1315     TSO_LINK(CurrentTSO) = (P_) PrelBase_Z91Z93_closure;                \
1316     SVAR_TAIL(node) = CurrentTSO;                       \
1317     DO_YIELD(liveness << 1);                            \
1318   }                                                     \
1319   SET_INFO_PTR(node, EmptySVar_info);                   \
1320   r = SVAR_VALUE(node);                                 \
1321   SVAR_VALUE(node) = PrelBase_Z91Z93_closure;                           \
1322 }
1323
1324 #else
1325
1326 #define takeMVarZh(r, liveness, node)                   \
1327 {                                                       \
1328   if (INFO_PTR(node) != (W_) FullSVar_info) {           \
1329     /* Don't wrap the calls; we're done with STG land */\
1330     fflush(stdout);                                     \
1331     fprintf(stderr, "takeMVar#: MVar is empty.\n");     \
1332     EXIT(EXIT_FAILURE);                                 \
1333   }                                                     \
1334   SET_INFO_PTR(node, EmptySVar_info);                   \
1335   r = SVAR_VALUE(node);                                 \
1336   SVAR_VALUE(node) = PrelBase_Z91Z93_closure;                           \
1337 }
1338
1339 #endif
1340 \end{code}
1341
1342 \begin{code}
1343 #ifdef CONCURRENT
1344
1345 #ifdef GRAN
1346
1347 /* Only difference to the !GRAN def: RunnableThreadsHd has been replaced by */
1348 /* ThreadQueueHd i.e. the tso is added at the end of the thread queue on */
1349 /* the CurrentProc. This means we have an implicit context switch after */
1350 /* putMVar even if unfair scheduling is used in GranSim (default)!  -- HWL */
1351
1352 #define putMVarZh(node, value)                          \
1353 {                                                       \
1354   P_ tso;                                               \
1355   if (INFO_PTR(node) == (W_) FullSVar_info) {           \
1356     /* Don't wrap the calls; we're done with STG land */\
1357     fflush(stdout);                                     \
1358     fprintf(stderr, "putMVar#: MVar already full.\n");  \
1359     EXIT(EXIT_FAILURE);                                 \
1360   }                                                     \
1361   SET_INFO_PTR(node, FullSVar_info);                    \
1362   SVAR_VALUE(node) = value;                             \
1363   tso = SVAR_HEAD(node);                                \
1364   if (tso != (P_) PrelBase_Z91Z93_closure) {                            \
1365     if (DO_QP_PROF)                                     \
1366       STGCALL3(void,(void *, char *, P_, P_),QP_Event2,do_qp_prof > 1 ? "RA" : "RG",tso,CurrentTSO);    \
1367     if (ThreadQueueHd == PrelBase_Z91Z93_closure)               \
1368       ThreadQueueHd = tso;                      \
1369     else                                                \
1370       TSO_LINK(ThreadQueueTl) = tso;            \
1371     ThreadQueueTl = tso;                                \
1372     SVAR_HEAD(node) = TSO_LINK(tso);                    \
1373     TSO_LINK(tso) = (P_) PrelBase_Z91Z93_closure;                       \
1374     if(SVAR_HEAD(node) == (P_) PrelBase_Z91Z93_closure)                 \
1375       SVAR_TAIL(node) = (P_) PrelBase_Z91Z93_closure;           \
1376   }                                                     \
1377 }
1378
1379 #else /* !GRAN */
1380
1381 #define putMVarZh(node, value)                          \
1382 {                                                       \
1383   P_ tso;                                               \
1384   if (INFO_PTR(node) == (W_) FullSVar_info) {           \
1385     /* Don't wrap the calls; we're done with STG land */\
1386     fflush(stdout);                                     \
1387     fprintf(stderr, "putMVar#: MVar already full.\n");  \
1388     EXIT(EXIT_FAILURE);                                 \
1389   }                                                     \
1390   SET_INFO_PTR(node, FullSVar_info);                    \
1391   SVAR_VALUE(node) = value;                             \
1392   tso = SVAR_HEAD(node);                                \
1393   if (tso != (P_) PrelBase_Z91Z93_closure) {                            \
1394     if (DO_QP_PROF)                                     \
1395       STGCALL3(void,(void *, char *, P_, P_),QP_Event2,do_qp_prof > 1 ? "RA" : "RG",tso,CurrentTSO);    \
1396     if (RunnableThreadsHd == PrelBase_Z91Z93_closure)                   \
1397       RunnableThreadsHd = tso;                          \
1398     else                                                \
1399       TSO_LINK(RunnableThreadsTl) = tso;                \
1400     RunnableThreadsTl = tso;                            \
1401     SVAR_HEAD(node) = TSO_LINK(tso);                    \
1402     TSO_LINK(tso) = (P_) PrelBase_Z91Z93_closure;                       \
1403     if(SVAR_HEAD(node) == (P_) PrelBase_Z91Z93_closure)                 \
1404       SVAR_TAIL(node) = (P_) PrelBase_Z91Z93_closure;           \
1405   }                                                     \
1406 }
1407
1408 #endif  /* GRAN */
1409
1410 #else
1411
1412 #define putMVarZh(node, value)                          \
1413 {                                                       \
1414   P_ tso;                                               \
1415   if (INFO_PTR(node) == (W_) FullSVar_info) {           \
1416     /* Don't wrap the calls; we're done with STG land */\
1417     fflush(stdout);                                     \
1418     fprintf(stderr, "putMVar#: MVar already full.\n");  \
1419     EXIT(EXIT_FAILURE);                                 \
1420   }                                                     \
1421   SET_INFO_PTR(node, FullSVar_info);                    \
1422   SVAR_VALUE(node) = value;                             \
1423 }
1424
1425 #endif
1426 \end{code}
1427
1428 \begin{code}
1429 #ifdef CONCURRENT
1430
1431 #define readIVarZh(r, liveness, node)                   \
1432 {                                                       \
1433   if (INFO_PTR(node) != (W_) ImMutArrayOfPtrs_info) {   \
1434     if (SVAR_HEAD(node) == PrelBase_Z91Z93_closure)             \
1435       SVAR_HEAD(node) = CurrentTSO;                     \
1436     else                                                \
1437       TSO_LINK(SVAR_TAIL(node)) = CurrentTSO;           \
1438     TSO_LINK(CurrentTSO) = (P_) PrelBase_Z91Z93_closure;                \
1439     SVAR_TAIL(node) = CurrentTSO;                       \
1440     DO_YIELD(liveness << 1);                            \
1441   }                                                     \
1442   r = SVAR_VALUE(node);                                 \
1443 }
1444
1445 #else
1446
1447 #define readIVarZh(r, liveness, node)                   \
1448 {                                                       \
1449   if (INFO_PTR(node) != (W_) ImMutArrayOfPtrs_info) {   \
1450     /* Don't wrap the calls; we're done with STG land */\
1451     fflush(stdout);                                     \
1452     fprintf(stderr, "readIVar#: IVar is empty.\n");     \
1453     EXIT(EXIT_FAILURE);                                 \
1454   }                                                     \
1455   r = SVAR_VALUE(node);                                 \
1456 }
1457
1458 #endif
1459 \end{code}
1460
1461 \begin{code}
1462 #ifdef CONCURRENT
1463
1464 #ifdef GRAN
1465
1466 /* Only difference to the !GRAN def: RunnableThreadsHd has been replaced by */
1467 /* ThreadQueueHd i.e. the tso is added at the end of the thread queue on */
1468 /* the CurrentProc. This means we have an implicit context switch after */
1469 /* writeIVar even if unfair scheduling is used in GranSim (default)!  -- HWL */
1470
1471 #define writeIVarZh(node, value)                        \
1472 {                                                       \
1473   P_ tso;                                               \
1474   if (INFO_PTR(node) == (W_) ImMutArrayOfPtrs_info) {   \
1475     /* Don't wrap the calls; we're done with STG land */\
1476     fflush(stdout);                                     \
1477     fprintf(stderr, "writeIVar#: IVar already full.\n");\
1478     EXIT(EXIT_FAILURE);                                 \
1479   }                                                     \
1480   tso = SVAR_HEAD(node);                                \
1481   if (tso != (P_) PrelBase_Z91Z93_closure) {                            \
1482     if (ThreadQueueHd == PrelBase_Z91Z93_closure)               \
1483       ThreadQueueHd = tso;                      \
1484     else                                                \
1485       TSO_LINK(ThreadQueueTl) = tso;            \
1486     while(TSO_LINK(tso) != PrelBase_Z91Z93_closure) {                   \
1487       if (DO_QP_PROF)                                   \
1488         STGCALL3(void,(void *, char *, P_, P_),QP_Event2,do_qp_prof > 1 ? "RA" : "RG",tso,CurrentTSO);  \
1489       tso = TSO_LINK(tso);                              \
1490     }                                                   \
1491     if (DO_QP_PROF)                                     \
1492       STGCALL3(void,(void *, char *, P_, P_),QP_Event2,do_qp_prof > 1 ? "RA" : "RG",tso,CurrentTSO);    \
1493     ThreadQueueTl = tso;                                \
1494   }                                                     \
1495   /* Don't use freeze, since it's conditional on GC */  \
1496   SET_INFO_PTR(node, ImMutArrayOfPtrs_info);            \
1497   MUTUPLE_CLOSURE_SIZE(node) = (MUTUPLE_VHS+1);         \
1498   SVAR_VALUE(node) = value;                             \
1499 }
1500
1501 #else /* !GRAN */
1502
1503 #define writeIVarZh(node, value)                        \
1504 {                                                       \
1505   P_ tso;                                               \
1506   if (INFO_PTR(node) == (W_) ImMutArrayOfPtrs_info) {   \
1507     /* Don't wrap the calls; we're done with STG land */\
1508     fflush(stdout);                                     \
1509     fprintf(stderr, "writeIVar#: IVar already full.\n");\
1510     EXIT(EXIT_FAILURE);                                 \
1511   }                                                     \
1512   tso = SVAR_HEAD(node);                                \
1513   if (tso != (P_) PrelBase_Z91Z93_closure) {                            \
1514     if (RunnableThreadsHd == PrelBase_Z91Z93_closure)                   \
1515       RunnableThreadsHd = tso;                          \
1516     else                                                \
1517       TSO_LINK(RunnableThreadsTl) = tso;                \
1518     while(TSO_LINK(tso) != PrelBase_Z91Z93_closure) {                   \
1519       if (DO_QP_PROF)                                   \
1520         STGCALL3(void,(void *, char *, P_, P_),QP_Event2,do_qp_prof > 1 ? "RA" : "RG",tso,CurrentTSO);  \
1521       tso = TSO_LINK(tso);                              \
1522     }                                                   \
1523     if (DO_QP_PROF)                                     \
1524       STGCALL3(void,(void *, char *, P_, P_),QP_Event2,do_qp_prof > 1 ? "RA" : "RG",tso,CurrentTSO);    \
1525     RunnableThreadsTl = tso;                            \
1526   }                                                     \
1527   /* Don't use freeze, since it's conditional on GC */  \
1528   SET_INFO_PTR(node, ImMutArrayOfPtrs_info);            \
1529   MUTUPLE_CLOSURE_SIZE(node) = (MUTUPLE_VHS+1);         \
1530   SVAR_VALUE(node) = value;                             \
1531 }
1532
1533 #endif  /* GRAN */
1534
1535 #else
1536
1537 #define writeIVarZh(node, value)                        \
1538 {                                                       \
1539   P_ tso;                                               \
1540   if (INFO_PTR(node) == (W_) ImMutArrayOfPtrs_info) {   \
1541     /* Don't wrap the calls; we're done with STG land */\
1542     fflush(stdout);                                     \
1543     fprintf(stderr, "writeIVar#: IVar already full.\n");\
1544     EXIT(EXIT_FAILURE);                                 \
1545   }                                                     \
1546   /* Don't use freeze, since it's conditional on GC */  \
1547   SET_INFO_PTR(node, ImMutArrayOfPtrs_info);            \
1548   MUTUPLE_CLOSURE_SIZE(node) = (MUTUPLE_VHS+1);         \
1549   SVAR_VALUE(node) = value;                             \
1550 }
1551
1552 #endif
1553 \end{code}
1554
1555 %************************************************************************
1556 %*                                                                      *
1557 \subsubsection[StgMacros-Wait-primops]{Delay/Wait PrimOps}
1558 %*                                                                      *
1559 %************************************************************************
1560
1561 \begin{code}
1562 #ifdef CONCURRENT
1563
1564 /* ToDo: for GRAN */
1565
1566 #define delayZh(liveness, us)                           \
1567   {                                                     \
1568     if (WaitingThreadsTl == PrelBase_Z91Z93_closure)            \
1569       WaitingThreadsHd = CurrentTSO;                    \
1570     else                                                \
1571       TSO_LINK(WaitingThreadsTl) = CurrentTSO;          \
1572     WaitingThreadsTl = CurrentTSO;                      \
1573     TSO_LINK(CurrentTSO) = PrelBase_Z91Z93_closure;                     \
1574     TSO_EVENT(CurrentTSO) = (W_) ((us) < 1 ? 1 : (us)); \
1575     DO_YIELD(liveness << 1);                            \
1576   }
1577
1578 #else
1579
1580 #define delayZh(liveness, us)                           \
1581   {                                                     \
1582     fflush(stdout);                                     \
1583     fprintf(stderr, "delay#: unthreaded build.\n");     \
1584     EXIT(EXIT_FAILURE);                                 \
1585   }
1586
1587 #endif
1588
1589 #ifdef CONCURRENT
1590
1591 /* ToDo: something for GRAN */
1592
1593 #define waitReadZh(liveness, fd)                        \
1594   {                                                     \
1595     if (WaitingThreadsTl == PrelBase_Z91Z93_closure)            \
1596       WaitingThreadsHd = CurrentTSO;                    \
1597     else                                                \
1598       TSO_LINK(WaitingThreadsTl) = CurrentTSO;          \
1599     WaitingThreadsTl = CurrentTSO;                      \
1600     TSO_LINK(CurrentTSO) = PrelBase_Z91Z93_closure;                     \
1601     TSO_EVENT(CurrentTSO) = (W_) (-(fd));               \
1602     DO_YIELD(liveness << 1);                            \
1603   }
1604
1605 #else
1606
1607 #define waitReadZh(liveness, fd)                        \
1608   {                                                     \
1609     fflush(stdout);                                     \
1610     fprintf(stderr, "waitRead#: unthreaded build.\n");  \
1611     EXIT(EXIT_FAILURE);                                 \
1612   }
1613
1614 #endif
1615
1616 #ifdef CONCURRENT
1617
1618 /* ToDo: something for GRAN */
1619
1620 #ifdef HAVE_SYS_TYPES_H
1621 #include <sys/types.h>
1622 #endif  HAVE_SYS_TYPES_H */
1623
1624 #define waitWriteZh(liveness, fd)                       \
1625   {                                                     \
1626     if (WaitingThreadsTl == PrelBase_Z91Z93_closure)            \
1627       WaitingThreadsHd = CurrentTSO;                    \
1628     else                                                \
1629       TSO_LINK(WaitingThreadsTl) = CurrentTSO;          \
1630     WaitingThreadsTl = CurrentTSO;                      \
1631     TSO_LINK(CurrentTSO) = PrelBase_Z91Z93_closure;                     \
1632     TSO_EVENT(CurrentTSO) = (W_) (-(fd+FD_SETSIZE));    \
1633     DO_YIELD(liveness << 1);                            \
1634   }
1635
1636 #else
1637
1638 #define waitWriteZh(liveness, fd)                       \
1639   {                                                     \
1640     fflush(stdout);                                     \
1641     fprintf(stderr, "waitWrite#: unthreaded build.\n"); \
1642     EXIT(EXIT_FAILURE);                                 \
1643   }
1644
1645 #endif
1646
1647 \end{code}
1648
1649 %************************************************************************
1650 %*                                                                      *
1651 \subsubsection[StgMacros-IO-primops]{Primitive I/O, error-handling primops}
1652 %*                                                                      *
1653 %************************************************************************
1654
1655 \begin{code}
1656 extern P_ TopClosure;
1657 EXTFUN(ErrorIO_innards);
1658 EXTFUN(__std_entry_error__);
1659
1660 #define errorIOZh(a)            \
1661     do { TopClosure=(a);        \
1662          (void) SAFESTGCALL1(I_,(void *, FILE *),fflush,stdout); \
1663          (void) SAFESTGCALL1(I_,(void *, FILE *),fflush,stderr); \
1664          JMP_(ErrorIO_innards); \
1665     } while(0)
1666
1667 #if !defined(CALLER_SAVES_SYSTEM)
1668 /* can use the macros */
1669 #define stg_getc(stream)        getc((FILE *) (stream))
1670 #define stg_putc(c,stream)      putc((c),((FILE *) (stream)))
1671 #else
1672 /* must not use the macros (they contain embedded calls to _filbuf/whatnot) */
1673 #define stg_getc(stream)        SAFESTGCALL1(I_,(void *, FILE *),fgetc,(FILE *) (stream))
1674 #define stg_putc(c,stream)      SAFESTGCALL2(I_,(void *, char, FILE *),fputc,(c),((FILE *) (stream)))
1675 #endif
1676
1677 int initialize_virtual_timer(int us);
1678 int install_segv_handler(STG_NO_ARGS);
1679 int install_vtalrm_handler(STG_NO_ARGS);
1680 void initUserSignals(STG_NO_ARGS);
1681 void blockUserSignals(STG_NO_ARGS);
1682 void unblockUserSignals(STG_NO_ARGS);
1683 IF_RTS(void blockVtAlrmSignal(STG_NO_ARGS);)
1684 IF_RTS(void unblockVtAlrmSignal(STG_NO_ARGS);)
1685 IF_RTS(void AwaitEvent(I_ delta);)
1686
1687 #if  defined(_POSIX_SOURCE) && !defined(nextstep3_TARGET_OS)
1688         /* For nextstep3_TARGET_OS comment see stgdefs.h. CaS */
1689 extern I_ sig_install PROTO((I_, I_, sigset_t *));
1690 #define stg_sig_ignore(s,m)     SAFESTGCALL3(I_,(void *, I_, I_),sig_install,s,STG_SIG_IGN,(sigset_t *)m)
1691 #define stg_sig_default(s,m)    SAFESTGCALL3(I_,(void *, I_, I_),sig_install,s,STG_SIG_DFL,(sigset_t *)m)
1692 #define stg_sig_catch(s,sp,m)   SAFESTGCALL3(I_,(void *, I_, I_),sig_install,s,sp,(sigset_t *)m)
1693 #else
1694 extern I_ sig_install PROTO((I_, I_));
1695 #define stg_sig_ignore(s,m)     SAFESTGCALL2(I_,(void *, I_, I_),sig_install,s,STG_SIG_IGN)
1696 #define stg_sig_default(s,m)    SAFESTGCALL2(I_,(void *, I_, I_),sig_install,s,STG_SIG_DFL)
1697 #define stg_sig_catch(s,sp,m)   SAFESTGCALL2(I_,(void *, I_, I_),sig_install,s,sp)
1698 #endif
1699
1700 #define STG_SIG_DFL     (-1)
1701 #define STG_SIG_IGN     (-2)
1702 #define STG_SIG_ERR     (-3)
1703
1704 StgInt getErrorHandler(STG_NO_ARGS);
1705 #ifndef PAR
1706 void   raiseError PROTO((StgStablePtr handler));
1707 StgInt catchError PROTO((StgStablePtr newErrorHandler));
1708 #endif
1709 void decrementErrorCount(STG_NO_ARGS);
1710
1711 #define stg_catchError(sp)        SAFESTGCALL1(I_,(void *, StgStablePtr),catchError,sp)
1712 #define stg_decrementErrorCount() SAFESTGCALL0(void,(void *),decrementErrorCount)
1713 \end{code}
1714
1715 %************************************************************************
1716 %*                                                                      *
1717 \subsubsection[StgMacros-stable-ptr]{Primitive ops for manipulating stable pointers}
1718 %*                                                                      *
1719 %************************************************************************
1720
1721
1722 The type of these should be:
1723
1724 \begin{verbatim}
1725 makeStablePointer#  :: a -> State# _RealWorld -> StateAndStablePtr# _RealWorld a
1726 deRefStablePointer# :: StablePtr# a -> State# _RealWorld -> StateAndPtr _RealWorld a
1727 \end{verbatim}
1728
1729 Since world-tokens are no longer explicitly passed around, the
1730 implementations have a few less arguments/results.
1731
1732 The simpler one is @deRefStablePointer#@ (which is only a primop
1733 because it is more polymorphic than is allowed of a ccall).
1734
1735 \begin{code}
1736 #ifdef PAR
1737
1738 #define deRefStablePtrZh(ri,sp)                                     \
1739 do {                                                                \
1740     fflush(stdout);                                                 \
1741     fprintf(stderr, "deRefStablePtr#: no stable pointer support.\n");\
1742     EXIT(EXIT_FAILURE);                                             \
1743 } while(0)
1744
1745 #else /* !PAR */
1746
1747 extern StgPtr _deRefStablePointer PROTO((StgInt, StgPtr));
1748
1749 #define deRefStablePtrZh(ri,sp) \
1750    ri = SAFESTGCALL2(I_,(void *, I_, P_),_deRefStablePointer,sp,StorageMgrInfo.StablePointerTable);
1751 \end{code}
1752
1753 Declarations for other stable pointer operations.
1754
1755 \begin{code}
1756 void    freeStablePointer       PROTO((I_ stablePtr));
1757
1758 void    enterStablePtr          PROTO((StgStablePtr, StgFunPtr));
1759 void    performIO               PROTO((StgStablePtr));
1760 I_      enterInt                PROTO((StgStablePtr));
1761 I_      enterFloat              PROTO((StgStablePtr));
1762 P_      deRefStablePointer      PROTO((StgStablePtr));
1763 IF_RTS(I_ catchSoftHeapOverflow PROTO((StgStablePtr, I_));)
1764 IF_RTS(I_ getSoftHeapOverflowHandler(STG_NO_ARGS);)
1765 IF_RTS(extern StgStablePtr softHeapOverflowHandler;)
1766 IF_RTS(void shutdownHaskell(STG_NO_ARGS);)
1767
1768 EXTFUN(stopPerformIODirectReturn);
1769 EXTFUN(startPerformIO);
1770 EXTFUN(stopEnterIntDirectReturn);
1771 EXTFUN(startEnterInt);
1772 EXTFUN(stopEnterFloatDirectReturn);
1773 EXTFUN(startEnterFloat);
1774
1775 void enterStablePtr PROTO((StgStablePtr stableIndex, StgFunPtr startCode));
1776
1777 #endif /* !PAR */
1778
1779 IF_RTS(extern I_ ErrorIO_call_count;)
1780 \end{code}
1781
1782 Somewhat harder is @makeStablePointer#@ --- it is usually simple but
1783 if we're unlucky, it will have to allocate a new table and copy the
1784 old bit over.  Since we might, very occasionally, have to call the
1785 garbage collector, this has to be a macro... sigh!
1786
1787 NB @newSP@ is required because it is entirely possible that
1788 @stablePtr@ and @unstablePtr@ are aliases and so we can't do the
1789 assignment to @stablePtr@ until we've finished with @unstablePtr@.
1790
1791 Another obscure piece of coding is the recalculation of the size of
1792 the table.  We do this just in case Jim's threads decide they want to
1793 context switch---in which case any stack-allocated variables may get
1794 trashed.  (If only there was a special heap check which didn't
1795 consider context switching...)
1796
1797 \begin{code}
1798 #ifndef PAR
1799
1800 /* Calculate SP Table size from number of pointers */
1801 #define SPTSizeFromNoPtrs( newNP ) (DYN_VHS + 1 + 2 * (newNP))
1802
1803 /* Calculate number of pointers in new table from number in old table:
1804    any strictly increasing expression will do here */
1805 #define CalcNewNoSPtrs( i ) ((i)*2 + 100)
1806
1807 void enlargeSPTable PROTO((P_, P_));
1808
1809 #define makeStablePtrZh(stablePtr,liveness,unstablePtr)             \
1810 do {                                                                \
1811   EXTDATA_RO(StablePointerTable_info);                              \
1812   EXTDATA(UnusedSP);                                                \
1813   StgStablePtr newSP;                                               \
1814                                                                     \
1815   if (SPT_EMPTY(StorageMgrInfo.StablePointerTable)) { /* free stack is empty */ \
1816     { /* Variables used before the heap check */                    \
1817       I_ OldNoPtrs = SPT_NoPTRS( StorageMgrInfo.StablePointerTable ); \
1818       I_ NewNoPtrs = CalcNewNoSPtrs( OldNoPtrs );                   \
1819       I_ NewSize = SPTSizeFromNoPtrs( NewNoPtrs );                  \
1820       HEAP_CHK(liveness, _FHS+NewSize, 0);                          \
1821     }                                                               \
1822     { /* Variables used after the heap check - same values */       \
1823       I_ OldNoPtrs = SPT_NoPTRS( StorageMgrInfo.StablePointerTable ); \
1824       I_ NewNoPtrs = CalcNewNoSPtrs( OldNoPtrs );                   \
1825       I_ NewSize = SPTSizeFromNoPtrs( NewNoPtrs );                  \
1826       P_ SPTable = Hp + 1 - (_FHS + NewSize);                       \
1827                                                                     \
1828       CC_ALLOC(CCC, _FHS+NewSize, SPT_K); /* cc prof */             \
1829       SET_DYN_HDR(SPTable,StablePointerTable_info,CCC,NewSize,NewNoPtrs);\
1830       SAFESTGCALL2(void, (void *, P_, P_), enlargeSPTable, SPTable, StorageMgrInfo.StablePointerTable);      \
1831       StorageMgrInfo.StablePointerTable = SPTable;                  \
1832     }                                                               \
1833   }                                                                 \
1834                                                                     \
1835   newSP = SPT_POP(StorageMgrInfo.StablePointerTable);               \
1836   SPT_SPTR(StorageMgrInfo.StablePointerTable, newSP) = unstablePtr; \
1837   CHECK_SPT_CLOSURE( StorageMgrInfo.StablePointerTable );           \
1838   stablePtr = newSP;                                                \
1839 } while (0)
1840
1841 #else
1842
1843 #define makeStablePtrZh(stablePtr,liveness,unstablePtr)             \
1844 do {                                                                \
1845     fflush(stdout);                                                 \
1846     fprintf(stderr, "makeStablePtr#: no stable pointer support.\n");\
1847     EXIT(EXIT_FAILURE);                                             \
1848 } while(0)
1849
1850 #endif /* !PAR */
1851 \end{code}
1852
1853 %************************************************************************
1854 %*                                                                      *
1855 \subsubsection[StgMacros-unsafePointerEquality]{Primitive `op' for breaking referential transparency}
1856 %*                                                                      *
1857 %************************************************************************
1858
1859 The type of this is @reallyUnsafePtrEquality :: a -> a -> Int#@ so we
1860 can expect three parameters: the two arguments and a "register" to put
1861 the result into.
1862
1863 Message to Will: This primop breaks referential transparency so badly
1864 you might want to leave it out.  On the other hand, if you hide it
1865 away in an appropriate monad, it's perfectly safe. [ADR]
1866
1867 Note that this primop is non-deterministic: different results can be
1868 obtained depending on just what the garbage collector (and code
1869 optimiser??) has done.  However, we can guarantee that if two objects
1870 are pointer-equal, they have the same denotation --- the converse most
1871 certainly doesn't hold.
1872
1873 ToDo ADR: The degree of non-determinism could be greatly reduced by
1874 following indirections.
1875
1876 \begin{code}
1877 #define reallyUnsafePtrEqualityZh(r,a,b) r=((StgPtr)(a) == (StgPtr)(b))
1878 \end{code}
1879
1880 %************************************************************************
1881 %*                                                                      *
1882 \subsubsection[StgMacros-parallel-primop]{Primitive `op' for sparking (etc)}
1883 %*                                                                      *
1884 %************************************************************************
1885
1886 Assuming local sparking in some form, we can now inline the spark request.
1887
1888 We build a doubly-linked list in the heap, so that we can handle FIFO
1889 or LIFO scheduling as we please.
1890
1891 Anything with tag >= 0 is in WHNF, so we discard it.
1892
1893 \begin{code}
1894 #ifdef CONCURRENT
1895
1896 ED_(PrelBase_Z91Z93_closure);
1897 ED_(True_closure);
1898
1899 #if defined(GRAN)
1900 #define parZh(r,node)                           \
1901         PARZh(r,node,1,0,0,0,0,0)
1902
1903 #define parAtZh(r,node,where,identifier,gran_info,size_info,par_info,rest) \
1904         parATZh(r,node,where,identifier,gran_info,size_info,par_info,rest,1)
1905
1906 #define parAtAbsZh(r,node,proc,identifier,gran_info,size_info,par_info,rest) \
1907         parATZh(r,node,proc,identifier,gran_info,size_info,par_info,rest,2)
1908
1909 #define parAtRelZh(r,node,proc,identifier,gran_info,size_info,par_info,rest) \
1910         parATZh(r,node,proc,identifier,gran_info,size_info,par_info,rest,3)
1911
1912 #define parAtForNowZh(r,node,where,identifier,gran_info,size_info,par_info,rest)        \
1913         parATZh(r,node,where,identifier,gran_info,size_info,par_info,rest,0)
1914
1915 #define parATZh(r,node,where,identifier,gran_info,size_info,par_info,rest,local)        \
1916 {                                                       \
1917   sparkq result;                                                \
1918   if (SHOULD_SPARK(node)) {                             \
1919     SaveAllStgRegs();                                   \
1920     { sparkq result;                                            \
1921       result = NewSpark((P_)node,identifier,gran_info,size_info,par_info,local);        \
1922       if (local==2) {         /* special case for parAtAbs */   \
1923         GranSimSparkAtAbs(result,(I_)where,identifier);\
1924       } else if (local==3) {  /* special case for parAtRel */   \
1925         GranSimSparkAtAbs(result,(I_)(CurrentProc+where),identifier);   \
1926       } else {       \
1927         GranSimSparkAt(result,where,identifier);        \
1928       }        \
1929       context_switch = 1;                               \
1930     }                                                   \
1931     RestoreAllStgRegs();                                \
1932   } else if (do_qp_prof) {                              \
1933     I_ tid = threadId++;                                \
1934     SAFESTGCALL2(void,(I_, P_),QP_Event0,tid,node);     \
1935   }                                                     \
1936   r = 1; /* return code for successful spark -- HWL */  \
1937 }
1938
1939 #define parLocalZh(r,node,identifier,gran_info,size_info,par_info,rest) \
1940         PARZh(r,node,rest,identifier,gran_info,size_info,par_info,1)
1941
1942 #define parGlobalZh(r,node,identifier,gran_info,size_info,par_info,rest) \
1943         PARZh(r,node,rest,identifier,gran_info,size_info,par_info,0)
1944
1945 #if 1
1946
1947 #define PARZh(r,node,rest,identifier,gran_info,size_info,par_info,local) \
1948 {                                                       \
1949   if (SHOULD_SPARK(node)) {                             \
1950     SaveAllStgRegs();                                   \
1951     { sparkq result;                                            \
1952       result = NewSpark((P_)node,identifier,gran_info,size_info,par_info,local);\
1953       add_to_spark_queue(result);                               \
1954       GranSimSpark(local,(P_)node);                                     \
1955       context_switch = 1;                               \
1956     }                                                   \
1957     RestoreAllStgRegs();                                \
1958   } else if (do_qp_prof) {                              \
1959     I_ tid = threadId++;                                \
1960     SAFESTGCALL2(void,(I_, P_),QP_Event0,tid,node);     \
1961   }                                                     \
1962   r = 1; /* return code for successful spark -- HWL */  \
1963 }
1964
1965 #else
1966
1967 #define PARZh(r,node,rest,identifier,gran_info,size_info,par_info,local) \
1968 {                                                       \
1969   sparkq result;                                                \
1970   if (SHOULD_SPARK(node)) {                             \
1971     result = NewSpark((P_)node,identifier,gran_info,size_info,par_info,local);\
1972     ADD_TO_SPARK_QUEUE(result);                         \
1973     SAFESTGCALL2(void,(W_),GranSimSpark,local,(P_)node);        \
1974     /* context_switch = 1;  not needed any more -- HWL */       \
1975   } else if (do_qp_prof) {                              \
1976     I_ tid = threadId++;                                \
1977     SAFESTGCALL2(void,(I_, P_),QP_Event0,tid,node);     \
1978   }                                                     \
1979   r = 1; /* return code for successful spark -- HWL */  \
1980 }
1981
1982 #endif 
1983
1984 #define copyableZh(r,node)                              \
1985   /* copyable not yet implemented!! */
1986
1987 #define noFollowZh(r,node)                              \
1988   /* noFollow not yet implemented!! */
1989
1990 #else  /* !GRAN */
1991
1992 extern I_ required_thread_count;
1993
1994 #ifdef PAR
1995 #define COUNT_SPARK     TSO_GLOBALSPARKS(CurrentTSO)++; sparksCreated++
1996 #else
1997 #define COUNT_SPARK
1998 #endif
1999
2000 /* 
2001    Note that we must bump the required thread count NOW, rather
2002    than when the thread is actually created.  
2003  */
2004
2005 #define forkZh(r,liveness,node)                         \
2006 {                                                       \
2007   while (PendingSparksTl[REQUIRED_POOL] == PendingSparksLim[REQUIRED_POOL]) \
2008     DO_YIELD((liveness << 1) | 1);                      \
2009   COUNT_SPARK;                                          \
2010   if (SHOULD_SPARK(node)) {                             \
2011     *PendingSparksTl[REQUIRED_POOL]++ = (P_)(node);     \
2012   } else if (DO_QP_PROF) {                              \
2013     I_ tid = threadId++;                                \
2014     SAFESTGCALL2(void,(I_, P_),QP_Event0,tid,node);     \
2015   }                                                     \
2016   required_thread_count++;                              \
2017   context_switch = 1;                                   \
2018   r = 1; /* Should not be necessary */                  \
2019 }
2020
2021 #define parZh(r,node)                                   \
2022 {                                                       \
2023   COUNT_SPARK;                                          \
2024   if (SHOULD_SPARK(node) &&                             \
2025    PendingSparksTl[ADVISORY_POOL] < PendingSparksLim[ADVISORY_POOL]) {  \
2026     *PendingSparksTl[ADVISORY_POOL]++ = (P_)(node);     \
2027   } else {                                              \
2028     sparksIgnored++;                                    \
2029     if (DO_QP_PROF) {                                   \
2030       I_ tid = threadId++;                              \
2031       SAFESTGCALL2(void,(I_, P_),QP_Event0,tid,node);   \
2032     }                                                   \
2033   }                                                     \
2034   r = 1; /* Should not be necessary */                  \
2035 }
2036
2037 #endif  /* GRAN */ 
2038
2039 #endif  /* CONCURRENT */
2040 \end{code}
2041
2042 The following seq# code should only be used in unoptimized code.
2043 Be warned: it's a potential bug-farm.
2044
2045 First we push two words on the B stack: the current value of RetReg 
2046 (which may or may not be live), and a continuation snatched largely out
2047 of thin air (it's a point within this code block).  Then we set RetReg
2048 to the special polymorphic return code for seq, load up Node with the
2049 closure to be evaluated, and we're off.  When the eval returns to the
2050 polymorphic seq return point, the two words are popped off the B stack,
2051 RetReg is restored, and we jump to the continuation, completing the
2052 primop and going on our merry way.
2053
2054 \begin{code}
2055
2056 ED_RO_(vtbl_seq);
2057
2058 #define seqZh(r,liveness,node)              \
2059   ({                                        \
2060     __label__ cont;                         \
2061     /* STK_CHK(liveness,0,2,0,0,0,0); */    \
2062     /* SpB -= BREL(2); */                   \
2063     SpB[BREL(0)] = (W_) RetReg;             \
2064     SpB[BREL(1)] = (W_) &&cont;             \
2065     RetReg = (StgRetAddr) vtbl_seq;         \
2066     Node = node;                            \
2067     ENT_VIA_NODE();                         \
2068     InfoPtr = (D_)(INFO_PTR(Node));         \
2069     JMP_(ENTRY_CODE(InfoPtr));              \
2070     cont:                                   \
2071     r = 1; /* Should be unnecessary */      \
2072   })
2073
2074 \end{code}
2075
2076 %************************************************************************
2077 %*                                                                      *
2078 \subsubsection[StgMacros-foreign-objects]{Foreign Objects}
2079 %*                                                                      *
2080 %************************************************************************
2081
2082 [Based on previous MallocPtr comments -- SOF]
2083
2084 This macro is used to construct a ForeignObj on the heap.
2085
2086 What this does is plug the pointer (which will be in a local
2087 variable) together with its finalising/free routine, into a fresh heap
2088 object and then sets a result (which will be a register) to point
2089 to the fresh heap object.
2090
2091 To accommodate per-object finalisation, augment the macro with a
2092 finalisation routine argument. Nothing spectacular, just plug the
2093 pointer to the routine into the ForeignObj -- SOF 4/96
2094
2095 Question: what's this "SET_ACTIVITY" stuff - should I be doing this
2096 too?  (It's if you want to use the SPAT profiling tools to
2097 characterize program behavior by ``activity'' -- tail-calling,
2098 heap-checking, etc. -- see Ticky.lh.  It is quite specialized.
2099 WDP 95/1)
2100
2101 (Swapped first two arguments to make it come into line with what appears
2102 to be `standard' format, return register then liveness mask. -- SOF 4/96)
2103
2104 \begin{code}
2105 #ifndef PAR
2106
2107 StgInt eqForeignObj PROTO((StgForeignObj p1, StgForeignObj p2));
2108
2109 #define makeForeignObjZh(r, liveness, mptr, finalise)    \
2110 do {                                                     \
2111   P_ result;                                             \
2112                                                          \
2113   HEAP_CHK((W_)liveness, _FHS + ForeignObj_SIZE,0);              \
2114   CC_ALLOC(CCC,_FHS + ForeignObj_SIZE,ForeignObj_K); /* cc prof */   \
2115                                                                    \
2116   result = Hp + 1 - (_FHS + ForeignObj_SIZE);                      \
2117   SET_ForeignObj_HDR(result,ForeignObj_info,CCC,_FHS + ForeignObj_SIZE,0); \
2118   ForeignObj_CLOSURE_DATA(result)      = (P_)mptr;                 \
2119   ForeignObj_CLOSURE_FINALISER(result) = (P_)finalise;             \
2120   ForeignObj_CLOSURE_LINK(result) = StorageMgrInfo.ForeignObjList; \
2121   StorageMgrInfo.ForeignObjList = result;                          \
2122                                                         \
2123                                                         \
2124  /*fprintf(stderr,"DEBUG: ForeignObj(0x%x) = <0x%x, 0x%x, 0x%x, 0x%x>\n",       \
2125       result,                                           \
2126       result[0],result[1],                              \
2127       result[2],result[3]);*/                           \
2128                                                         \
2129   CHECK_ForeignObj_CLOSURE( result );                   \
2130   VALIDATE_ForeignObjList( StorageMgrInfo.ForeignObjList ); \
2131                                                         \
2132   (r) = (P_) result;                                    \
2133 } while (0)
2134
2135 #define writeForeignObjZh(res,datum)    ((PP_) ForeignObj_CLOSURE_DATA(res)) = ((P_)datum)
2136
2137 #else
2138 #define makeForeignObjZh(r, liveness, mptr, finalise)               \
2139 do {                                                                \
2140     fflush(stdout);                                                 \
2141     fprintf(stderr, "makeForeignObj#: no foreign object support.\n");\
2142     EXIT(EXIT_FAILURE);                                             \
2143 } while(0)
2144
2145 #define writeForeignObjZh(res,datum)    \
2146 do {                                                                \
2147     fflush(stdout);                                                 \
2148     fprintf(stderr, "writeForeignObj#: no foreign object support.\n");\
2149     EXIT(EXIT_FAILURE);                                             \
2150 } while(0)
2151
2152 #endif /* !PAR */
2153 \end{code}
2154
2155
2156 End-of-file's multi-slurp protection:
2157 \begin{code}
2158 #endif /* ! STGMACROS_H */
2159 \end{code}